潘恒 + 原创做品转载请注明出处 + 《Linux内核分析》MOOC课程http://mooc.study.163.com/course/USTC-1000029000 编程
1、使用库函数API和C代码中嵌入汇编代码两种方式使用同一个系统调用安全
1.使用库函数API:函数
我选用第2号系统调用,forkspa
实验截图以下:先是编写调用函数的c代码指针
开始运行:code
2.嵌入汇编代码:blog
汇编代码分析: 接口
"mov $0x2,%%eax\n\t" /*将系统调用号2放入eax中*/ "int $0x80\n\t" /*中断向量号0x80,即128*/ "mov %%eax,%o\n\t" /*将保存在eax中的返回值赋给pid*/ :"=m"(pid)
运行:进程
2、总结事件
系统调用的工做机制:
通常状况下,应用程序经过应用编程接口(API)而不是直接经过系统调用来编程。这点很重要,由于应用程序使用的这种编程接口实际上并不须要和内核提供的系统调用一一对应。一个API定义了一组应用程序使用的编程接口。它们能够实现成一个系统调用,也能够经过调用多个系统调用来实现,而彻底不使用任何系统调用也不存在问题。
用户空间的程序没法直接执行内核代码。它们不能直接调用内核空间中的函数,由于内核驻留在受保护的地址空间上。若是进程能够直接在内核的地址空间上读写的话,系统安全就会失去控制。因此,应用程序应该以某种方式通知系统,告诉内核本身须要执行一个系统调用,但愿系统切换到内核态,这样内核就能够表明应用程序来执行该系统调用了。
通知内核的机制是靠软件中断实现的。首先,用户程序为系统调用设置参数。其中一个参数是系统调用编号。参数设置完成后,程序执行“系统调用”指令。x86系统上的软中断由int产生。这个指令会致使一个异常:产生一个事件,这个事件会导致处理器切换到内核态并跳转到一个新的地址,并开始执行那里的异常处理程序。
在Linux中,每一个系统调用被赋予一个系统调用号。这样,经过这个独一无二的号就能够关联系统调用。当用户空间的进程执行一个系统调用的时候,这个系统调用号就被用来指明究竟是要执行哪一个系统调用。进程不会说起系统调用的名称。
除了系统调用号之外,大部分系统调用都还须要一些外部的参数输人。因此,在发生异常的时候,应该把这些参数从用户空间传给内核。最简单的办法就是像传递系统调用号同样把这些参数也存放在寄存器里。在x86系统上,ebx, ecx, edx, esi和edi按照顺序存放前五个参数。须要六个或六个以上参数的状况很少见,此时,应该用一个单独的寄存器存放指向全部这些参数在用户空间地址的指针。