【转】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 ...
随机推荐
- 微信小程序中如何使用setData --- 修改数组对象、修改对象
看代码吧~ 这是修改对象 this.setData({ allStageIndex: e.detail.value, [`projectDetailsData.stage`]: this.data.a ...
- python的安装教学
1.首先登陆到python的官方网站 https://www.python.org/ 2.鼠标放在Download上,点击下面对应的型号,我的是Windows 3.点击Windows到此页面,点击3. ...
- oracle数据库当前用户下所有表名和表名的注释
select a.TABLE_NAME,b.COMMENTSfrom user_tables a,user_tab_comments bWHERE a.TABLE_NAME=b.TABLE_NAMEo ...
- QT5每日一学(一)下载与安装
一.Qt SDK的下载和安装 1.下载 Qt官网主页提供了最新版Qt的下载,不过我们更倾向于去资源下载页面(https://download.qt.io/official_release ...
- python优缺点分析及python种类
Python的缺点: 相较于其它类型的语言可能运行速度上会略差.C语言的运行性能速度上最好,因为C最接近计算机底层. Python的优点: 大数据处理,有专门的功能模块,比较方便. Linux自带Py ...
- visual studio 2015 key vs2015密钥
Visual Studio Professional 2015简体中文版(专业版)KEY:HMGNV-WCYXV-X7G9W-YCX63-B98R2Visual Studio Enterprise 2 ...
- 不支持正在使用的 .Net 组帧模式。有关详细信息,请参阅服务器日志--解决方案
问题在于 NetTcpBinding 服务端和客户端配置不一致. 至少 客户端和服务端:安全性.是否启用可靠会话以及传输方式必须一致 主要是传输方式导致 "不支持正在使用的 .Net 组帧 ...
- listBox 搜索左右移动
<td align="left" width="50%"> 查询:<asp:TextBox ID="SacffSearch" ...
- AJPFX总结IO流中的缓冲思想
缓冲思想 (因为内存的运算速度要远大于硬盘的原酸速度,所以只要降低硬盘的读写次数,就可以提高效率) 1. 字节流一次读写一个数组的速度明显比一次读写一个字节的速度快很多, 2. 这是加 ...
- 来自AJPFX的二分法查找
package com.heima.array; public class Demo2_Array { /** * * A:案例演示 * ...