假如在父进程中调用了标准IO,会在用户空间产生一个结构体,其中封装了文件IO返回的文件描述符fd,同时还有针对不同函数的输入输出缓冲区,与之对应的内核空间也有一个文件IO创建的结构体。所以,stdin、stdout和stderr都指向的是用户空间的那个结构体,类型是FILE *。
当调用fork函数创建了子进程后,对于内核空间的那个结构体,子进程不会拷贝,但是对于用户空间的那个结构体,子进程会进行拷贝。即:子进程中的stdin、stdout和stderr的指向是与父进程中的stdin、stdout和stderr不同的(所以子进程的输入缓冲区与父进程的输入缓冲区不在一个位置,同理,他俩的输出缓冲区也不在一个位置),但是内核空间的那个结构体是相同的。
下面一个例子:
1: #include <stdio.h>
2: #include <unistd.h>
3: #include <stdlib.h>
4:
5:
6: int main(void)
7: {
8: pid_t pid;
9: char ch[100] = {"000000000"};
10:
11: if((pid = fork()) == -1)
12: {
13: perror("fork error!");
14: exit(-1);
15: }
16: if(pid == 0)
17: {
18: printf("child ");
19: while(1);
20: }
21: else
22: {
23: sleep(1);
24: printf("parent");
25: fflush(stdout);
26: printf("\n");
27: }
28: return 0;
29: }
看一下输出结果:
结果描述:运行后,过了一秒,屏幕输出parent,然后回车换行,程序退出。尽管父进程调用了函数fflush,程序没有输出child 这句话,这充分说明了,父子进程的输入输出缓冲区是不同的。至于程序为什么会退出?解释:其实这个时候子进程还没有退出,只是变成了一个孤儿进程,由init进程管理,子进程已经脱离bash终端,成为后台进程,或者说bash终端已经失去对子进程的控制。
执行命令 ps –ef 可以看到:./a.out的父进程号变成了1,即init进程。执行命令 kill –9 6869 可以将其杀死。