通常使用 poll 检测 socket 或标准输入时,只要指定 POLLIN 标志位,就能够检测是否有数据到达,或者链接断开:git
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 时表示相应链接断开。github
而对于 pipe,只检测POLLIN是感知不到管道断开的,当管道断开时,会在revents设置POLLHUP,必需额外检测此标志位:数组
1 if (pfd[2].revents & POLLHUP) { 2 // handle pipe break 3 ... 4 }
而当 poll 一个已经关闭的句柄时(句柄号 >=0 有效),poll 自己并不返回错误,而是给对应的句柄事件中设置 POLLNVAL 标志位:socket
1 if (pfd[2].revents & POLLNVAL) { 2 // handle pipe close 3 ... 4 }
若 poll 一个无效句柄时(句柄号为-1),poll 自己仍不返回错误,但该句柄必定没有任何事件可供检测与返回。所以可用于占位处理,测试
例如固定从数组某个下标中取出某个句柄时能够在不相关位置设置-1句柄,这样就不用再去判断当前有事件的句柄的源句柄是哪个了:spa
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]中取出管道句柄。code
固然若是传入 poll 的句柄数组中全部句柄都为无效句柄时,poll仍不返回错误,此时若提供超时,可当成sleep使用;blog
若不提供超时,则会进入无限期等待……事件
测试代码 ip