我想知道当 poll 设置这些位时应该做什么?关闭套接字,忽略它还是什么?
4 回答
APOLLHUP
表示套接字不再连接。在 TCP 中,这意味着 FIN 已被接收和发送。
APOLLERR
表示套接字出现异步错误。在 TCP 中,这通常意味着 RST 已被接收或发送。如果文件描述符不是套接字,则POLLERR
可能意味着设备不支持轮询。
对于上述两种情况,套接字文件描述符仍处于打开状态,并且尚未关闭(但shutdown()
可能已经被调用)。close()
文件描述符上的A将代表套接字释放仍保留的资源。理论上,应该可以立即重用套接字(例如,通过另一个connect()
调用)。
APOLLNVAL
表示套接字文件描述符未打开。这将是一个错误close()
。
这取决于确切的错误性质。使用 getsockopt() 查看问题:
int error = 0;
socklen_t errlen = sizeof(error);
getsockopt(fd, SOL_SOCKET, SO_ERROR, (void *)&error, &errlen);
价值观:http ://www.xinotes.net/notes/note/1793/
最简单的方法是假设套接字在任何情况下都不再可用并关闭它。
POLLNVAL
表示文件描述符值无效。它通常表示您的程序中存在错误,但如果您关闭了文件描述符并且此后没有打开任何可能重用描述符的文件,您可以依赖poll
返回。POLLNVAL
POLLERR
类似于来自 的错误事件select
。它表示read
orwrite
调用将返回错误条件(例如 I/O 错误)。这不包括select
通过其errorfds
掩码poll
发送信号但通过 发送信号的带外数据POLLPRI
。
POLLHUP
基本上意味着连接另一端的东西已经关闭了它的连接端。POSIX将其描述为
设备已断开连接。此事件和 POLLOUT 互斥;如果发生挂断,则流永远不可写。
这对于终端来说已经足够清楚了:终端已经消失(生成 SIGHUP 的同一事件:调制解调器会话已终止,终端仿真器窗口已关闭等)。POLLHUP
永远不会为常规文件发送。对于管道和套接字,它取决于操作系统。Linux设置POLLHUP
管道写入端的程序何时关闭管道,并设置POLLIN|POLLHUP
套接字的另一端何时关闭套接字,但POLLIN
仅用于套接字关闭。POLLIN|POLLUP
当管道的写入端关闭管道时,最近的 *BSD 设置,并且套接字的行为更加多变。
最小 FIFO 示例
一旦您了解了这些情况何时发生,就应该很容易知道如何处理它们。
民意调查.c
#define _XOPEN_SOURCE 700
#include <fcntl.h> /* creat, O_CREAT */
#include <poll.h> /* poll */
#include <stdio.h> /* printf, puts, snprintf */
#include <stdlib.h> /* EXIT_FAILURE, EXIT_SUCCESS */
#include <unistd.h> /* read */
int main(void) {
char buf[1024];
int fd, n;
short revents;
struct pollfd pfd;
fd = open("poll0.tmp", O_RDONLY | O_NONBLOCK);
pfd.fd = fd;
pfd.events = POLLIN;
while (1) {
puts("loop");
poll(&pfd, 1, -1);
revents = pfd.revents;
if (revents & POLLIN) {
n = read(pfd.fd, buf, sizeof(buf));
printf("POLLIN n=%d buf=%.*s\n", n, n, buf);
}
if (revents & POLLHUP) {
printf("POLLHUP\n");
close(pfd.fd);
pfd.fd *= -1;
}
if (revents & POLLNVAL) {
printf("POLLNVAL\n");
}
if (revents & POLLERR) {
printf("POLLERR\n");
}
}
}
编译:
gcc -o poll.out -std=c99 poll.c
用法:
sudo mknod -m 666 poll0.tmp p
./poll.out
在另一个外壳上:
printf a >poll0.tmp
民意调查
如果您不修改源:./poll.out
输出:
loop
POLLIN n=1 buf=a
loop
POLLHUP
loop
所以:
POLLIN
当输入可用时发生POLLHUP
当文件被关闭时发生printf
close(pfd.fd);
把东西pfd.fd *= -1;
清理干净,我们就停止接收了POLLHUP
poll
永远挂起
这是正常操作。
您现在可以重新启动 FIFO 以等待下一个open
,或者在完成后退出循环。
轮询
如果您注释掉pfd.fd *= -1;
:./poll.out
打印:
POLLIN n=1 buf=a
loop
POLLHUP
loop
POLLNVAL
loop
POLLNVAL
...
并永远循环。
所以:
POLLIN
并且像以前一样POLLHUP
发生close
- 因为我们没有设置
pfd.fd
为负数,poll
所以一直尝试使用fd
我们关闭的 - 这将
POLLNVAL
永远返回
所以我们看到这不应该发生,并表明您的代码中存在错误。
轮询器
我不知道如何POLLERR
使用 FIFO 生成一个。让我知道是否有办法。但这应该可以使用file_operations
设备驱动程序。
在 Ubuntu 14.04 中测试。