管道分写端和读端,当写端全部close()
时,读端会收到状态码0,这样读端就可以以此退出循环
while(receive_msg(&val, sizeof val)){
...
}
但是管道如果没有正确的关闭,读端可能就无法收到退出状态码,从而陷入阻塞
以以下程序为例
int p[2];
int main()
{
pipe(p);
int pid = fork();
if(pid == 0) //child thread
{
char buf[20];
while (read(p[0], buf, 5))
{
buf[5] = 0;
printf("%s.\n", buf);
}
close(p[1]), close(p[0]);
exit(0);
}
else
{
for(int i = 0; i < 10; i++)
write(p[1], "hello", 5);
close(p[0]), close(p[1]);
wait(0);
}
}
运行后会发现程序陷入阻塞, 永远无法退出,明明主线程已经关闭了管道文件,为什么会这样呢?这就是因为管道没有正确关闭
管道使用的是引用计数法,上面的程序,正常运行时是这样
父进程和子进程都有一个指向两端的引用,因此当主线程close
两个端后,管道的引用状态是这样
因此读端无法收到退出的状态码,导致陷入阻塞
启发
不需要的使用的端口一定要尽早关闭,只需要读的端,一开始就把写端关闭,
上述代码可以改成这样
int p[2];
int main()
{
pipe(p);
int pid = fork();
if(pid == 0) //child thread
{
close(p[1]),
char buf[20];
while (read(p[0], buf, 5))
{
buf[5] = 0;
printf("%s.\n", buf);
}
close(p[0]);
exit(0);
}
else
{
close(p[0]);
for(int i = 0; i < 10; i++)
write(p[1], "hello", 5);
close(p[1]);
wait(0);
}
}
这样就可以正常退出了
管道的管理使用的是