参见百度百科API说明:

fork

头文件:

#include<unistd.h>

#include<sys/types.h>

函数原型:

pid_t fork( void);

(pid_t 是一个宏定义,其实质是int 被定义在#include<sys/types.h>中)

返回值: 若成功调用一次则返回两个值,子进程返回0,父进程返回子进程ID;否则,出错返回-1

函数说明:

一个现有进程可以调用fork函数创建一个新进程。由fork创建的新进程被称为子进程(child process)。fork函数被调用一次但返回两次。两次返回的唯一区别是子进程中返回0值而父进程中返回子进程ID。

子进程是父进程的副本,它将获得父进程数据空间、堆、栈等资源的副本。注意,子进程持有的是上述存储空间的“副本”,这意味着父子进程间不共享这些存储空间。

UNIX将复制父进程地址空间内容给子进程,因此,子进程有了独立的地址空间。在不同的UNIX (Like)系统下,我们无法确定fork之后是子进程先运行还是父进程先运行,这依赖于系统的实现。所以在移植代码的时候我们不应该对此作出任何的假设。

为什么fork会返回两次?

由于在复制时复制了父进程堆栈段,所以两个进程都停留在fork函数中,等待返回。因此fork函数会返回两次,一次是在父进程中返回,另一次是在子进程中返回,这两次的返回值是不一样的。过程如下图

调用fork之后,数据、堆栈有两份,代码仍然为一份但是这个代码段成为两个进程的共享代码段都从fork函数中返回,箭头表示各自的执行处。当父子进程有一个想要修改数据或者堆栈时,两个进程真正分裂。

fork函数的特点概括起来就是“调用一次,返回两次”,在父进程中调用一次,在父进程和子进程中各返回一次。

fork的另一个特性是所有由父进程打开的描述符都被复制到子进程中。父、子进程中相同编号的文件描述符内核中指向同一个file结构体,也就是说,file结构体的引用计数要增加。

vfork

vfork(建立一个新的进程)

相关函数wait,execve

头文件 #include<unistd.h>

定义函数pid_t vfork(void);

vfork()会产生一个新的子进程.但是vfork创建的子进程与父进程共享数据段,而且由vfork创建的

子进程将先于父进程运行.fork()的使用详见百度词条fork().

vfork()用法与fork()相似.但是也有区别,具体区别归结为以下3点:

1. fork():子进程拷贝父进程的数据段,代码段. vfork():子进程与父进程共享数据段.

2. fork():父子进程的执行次序不确定.

vfork():保证子进程先运行,在调用exec或exit之前与父进程数据是共享的,在它调用exec

或exit之后父进程才可能被调度运行。

3. vfork()保证子进程先运行,在她调用exec或exit之后父进程才可能被调度运行。如果在

调用这两个函数之前子进程依赖于父进程的进一步动作,则会导致死锁。

4.当需要改变共享数据段中变量的值,则拷贝父进程。

个人理解:
fork和vfork都可以用来创建子进程.fork创建子进程后,父子进程的数据段和堆栈段分离,会产生复制消耗资源.而在实际的应用中,有时是不需要的.比如子进程创建后就执行exec调用了.这样就产生了vfork,其产生的子进程和父进程共享数据段. 同时fork创建的子进程和父进程的运行的先后顺序是没有保证的,即可能父进程先运行,也可能子进程先运行.而vfork的特点是保证子进程先运行.只有子进程通过通过exec或者exit退出后,父进程才能运行.但这个特定也决定了,如果子进程依赖父进程的操作的话,就会产生死锁(即其需要父进程执行,而父进程必须在其完成后才能执行,互相等待)。

使用实例

下面通过几个例子加以说明:
第一:子进程拷贝父进程的代码段的例子:

   1: #include<sys/types.h>

   2: #include<unistd.h>

   3: #include<stdio.h>

   4:  

   5: int main()  

   6: {  

   7:     pid_t pid;  

   8:     pid = fork();  

   9: if(pid<0)  

  10:         printf("error in fork!\n");  

  11: else if(pid == 0)  

  12:         printf("I am the child process,ID is %d\n",getpid());  

  13: else

  14:         printf("I am the parent process,ID is %d\n",getpid());  

  15: return 0;  

  16:  

  17: }  

运行结果:

cnt=1

I am the child process,ID is 2164

cnt=1

I am the parent process,ID is 2163

为什么两条语 都会打印呢?这是因为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,而打印出第二句话。于是得到了上面的运行结果。

再来看一个拷贝数据段的例子:

   1: #include<sys/types.h>

   2: #include<unistd.h>

   3: #include<stdio.h>

   4:  

   5: int main()  

   6: {  

   7:     pid_t pid;  

   8: int cnt = 0;  

   9:     pid = fork();  

  10: if(pid<0)  

  11:         printf("error in fork!\n");  

  12: else if(pid == 0)  

  13:     {  

  14:         cnt++;  

  15:         printf("cnt=%d\n",cnt);  

  16:         printf("I am the child process,ID is %d\n",getpid());  

  17:     }  

  18: else

  19:     {  

  20:         cnt++;  

  21:         printf("cnt=%d\n",cnt);  

  22:         printf("I am the parent process,ID is %d\n",getpid());  

  23:     }  

  24: return 0;  

  25: }  

大家觉着打印出的值应该是多少呢?是不是2 呢?先来看下运行结果吧

  1. [root@localhost fork]# ./fork2 
  2. cnt=1 
  3. I am the child process,ID is 5077 
  4. cnt=1 
  5. 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(),运行结果是什么

样子的呢?

  1. cnt=1  
  2. I am the child process,ID is 4711  
  3. cnt=1  
  4. I am the parent process,ID is 4710  
  5. 段错误 

本来vfock()是共享数据段的,结果应该是2,为什么不是预想的2 呢?先看一个知识点:

vfork 和fork 之间的另一个区别是:vfork 保证子进程先运行,在她调用exec 或exit 之

后父进程才可能被调度运行。如果在调用这两个函数之前子进程依赖于父进程的进一步动

作,则会导致死锁。

这样上面程序中的fork ()改成vfork()后,vfork ()创建子进程并没有调用exec 或exit,

所以最终将导致死锁。

怎么改呢?看下面程序:

   1: #include<sys/types.h>

   2: #include<unistd.h>

   3: #include<stdio.h>

   4:  

   5: int main()  

   6: {  

   7:     pid_t pid;  

   8: int cnt = 0;  

   9:     pid = vfork();  

  10: if(pid<0)  

  11:         printf("error in fork!\n");  

  12: else if(pid == 0)  

  13:     {  

  14:         cnt++;  

  15:         printf("cnt=%d\n",cnt);  

  16:         printf("I am the child process,ID is %d\n",getpid());  

  17:        _exit(0);  

  18:     }  

  19: else

  20:     {  

  21:         cnt++;  

  22:         printf("cnt=%d\n",cnt);  

  23:         printf("I am the parent process,ID is %d\n",getpid());  

  24:     }  

  25: return 0;  

  26:  

  27: }  

如果没有_exit(0)的话,子进程没有调用exec 或exit,所以父进程是不可能执行的,在子

进程调用exec 或exit 之后父进程才可能被调度运行。

所以我们加上_exit(0);使得子进程退出,父进程执行,这样else 后的语句就会被父进程执行,

又因在子进程调用exec 或exit之前与父进程数据是共享的,所以子进程退出后把父进程的数

据段count改成1 了,子进程退出后,父进程又执行,最终就将count变成了2,看下实际

运行结果:

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

 

refer:http://baike.baidu.com/view/1952900.htm

         http://baike.baidu.com/view/1745340.htm

         http://blog.csdn.net/jianchi88/article/details/6985326

fork和vfork的区别的更多相关文章

  1. fork()和vfork()的区别(转载)

    fork和vfork 转载 http://coolshell.cn/articles/12103.html 在知乎上,有个人问了这样的一个问题--为什么vfork的子进程里用return,整个程序会挂 ...

  2. fork()和vfork()的区别,signal函数用法,exec()系列函数的用法小结

    一:fork()和vfork()的区别:    fork()函数可以创建子进程,有两个返回值,即调用一次返回两个值,一个是父进程调用fork()后的返回值,该返回值是刚刚创建的子进程的ID;另一个是子 ...

  3. fork与vfork的区别与联系

    fork()与vfock()都是创建一个进程,那他们有什么区别呢?总结有以下三点区别: 1. fork ():子进程拷贝父进程的数据段,代码段 vfork ( ):子进程与父进程共享数据段 2. fo ...

  4. 嵌入式 fork与vfork的区别

    fork()与vfock()都是创建一个进程,那他们有什么区别呢?总结有以下三点区别: 1.  fork  ():子进程拷贝父进程的数据段,代码段     vfork ( ):子进程与父进程共享数据段 ...

  5. fork与vfork的区别

    fork()与vfock()都是创建一个进程,那他们有什么区别呢?总结有以下三点区别: 1.  fork  ():子进程拷贝父进程的数据段,代码段     vfork ( ):子进程与父进程共享数据段 ...

  6. 转:fork与vfork的区别

    源地址:http://blog.csdn.net/jianchi88/article/details/6985326 有大量驱动文章 fork()与vfock()都是创建一个进程,那他们有什么区别呢? ...

  7. fork 和 vfork 的区别与联系

    vfork用于创建一个新进程,而该新进程的目的是exec一个新进程,vfork和fork一样都创建一个子进程,但是它并不将父进程的地址空间完全复制到子进程中,不会复制页表.因为子进程会立即调用exec ...

  8. fork与vfork

    先看一个fork的例子: ; int main(void) { int var, pid; ; ) { printf("vfork error"); exit(-); } ) { ...

  9. Linux下fork()、vfork()、clone()和exec()的区别

    转自Linux下fork().vfork().clone()和exec()的区别 前三个和最后一个是两个类型.前三个主要是Linux用来创建新的进程(线程)而设计的,exec()系列函数则是用来用指定 ...

随机推荐

  1. POJ 1432 Decoding Morse Sequences (DP)

    Decoding Morse Sequences 题目链接: http://acm.hust.edu.cn/vjudge/contest/129783#problem/D Description Be ...

  2. 你的MySQL服务器开启SSL了吗?(转载)

    最近,准备升级一组MySQL到5.7版本,在安装完MySQL5.7后,在其data目录下发现多了很多.pem类型的文件,然后通过查阅相关资料,才知这些文件是MySQL5.7使用SSL加密连接的.本篇主 ...

  3. C#中使用Join与GroupJoin将两个集合进行关联与分组

    转自:https://www.cnblogs.com/cncc/p/7985843.html 对于Join的用法说明如下: 语法: public static IEnumerable<TResu ...

  4. p2p传输协议

    老司机是如何飙车的——P2P传输协议 转载来自2017-03-27 15:23 点波蓝字关注变智者 秋明山上人行稀,常有车手较高低,如今车道依旧在,不见当年老司机.其实老司机们从未离去,只不过好的车手 ...

  5. ORACLE DG 库参数db_file_name_convert和log_file_name_convert的作用

    https://www.cnblogs.com/xqzt/p/5089826.html ORACLE DG 库参数db_file_name_convert和log_file_name_convert的 ...

  6. 【洛谷P5018 对称二叉树】

    话说这图也太大了吧 这题十分的简单,我们可以用两个指针指向左右两个对称的东西,然后比较就行了 复杂度O(n*logn) #include<bits/stdc++.h> using name ...

  7. iOS即时通讯之CocoaAsyncSocket源码解析四

    原文 前言: 本文为CocoaAsyncSocket源码系列中第二篇:Read篇,将重点涉及该框架是如何利用缓冲区对数据进行读取.以及各种情况下的数据包处理,其中还包括普通的.和基于TLS的不同读取操 ...

  8. MongoDB--(NoSQL)入门介绍

    NoSQL中比较优秀的产品 windows 下载安装 shell 基本操作(javascript 引擎) BSON扩充的数据类型(JSON的扩展,浮点型,日期型的扩充) step1.创建数据库 use ...

  9. Linux pip命令报错 -bash: pip: command not found

    下载 $ wget https://bootstrap.pypa.io/get-pip.py 安装 $ python get-pip.py 查看版本 $ pip -V 查看安装路径: find / - ...

  10. JSONPath解析json

    JSONPath - 用于JSON的XPath 用来解析多层嵌套的json数据;JsonPath 是一种信息抽取类库,是从JSON文档中抽取指定信息的工具. 考虑到接下来计划开发一个自动化测试平台,在 ...