Chinaunix首页 | 论坛 | 博客
  • 博客访问: 145326
  • 博文数量: 10
  • 博客积分: 1883
  • 博客等级: 上尉
  • 技术积分: 115
  • 用 户 组: 普通用户
  • 注册时间: 2009-12-01 11:26
文章分类
文章存档

2012年(2)

2011年(4)

2010年(3)

2009年(1)

分类: LINUX

2009-12-22 15:02:49

在 ./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 中

#define __NR_fork 2



将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 的定义

    typedef int (*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) |
0

上一篇:没有了

下一篇:配置TFTP服务

给主人留下些什么吧!~~