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