Linux fork()分析

Linux通过clone()系统调用实现fork()。这个系统调用通过一系列的参数标志来指明父、子进程需要共享的资源。fork()、vfork()和__clone()库函数都根据各自需要的参数标志去条用clone(),然后由clone()去调用do_fork()。
do_fork()完成了创建中的大部分工作,他的定义在kernel/fork.c文件中。该函数调用copy_process()函数,然后让进程开始运行。copy_process()函数完成的工作如下:
(1)调用dup_task_struct()为新进程创建一个内核栈、thread_info结构和task_struct,这些值与当前进程的值相同。此时,子进程和父进程的描述符完全相同。
(2)检查并确保新创建这个子进程后,当前用户所拥有的进程数目没有超过给它分配的资源的限制。
(3)子进程着手使自己与父进程区别开来。进程描述符内的许多成员都要被清0或设为初始值。那些不是继承而来的进程描述符成员,主要是统计信息。task_struct中的大多数数据都依然为被修改。
(4)子进程的状态被设置为TASK_UNINTERRUPTIBLE,以保证他不会投入运行。
(5)调用copy_flags()以更新task_struct的flags成员。表明进程是否拥有超级用户权限的PF_SUPERPRIV标志被清0。表明进程还没有调用exec()函数的PF_FORKNOEXEC标志被设置。
(6)调用alloc_pid()为新进程分配一个有效的PID。
(7)根据传递给clone()的参数标志,copy_process()拷贝或共享打开的文件、文件系统信息、信号处理函数、进程地址空间和命名空间等。在一般情况下,这些资源会被给定进程的所有线程共享;否则,这些资源对每个进程都是不同的,因此被拷贝到这里。
(8)最后,copy_process()做扫尾工作并返回一个指向子进程的指针。
再回到do_fork()函数,如果copy_process()函数成功返回,新创建的子进程被唤醒并让其投入运行。内核有意选择子进程首先执行。因为一半子进程都会马上调用exec()函数,这样可以避免写时拷贝的额外开销,如果父进程首先执行的话,有可能会开始向地址空间写入。
这里写图片描述

如有错误请指正

猜你喜欢

转载自blog.csdn.net/baidu_34045013/article/details/79889001