fork创建进程过程(底层实现) 和 写实拷贝

.

现在我们来总结一下fork的整个处理流程。从C语言中的函数开始,它在glibc库中会被转换为int0x80加调用号的形式,触发中断。该中断在系统初始化过程中注册,它的处理函数是system_call,这个函数在system_call.s文件中,在这里面它首先压栈一些参数,然后会根据调用号调用sys_call_table的相应表项,sys_call_table定义在include/linux/sys.h中,它是一个函数指针数组。现在对应的就是sys_fork函数,它仍然是在system_call.s中定义的。我们来看它的处理过程,首先它会调用find_empty_process函数来从task数组中查找一个还没有使用的task,

找到之后把对应的索引返回(保存到eax中),随后它又保存了其他一些寄存器,并且把返回的任务索引压入栈中,依次作为参数来调用copy_process函数。下面我们来看copy_process的处理过程。首先,它会分配一个内存页,把task_struct结构体保存到这个内存页的最开始位置(同时需要注册进task数组),并把内核栈指针设为该页的顶端。紧接着为这个新的task_struct复制为之前的task_struct,然后需要修改一些域,这些域都是不能直接从父进程继承的。这些域包括进程id设置为我们在find_empty_process过程中找到的id,pid设置为调用fork的进程id,leader不能继承父类的,时钟和信号也不继承,设置eip,设置eax为0,设置内核栈指针等等。然后比较重要的现在需要为它设置页表了。我们再详细总结一下设置页表的过程。
为了设置页表,我们需要知道一个进程的代码段和数据段的起始地址以及占用了多大的空间。由于二者是重叠的,我们设置一个就可以了。获取的过程是通过查看进程ldt表项来获取基址和限长。由于linux0.11中进程的起始地址为64M×nr,所以前面的基址其实并没有太大作用,知道了起始地址,现在就可
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值