fork和vfork
区别
fork函数和vfork函数都可以用来创建一个子进程。他们有什么区别呢?
首先是fork:
- 内核会给子进程分配虚拟内存空间和id,但不会分配物理内存
- 子进程一开始是共享父进程的物理空间
- 子进程写入数据后内核会给它分配物理内存
然后是vfork:
- 子进程共享父进程的虚拟地址空间
下面通过两个图来分别展示他们的特点:
- 进程P1通过fork函数创建一个子进程P2:
分析:
如上图所示,P1创建了一个子进程P2,内核为这个子进程分配了虚拟内存空间,并且把P1的正文段、数据段、堆、栈的虚拟空间的内容直接复制到子进程相应的虚拟空间上;但是内核并没有给子进程分配物理空间,所以子进程P2的虚拟空间是直接指向了父进程P1的物理空间。
那问题来了,子进程什么时候可以拥有自己的物理空间呢?
当子进程尝试修改数据段或堆栈中的数据时,内核会通过写时拷贝技术给子进程分配新的物理空间,并把父进程相应的段的数据拷贝过来。
为什么要使用写时拷贝技术?
因为大多数情况下,创建子进程之后都是让它去执行一个新程序;如果把父进程
的数据直接拷贝过来但是又不使用就会造成浪费:浪费cpu资源、占用空间。
- 进程P1通过vfork函数创建一个子进程P2:
从上图可以看出,内核连虚拟内存空间都不分配,子进程是直接共享父进程的虚拟内存空间,所以也就共享父进程的数据。
特点
我们汇总一下fork函数和vfork函数的特点
函数 | 特点 |
---|---|
fork | 1、使用写时拷贝技术 2、子进程创建之后父子进程执行的顺序具有不确定性 |
vfork | 1、直接共享父进程的地址空间和数据 2、子进程创建之后可以确定子进程先执行,当它调用exit退出或者调用exec函数执行新程序后父进程才可能被调度 |
简单代码示例
fork示例
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
int main(int argc, char *