int main()
{
char *msg="hello";
char buff[MAX];
int p[2];
pipe(p);
int i,pid=fork();
if(pid>0){
//close(p[1]);
read(p[0],buff, MAX);
}
else
{
printf("child exiting\n");
}
}
为什么以上代码最终会被阻止?但是如果我们删除评论并放置
close(p[1])
那为什么代码会立即结束?
答案 0 :(得分:2)
创建管道后,它会有四个结束:
p[0]
p[1]
p[0]
p[1]
除非两个写入结束都已关闭,否则UNIX不会将EOF
传递给阅读器,因为它知道管道仍然可写。
当子进程退出时,它会关闭管道两端的两端。但是,父级仍然有一个可写端打开,因此从管道块读取而不是向父级提供EOF
。这就是UNIX手册指示立即关闭管道的未使用端的原因:
使用
pipe(2)
和fork(2)
的应用程序应使用合适的close(2)
调用来关闭不必要的重复文件描述符;这可以确保在适当的时候传递文件结尾和SIGPIPE
/EPIPE
。
以下是如何在不关闭父级p[1]
的情况下阻止程序阻止的示例:
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
void* write_pipe(void* pp) {
int* p = (int*)pp;
char msg[] = "Hello from another thread!";
write(p[1], msg, sizeof(msg));
return NULL;
}
int main()
{
char buff[100];
int p[2];
pipe(p);
int pid=fork();
if(pid>0){
pthread_t thread1;
pthread_create (&thread1, NULL, &write_pipe, (void *)p);
read(p[0],buff, 100);
printf("%s\n", buff);
printf("parent exiting\n");
}
else
{
printf("child exiting\n");
}
return 0;
}
上面的代码从父进程内的线程写入管道的写入端,而不是从子进程写入它。这也是管道的合法使用,说明了为什么UNIX无法传递EOF
,除非管道的父级写入端已关闭。
答案 1 :(得分:0)
Read是一个阻塞调用,只有在收到EOF时才会返回。如果你不关闭管道的写端,读取结束将不会得到EOF,因此,程序将保持阻止