简述系统调用的过程,以C语言库函数time为例。
首先,调用time c语言api。
第二步, api 通过中断处理,调用syscall,完成从用户态到内核态的转变。期间保存寄存器。
第三步,调用sys_time。
第四步, 切换回用户态,恢复寄存器的值。
如果CS寄存器最低两位是0, 则表示内核态, 如果是3, 则为用户态。
当进行内核态到用户态以及用户态到内核态的转变时,都会修改这个值。
time_t tt;
struct tm *t;
/*tt = time(NULL);*/
asm volatile(
"mov $0, %%ebx\n\t"
"mov $0xd, %%eax\n\t"
"int $0x80\n\t"
"mov %%eax, %0\n\t"
: "=m" (tt)
);
t = localtime(&tt);
printf("%d %d %d %d %d %d\n", t->tm_year, t->tm_mon, t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec);
这一段内嵌代码调用了13号中断。注意%eax寄存器中存储syscall number,而%ebx中存储变量, 最后把返回值赋值给tt。
这段函数和直接调用time(NULL)是得到相同结果。
下面实现一个getpid()的系统调用。
#include <time.h>
#include <stdio.h>
#include <unistd.h>
void my_sys_getpid()
{
printf("%s\n", "getpid...");
long ID;
asm volatile(
"mov $0x14, %%eax\n\t"
"int $0x80\n\t"
"mov %%eax, %0\n\t"
: "=m"(ID)
);
printf("%s %ld\n", "getpid() = ", ID);
}
int main(void)
{
my_sys_getpid(); /*my syscall*/
long ID = getpid(); /* C API getpid()*/
printf("%s %ld\n", "getpid() = ", ID);
return 0;
}
同样的,在%eax寄存器中存储syscall number,把返回值赋值个给ID。
exit...
getpid() = 16810
getpid() = 16810
通过验证,我的程序是正确的。 原创作品转载请注明出处 《Linux内核分析》MOOC课程http://mooc.study.163.com/course/USTC-1000029000