当它被重定向到另一个进程时,将“\n”添加到 stdout 的重要性是什么?

What is the importance of adding "\n" to stdout when it's redirected to another process?

所以,我在用 c 语言玩管道,我有一个练习,我通过命令行调用一个程序,如下所示:“./self 1”,然后使用 execlp 调用自身,但参数为 2: “./self 2”进一步用参数 3 调用自身:“./self 3”。这些进程的重点是:process1 从键盘获取一行并将其放入 pipe1,然后 process2 从 pipe1 获取该行并将其放入 pipe2,然后 process3 从 pipe2 获取它并计算 space 个字符.如果我在使用 fprintf(stdout,"\n") 进行输入之前不在屏幕上打印换行符,则此代码永远不会工作; .这是为什么?

代码如下:

#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>

int main(int argc, char* argv[]) {
    
    if (strcmp(argv[1], "1") == 0) {
        int fdpipe1[2];
        if (pipe(fdpipe1)) {
            printf("Error pipe1\n");
            return 0;
        }
        pid_t p;
        p = fork();
        
        if (p == 0) {
            close(fdpipe1[1]);
            dup2(fdpipe1[0], 0);
            execlp("./self", "./self", "2", NULL);
        } else {
            close(fdpipe1[0]);
            fprintf(stdout, "\n");
            dup2(fdpipe1[1], 1);
            char input[100];
            gets(input);
            puts(input);
            wait(NULL);
        }
    }
    else if (strcmp(argv[1], "2") == 0) {
        int fdpipe2[2];
        if (pipe(fdpipe2)) {
            printf("Error pipe2\n");
            return 0;
        }
        pid_t p;
        p = fork();
        if (p == 0) {
            close(fdpipe2[1]);
            dup2(fdpipe2[0], 0);
            execlp("./self", "./self", "3", NULL);
        } else {
            close(fdpipe2[0]);
            fprintf(stdout, "\n");
            dup2(fdpipe2[1], 1);
            char input[100];
            gets(input);
            puts(input);
            wait(NULL);
        }
    } 
    else if (strcmp(argv[1], "3") == 0) {
        char input[100];
        gets(input);
        int i = 0, counter = 0;
        while (input[i] != '[=10=]') {
            if (input[i++] == ' ') counter++;
        }
        printf("%d\n", counter);
    }
    return;
}

在这种构造中,当您通过未命名管道将进程的 stdout 连接到另一个进程的 stdin 时,通常会添加换行符以确保发送流, stdout 缓冲区被刷新,作为并行示例,当您使用 scanf 时,仅当您按下回车时(换行符添加到 stdin)是读取的流,这里也适用类似的原理。

我建议您使用 STDIN_FILENOSTDOUT_FILENO 内置宏而不是硬编码的文件描述符,如果不是为了别的,它使代码对于不熟悉此事的人更具可读性。


请避免使用gets,这是一个危险的函数,它不检查目标缓冲区的边界,它会导致各种麻烦,以至于它被弃用了,后来被从标准,虽然它仍然可以与某些编译器一起使用,但出于我想象的遗留原因,请在 post 上查看关于此主题的精彩答案:

Why is the gets function so dangerous that it should not be used?

建议改用 fgets