文章转自 :http://blog.csdn.net/jianchi88/article/details/6985326

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

#include<sys/types.h>
#include<unistd.h>
#include<stdio.h>  int main()
{  pid_t pid;  pid = fork();  if(pid<0)  printf("error in fork!\n");  else if(pid == 0)  printf("I am the child process,ID is %d\n",getpid());  else   printf("I am the parent process,ID is %d\n",getpid());  return 0;  }

运行结果:
[cpp] view plain copy
print?

[root@localhost fork]# gcc -o fork fork.c
[root@localhost fork]# ./fork

[cpp] view plain copy
print?

I am the child process,ID is 4711
I am the parent process,ID is 4710

为什么两条语 都会打印呢?这是因为fork()函数用于从已存在的进程中创建一个新的进
程,新的进程称为子进程,而原进程称为父进程,fork ()的返回值有两个,子进程返回0,
父进程返回子进程的进程号,进程号都是非零的正整数,所以父进程返回的值一定大于零,
在pid=fork();语句之前只有父进程在运行,而在pid=fork();之后,父进程和新创建的子进程
都在运行,所以如果pid==0,那么肯定是子进程,若pid !=0 (事实上肯定大于0),那么是
父进程在运行。而我们知道fork()函数子进程是拷贝父进程的代码段的,所以子进程中同样

if(pid<0)
printf(“error in fork!”);
else if(pid==0)
printf(“I am the child process,ID is %d\n”,getpid());
else
printf(“I am the parent process,ID is %d\n”,getpid());
}
这么一段代码,所以上面这段代码会被父进程和子进程各执行一次,最终由于子进程的pid= =0,

而打印出第一句话,父进程的pid>0,而打印出第二句话。于是得到了上面的运行结果。
再来看一个拷贝数据段的例子:
[cpp] view plain copy
print?

#include<sys/types.h>
#include<unistd.h>
#include<stdio.h>  int main()
{  pid_t pid;  int cnt = 0;  pid = fork();  if(pid<0)  printf("error in fork!\n");  else if(pid == 0)  {  cnt++;  printf("cnt=%d\n",cnt);  printf("I am the child process,ID is %d\n",getpid());  }  else  {  cnt++;  printf("cnt=%d\n",cnt);  printf("I am the parent process,ID is %d\n",getpid());  }  return 0;
}

大家觉着打印出的值应该是多少呢?是不是2 呢?先来看下运行结果吧
[cpp] view plain copy
print?

[root@localhost fork]# ./fork2
cnt=1
I am the child process,ID is 5077
cnt=1
I am the parent process,ID is 5076

为什么不是2 呢?因为我们一次强调fork ()函数子进程拷贝父进程的数据段代码段,所以
cnt++;
printf(“cnt= %d\n”,cnt);

return 0

将被父子进程各执行一次,但是子进程执行时使自己的数据段里面的(这个数据段是从父进
程那copy 过来的一模一样)count+1,同样父进程执行时使自己的数据段里面的count+1,
他们互不影响,与是便出现了如上的结果。

那么再来看看vfork ()吧。如果将上面程序中的fork ()改成vfork(),运行结果是什么
样子的呢?
[cpp] view plain copy
print?

[root@localhost fork]# gcc -o fork3 fork3.c
[root@localhost fork]# ./fork3
cnt=1
I am the child process,ID is 4711
cnt=1
I am the parent process,ID is 4710
段错误

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

#include<sys/types.h>
#include<unistd.h>
#include<stdio.h>  int main()
{  pid_t pid;  int cnt = 0;  pid = vfork();  if(pid<0)  printf("error in fork!\n");  else if(pid == 0)  {  cnt++;  printf("cnt=%d\n",cnt);  printf("I am the child process,ID is %d\n",getpid());  _exit(0);  }  else  {  cnt++;  printf("cnt=%d\n",cnt);  printf("I am the parent process,ID is %d\n",getpid());  }  return 0;  }

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

[root@localhost fork]# gcc -o fork3 fork3.c
[root@localhost fork]# ./fork3
cnt=1
I am the child process,ID is 4711
cnt=2
I am the parent process,ID is 4710

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

