【问题标题】:2 children write to pipe, parent reads from pipe in C2个孩子写入管道,父母从C中的管道读取
【发布时间】:2012-11-07 22:53:56
【问题描述】:

我找了又找都无济于事,所以我终于来寻求帮助。 我的任务涉及(在 RedHat Linux 上运行的 C 语言中)创建两个子进程,每个子进程将任意数量的迭代写入管道的字符。该管道与创建它们的父进程共享。父级从管道读取,而子级仍然有要写入的字符。一旦孩子退出并且管道为空,则父母(主)可以终止。

这是我编写的代码逻辑的一个快速而肮脏的示例。

main()
{
      //create pipe

      fork(); //childA
      //writes to pipe 

      fork(); //childB
      //writes to pipe

      //parent reading
      while(condition) {
          //read from pipe + print chars to terminal
      }
}

现在,我的问题是关于 while 循环的条件。 当孩子们因管道满而无法写作时,我需要阅读,但我无法弄清楚什么类型的条件可以让我这样做。任何帮助将是绝对惊人的。

【问题讨论】:

  • 您应该始终阅读:这是摆脱“满管”状态的唯一方法。一旦最后一个孩子关闭管道,读取将返回 -1。
  • @wildplasser read 在文件结束时返回 0,在错误时返回 -1;所以当最后一个孩子关闭管道并且没有数据可供读取时,它将返回 0。 fread 返回的值小于您请求的对象数(或 0),您需要使用 feofferror 来确定您是否有文件结尾或错误。

标签: c fork pipe


【解决方案1】:

阅读时是否要求管道必须充满?还是只是要求您继续从两个孩子那里阅读,即使其中一个管道已满,因此孩子无法写作?

如果管子满了,我不知道有什么标准的方法可以提高身高。您可以尝试使用FIONREAD ioctl 来确定管道上要读取的数据量,并将其与PIPE_BUF 进行比较,但如果管道中的数据少于PIPE_BUF,则可能无法正常工作,但是孩子正在写一个会把它放在PIPE_BUF上的东西;该调用可能会阻塞而不填满管道。我不会依赖这种技术来工作。

无论哪一个已准备好,继续读取两个文件描述符的常用方法是使用select 系统调用。这允许您等到一个或另一个文件描述符有可用数据。这意味着父进程不会阻塞尝试从一个没有任何可用数据的子进程中读取数据,而另一个子进程会因为缓冲区已满而阻塞。

编辑:重新阅读您的问题后,听起来实际上只有一个管道,两个孩子都在写信。那是对的吗?同样,问题出现了,您是否需要等到孩子们阻塞。如果父级只是从管道中读取,它将阻塞,直到其中一个子级写入管道为止;你不需要做任何特别的事情。

如果您的任务要求您等到管道实际上已满,我有兴趣查看确切的措辞,因为我不确定您为什么要这样做。

编辑 2:在评论中回答您的问题:

  1. 我的父进程的代码是否需要在程序中跟随我的两个子进程的代码?

    不,对父进程或子进程的代码顺序没有要求。为了区分父运行的代码和子运行的代码,您检查fork() 的返回值。如果返回值为 0,则处于子进程中。如果不是,那么您在父母中;如果返回值为-1,则有错误,如果为正,则为子进程的PID。

    所以,你可以这样写代码:

    int pid = fork();
    if (pid) { 
        // in the parent, check if pid is -1 for errors
    } else {
        // in the child
    }
    

    或者:

    int pid = fork();
    if (pid == 0) {
        // in the child, do whatever you need to do and...
        exit(0);
    }
    
    // in the parent; since the child calls exit() above, control will never
    // reach here in the child.  Or you could do an execl() in the child, which 
    // replaces the current program with another one, so again, control will 
    // never reach here within the child process.
    
  2. 如何在两个孩子终止并且管道为空之前一直从管道读取数据?

    一直读直到read返回0。在管道的读端read不会返回0,直到所有进程都关闭了管道的写端,并且所有的数据都已经从管道中读出。如果某些东西仍然打开,但管道中没有数据,read 将阻塞,直到数据写入管道。

    一个问题是记住在尝试read之前关闭父进程中管道的写入端;否则,当父级在子级完成后尝试执行read 时,它将阻塞等待它关闭自己的管道。

【讨论】:

  • 实际上只有一个管道,两个子级都在写入,而父级正在读取。好吧,分配的要求是父每次读取时从管道中读取 100 个字符,然后将这些字符打印到终端。这样做直到每个孩子都完成了它的每次迭代(childA = 900 次迭代,childB = 260 次迭代)。我想我不必等到孩子们阻塞,但我确实需要在每次读取时从管道中读取 100 个字符。
  • 我想我的主要问题是: 1. 我的父进程的代码是否需要遵循程序中我的两个子进程的代码? 2. 如何在两个孩子终止且管道为空之前一直从管道读取数据?
  • @user1807614 我已经在回答中解决了您的问题
猜你喜欢
  • 2017-08-26
  • 2015-01-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-03-28
  • 1970-01-01
相关资源
最近更新 更多