如何回写父母的管道?

时间:2014-03-01 04:26:34

标签: c++ c fork posix

假设我有以下代码。是否有可能从孩子写回父母?我可以通过相同的管道 mypipe吗?我是否需要另一个等待功能?

int mypipe[2];
int i, pid;

pipe (mypipe);
value = fork ();
if (value == -1)
  {
    exit (0);
  }
else if (value == 0)
  {
    read (mypipe[0], (char *) &i, sizeof (int));
    cout << "i = " << i << endl;
    exit (0);
  }
else
  {
    i = 7;
    write (mypipe[1], (char *) &i, sizeof (int));
    wait (&pid);
  }

3 个答案:

答案 0 :(得分:0)

管道是单向的。有一个写端和一个读端。如果您有多个进程(子进程和父进程)读取管道,则未定义每个进程将读取哪些消息。

是的,孩子可以写信给(通常是父母到孩子的管道),但如果它转过来再从管道读取,在父母可以之前,它会读取自己的消息!

最好的办法是使用一对管道(每个方向一个)或双向PF_LOCAL插座连接。

答案 1 :(得分:0)

是的,您可以使用管道以便父级写入并且子级读取,或者使子级写入并且父级读取。管道是单向的,所以你不能同时做到这两点(如果你想同时做两件事,你会想要socketpair)。

从联系手册:

  

pipe()创建一个管道,一个可用于进程间通信的单向数据通道。数组pipefd用于返回引用管道末端的两个文件描述符。 pipefd[0]指的是管道的读取端。 pipefd[1]指的是管道的 write 端。写入管道写端的数据由内核缓冲,直到从管道的读端读取。有关详细信息,请参阅pipe(7)

我已经清除了你的程序,并用C语言编译(没有cout),它可以工作:

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

int mypipe[2];
int i, pid;

int
main (int argc, char **argv)
{
  int value;
  pipe (mypipe);
  value = fork ();
  if (value == -1)
    {
      perror ("Cannot fork");
      exit (1);
    }
  else if (value == 0)
    {
      read (mypipe[0], &i, sizeof (int));
      printf ("i = %d\n", i);
      wait (&pid);
      exit (0);
    }
  else
    {
      i = 7;
      write (mypipe[1], &i, sizeof (int));
      exit (0);
    }
}

正如您所看到的,没有重大更改(除了出于某种原因,您尝试使用char指针编写一个int,在小端机器上将写入0)。

您的程序读入子项并写入父项。

这是一个读取父级并在子级中写入的版本,也可以正常工作。正如您所看到的那样,只需要交换读写位。

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

int mypipe[2];
int i, pid;

int
main (int argc, char **argv)
{
  int value;
  pipe (mypipe);
  value = fork ();
  if (value == -1)
    {
      perror ("Cannot fork");
      exit (0);
    }
  else if (value == 0)
    {
      i = 7;
      write (mypipe[1], &i, sizeof (int));
      exit (0);
    }
  else
    {
      read (mypipe[0], &i, sizeof (int));
      printf ("i = %d\n", i);
      wait (&pid);
      exit (0);
    }
}

答案 2 :(得分:0)

只要您以某种方式控制两个进程之间的同步,就可以使用单个管道从父级到子级以及从子级到父级进行写入。例如:

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

int main(void)
{
    int mypipe[2];
    int i, pid;
    pipe(mypipe);
    pid = fork();
    if (pid == -1)
    {
        perror("Cannot fork");
        return 1;
    }
    else if (pid == 0)
    {
        read(mypipe[0], &i, sizeof(int));
        printf("child: i = %d\n", i);
        i += 13;
        write(mypipe[1], &i, sizeof(int));
    }
    else
    {
        i = 7;
        write(mypipe[1], &i, sizeof(int));
        int status;
        int corpse = wait(&status);
        read(mypipe[0], &i, sizeof(int));
        printf("parent: i = %d (child = %d = %d; status = 0x%.4X)\n",
               i, pid, corpse, status);
    }
    return 0;
}

示例运行:

child: i = 7
parent: i = 20 (child = 62299 = 62299; status = 0x0000)

这里的同步是父进程在阅读孩子的遗书之前等待孩子死亡。

这很少使用 - 您通常会创建两个单独的管道,一个用于父级写入子级,另一个用于子级写入父级 - 因为它简化了同步。您必须注意的唯一问题是没有填充管道,以便在孩子被阻止尝试写入父级时(死锁)阻止父级尝试写入子级。如果您有一个简单的半双工协议(以便每个进程知道另一个进程何时完成了当前消息),或者如果每个进程中都有单独的读写器线程,则可以避免死锁。

请注意,某些系统(BSD)提供双向管道。套接字也是双向通信通道。