热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

父进程,创建2子进程并使用管道发送数据-Parentprocess,create2childprocessandsenddatawithpipes

Ihavetocreate2childprocessandsenddatafromtheparenttothetwo,soIusedthepipe.我必须创建

I have to create 2 child process and send data from the parent to the two, so I used the pipe.

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

If I just use 1 child process and 1 pipe, all works perfectly with fdopen, fscanf and fprintf. Also, if I create 2 pipe and send data to a single process, still works perfectly.

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

But, if I create a second process and try to read from the second pipe, nothing happen.

但是,如果我创建第二个进程并尝试从第二个管道读取,则没有任何反应。

for example:

例如:

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 {

        }
    }
}

I really tried all combination. Declare all the pipe together, close or not close pipe. everything but nothing.

我真的尝试了所有组合。将所有管道声明在一起,关闭或不关闭管道。一切都没有。

1 个解决方案

#1


1  

This code fixes the problems identified in my comment and some stray issues.

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

#include 
#include 
#include 
#include 
#include 

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;
}

Note that I changed the child processes so that (a) they explicitly exit in the code block, and (b) made their body into a loop so that all the data sent is printed. That required me to move the close(a[1]) in the first child; otherwise, the loop doesn't terminate because the o/s sees that child 1 has the descriptor open for writing.

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

When executed on a Mac running macOS 10.13.6 High Sierra (GCC 8.2.0 as the compiler), I get the output:

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

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

推荐阅读
  • 本文讨论了clone的fork与pthread_create创建线程的不同之处。进程是一个指令执行流及其执行环境,其执行环境是一个系统资源的集合。在调用系统调用fork创建一个进程时,子进程只是完全复制父进程的资源,这样得到的子进程独立于父进程,具有良好的并发性。但是二者之间的通讯需要通过专门的通讯机制,另外通过fork创建子进程系统开销很大。因此,在某些情况下,使用clone或pthread_create创建线程可能更加高效。 ... [详细]
  • 第四讲ApacheLAMP服务器基本配置Apache的编译安装从Apache的官方网站下载源码包:http:httpd.apache.orgdownload.cgi今 ... [详细]
  • 本文介绍了九度OnlineJudge中的1002题目“Grading”的解决方法。该题目要求设计一个公平的评分过程,将每个考题分配给3个独立的专家,如果他们的评分不一致,则需要请一位裁判做出最终决定。文章详细描述了评分规则,并给出了解决该问题的程序。 ... [详细]
  • 本文介绍了操作系统的定义和功能,包括操作系统的本质、用户界面以及系统调用的分类。同时还介绍了进程和线程的区别,包括进程和线程的定义和作用。 ... [详细]
  • 本文介绍了在Cpp中将字符串形式的数值转换为int或float等数值类型的方法,主要使用了strtol、strtod和strtoul函数。这些函数可以将以null结尾的字符串转换为long int、double或unsigned long类型的数值,且支持任意进制的字符串转换。相比之下,atoi函数只能转换十进制数值且没有错误返回。 ... [详细]
  • PG12新增的VACUUM命令的SKIP_LOCKED选项
    PG12版本的VACUUM命令新增了SKIP_LOCKED选项,该选项使得vacuum命令在遇到被lock住的table时可以跳过并被视为成功执行。之前的版本中,vacuum命令会一直处于等待状态。本文还提到了PostgreSQL 12.1版本的相关信息。 ... [详细]
  • linux进阶50——无锁CAS
    1.概念比较并交换(compareandswap,CAS),是原⼦操作的⼀种,可⽤于在多线程编程中实现不被打断的数据交换操作࿰ ... [详细]
  • tcpdump 4.5.1 crash 深入分析
    tcpdump 4.5.1 crash 深入分析 ... [详细]
  • 原文地址http://balau82.wordpress.com/2010/02/28/hello-world-for-bare-metal-arm-using-qemu/最开始时 ... [详细]
  • 很多时候在注册一些比较重要的帐号,或者使用一些比较重要的接口的时候,需要使用到随机字符串,为了方便,我们设计这个脚本需要注意 ... [详细]
  • 三、查看Linux版本查看系统版本信息的命令:lsb_release-a[root@localhost~]#lsb_release-aLSBVersion::co ... [详细]
  • Nginx使用AWStats日志分析的步骤及注意事项
    本文介绍了在Centos7操作系统上使用Nginx和AWStats进行日志分析的步骤和注意事项。通过AWStats可以统计网站的访问量、IP地址、操作系统、浏览器等信息,并提供精确到每月、每日、每小时的数据。在部署AWStats之前需要确认服务器上已经安装了Perl环境,并进行DNS解析。 ... [详细]
  • 本文介绍了如何使用Express App提供静态文件,同时提到了一些不需要使用的文件,如package.json和/.ssh/known_hosts,并解释了为什么app.get('*')无法捕获所有请求以及为什么app.use(express.static(__dirname))可能会提供不需要的文件。 ... [详细]
  • SpringMVC接收请求参数的方式总结
    本文总结了在SpringMVC开发中处理控制器参数的各种方式,包括处理使用@RequestParam注解的参数、MultipartFile类型参数和Simple类型参数的RequestParamMethodArgumentResolver,处理@RequestBody注解的参数的RequestResponseBodyMethodProcessor,以及PathVariableMapMethodArgumentResol等子类。 ... [详细]
  • 开源Keras Faster RCNN模型介绍及代码结构解析
    本文介绍了开源Keras Faster RCNN模型的环境需求和代码结构,包括FasterRCNN源码解析、RPN与classifier定义、data_generators.py文件的功能以及损失计算。同时提供了该模型的开源地址和安装所需的库。 ... [详细]
author-avatar
雷子的世界6888
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有