一、fork函数与vfork函数的简介
(1)fork函数
在Linux下fork函数很重要,它的作用是创建子进程,即在当前进程中创建一个新的进程,新进程为子进程,原来的进程为父进程。
我们来看一下这个函数的返回值和类型
#include <unistd.h>
pid_t fork(void);
我们可以看到这个函数的返回值是一个pid_t的类型,它的返回类型分别为:
- 子进程返回0
- 父进程返回子进程的ID
- 出错返回-1
当我们调用fork函数后控制转移到内核的fork的代码中,内核需要做一系列的动作然后就产生了两个二进制代码相同的进程,它们都运行到同一个地方,它在创建子进程的时候返回父进程的下一个语句,即返回到父进程执行fork函数的下一句。这个时候每个进程都有各自的旅行。
此时我们需要注意的是:fork之后谁先执行完全由调度器来决定。
fork的子进程与父进程贡献一段存储空间,但是子进程不需要把父进程的4G内存空间全部全部拷贝,太浪费了,在《UNIX环境高级编程》一书中有详细介绍什么拷贝什么不拷贝,例如代码段不需要共享,但是数据段在父进程更改的时候子进程也更改,这个技术叫做写时拷贝。
fork函数的常规用法
- 一个父进程希望子进程复制自己,使父子进程同时执行不同的代码段。例如:父进程等待客户端的请求,生成子进程来处理请求。
- 一个进程要执行一个不同的程序。例如:子进程从fork返回后调用exec函数。
fork函数失败的原因
- 每个操作系统都设置的有进程的上限数字,一旦我们用户的进程数目超过了这个值,那么此时就会创建子进程失败。
- 一旦当系统有太多的进程,那么此时也可能会创建进程失败。
(2)vfork函数
由于fork函数创建的子进程有一段自己的地址空间,但是我们有时候并不希望这样,所以此时便有了vfork函数。
#include <sys/types.h>
#include <unistd.h>
pid_t vfork(void);
vfork的函数返回值和fork函数的返回值是一样的。
vfork函数也是用来创建子进程的,它不会拷贝4G进程空间,它保证了子进程先运行,但是它与fork创建的子进程有如下的区别:
- vfork创建的子进程和父进程共享地址空间,fork的子进程有独立地址空间
- vfork保证子进程先运行,在子进程调用exec或者exit函数之后父进程才会被调度运行。fork函数则没有这样。
缺点:
vfork的底层实现有点问题,所以一般我们不建议使用(因为可能会出现段错误),但是如果我们在最后使用exit函数进行退出即可保证程序正确。
二、fork函数与vfork函数的区别与总结
- 1、fork出来的父子进程交替运行,vfork出来的进程是父进程阻塞,直到子进程结束。
- 2、fork实现了写时拷贝,vfork就算是写,也不拷贝。
- 3、vfork必须使用exit或者exec后父进程才会运行。
- 4、我们就算是把fork实现了写时拷贝,它的性能也没有vfork高。
- 5、每个系统是的vfork都有问题,不建议使用。