现在的位置: 首页 > 综合 > 正文

linux学习之十—vfork()&fork()函数

2017年02月05日 ⁄ 综合 ⁄ 共 1396字 ⁄ 字号 评论关闭

vfork()也可以用来创建一个新进程,与fork()函数一样都是调用一次,返回两次,但它有自己的独特之处,区别如下:

1.使用fork创建一个子进程,子进程完全复制父进程的资源,这样得到的子进程独立于父进程,具有良好的并发性。而使用vfork创建一个子进程,操作系统并不将父进程的地址可见完全复制到子进程,用vfork创建的子进程共享父进程的地址空间,也就是说子进程完全运行在父进程的地址空间上。子进程对该地址空间中任何数据的修改同样为父进程所见。

2.使用fork创建一个子进程时,哪个进程先运行取决于系统的调度算法。而vfork一个进程时,vfork保证子进程先运行,当它调用exec或exit之后,父进程才可能被调度运行。如果在调用exec或exit之前子进程要依赖父进程的某个行为,就会导致死锁。

什么时候用vfork?

因为使用fork创建一个子进程时,子进程需要将父进程几乎每种资源都复制,所以fork是一个开销很大的系统调用,这样的开销不是所有情况都需要的。比如fork一个进程后,立即调用exec执行另一个应用程序,那么fork过程中子进程对父进程地址空间的复制将是一个多余的过程。而vfork不拷贝父进程的地址空间,这大大减少立系统开销。

#include<stdio.h>
#include<sys/types.h>
#include<unistd.h>

int glodVar = 5;

int main()
{
   pid_t pid;
  
   int Var=1,i;
   
   printf("fork is different with vfork\n");
   pid = fork();
   //pid = vfork();
   switch(pid)
   {

      case 0:
      i=3;
      while(i-->0)
      {
        printf("Child process is running\n");
        glodVar++;
        Var++;
        sleep(1);    
      }
      printf("Child's goldVar=%d,var=%d\n",glodVar,Var);
      exit(0);
      case -1:
      perror("Process creation failed\n");
      exit(0);
      default:
      i=5;
      while(i-->0)
      {
        printf("Parent process is running\n");
        glodVar++;
        Var++;
        sleep(1); 
      } 
      printf("Parent's goldVar=%d,var=%d\n",glodVar,Var);
      exit(0);
   } 
  
   return 0;
}

fork()

vfork()

运行分析:

1.使用fork创建子进程时,子进程继承立父进程的全局变量与局部变量。
子进程中,最后全局变量glodar和局部变量Var的值均递增3,分别为8和4;
而父进程中,两个变量分别递增5,分别为10和6;
这证明了fork的子进程有自己独立的地址空间,不管是全局变量还是局部变量,子进程与父进程对它们的修改互不影响。
2.vfork创建了子进程后,父进程中的glodVar和Var最后均递增了8,这是因为vfork的子进程共享父进程的地址空间,子进程修改变量对父进程是可见的。
3.用fork创建了进程后,父进程与子进程是交替执行的;而使用vfork创建子进程后,打印结果是子进程在前,父进程在后,说明vfork保证子进程先执行,在子进程调用exit或exec之前父进程处于阻塞等待状态。

抱歉!评论已关闭.