将 child 的标准输出通过管道传输到 c 中另一个 child 的标准输入

pipe stdout of a child to stdin of another child in c

这就是我想要做的:一个 parent 进程创建两个 child 进程,然后将一个进程的标准输出通过管道传输到另一个进程的标准输入。然后 parent 等待 5 秒并杀死第一个 child.

我是这样处理的:首先我创建了一个管道。然后 fork 创建第一个 child (代码中的 gen)和 dup2 以复制管道对 stdout 的写入。第二个 child 的另一个分支(在代码中称为 cons),dup2 将读取结束复制到标准输入。缺点只是打印数据。 Parent 将 SIGTERM 发送到第一个 child,第二个 child 读取到 EOF,因此它自行关闭。

只打印了我的错误输出(此处用于调试)。 Gen 生成两个随机数,但 cons 中的循环不会被执行。所以我想 cons 的 stdin 上没有任何内容。 我咨询了 Google 并遵循了这个 How do I chain stdout in one child process to stdin in another child in C?,但没能弄清楚我搞砸了什么。将不胜感激任何帮助。谢谢

编译:gcc -std=c99 -Wall -Werror main.c -o main 在 Bash 上 Windows 10

代码:

#define _POSIX_SOURCE
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <stdlib.h>
#include <signal.h>

#define READ_END 0
#define WRITE_END 1
#define BUF_SIZE 10

int main(int argc, char* argv[])
{
    pid_t gen, cons;
    int fd[2];

    if (pipe(fd) < 0) {
        // pipe error
        exit(1);
    }

    gen = fork();

    if (gen < 0) {
        // fork error
        close(fd[READ_END]);
        close(fd[WRITE_END]);
        exit(2);
    } else if (gen == 0) {
        // gen child
        close(fd[READ_END]);
        time_t t;
        srand((unsigned)time(&t));
        dup2(fd[WRITE_END], STDOUT_FILENO);
        close(fd[WRITE_END]);
        while(1) {
            int a = rand() % 1000;
            int b = rand() % 1000;
            printf("gen %d %d\n", a, b);
            fprintf(stderr, "err, gen %d %d\n", a, b);
            sleep(1);
        }
    }
    else {
        cons = fork();
        if (cons < 0) {
                // fork error
            close(fd[READ_END]);
            close(fd[WRITE_END]);
            kill(gen, SIGKILL);
            exit(2);
        } else if (cons == 0) {
            // cons child
            close(fd[WRITE_END]);
            dup2(fd[READ_END], STDIN_FILENO);
            close(fd[READ_END]);
            char line[BUF_SIZE];
            while (fgets(line, sizeof(line), stdin)) {
                printf("cons received: %s\n", line);
                fprintf(stderr, "cons lives!\n");
            }
        } else {
            // parent
            close(fd[READ_END]);
            close(fd[WRITE_END]);
            sleep(5);
            kill(gen, SIGTERM);
        }
    }
    return 0;
}

默认情况下标准输出是缓冲的,因此您的 gen child 仅将输出排队等待稍后发送。所以你必须fflush它来强制你的消息被立即传递:

        ...
        printf("gen %d %d\n", a, b);
        fprintf(stderr, "err, gen %d %d\n", a, b);
        fflush(stdout);             // <= force immediate send
        sleep(1);
        ...