SA16225055冯金明
原创作品转载请注明出处
《Linux内核分析》MOOC课程http://mooc.study.163.com/course/USTC-1000029000
实验相关内容
实验要求:
- 选择一个系统调用(13号系统调用time除外)
- 参考视频中的方式使用库函数API和C代码中嵌入汇编代码两种方式使用同一个系统调用
实验代码以及相关截图
汇编代码分析
"mov $0x14, %%eax\n\t"/*0x14转化为10进制为20,将20传值给eax,20是getpid的系统调用号*/
"int $0x80\n\t" /*执行系统调用,中断号为0x80,实现了用户态到内核态的切换*/
"mov %%eax, %0\n\t" /*把系统调用之后的返回值(此返回值自动存放在寄存器eax中)放入到参数pid中*/
:"=m"(pid) /*"="表示操作数在指令中是只写的,"m"表示内存变量,这条指令表示将pid的值写入到内存中,而不是寄存器中*/
简析系统调用
首先,我们需要知道CPU有几种不同的指令执行级别。在Linux系统环境下,只有两种级别:0级代表内核态,3级代表用户态。中断处理是用户态进入内核态的主要方式,而系统调用则是一种特殊的中断。系统调用是:操作系统为用户态进程于硬件设备进行交互提供的一组接口!
说道系统调用,就必须说说API(application program interface应用编程接口)。我们需要清楚二者之间的联系:
API只是一个函数定义
系统调用则是通过软中断向内核发出的一个明确的请求
Libc库定义了一些API引用的封装例程,而一般每一个系统调用对应封装了一个例程,库再用这些封装例程来定义给出用户的API
理解系统调用的三层皮:xyz(API),system_call(中断向量),sys_xyz(中断服务程序)
以老师课堂上的那张图为例进行解析:
我的理解是这样的:用户编写程序,调用API,API中包含着封装例程,而封装例程对应着系统调用(通过执行int $0x80来执行系统调用 )。当用户态进程调用一个系统调用时,CPU切换到内核态并开始执行一个内核函数。在用户态时,系统调用号就已经存放在了eax中了,内核态中,系统可以根据这个系统调用号寻找到相应的中断服务程序,并执行之。执行完后,会通过相应的寄存器将执行结果返回(例如实验中的getpid保存至eax中),再之就是退出系统调用,退出内核态,返回用户态,接着运行源程序。
小弟之拙见,如有什么理解错误之处,还请指点出来。老实说,老铁,这回可以给我个5分嘛!!!