fork()与vfork()的内核剖析

  fork()

   Linux通过clone()系统调用实现fork().这个调用通过一系列的参数标志来指明父,子进程需要共享的资源。fork(),vfork()和_clone()库函数都根据各自需要的参数标志去调用clone(),然后由clone()去调用do_fork();

       do_fork()完成创建中的大部分工作,它在定义的kernel/fork.c文件中。该函数调用copy_process()函数,然后让进程开始运行工作流程如下:

  • 调用dup_task_struct()为新进程创建一个内核栈,thread_info结构和task_struct( 进程是处于执行期的程序以及它所管理的资源(如打开的文件、挂起的信号、进程状态、地址空间等等)的总称。),这些值与当前进程的值相同。此时,子进程和父进程的描述符完全相同;
  • 检查并确保新创建这个子进程后,当前用户所拥有的进程数目没有超出给它分配的资源限制。
  • 子进程着手使自己与父进程区分开来。子进程描述符里面的许多成员都要被清0或者设为初始化值。那些不是继承而来的进程描述符成员,主要统计信息。task_struct中的大多数据都依然未被修改。
  • 子进程的状态被设置为TASK_UNINTREEUPTIBLE,以保证它不会投入运行。
  • copy_process()调用copy_flags()以更新task_struct中flags成员。表明进程是否拥有超级用户的权限PF_SUPERPRIV标志被清0。表明进程还没有调用exec()函数标志被设置。
  • 调用alloc_pid()为新进程分配一个有效的PID。
  • 根据传递的clone()的参数标志,copy_process()拷贝或共享打开的文件,文件系统信息,信号处理函数,进程地址空间和命名空间等。在一般的情况下,这些资源会被给定的进程的所有线程共享;
  • 最后,copy_process()做扫尾工程,并返回一个指向子进程的指针。

  再返回do_fork()函数,如果copy_process()函数成功返回,新创建的子进程被唤醒并让其投入运行。内核有意选择子进程首先执行。因为一般子进程都会马上调用execv()函数,这样可以避免写时拷贝的额外开销。如果父进程首先执行的话,有可能会开始向地址空间写入。

vfork()

      除了不拷贝父进程的页表项外,vfork()系统调用和fork()的功能相同。子进程作为父进程一个单独的线程在它的地址空间里运行,父进程被阻塞,直到子进程退出或者执行exec().

      vfork()系统调用的实现是通过clone()系统调用传递一个特殊标志来进行的。

  •   在调用copy_process()时,task_struct的vfor_done成员被设置为NULL。
  •  在执行do_fork()时,如果给定特定的标志,则vfork_done会指向一个特定的地址
  • 子进程先开始运行,父进程不是马上恢复执行,而是一直的等待,直到子进程通过vfork_done指针向它发送信号。
  • 在调用mm_release()时,该函数用于进程退出内存地址空间,并且检查vfork_done是否为空,如果不为空,则向父进程发送信号 。
  • 回到do_fork(),父进程醒来并返回。

fork和vfork的区别:

1. fork( )的子进程拷贝父进程的数据段和代码段;vfork( )的子进程与父进程共享数据段

2. fork( )的父子进程的执行次序不确定;vfork( )保证子进程先运行,在调用exec或exit之前与父进程数据是共享的,在它调用exec或exit之后父进程才可能被调度运行。

3. vfork( )保证子进程先运行,在它调用exec或exit之后父进程才可能被调度运行。如果在调用这两个函数之前子进程依赖于父进程的进一步动作,则会导致死锁。

4.当需要改变共享数据段中变量的值,则拷贝父进程。

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值