假设我有以下代码。是否有可能从孩子写回父母?我可以通过相同的管道 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);
}
答案 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)提供双向管道。套接字也是双向通信通道。