【转】vfork 和 fork的区别
fork()与vfock()都是创建一个进程,那他们有什么区别呢?总结有以下三点区别:
1. fork ():子进程拷贝父进程的数据段,代码段
vfork ( ):子进程与父进程共享数据段
2. fork ()父子进程的执行次序不确定
vfork 保证子进程先运行,在调用exec 或exit 之前与父进程数据是共享的,在它调用exec或exit 之后父进程才可能被调度运行。
3. vfork ()保证子进程先运行,在她调用exec 或exit 之后父进程才可能被调度运行。如果在调用这两个函数之前子进程依赖于父进程的进一步动作,则会导致死锁。
下面通过几个例子加以说明:
第一:子进程拷贝父进程的代码段的例子:
#include<sys/types.h>
#include<unistd.h>
#include<stdio.h> int main()
{
pid_t pid;
pid = fork();
if(pid<)
printf("error in fork!\n");
else if(pid == )
printf("I am the child process,ID is %d\n",getpid());
else
printf("I am the parent process,ID is %d\n",getpid());
return ; }
运行结果:
[root@localhost fork]# gcc -o fork fork.c
[root@localhost fork]# ./fork
I am the child process,ID is
I am the parent process,ID is
为什么两条语 都会打印呢?这是因为fork()函数用于从已存在的进程中创建一个新的进程,新的进程称为子进程,而原进程称为父进程,fork ()的返回值有两个,子进程返回0,父进程返回子进程的进程号,进程号都是非零的正整数,所以父进程返回的值一定大于零,在pid=fork();语句之前只有父进程在运行,而在pid=fork();之后,父进程和新创建的子进程都在运行,所以如果pid==0,那么肯定是子进程,若pid !=0 (事实上肯定大于0),那么是父进程在运行。而我们知道fork()函数子进程是拷贝父进程的代码段的,所以子进程中同样有
if(pid<)
printf("error in fork!");
else if(pid==)
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,而打印出第二句话。于是得到了上面的运行结果。
再来看一个拷贝数据段的例子:
#include<sys/types.h>
#include<unistd.h>
#include<stdio.h> int main()
{
pid_t pid;
int cnt = ;
pid = fork();
if(pid<)
printf("error in fork!\n");
else if(pid == )
{
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 ;
}
[root@localhost fork]# ./fork2
cnt=
I am the child process,ID is
cnt=
I am the parent process,ID is
为什么不是2 呢?因为我们一次强调fork ()函数子进程拷贝父进程的数据段代码段,所以
cnt++;
printf("cnt= %d\n",cnt); return
将被父子进程各执行一次,但是子进程执行时使自己的数据段里面的(这个数据段是从父进程那copy 过来的一模一样)count+1,同样父进程执行时使自己的数据段里面的count+1,他们互不影响,与是便出现了如上的结果。
那么再来看看vfork ()吧。如果将上面程序中的fork ()改成vfork(),运行结果是什么样子的呢?
[root@localhost fork]# gcc -o fork3 fork3.c
[root@localhost fork]# ./fork3
cnt=
I am the child process,ID is
cnt=
I am the parent process,ID is
本来vfock()是共享数据段的,结果应该是2,为什么不是预想的2 呢?先看一个知识点:vfork 和fork 之间的另一个区别是:vfork 保证子进程先运行,在她调用exec 或exit 之后父进程才可能被调度运行。如果在调用这两个函数之前子进程依赖于父进程的进一步动作,则会导致死锁。这样上面程序中的fork ()改成vfork()后,vfork ()创建子进程并没有调用exec 或exit,所以最终将导致死锁。 怎么改呢?看下面程序:
#include<sys/types.h>
#include<unistd.h>
#include<stdio.h> int main()
{
pid_t pid;
int cnt = ;
pid = vfork();
if(pid<)
printf("error in fork!\n");
else if(pid == )
{
cnt++;
printf("cnt=%d\n",cnt);
printf("I am the child process,ID is %d\n",getpid());
_exit();
}
else
{
cnt++;
printf("cnt=%d\n",cnt);
printf("I am the parent process,ID is %d\n",getpid());
}
return ; }
如果没有_exit(0)的话,子进程没有调用exec 或exit,所以父进程是不可能执行的,在子进程调用exec 或exit 之后父进程才可能被调度运行。所以我们加上_exit(0);使得子进程退出,父进程执行,这样else 后的语句就会被父进程执行,又因在子进程调用exec 或exit之前与父进程数据是共享的,所以子进程退出后把父进程的数 据段count改成1 了,子进程退出后,父进程又执行,最终就将count变成了2,看下实际
运行结果:
[root@localhost fork]# gcc -o fork3 fork3.c
[root@localhost fork]# ./fork3
cnt=
I am the child process,ID is
cnt=
I am the parent process,ID is
【转】vfork 和 fork的区别的更多相关文章
- vfork与fork的区别
vfork()用法与fork()相似,但是也有区别,具体区别归结为以下3点: 1. fork():子进程拷贝父进程的数据段,代码段.vfork():子进程与父进程共享数据段. 2. fork():父子 ...
- fork()、vfork()、clone()的区别
因为生活的复杂,这是一个并行的世界,在同一时刻,会发生很多奇妙的事情,北方下雪,南方下雨,这里在吃饭,那边在睡觉,有人在学习,有人在运动,所以这时一个多彩多姿的世界,每天都发生着很多事情,所以要想很好 ...
- linux之return和exit引发的大问题(vfork和fork)
在coolshell.cn上看到的一个问题.为此拿来研究一下. 首先 看看return和exit的差别 在linux上分别跑一下这个代码 int main() { return 0; //exit(0 ...
- shell中sh, exec, source, fork, ./的区别
shell中sh, exec, source, fork, ./的区别 1,sh sh test.sh sh是通过创建子进程(subshell)去执行脚本,父进程无法使用子进程中的变量,而子进程对 ...
- redux-saga call 和 fork的区别
call 为阻塞调用, fork为非阻塞调用
- 转:Linux fork与vfork的深入分析
源地址:http://linux.chinaitlab.com/c/831529.html 一)fork的概述 .操作系统对进程的管理,是通过进程表完成的.进程表中的每一个表项,记录的是当前操作系统中 ...
- 《Linux内核分析》之第三章读书笔记
进程管理 进程是处于执行期的程序以及相关的资源的总称,也称作任务.执行线程,简称线程,是在进程中活动的对象. 可以两个或两个以上的进程执行同一个程序 也可以两个或两个以上并存的进程共享许多资源 内核调 ...
- Unix高级环境编程—进程控制(一)
一.函数fork #include<unistd.h> pid_t fork(void) ...
- linux 进程管理与调度(一)
进程结构 进程在内核的源代码中以结构体表示,篇幅很长,在此列举一小段关键代码,可以发现是个双向链表,具体的可以在内核目录下找一个叫"sched.h"的头文件. struct tas ...
随机推荐
- Ocelot(六)- 架构图
简介 Ocelot是一个用.NET Core实现并且开源的API网关,它功能强大,包括了:路由.请求聚合.服务发现.认证.鉴权.限流熔断.并内置了负载均衡器与Service Fabric.Butter ...
- bzoj 2257[Jsoi2009]瓶子和燃料 数论/裴蜀定理
题目 Description jyy就一直想着尽快回地球,可惜他飞船的燃料不够了. 有一天他又去向火星人要燃料,这次火星人答应了,要jyy用飞船上的瓶子来换.jyy 的飞船上共有 N个瓶子(1< ...
- [HNOI2008]Card洗牌
Description 小春现在很清闲,面对书桌上的N张牌,他决定给每张染色,目前小春只有3种颜色:红色,蓝色,绿色.他询问Sun有多少种染色方案,Sun很快就给出了答案.进一步,小春要求染出Sr张红 ...
- Poj 3294 Life Forms (后缀数组 + 二分 + Hash)
题目链接: Poj 3294 Life Forms 题目描述: 有n个文本串,问在一半以上的文本串出现过的最长连续子串? 解题思路: 可以把文本串用没有出现过的不同字符连起来,然后求新文本串的heig ...
- 计算机视觉-SIFT特征匹配进行目标转换
Lowe将SIFT算法分解为如下四步: 1. 尺度空间极值检测:搜索所有尺度上的图像位置.通过高斯微分函数来识别潜在的对于尺度和旋转不变的兴趣点. 关键点定位:在每个候选的位置上,通过一个拟合精细的模 ...
- Cunning Gena CodeForces - 417D
Cunning Gena CodeForces - 417D 题意 先将小伙伴按需要的监视器数量排序.然后ans[i][j]表示前i个小伙伴完成j集合内题目所需最少钱.那么按顺序枚举小伙伴,用ans[ ...
- 题解报告:hdu 2094 产生冠军
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2094 Problem Description 有一群人,打乒乓球比赛,两两捉对撕杀,每两个人之间最多打 ...
- dotnetty源码解读一些要点
DefaultAttributeMap 它绑定在Channel或者ChannelHandlerContext上的一个附件. ChannelHandlerContext都是ChannelHandler和 ...
- C# KeepAlive的设置
C# KeepAlive的相关设置 网上有很多相关KeepAlive的内容,终于找到了有关C#的这方面资料,设置了下,有行可靠! TcpListener myListener = new TcpLis ...
- Android Studio 打包APK时,出现3个或多个APK
Android Studio 打包APK时,原来只会出现一个apk,结果现在出现3个apk,仔细检查了一下项目文件发现: Android Studio 的 buid.gradle文件里有个配置项被更改 ...