在操作系统中我们进程会听到‘系统调用’。并且在变编程中我们用到的很多函数都是通过系统调用实现的。例如fork() 函数、pause()
函数 、printf() 函数……
我学习了linux 0.11 内核的系统调用。
系统调用使用的函数名叫做:syscall [0,1,2……],
标注:在方括号的数字表示的系统调用的函数含有几个参数。其中syscall函数在system_call.s 实现。
对于系统调用实际就是:用户使用终端调用int 0x80和放在eax寄存器的功能号来使用呢和提供的
各种功能服务。操作系统提供的功能叫做系统调用。
对于所用系统调用的实现函数,内横将它们按照系统调用功能号数排列成一张函数指针表(在include/linux/sys.h):
sys_call_table(72个)。然后在中断 int 0x80
的处理过程中根用户提供的功能号调用对应的系统调用函数。sys_name
对于系统调用的中断处理过程,可以将它看作一个'接口'进程。
这个程序在刚开始检测eax(功能号)是否有效。如果无效在退出。否则保存一些有用的寄存器的值到堆栈上,例如 linux
内核默认把段寄存器ds,es存储内核数据段,而fs用于用户数据段。然后根据地址跳转表(sys_call_table)调用对应的C语言。在C语言调用完之后将返回值压入栈保存其来。
接下来查看当前进程的状态,如果进程已经不出运行状态(由于调用函数、
时间片用完等其他原因)则调用schedule函数。由于在调度函数在运行之前已将返回地址ret_from_sys_call入栈了,所以只要调用schedule后最终返回即可。从ret_from_sys_call
开始做一些系统调用后的处理工作。
1》如果当前进程为进程0 ,在直接退出此次系统调用,中断返回
2》如果当前进程是内核进程(根据代码段描述符和堆栈判断),弹出栈 ,终中断返回
在末端用来处理调用系统调用的信号。
最后,该程序回复保存的寄存器内容,推出此次中断并且返回
在main.c中:
static inline _syscall0(int, fork);因为inline是替换的意思:
- static inline int fork(void)
- {
- __asm__ volatile("int $0x80","=a"(__res):"0"(NR_fork));
- if(__res>=0)
- return (int)__res;
- errno = -__res;
- return -1;
- }
在linux 中sys_fork在sys_call.s中实现
流程:
call find_empty_process
------>返回nr
call
copy_process------->创建进程,将父进程想过数据结构赋值到子进程。
|
|
copy_mem 此时父子进程共享地址空间
标注; 在用户态调用fork时,我使用命令:gcc -E name.c -o name,i
……
extern __pid_t fork (void) __attribute__ ((__nothrow__));
……
阅读(2900) | 评论(3) | 转发(1) |