朱宇轲 + 原创作品转载请注明出处 + 《Linux内核分析》MOOC课程http://mooc.study.163.com/course/USTC-1000029000
在本次的实验中,我们将通过用C和汇编实现的同样一段代码来解析系统调用的过程。
废话少说,开始实验!
C语言程序如下所示:
/*test.c*/
#include<sys/types.h> #include<sys/stat.h> int main() { int status; int type=S_IRWXG; char string[]="./newdir"; status=mkdir(string,type); return 0; }
汇编语言程序如下所示:
/*test2.c*/
#include<sys/types.h> #include<sys/stat.h> int main() { int status; int type=S_IRWXG; char string[]="./newdir2"; asm volatile( "mov $0x27,%%eax " "int $0x80 " "mov %%eax,%0 " :"=m"(status) :"b"(string),"c"(type) ); return 0; }
我们本次使用的API是mkdir函数,它是Linux下的创建目录函数。它的函数原型是:
int mkdir(const char *path, mode_t mode);
参数:
path是目录名
mode是目录权限
返回值:
返回0 表示成功, 返回 -1表示错误,并且会设置errno值。
执行C程序后的运行结果是:
可以看见编译执行text.c后,home中多出了newdir目录。
执行汇编程序后的结果是:
可以看见编译执行text2.c后,home中多出了newdir2目录。
接下来分析汇编程序。
asm volatile( "mov $0x27,%%eax " "int $0x80 " "mov %%eax,%0 " :"=m"(status) :"b"(string),"c"(type) );
首先,将存储着目录名与权限的变量string和type存入ebx与ecx中,当做mkdir的参数传入(代码第六行)。
之后,将要调用的系统调用号0x27(十进制的话就是39,对应mkdir函数)传入eax中,然后通过int命令触发中断,进入中断处理程序。带中断处理结束后,再讲eax的内容返回至status变量,这样mkdir就算是调用完成了。
系统调用的执行过程实际上就是像老师课上讲的那样,分为API->中断处理程序->系统调用三个层次。注意系统调用和API并不是一一对应的,有可能一个API对应多个系统调用,也有可能一个系统调用对应多个API。我个人理解,API实际上可以算是对系统调用的封装。具体的执行过程,如下所示。
本次就分析到这里,谢谢大家。