在 ./init/main.c 中第一次出现fork调用
static inline _syscall0(int,fork) void main(void) { if( !fork() ){ init(); } }
|
其中 _syscall0 是一个宏定义,在 ./include/initd.h 中
#define _syscall0(type,name) \ type name(void) \ { \ long __res; \ __asm__ volatile ( "int $0x80" \ :"=a" (__res) \ :"" (__NR_##name));\ if (__res >= 0) \ return (type) __res;\ errno = -__res; \ return -1;\ }
|
在 ./include/unistd.h 中
将fork进行宏替换
static int fork(void) { long _res; _asm_ volatile ("int $0x80" : "=a"(_res) : "0"(_NR_fork)); if( _res >= 0 ) return (int) _res; errno = -_res; return -1; }
|
函数是用NR_fork 来初始化eax (eax=2), 说明fork就是int 0x80的 2号调用(至于怎么联系,另一个帖子有解释),好,进入中断
在 ./kernel/system_call.s 中找到int 0x80中断的处理函数
.align 2 _system_call: cmpl $nr_system_calls-1,%eax ja bad_sys_call push %ds push %es push %fs pushl %edx pushl %ecx # push %ebx,%ecx,%edx as parameters pushl %ebx # to the system call movl $0x10,%edx # set up ds,es to kernel space mov %dx,%ds mov %dx,%es movl $0x17,%edx # fs points to local data space mov %dx,%fs call _sys_call_table(,%eax,4)
|
在./include/linux/sched.h 中有 fn_ptr 的定义
在 ./include/linux/sys.h 中
fn_ptr sys_call_table[] = { sys_setup, sys_exit,sys_fork,...}
|
所以call 的调用地址就是 _sys_call_table + %eax * 4 即:sys_fork ( 其中eax=2, 每个指针的长度是4, 所以用_sys_call_table的首地址加 2*4, 就是 _sys_call_table 数组中的第二个元素的地址,即sys_fork )
call _sys_call_table(,%eax,4) 即:call _sys_fork
在./kernel/system_call.s中 .align 2 _sys_fork: call _find_empty_process test1 %eax,%eax js 1f push %gs pushl %esi pushl %esi pushl %esi pushl %esi call _copy_process add $20,%esp 1: ret
|
可见fork又主要是调用了两个函数:
find_empty_process 和 copy_process ;它们都在kernel/fork.c中实现
说明:gcc编译器在生成汇编代码,其函数名及变量名前都会都会加_,所以在汇编中调用C的函數或变量的时候,需要手动加上一个下划线。
阅读(1499) | 评论(0) | 转发(1) |