多进程 fork()与vfork()相关推荐

  1. 进程创建函数fork()和vfork()

    Linux下使用fork()创建一个新的进程,该函数不需要参数,返回值是一个进程id.对于不同的对象,分别是:新建的子进程id(返回给父进程),0(返回给创建的子进程)或者-1(子进程创建失败,返回给 ...

  2. c语言exit和return区别,在fork和vfork中使用

    转自c语言exit和return区别,在fork和vfork中使用 exit函数在头文件stdlib.h中. 简述: exit(0):正常运行程序并退出程序: exit(1):非正常运行导致退出程序: ...

  3. 5.fork和vfork

    fork和vfork函数都是用于创建子进程的系统函数. fork函数调用一次,返回两次.两次返回的返回值不同. 1)返回值等于0时,处于子进程空间. 理由:一个进程只会有一个父进程,所以子进程总是可以 ...

  4. UNIX高级环境编程(9)进程控制(Process Control)- fork,vfork,僵尸进程,wait和waitpid...

    本章包含内容有: 创建新进程 程序执行(program execution) 进程终止(process termination) 进程的各种ID 1 进程标识符(Process Identifiers ...

  5. OS / Linux / clone、fork、vfork 与 pthread_create 创建线程有何不同

    进程是一个指令执行流及其执行环境,其执行环境是一个系统资源的集合,这些资源在Linux中被抽象成各种数据对象:进程控制块.虚存空间.文件系统,文件I/O.信号处理函数.所以创建一个进程的过程就是这些数 ...

  6. Linux fork() 和 vfork()

    代码 #include <unistd.h> #include <sys/types.h> #include <iostream> #include <err ...

  7. fork和vfork,return和exit的理解

    fork和vfork的差别: 1.fork是创建一个子进程,并把父进程的内存数据copy到子进程中. vfork是创建一个子进程,并和父进程的内存数据share一起. 2.vfork是这样的工作的: ...

  8. 细究fork()和vfork()

    在linux系统下,对于程序执行的过程中,我们都会想到进程.而创建进程通常使用fork函数,当然还有vfork函数. 今天在这,我将分享一下我的学习心得:关于fork()和vfork() fork() ...

  9. fork与vfork的区别

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

最新文章

  1. springCloud(微服务的概念)1-1
  2. 理解 python 装饰器
  3. npoi 所有列调整为一页_Word节约纸张打印 多页内容一页打印
  4. linux 内核修炼之道——系统调用
  5. 今天,一起吐槽容器镜像中那些让人一言难尽的事情
  6. 中文字体的FontMetrics解析
  7. C语言大作业:车辆信息管理系统
  8. 计算机网络实用技术教程txt,计算机网络实用技术教程
  9. 网络安全篇 全局ACL与URPF-12
  10. 机器学习入门(1、特征抽取)
  11. android /data/system/dropbox,Android dropbox日志浅谈
  12. 全面解读“资金二清”与“信息二清”
  13. [Unity插件]着色器关键字分析工具ShaderControl
  14. 两行命令查看wifi密码
  15. 紧耦合LIO综述 | 6篇顶会论文看透紧耦合LIO玩儿法(LIOM/LIO-SAM)
  16. [考试反思]0820NOIP模拟测试27:幻影
  17. 抖音实战~首页视频~下拉刷新
  18. 芭芭拉--金字塔原理——读后感
  19. java 求1000以内完数
  20. D3.js实现人物关系图谱有移动、拖拽、放大功能

热门文章

  1. django手机访问_Django从入门到大作业:2-见网页
  2. tkmybatis 子查询_dnssearch 子域名枚举工具
  3. Java黑皮书课后题第5章:*5.39(金融应用:求销售总额)假设你正在某百货商店开始销售工作。你的工资包括基本工资和提成。基本工资是5000美元。你的目标是一年挣30000美元,编写程序找最小销售额
  4. C语言学习之求∑n!(即求1!+2!+3!+...+20!)
  5. getchar、scanf以及缓冲区的概念
  6. 小程序导航组件navigator活学活用
  7. 选择 Python3.6 还是 Python 3.7
  8. css实现垂直居中定位
  9. 11月25日struts培训日记
  10. RxSwift之订阅UITableViewCell里的按钮点击事件