为了安全,Linux 中分为用户态和内核态两种运行状态。对于普通进程,平时都是运行在用户态下,仅拥有基本的运行能力。当进行一些敏感操作,比如说要打开文件(open)然后进行写入(write)、分配内存(malloc)时,就会切换到内核态。内核态进行相应的检查,如果通过了,则按照进程的要求执行相应的操作,分配相应的资源。这种机制被称为系统调用,用户态进程发起调用,切换到内核态,内核态完成,返回用户态继续执行,是用户态唯一主动切换到内核态的合法手段(exception 和 interrupt 是被动切换)。
#include <stdio.h> #include<stdlib.h> #include<sys/types.h> #include<sys/stat.h> #include <fcntl.h> int main(int argc,char *argv[]) { int fd; //fd= creat(argv[1],0755); //if (fd<0) // printf("error!"); asm volatile( "movl %1,%%ebx\n\t" //系统调?传递第?个参数使?EBX寄存器,为argv[1] "movl $0755,%%ecx\n\t"//系统调?传递第二个参数使?ECX寄存器,为0755 "movl $0x8,%%eax\n\t"//使?%eax传递系统调?号8,?16进制为0x8 "int $0x80\n\t" //触发系统调? "movl %%eax,%0\n\t" //通过EAX寄存器返回系统调?值 :"=m"(fd) :"b"(argv[1]) ); printf("%d\n",fd); fclose(fd); return 0; }
在gdb中加断点__ia32_sys_creat,运行test.c编译成的可执行程序test,在断点处停止,观察堆栈情况。
"int $0x80\n\t"指令触发系统调用后,先执行entry_INT80_compat函数,该函数对现场进行保存,之后调用do_int80_syscall_32函数,由用户态切换至内核态,再调用do_syscall_32_irqs_on函数,在其内调用__ia32_sys_creat函数完成creat系统调用的功能,之后切换回用户态,entry_INT80_compat函数恢复现场。
运行test 2.txt命令成功创建了2.txt文件。
原文:https://www.cnblogs.com/gy101/p/12960894.html