【问题描述】
最近使用fork(),有几个问题觉得值得总结一下:
1 为什么子进程pid编号为0?
2 fork()调用一次,返回2次,机理是什么?
3 fork()执行后,先创建子进程,还是父进程?先返回的是子进程,还是父进程?
【分析】
1 为什么子进程pid编号为0?
因为子进程可能有多个,不可能返回所有的子进程编号,而父进程只有一个。
2 fork()调用一次,返回2次,机理是什么?
由于在复制时,复制了父进程的堆栈段,所以两个进程都停留在fork函数中,等待返回。因为fork函数会返回两次,一次是在父进程中返回,另一次是在子进程中返回,这两次的返回值是不一样的。调用fork之后,数据、堆栈有两份,代码仍然为一份,但是这个代码段成为两个进程的共享代码段,都从fork函数中返回。为什么这样呢?
如果对递归有深入认识,就不难理解了。fork()的调用是运用了堆栈这种数据结构。堆栈是一种先进后出的数据结构。创建父进程后,在返回之前,创建子进程,等待子进程创建完成后,再返回父进程。具体的过程fork()两次不同返回值的实现 讲得比较透彻,此处不再赘述。
3 fork()执行后,先创建子进程,还是父进程?先返回的是子进程,还是父进程?
看一个fork()和pipe()结合的例子
#include <unistd.h>
#include <sys/types.h>
#include <errno.h>
#include <stdlib.h>
#include <stdio.h>
#define MAX_DATA_LEN 256
#define DELAY_TIME 1
#define DEBUG 1
int main()
{
pid_t pid;
int pipe_fd[2];
char buf[MAX_DATA_LEN];
const char data[] = "Pipe Test Program";
int real_read, real_write;
memset((void *)buf, 0, sizeof(buf));
if(pipe(pipe_fd)<0)
{
perror("Pipe");
exit(1);
}
pid = fork();
if(pid == 0)
{
#if DEBUG
printf("a1\n");
#endif
close(pipe_fd[1]);
sleep(DELAY_TIME*3);
#if DEBUG
printf("a2\n");
#endif
if((real_read = read(pipe_fd[0], buf, MAX_DATA_LEN)) >0 )
{
printf("%d bytes read from the pipe is '%s'\n",real_read,buf);
}
close(pipe_fd[0]);
}
else if(pid > 0)
{
#if DEBUG
printf("b1\n");
#endif
close(pipe_fd[0]);
sleep(DELAY_TIME);
#if DEBUG
printf("b2\n");
#endif
if((real_write = write(pipe_fd[1], data, MAX_DATA_LEN)) != -1 )
{
printf("Parent wrote %d bytes : '%s'\n",real_write,data);
}
close(pipe_fd[1]);
waitpid(pid, NULL, 0);
exit(0);
}
}
运行结果如下:
[tandesir@localhost test]$ ./pipe
a1
b1
b2
Parent wrote 256 bytes : 'Pipe Test Program'
a2
256 bytes read from the pipe is 'Pipe Test Program'
上面的程序如果将DEBUG定义为0,则会给人一种假象,好像是先返回了父进程,再返回子进程。输出如下:
[tandesir@localhost test]$ ./pipe
Parent wrote 256 bytes : 'Pipe Test Program'
256 bytes read from the pipe is 'Pipe Test Program'
由上述程序,可以证实,先返回的是子进程。
父进程都没有创建,当然不会有子进程。所以先创建父进程。之所有先返回子进程,这是由堆栈的特性决定的。
结论:先创建父进程,后创建子进程。先返回子进程,后返回父进程。
【学习参考】
(1) http://baike.baidu.com/view/1952900.htm?fromTaglist
(2) fork()两次不同返回值的实现
(3) fork调用的内核实现
(4) 一个fork的面试题(推荐阅读)
转载请标明出处,仅供学习交流,勿用于商业目的
Copyright @ http://blog.youkuaiyun.com/tandesir