父进程,创建2个子进程并用管道发送数据

莫森科

我必须创建 2 个子进程并将数据从父进程发送到两个子进程,所以我使用了pipe.

如果我只使用 1 个子进程和 1 个管道,那么一切都可以与fdopen,fscanf完美配合fprintf此外,如果我创建 2 个管道并将数据发送到单个进程,仍然可以正常工作。

但是,如果我创建第二个进程并尝试从第二个进程中读取pipe,则什么也不会发生。

例如:

int main() {
    pid_t pid1, pid2;

    int a[2];
    pipe(a);


    pid1 = fork();

    if(pid1 == 0) {
        char x,y;
        FILE *stream;
        stream = fdopen(a[0],"r");

        fscanf(stream,"%c",&x);
        printf("%c\n", x);

        close(a[1]);
        close(a[0]);
    } else {
        int b[2];
        pipe(b);
        pid2 = fork();
        FILE *stream1, *stream2;
        close(a[0]);
        close(b[0]);
        stream1 = fdopen(a[1],"w");
        stream2 = fdopen(b[1],"w");

        fprintf(stream1, "yo bella zio\n");
        fprintf(stream2, "como estas\n");

        fflush(stream1);
        fflush(stream2);
        close(a[1]);
        close(b[1]);

        waitpid (pid1, NULL, 0);
        waitpid (pid2, NULL, 0);

        if (pid2 == 0) {     
            FILE *stream;
            close(b[1]);
            close(a[1]);
            close(a[0]);
            stream = fdopen(b[0],"r");

            fscanf(stream,"%c",&x);

            printf("%c\n", x);
        } else {

        }
    }
}

我真的尝试了所有的组合。一起声明所有管道,关闭或不关闭管道。一切,但一无所有。

乔纳森·莱夫勒

此代码修复了我的评论中发现的问题和一些杂散问题。

#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

int main(void)
{
    pid_t pid1, pid2;
    int a[2];
    int b[2];
    pipe(a);

    pid1 = fork();

    if (pid1 < 0)
    {
        fprintf(stderr, "failed to fork child 1 (%d: %s)\n", errno, strerror(errno));
        exit(EXIT_FAILURE);
    }
    else if (pid1 == 0)
    {
        close(a[1]);    // Must be closed before the loop
        FILE *stream = fdopen(a[0], "r");
        if (stream == NULL)
        {
            fprintf(stderr, "failed to create stream for reading (%d: %s)\n", errno, strerror(errno));
            exit(EXIT_FAILURE);
        }

        int c;
        while ((c = getc(stream)) != EOF)
            putchar(c);

        //char x;
        //fscanf(stream, "%c", &x);
        //printf("%c\n", x);

        //close(a[0]);  -- Bad idea once you've used fdopen() on the descriptor 
        printf("Child 1 done\n");
        exit(0);
    }
    else
    {
        pipe(b);
        pid2 = fork();
        if (pid2 < 0)
        {
            fprintf(stderr, "failed to fork child 2 (%d: %s)\n", errno, strerror(errno));
            exit(EXIT_FAILURE);
        }
        else if (pid2 == 0)
        {
            close(b[1]);
            close(a[1]);
            close(a[0]);
            FILE *stream = fdopen(b[0], "r");
            if (stream == NULL)
            {
                fprintf(stderr, "failed to create stream for reading (%d: %s)\n", errno, strerror(errno));
                exit(EXIT_FAILURE);
            }

            int c;
            while ((c = getc(stream)) != EOF)
                putchar(c);

            //char x;
            //fscanf(stream, "%c", &x);
            //printf("%c\n", x);

            printf("Child 2 done\n");
            exit(0);
        }
    }

    close(a[0]);
    close(b[0]);

    FILE *stream1 = fdopen(a[1], "w");
    if (stream1 == NULL)
    {
        fprintf(stderr, "failed to create stream for writing (%d: %s)\n", errno, strerror(errno));
        exit(EXIT_FAILURE);
    }
    FILE *stream2 = fdopen(b[1], "w");
    if (stream2 == NULL)
    {
        fprintf(stderr, "failed to create stream for writing (%d: %s)\n", errno, strerror(errno));
        exit(EXIT_FAILURE);
    }

    fprintf(stream1, "yo bella zio\n");
    fprintf(stream2, "como estas\n");

    fflush(stream1);    // Not necessary because fclose flushes the stream
    fflush(stream2);    // Not necessary because fclose flushes the stream
    fclose(stream1);    // Necessary because child won't get EOF until this is closed
    fclose(stream2);    // Necessary because child won't get EOF until this is closed
    //close(a[1]);      -- bad idea once you've used fdopen() on the descriptor
    //close(b[1]);      -- bad idea once you've used fdopen() on the descriptor

    waitpid(pid1, NULL, 0);
    waitpid(pid2, NULL, 0);
    printf("All done!\n");
    return 0;
}

请注意,我更改了子进程,以便 (a) 它们在代码块中显式退出,并且 (b) 将它们的主体放入一个循环中,以便打印所有发送的数据。这需要我移动close(a[1])第一个孩子;否则,循环不会终止,因为 o/s 看到 child 1 已打开描述符以进行写入。

在运行 macOS 10.13.6 High Sierra(GCC 8.2.0 作为编译器)的 Mac 上执行时,我得到输出:

yo bella zio
Child 1 done
como estas
Child 2 done
All done!

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

父进程有多个子进程,而两个子进程有一个子进程

无法运行2个子进程

杀死子管道进程的父进程

在父进程中从 .txt 中读取数字,并通过管道将其发送到子进程并写入

setuid创建一个子进程

派生后,父进程和子进程是否共享管道创建的文件描述符?

使用两个管道在父进程和子进程之间进行通信

如何使用管道将数据从子进程发送到父进程进行进程间通信?

Windows cmd .bat-启动一个子进程,该进程同时运行到父进程,并在父进程关闭时关闭

子进程不从管道读取,除非父进程在 dup2 之前调用 printf

从父父进程到子进程的管道不起作用

往返于2个Python子进程的循环管道

在C中为一个父级创建多个子进程

子进程在使用父级将数据写入管道之前先读取数据

使用C创建子进程和父进程

从低级父进程创建中级子进程?

是否可以在同一父级(LINUX,POSIX)创建的两个子进程之间建立管道

子进程是否继承父进程的数据结构?

使用子进程的stdout作为另一个进程的stdin时,有时数据不会传递给第二个子进程

继续从同一父级创建多个子进程

“ 3向” Python子进程管道:将stdout和stderr发送到两个不同的进程?

我创建了3个子进程,为什么它返回7?

Perl:将子标准输出管道到父进程

将数据发送到子进程

我正在尝试创建进程的二叉树结构,其中每个进程的子进程不超过2个

通过python3子进程发送管道命令

在父进程中仅将一个写入流用于多个子进程

如何并行产生五个子进程

如何区分一个子进程与其他子进程