在fork()创建子进程过程中发现了一个有趣的现象。
源代码
1 #include<stdio.h> 2 #include<stdlib.h> 3 #include<unistd.h> 4 int main(){ 5 printf("before fork %d\n",getpid()); 6 pid_t pid= fork(); 7 if(pid==-1){ 8 perror("fork error"); 9 exit(1); 10 } 11 else if(pid==0){ 12 printf("i am child,my pid=%d\n",getpid()); 13 } 14 else if(pid>0){ 15 printf("i am parent,my pid= %d\n",getpid()); 16 } 17 printf("after fork-------%d\n",getpid()); 18 return 0; 19 }
理论上,“before fork”这段话应该只打印一次,在终端上确实只打印了一次。但是如果把输出结果重定向到另一个文件中,会发现“before fork”打印了两次。
//file before fork 4392 i am parent,my pid= 4392 after fork-------4392 before fork 4392 i am child,my pid=4393 after fork-------4393
这是因为往屏幕上打印是行缓冲模式,在输入输出时遇到'\n'时,会自动刷新缓冲区。当我们把输出的数据重定向到文件中,在这种情况下,是全缓冲模式,遇到“\n”不会刷新缓冲区。当“befor fork\n”进入缓冲区时并没有刷新,紧接着进行fork()了子进程,那么在父子进程的缓冲区都有一个"befor fork\n"
解决办法就是在源文件fork()函数执行之前添加“fflush()”刷新流。
在使用exec函数族的时候出现同样的现象
1 puts("begin!"); 2 //fflush(NULL); 3 execlp("ls","ls","-l",NULL); 4 perror("execlp() is error\n"); 5 exit(1); 6 puts("end!"); 7 exit(0);
输出到终端
begin! 总用量 28 -rwxrwxr-x 1 tx tx 16824 1月 31 23:50 exe -rw-rw-r-- 1 tx tx 183 1月 31 23:49 exe.c -rw-rw-r-- 1 tx tx 154 1月 31 23:11 out
输出到文件,发现并没有begin
总用量 24 -rwxrwxr-x 1 tx tx 16824 1月 31 23:50 exe -rw-rw-r-- 1 tx tx 183 1月 31 23:49 exe.c -rw-rw-r-- 1 tx tx 0 1月 31 23:50 out
这是因为,begin放在缓冲区中还没有来及往外输出,执行exec()会有一个新的进程映像来替代原有的进程印象。所以在执行exec函数之前要使用fflush()函数刷新所有该刷新的流。