【问题标题】:Can I use pipe as read at parent and write in child?我可以使用管道作为父级读取并写入子级吗?
【发布时间】:2018-12-16 23:52:46
【问题描述】:

我现在正在学习如何正确使用管道。我找到了仅用于在父级中写入和在子级中读取的示例,但我想知道如何反向操作。我试过这样:

#include <stdlib.h>
#include <stdio.h>
#include <signal.h>
#include <sys/types.h>

int main(){

  int  p1[2], p2[2];
  char original[]="This is a string\n ";

  pid_t child2;
  pid_t child=fork();

  if (child>0)
  {
    child2 = fork();
    if(child2>0){
      wait();
      printf("I'm the parrent.\n");

      close(p1[1]);
      close(p2[1]);

      printf("Parrent read p1:\n");
      if (read(p1[0], original, sizeof(original)) == -1)
        perror("read() error in parent p1");
      else printf("parent read '%s' from pipe 1\n", original);

      printf("Parrent read p2:\n");
      if (read(p2[0], original, sizeof(original)) == -1)
        perror("read() error in parent p2");
      else printf("parent read '%s' from pipe 2\n", original);
    }
    else{
      printf("Child2 \n");
      pipe(p2);
      close(p2[0]);
      if (write(p2[1], original, sizeof(original)+1) == -1)
        perror("write() error in child2");
      //close(p2[1]);
    }
  }
  else
  {
    printf("Child1 \n");

    pipe(p1);
    close(p1[0]);
    if (write(p1[1], original, sizeof(original)+1) == -1)
      perror("write() error in child1");
    //close(p1[1]);
  }
  return 0;
}

但是这种方式让我在阅读父母时出错。 read() error in parent p1: Bad file descriptor 两次,p1p2。那么,我可以这样做吗?或者这只是一些微不足道的错误?

【问题讨论】:

  • 完全可以做到;你只是颠倒了正常的感觉。查找任何有关父子之间双向通信(不使用套接字)的问题,您会找到示例。您需要在 fork 将使用它的孩子之前创建管道。您还需要确保在每个子项和父项中关闭足够多的文件描述符。
  • 您遇到错误是因为您没有在分叉之前调用 pipe() 并且您的 p1 和 p2 数组在大多数地方都未初始化。
  • 也不清楚是否应该尽早等待。通常,您不应该调用wait(),直到您在关闭管道之前在管道上获得EOF,然后等待死孩子(或即将成为死孩子)。您对wait() 的调用是错误的,部分原因是您省略了#include &lt;sys/wait.h&gt;。你也缺少#include &lt;unistd.h&gt;,但你并不真正需要#include &lt;sys/types.h&gt;
  • @Shawn 你说得对。请把它写成答案,然后我可以接受。谢谢!
  • 如果包含标头,编译器应该告诉您wait() 需要一个您未提供的int * 参数。您也可以提供一个空指针。您没有参数的调用是错误的,如果您包含 &lt;sys/wait.h&gt; 标头,编译器应该会抱怨(如果您不包含它,应该抱怨该函数未声明)。如果您没有收到投诉,则说明您的编译器太旧,或者您没有使用足够的警告选项(尽管警告选项不是必需的)。

标签: c pipe parent-child


【解决方案1】:

如前所述,您只需反转索引以关闭管道和读/写。

您的代码几乎是正确的。有两件事是错误的:在父节点上,您首先关闭管道,然后调用pipe():应该反过来:首先创建两个管道,然后关闭相应的元素,全部在父节点中。

其次,您应该在设置管道后调用wait,否则它不起作用。猜你想等待所有你应该打电话给wait(NULL)的孩子。我不知道你说的wait()是什么意思。

完整代码:

#include <stdio.h>
#include <unistd.h>
#include <sys/wait.h>

int main(){

  int  p1[2], p2[2];
  char original[]="This is a string\n ";

  pid_t child2;
  pid_t child=fork();

  if (child>0)
  {
    child2 = fork();
    if(child2>0){

      printf("I'm the parrent.\n");
      pipe(p1); //ADDED
      pipe(p2); //ADDED
      close(p1[1]);
      close(p2[1]);
      wait(NULL); //DON'T GET IT WHY? if u want to wait all children,
      //wait after setting the pipes.
      printf("Parrent read p1:\n");
      if (read(p1[0], original, sizeof(original)) == -1)
        perror("read() error in parent p1");
      else printf("parent read '%s' from pipe 1\n", original);

      printf("Parrent read p2:\n");
      if (read(p2[0], original, sizeof(original)) == -1)
        perror("read() error in parent p2");
      else printf("parent read '%s' from pipe 2\n", original);
    }
    else{
      printf("Child2 \n");
      //pipe(p2); ERROR HERE
      close(p2[0]);
      if (write(p2[1], original, sizeof(original)+1) == -1)
        perror("write() error in child2");
      //close(p2[1]);
    }
  }
}

【讨论】:

    猜你喜欢
    • 2017-04-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-11-25
    • 2021-10-20
    • 1970-01-01
    相关资源
    最近更新 更多