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的区别的更多相关文章

  1. vfork与fork的区别

    vfork()用法与fork()相似,但是也有区别,具体区别归结为以下3点: 1. fork():子进程拷贝父进程的数据段,代码段.vfork():子进程与父进程共享数据段. 2. fork():父子 ...

  2. fork()、vfork()、clone()的区别

    因为生活的复杂,这是一个并行的世界,在同一时刻,会发生很多奇妙的事情,北方下雪,南方下雨,这里在吃饭,那边在睡觉,有人在学习,有人在运动,所以这时一个多彩多姿的世界,每天都发生着很多事情,所以要想很好 ...

  3. linux之return和exit引发的大问题(vfork和fork)

    在coolshell.cn上看到的一个问题.为此拿来研究一下. 首先 看看return和exit的差别 在linux上分别跑一下这个代码 int main() { return 0; //exit(0 ...

  4. shell中sh, exec, source, fork, ./的区别

    shell中sh, exec, source, fork, ./的区别 1,sh sh test.sh ​ sh是通过创建子进程(subshell)去执行脚本,父进程无法使用子进程中的变量,而子进程对 ...

  5. redux-saga call 和 fork的区别

    call 为阻塞调用, fork为非阻塞调用

  6. 转:Linux fork与vfork的深入分析

    源地址:http://linux.chinaitlab.com/c/831529.html 一)fork的概述 .操作系统对进程的管理,是通过进程表完成的.进程表中的每一个表项,记录的是当前操作系统中 ...

  7. 《Linux内核分析》之第三章读书笔记

    进程管理 进程是处于执行期的程序以及相关的资源的总称,也称作任务.执行线程,简称线程,是在进程中活动的对象. 可以两个或两个以上的进程执行同一个程序 也可以两个或两个以上并存的进程共享许多资源 内核调 ...

  8. Unix高级环境编程—进程控制(一)

    一.函数fork #include<unistd.h> pid_t  fork(void)                                                 ...

  9. linux 进程管理与调度(一)

    进程结构 进程在内核的源代码中以结构体表示,篇幅很长,在此列举一小段关键代码,可以发现是个双向链表,具体的可以在内核目录下找一个叫"sched.h"的头文件. struct tas ...

随机推荐

  1. SSM框架手动搭建

    SSM框架手动搭建 创建web项目 IDEA创建Maven项目 [File]-->[new]-->[project..] 将项目变为web项目 [File]-->[Project S ...

  2. Ubuntu 18 开机后直接进入命令行界面,没法进入桌面

    应该是之前不知道干啥,删了gnome的一个东西,导致没法正常进入 暴力解决,直接重装桌面环境 sudo apt install ubuntu-desktop

  3. 51nod 1068 Bash游戏 V3

    列出前几项可以发现是个规律题,不要被题目的文字所欺骗,字符串处理10^1000即可 #include <bits/stdc++.h> using namespace std; int ge ...

  4. 给ambari集群里的kafka安装基于web的kafka管理工具Kafka-manager(图文详解)

    不多说,直接上干货! 参考博客 基于Web的Kafka管理器工具之Kafka-manager的编译部署详细安装 (支持kafka0.8.0.9和0.10以后版本)(图文详解)(默认端口或任意自定义端口 ...

  5. java获取公网ip以及物理地址和代理商

    package ipconfig; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStr ...

  6. Myeclipse 6.0代码

    import java.util.*; import java.io.*; public class bbs { private static final String LL = "Deco ...

  7. reveal.js让程序员做ppt也享受快乐

    前言 程序员除了会写的一手漂亮的代码,也要求做出风格优雅的PPT,诸如向领导汇报工作.向小组成员反馈项目进展自己的工作等等.就本人而言,做ppt还要去找模板,还需要设计风格,内心是焦灼的.于是乎,我搜 ...

  8. linux下php开启pdo扩展

    前提:网页报错 为解决问题:Undefined class constant 'MYSQL_ATTR_INIT_COMMAND' 解决方案 : 下载安装PHP_MYSQL扩展 wget http:// ...

  9. Farseer.net轻量级开源框架 中级篇:SQL执行报告

    导航 目   录:Farseer.net轻量级开源框架 目录 上一篇:Farseer.net轻量级开源框架 中级篇: 数据库切换 下一篇:Farseer.net轻量级开源框架 中级篇: 探究ORM(M ...

  10. JavaScript操作DOM与jQuyer操作DOM的对比

    1.通过jQuery方法包装后的对象,是一个类数组对象.它与DOM对象完全不同,唯一相似的是它们都能操作DOM. 2.通过jQuery方法包装后的对象,是一个类数组对象.它与DOM对象完全不同,唯一相 ...