当前位置:   article > 正文

fork创建进程过程(底层实现) 和 写实拷贝_fork系统调用创建新进程的过程和原理,写时拷贝

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,所以前面的基址其实并没有太大作用,知道了起始地址,现在就可以知道它在页目录中的索引了,我们
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/weixin_40725706/article/detail/210713
推荐阅读
相关标签
  

闽ICP备14008679号