1

我找了又找都无济于事,所以我终于来寻求帮助。我的任务涉及(在 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 循环的条件。当孩子们因管道满而无法写作时,我需要阅读,但我无法弄清楚什么类型的条件可以让我这样做。任何帮助都将是绝对惊人的。

4

1 回答 1

0

阅读时是否要求管道必须充满?还是仅仅是要求您继续阅读两个孩子的内容,即使其中一个管道已满,因此孩子无法书写?

如果管子满了,我不知道有什么标准的增高方法。您可以尝试使用FIONREADioctl 来确定管道上要读取的数据量,并将PIPE_BUFPIPE_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;否则,当父级在子级完成后尝试执行 a 时read,它将阻塞等待它关闭自己的管道。

于 2012-11-07T23:35:58.897 回答