朱明涛 原创作品转载请注明出处 《Linux内核分析》MOOC课程http://mooc.study.163.com/course/USTC-1000029000
实验要求
1.选择一个系统调用(13号系统调用time除外),系统调用列表参见http://codelab.shiyanlou.com/xref/linux-3.18.6/arch/x86/syscalls/syscall_32.tbl
2.参考视频中的方式使用库函数API和C代码中嵌入汇编代码两种方式使用同一个系统调用,推荐在实验楼Linux虚拟机环境下完成实验。
实验过程
本次实验选择getpid进行系统调用
1.在实验楼环境中,使用vi getpid.c创建只用C语言编写的调用文件,如图
C语言使用库函数API代码
#include <stdio.h> #include <unistd.h> int main() { pid_t tt; tt = getpid(); printf("%u\n", tt); return 0; }
2.使用vi getpid-asm 创建嵌套有汇编代码的调用文件,如图所示
C代码中嵌入汇编代码
#include <stdio.h> #include <unistd.h> int main() { pid_t tt; asm volatile ( "mov $0,%%ebx\n\t" "mov $0x14, %%eax\n\t" "int $0x80\n\t" "mov %%eax, %0\n\t" :"=m"(tt) ); printf("%u\n", tt); return 0; }
内嵌汇编调用 system_call():系统调用号放入 eax 中,系统调用的参数,按顺序存入相应寄存器中,返回值使用 eax 传递值。
使用中断从用户态进入内核态,中断处理程序SAVE_ALL保存现场,然后进入内核态。
总结
系统调用是用户态和内核态的桥梁,而具体的措施就是中断。
采用内嵌汇编编写的代码,在运行时,通过eax准备系统调用号,使用ebx、ecx等传递具体参数,当触发0x80中断时,经过中断处理程序,进入内核态。
系统调用的三层皮:xyz( API )、system_call( 中断向量 )和 sys_xyz( 服务程序 )。用户态中的 xyz() 函数就是系统调用所对应的系统 API;在这个 API 中将系统调用封装好,并在执行时触发 int 0x80这个中断。这个中断在对应了内核态中的 System_call();System_call() 中可能会执行中断服务程序 sys_xyz()。中断服务完成后有可能会发生进程调度。如果没有发生进程调度,那么执行 iret返回用户态继续执行下面的其他指令。