我在使用C语言实现进程间通信时遇到了一些困难。我已将问题简化为以下代码块,其中我创建管道,分叉进程,并为子进程重定向IO:
int main(void) {
int parentToChild[2];
int childToParent[2];
pid_t pid = 1;
char buffer[80];
FILE *writeStream;
FILE *readStream;
pipe(parentToChild);
pipe(childToParent);
pid = fork();
if(pid == 0) { // I'm the child. I read from stdin, and write to stdout.
close(parentToChild[1]);
close(childToParent[0]);
dup2(parentToChild[0], 0);
dup2(childToParent[1], 1);
close(parentToChild[0]);
close(childToParent[1]);
fgets(buffer, 80, stdin); // wait for the parent to send something
fprintf(stderr, "I got %s\n", buffer); // tell the world I got it
fprintf(stdout, "Child message\n"); // send message back to the parent
}
if(pid != 0) { // I'm a parent
close(parentToChild[0]);
close(childToParent[1]);
/* writeStream connected to stdin of child */
writeStream = fdopen(parentToChild[1], "w");
/* readStream connected to stdout of child. */
readStream = fdopen(childToParent[0], "r");
fprintf(writeStream, "Hello, World!\n");
fgets(buffer, 80, readStream); // comment this out and the child will be able to read the "Hello World". Why is this?
fprintf(stderr, "Parent just got %s", buffer);
}
return 0;
}
如果我执行此操作,父母似乎永远等待孩子。我的流如何配置有什么明显的错误吗?如果我拥有它所以孩子只是阅读而父母只是写作(或反过来),它工作正常,但我无法管理两个进程读写。这个顺序看起来很好,孩子先期待stdin,父亲先写一个。
感谢。
答案 0 :(得分:2)
当我fflush (writeStream)
在父母fprintf(writeStream, "Hello, World!\n")
之后,一切正常。
我相信管道的缓冲存在问题。
尝试查看man 3 setvbuf
setvbuf()函数可用于任何打开的流来更改其缓冲区。 mode参数必须是以下三个宏之一:
_IONBF unbuffered _IOLBF line buffered _IOFBF fully buffered
所以我想将你的writeStream设置为_IONBF
(无缓冲)可以解决问题。
答案 1 :(得分:0)
来自dup2
手册页:
在从这些系统调用之一成功返回之后,旧文件描述符和新文件描述符可以互换使用。 他们引用相同的打开文件说明
因此,关闭其中一个管道将关闭其中一个标准文件描述符。不要那样做。