linux0.11内核fork实现分析(不看不知道,一看很简单)

曾几何时,只是一直在调用库函数fork,只知道它创建一个子进程,并且子进程返回值是0,父进程返回值是子进程pid。但是一直没有深究内核代码,今天终于使用gdb调试了一把fork的内核代码,下面就让我们一探究竟吧。

1.创建进程的本质是什么?

根据目前理解,其实就是构造了PCB,这个PCB会唯一标示一个进程的存在,并且会构建子进程的页目录和页表等等。

2.为什么fork()调用会有2个返回值,并且父进程返回子进程pid,子进程返回0?

首先搞明白一点,GCC调用函数的时候,返回值是放在eax中的。既然fork创建了新进程,说明那么父进程和子进程都有返回值,那么自然有两个返回值,并且子进程通过设置p->tss.eax=0(返回值放在eax中喔),当调度到子进程执行时,eax内容代表返回值,所以子进程返回0。而父进程eax存放子进程的pid,那么父进程返回值也就是子进程的pid。

通过看上面的描述肯定是云里雾里,我们通过函数库fork()调用到最后返回,分析看看(有分析过内核的基础,不然好像也不会看懂下面的东西)

fork()->_sys_call0)int,fork)

调用fork函数,内部会调用到_sys_call0(int,fork),这是内核定义的宏:

#define _syscall0(type,name) \
type name(void) \
{ \
long __res; \
__asm__ volatile ("int $0x80" \
: "=a" (__res) \
: "0" (__NR_##name)); \
if (__res >= 0) \
return (type) __res; \
errno = -__res; \
return -1; \
}

调用到int 0x80就进入到系统调用入口处理程序_system_call:

call _sys_call_table(,%eax,4)


这样就会跳转到_sys_fork:

.align 2
_sys_fork:
call _find_empty_process
testl %eax,%eax
js 1f
push %gs
pushl %esi
pushl %edi
pushl %ebp
pushl %eax
call _copy_process
addl $20,%esp
1: ret


find_empty_process的作用:取得子进程的进程id,然后调用进入copy_process函数,在里面会创建子进程的PCB和页目录、页表等等工作。

最后退出系统调用的时候会返回到

if (__res >= 0) \
return (type) __res; \
errno = -__res; \
return -1; \
}

从if(__res>=0)开始,如果调度到父进程return _res=pid,如果调度到子进程,return _res=0。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值