fork()与输出缓冲区:一个有意思的坑

来源:互联网 发布:宇信数据科技有限公司 编辑:程序博客网 时间:2024/05/01 22:57

先不多说,看代码:

#include <stdio.h>#include <stdlib.h>#include <sys/types.h>#include <sys/wait.h>#include <unistd.h>int main(void){    printf("A\n");    pid_t pid1 = fork();    if (pid1 < 0) {        fprintf(stderr, "fork error!\n");        exit(EXIT_FAILURE);    } else if (pid1 == 0) {        printf("B\n");    } else {        wait(NULL);        pid_t pid2 = fork();        if (pid2 < 0) {            fprintf(stderr, "fork error!\n");            exit(EXIT_FAILURE);        } else if (pid2 == 0) {            printf("C\n");        } else {            wait(NULL);        }    }    return 0;}

如果把上面A后面的'\n'去掉,最后会得到不同的结果(当然,这里不是说有没有换行……-_-|||)

不去掉的话,结果大概像这样:


去掉的话,大概像这样:

嗯,问题来了,我们可以很明显的看出:
  1. 后者多了两个看上去不应该存在的'A'
  2. 前者父进程的输出在子进程前面,后者父进程的输出在子进程的后面(单独的那个‘A’)
乍看上去感觉有点奇怪,但仔细想想的话其实可以发现:
  • 关于第一点,既然是fork,那么就会把父进程的各种东西都复制过去(实际上并不是一开始就复制,而是直到写的时候才发生复制,不过在这里不影响),所以也会把缓冲区里面的东西也复制过去,此时:
    • 前者因为加上'\n',所以printf会输出缓冲区内容并清空,所以fork的时候缓冲区没有内容
    • 而后者只是把‘A’弄到缓冲区,却并没有直接输出并清空缓冲区,fork的时候'A'依然保留着,所以子进程的缓冲区也有'A',从而造成了多出来两个'A'的现象。
  • 至于第二点,也是由于上面的原因,printf只是将‘A’弄到缓冲区,而没有直接输出并清空缓冲区,导致最后是在进程结束的时候才输出缓冲区的内容,而父进程结束最晚,所以输出也最晚,从而导致了第二点的现象!