[apue] 使用 poll 检测管道断开

一般使用 poll 检测 socket 或标准输入时,只要指定 POLLIN 标志位,就可以检测是否有数据到达,或者连接断开:

复制代码
 1 struct pollfd fds[3];
 2 fds[0].fd = STDIN_FILENO;
 3 fds[0].events = POLLIN; 
 4 fds[1].fd = sock_fd; 
 5 fds[1].events = POLLIN; 
 6 fds[2].fd = pipe_fd; 
 7 fds[2].events = POLLIN; 
 8 ret = poll(fds, 3, -1);
 9 if (ret > 0) { 
10     if (fds[0].revents & POLLIN) {
11         // handle stdin
12         ...
13     }
14     if (fds[1].revents & POLLIN) { 
15         // handle socket input
16         ...
17     }
18     if (fds[2].revents & POLLIN) { 
19         // handle pipe input
20         ...
21     }        
22 }
复制代码

当 read 结果返回 0 时表示相应连接断开。

而对于 pipe,只检测POLLIN是感知不到管道断开的,当管道断开时,会在revents设置POLLHUP,必需额外检测此标志位:

1 if (pfd[2].revents & POLLHUP) {
2       // handle pipe break
3       ...
4 }

 而当 poll 一个已经关闭的句柄时(句柄号 >=0 有效),poll 本身并不返回错误,而是给对应的句柄事件中设置  POLLNVAL 标志位:

1 if (pfd[2].revents & POLLNVAL) {
2       // handle pipe close
3       ...
4 }

若 poll 一个无效句柄时(句柄号为-1),poll 本身仍不返回错误,但该句柄一定没有任何事件可供检测与返回。因此可用于占位处理,

例如固定从数组某个下标中取出某个句柄时可以在不相关位置设置-1句柄,这样就不用再去判断当前有事件的句柄的源句柄是哪一个了:

复制代码
1 struct pollfd fds[3];
2 fds[0].fd = STDIN_FILENO;
3 fds[0].events = POLLIN; 
4 fds[1].fd = -1; 
5 fds[1].events = POLLIN; 
6 fds[2].fd = pipe_fd; 
7 fds[2].events = POLLIN; 
8 ret = poll(fds, 3, -1);
9 ……
复制代码

例如当没有 socket  句柄时,该位置保持-1,这样可以不用将管道句柄上移,从而可以固定从fds[2]中取出管道句柄。

当然如果传入 poll 的句柄数组中所有句柄都为无效句柄时,poll仍不返回错误,此时若提供超时,可当成sleep使用;

若不提供超时,则会进入无限期等待……

 

测试代码

 

posted @   goodcitizen  阅读(982)  评论(0编辑  收藏  举报
编辑推荐:
· 一个奇形怪状的面试题:Bean中的CHM要不要加volatile?
· [.NET]调用本地 Deepseek 模型
· 一个费力不讨好的项目,让我损失了近一半的绩效!
· .NET Core 托管堆内存泄露/CPU异常的常见思路
· PostgreSQL 和 SQL Server 在统计信息维护中的关键差异
阅读排行:
· DeepSeek “源神”启动!「GitHub 热点速览」
· 我与微信审核的“相爱相杀”看个人小程序副业
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 如何使用 Uni-app 实现视频聊天(源码,支持安卓、iOS)
· C# 集成 DeepSeek 模型实现 AI 私有化(本地部署与 API 调用教程)
点击右上角即可分享
微信分享提示