fork和vfork函数的区别

fork()与vfork()都是创建一个进程,那他们有什么区别呢?总结有以下三点区别:
1.  fork  ():子进程拷贝父进程的数据段,代码段
    vfork ( ):子进程与父进程共享数据段
2.  fork ()父子进程的执行次序不确定
    vfork 保子进程先运行,在调用exec 或exit 之前与父进程数据是共享的,在它调用exec
     或exit 之后父进程才可能被调度运行。
3.  vfork ()保证子进程先运行,在她调用exec 或exit 之后父进程才可能被调度运行。如果在
   调用这两个函数之前子进程依赖于父进程的进一步动作,则会导致死锁。
上一节主要说明fork函数的用法,这节主要用vfork函数举例子,以便两者比较查看。了下面通过几个例子加以说明:

例子1:
#include   
#include    
int main ()   
{   
    pid_t fpid; //fpid表示fork函数返回的值
    char *pstr = NULL;
    int count=0;  

    fpid=vfork();       if (fpid < 0)           printf("error in fork!\n");       else if (fpid == 0) {          printf("i am the child process, my process id is %d\n",getpid());           printf("child\n");          count++;    }      else {         printf("i am the parent process, my process id is %d\n",getpid());           printf("parent\n");          count++;      }      printf("%s, %d, %d\n", __FUNCTION__, __LINE__,count);       return 0; 

输出结果:

自己试一下狂打印之后才停止,而且日志都是乱的。


本来vfork()是共享数据段的,结果应该是2,为什么不是预想的2 呢?先看一个知识点:
vfork 和fork 之间的另一个区别是:vfork 保证子进程先运行,在她调用exec 或exit 之
后父进程才可能被调度运行。如果在调用这两个函数之前子进程依赖于父进程的进一步动
作,则会导致死锁。
这样上面程序中的fork ()改成vfork()后,vfork ()创建子进程并没有调用exec 或exit,
所以最终将导致死锁。

怎么改呢?看下面程序:

#include   #include    int main ()   {       pid_t fpid; //fpid表示fork函数返回的值     char *pstr = NULL;     int count=0; 

    fpid=vfork();       if (fpid < 0)           printf("error in fork!\n");       else if (fpid == 0) {          printf("i am the child process, my process id is %d\n",getpid());           printf("child\n");         count++;    _exit(0);   }      else {         printf("i am the parent process, my process id is %d\n",getpid());           printf("parent\n");          count++;      }      printf("%s, %d, %d\n", __FUNCTION__, __LINE__,count);       return 0; 

}

 输入结果为:

i am the child process, my process id is 17054
child
i am the parent process, my process id is 17053
parent
main, 99, 2

此结果中可以看到输出的count为2。所以可以看出vfork使用的时候要注意子进程要exit后父进程方可执行,而且栈中的count是父子共享的。跟fork是不同的。

如果没有_exit(0)的话,子进程没有调用exec 或exit,所以父进程是不可能执行的,在子进程调用exec 或exit 之后父进程才可能被调度运行。
所以我们加上_exit(0);使得子进程退出,父进程执行,这样else 后的语句就会被父进程执行,又因在子进程调用exec 或exit之前与父进程数据是共享的,所以子进程退出后把父进程的数据段count改成1 了,子进程退出后,父进程又执行,最终就将count变成了2,看下实际 运行结果: 
 

网上抄的一段,可以再理解理解:
为什么会有vfork,因为以前的fork 很傻, 它创建一个子进程时,将会创建一个新的地址空间,并且拷贝父进程的资源,而往往在子进程中会执行exec 调用,这样,前面的拷贝工作就是白费力气了,这种情况下,聪明的人就想出了vfork,它产生的子进程刚开始暂时与父进程共享地址空间(其实就是线程的概念了),因为这时候子进程在父进程的地址空间中运行,所以子进程不能进行写操作,并且在儿子 霸占”着老子的房子时候,要委屈老子一下了,让他在外面歇着(阻塞),一旦儿子执行了exec 或者exit 后,相儿子买了自己的房子了,这时候就相于分家了。

                                 

你可能感兴趣的:(Linux应用,linux,fork)