fork
fork 是linux下创建新进程的函数。 函数原型:
pid_t fork
(
void
);
(pid_t 是一个宏定义
,其实质是int 被定义在#
include
<
sys/types.h
>中)
返回值: 若成功调用一次则返回两个值,子进程返回0,父进程
返回子进程ID;否则,出错返回-1。
之所以父进程要返回子进程ID, 是因为我们有pid_t getppid(void) 可以获取一个进程的父进程id。
但是却没有相应的函数可以获取子进程的id,通过fork函数在父进程返回子进程ID,以使得父进程可以知道子进程的id。
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char** argv) {
fprintf(stdout, "fork test curpid is %d,ppid is %d \n", getpid(), getppid());
pid_t ret = fork();
if (ret < 0) {
fprintf(stdout, "failed to fork \n");
return -1;
} else if (0 == ret) {
fprintf(stdout, "ret is %d, pid is %d, ppid is %d\n", ret, getpid(), getppid());
} else{
fprintf(stdout, "ret is %d, pid is %d, ppid is %d\n", ret, getpid(), getppid());
}
return 0;
}
运行结果:
fork test curpid is 7430,ppid is 851
ret is 7431, pid is 7430, ppid is 851
ret is 0, pid is 7431, ppid is 7430
ret is 7431, pid is 7430, ppid is 851
ret is 0, pid is 7431, ppid is 7430
可以看出 父进程先还行,返回了子进程id。
子进程后执行了,返回为0
vfork
该函数和fork类似。成功则父进程返回子进程pid,子进程返回0. 失败返回-1,失败原因在errno中。
为什么会有vfork呢?
因为以前的fork当它创建一个子进程时,将会创建一个新的地址空间,并且拷贝父进程的资源,然后将会有两种行为:
1.执行从父进程那里拷贝过来的代码段
2.调用一个exec执行一个新的代码段
当进程调用exec函数时,一个新程序替换了当前进程的正文,数据,堆和栈段。这样,前面的拷贝工作就是白费力气了,这种情况下,聪明的人就想出了vfork。vfork并不复制父进程的进程环境,子进程在父进程的地址空间中运行,所以子进程不能进行写操作,并且在儿子“霸占”着老子的房子时候,要委屈老子一下了,让他在外面歇着(阻塞),一旦儿子执行了exec或者exit后,相当于儿子买了自己的房子了,这时候就相当于分家了。
因此,如果创建子进程是为了调用exec执行一个新的程序的时候,就应该使用vfork
另外还有的
区别就是:fork 是父进程和子进程的先后顺序不确定,而vfork则是子进程先运行,子进程完成后,父进程后运行。 切记注意这点,如果子进程再有等待父进程的行为,那么就死锁了。
另外注意的就是vfork时,子进程一定要exit。 不然会出现段错误。可参见:http://blog.chinaunix.net/uid-24261911-id-2620651.html