Linux下创建进程的三种方式及特点

原文链接: https://blog.csdn.net/wujiafei_njgcxy/article/details/77116175

https://blog.csdn.net/wujiafei_njgcxy/article/details/77116175(原文地址)

在Linux中主要提供了fork、vfork、clone三个进程创建方法。 
在linux源码中这三个调用的执行过程是执行fork(),vfork(),clone()时,通过一个系统调用表映射到sys_fork(),sys_vfork(),sys_clone(),再在这三个函数中去调用do_fork()去做具体的创建进程工作。

fork 
    fork创建一个进程时,子进程只是完全复制父进程的资源,复制出来的子进程有自己的task_struct结构和pid,但却复制父进程其它所有的资源。例如,要是父进程打开了五个文件,那么子进程也有五个打开的文件,而且这些文件的当前读写指针也停在相同的地方。所以,这一步所做的是复制。这样得到的子进程独立于父进程, 具有良好的并发性,但是二者之间的通讯需要通过专门的通讯机制,如:pipe,共享内存等机制, 另外通过fork创建子进程,需要将上面描述的每种资源都复制一个副本。这样看来,fork是一个开销十分大的系统调用,这些开销并不是所有的情况下都是必须的,比如某进程fork出一个子进程后,其子进程仅仅是为了调用exec执行另一个可执行文件,那么在fork过程中对于虚存空间的复制将是一个多余的过程。但由于现在Linux中是采取了copy-on-write(COW写时复制)技术,为了降低开销,fork最初并不会真的产生两个不同的拷贝,因为在那个时候,大量的数据其实完全是一样的。写时复制是在推迟真正的数据拷贝。若后来确实发生了写入,那意味着parent和child的数据不一致了,于是产生复制动作,每个进程拿到属于自己的那一份,这样就可以降低系统调用的开销。所以有了写时复制后呢,vfork其实现意义就不大了。 

vfork 
 vfork系统调用不同于fork,用vfork创建的子进程与父进程共享地址空间,也就是说子进程完全运行在父进程的地址空间上,如果这时子进程修改了某个变量,这将影响到父进程。 
 因此,上面的例子如果改用vfork()的话,那么两次打印a,b的值是相同的,所在地址也是相同的。 但此处有一点要注意的是用vfork()创建的子进程必须显示调用exit()来结束,否则子进程将不能结束,而fork()则不存在这个情况。 
Vfork也是在父进程中返回子进程的进程号,在子进程中返回0。 
用 vfork创建子进程后,父进程会被阻塞直到子进程调用exec(exec,将一个新的可执行文件载入到地址空间并执行之。)或exit。vfork的好处是在子进程被创建后往往仅仅是为了调用exec执行另一个程序,因为它就不会对父进程的地址空间有任何引用,所以对地址空间的复制是多余的 ,因此通过vfork共享内存可以减少不必要的开销。

clone 
  系统调用fork()和vfork()是无参数的,而clone()则带有参数。fork()是全部复制,vfork()是共享内存,而clone() 是则可以将父进程资源有选择地复制给子进程,而没有复制的数据结构则通过指针的复制让子进程共享,具体要复制哪些资源给子进程,由参数列表中的 clone_flags来决定。另外,clone()返回的是子进程的pid。

  一、fork 
  1. 调用方法 
  #include  
   #include  
   pid_t fork(void); 
   正确返回:在父进程中返回子进程的进程号,在子进程中返回0 
  错误返回:-1 
  2. fork函数调用的用途 
  一个进程希望复制自身,从而父子进程能同时执行不同段的代码。 

  二、vfork 
  1. 调用方法 
  与fork函数完全相同 
  #include  
  #include  
  pid_t vfork(void); 
  正确返回:在父进程中返回子进程的进程号,在子进程中返回0 
  错误返回:-1 
  2. vfork函数调用的用途 
  用vfork创建的进程主要目的是用exec函数执行另外的程序。 


  三、clone 
  1.调用方法 
  #include  
  int clone(int (*fn)(void *), void *child_stack, int flags, void *arg); 
  正确返回:返回所创建进程的PID,函数中的flags标志用于设置创建子进程时的相关选项,具体含义参看P25 
  错误返回:-1 
  2.clone()函数调用的用途 
  用于有选择地设置父子进程之间需共享的资源 


  四、fork,vfork,clone的区别 
  1. fork出来的子进程是父进程的一个拷贝,即,子进程从父进程得到了数据段和堆栈段的拷贝,这些需要分配新的内存;而对于只读的代码段,通常使用共享内存的方式访问;而vfork则是子进程与父进程共享内存空间, 子进程对虚拟地址空间任何数据的修改同样为父进程所见;clone则由用户通过参clone_flags 的设置来决定哪些资源共享,哪些资源拷贝。 
  2. fork不对父子进程的执行次序进行任何限制,fork返回后,子进程和父进程都从调用fork函数的下一条语句开始行,但父子进程运行顺序是不定的,它取决于内核的调度算法;而在vfork调用中,子进程先运行,父进程挂起,直到子进程调用了exec或exit之后,父子进程的执行次序才不再有限制;clone中由标志CLONE_VFORK来决定子进程在执行时父进程是阻塞还是运行,若没有设置该标志,则父子进程同时运行,设置了该标志,则父进程挂起,直到子进程结束为止。

 

你可能感兴趣的:(unix)