引言
先来看一段代码吧,
1 #include <sys/types.h> 2 #include <unistd.h> 3 #include <stdio.h> 4 #include <stdlib.h> 5 6 int main(int argc, char **argv) 7 { 8 pid_t pid = fork(); 9 if(pid < 0){ 10 fprintf(stderr,"error!"); 11 }else if(0 == pid){ 12 fprintf(stderr,"This is the child process.\r\n"); 13 }else{ 14 fprintf(stderr,"This is the parent process.\r\n"); 15 } 16 return 0; 17 }
执行后输出:
This is the parent process.
This is the child process.
是不是感觉比较奇怪,按照if结构的规则,应该只执行一个才对,也正因为此,fork()函数曾经迷惑了不少Linux/Unix平台的开发者。那么为什么呢?
一、函数原型
pid_t fork( void);
返回值: 若成功调用一次则返回两个值,子进程返回0,父进程返回子进程ID;否则,出错返回-1
二、函数说明
一个现有进程可以调用fork函数创建一个新进程。由fork创建的新进程被称为子进程(child process)。fork函数被调用一次但返回两次。两次返回的唯一区别是子进程中返回0值而父进程中返回子进程ID。子进程是父进程的副本,它将获得父进程数据空间、堆、栈等资源的副本。注意,子进程持有的是上述存储空间的“副本”,这意味着父间子进程间不共享这些存储空。
UNIX将复制父进程的地址空间内容给子进程,因此,子进程有了独立的地址空间。在不同的UNIX (Like)系统下,我们无法确定fork之后是子进程先运行还是父进程先运行,这依赖于系统的实现。所以在移植代码的时候我们不应该对此作出任何的假设。
关键词:子进程中返回0 父进程中返回子进程ID(>0);调用一次返回两次;复制父进程地址空间内容(非地址)给子进程;子进程拥有独立的地址空间;无法确定执行顺序;
三、为何fork函数会返回两次
先来看一个图:
由于在复制时复制了父进程的堆栈段,所以两个进程都停留在fork函数中,等待返回。因此fork函数会返回两次,一次是在父进程中返回,另一次是在子进程中返回,这两次的返回值是不一样的。调用fork之后,数据、堆栈有两份,代码仍然为一份但是这个代码段成为两个进程的共享代码段都从fork函数中返回,如上图箭头表示各自的执行处。当父子进程有一个想要修改数据或者堆栈时,两个进程真正分裂。
作者:张子良
出处:http://www.cnblogs.com/hadoopdev
本文版权归作者所有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。