我想知道在轮询设置这些位时应该怎么做?关闭套接字,忽略它或什么?
答案 0 :(得分:14)
POLLHUP
表示套接字不再连接。在TCP中,这意味着FIN已被接收并发送。
POLLERR
表示套接字出现异步错误。在TCP中,这通常意味着已经接收或发送了RST。如果文件描述符不是套接字,POLLERR
可能意味着设备不支持轮询。
对于上述两个条件,套接字文件描述符仍处于打开状态,尚未关闭(但可能已调用shutdown()
)。文件描述符上的close()
将释放仍代表套接字保留的资源。理论上,应该可以立即重用套接字(例如,使用另一个connect()
调用)。
POLLNVAL
表示套接字文件描述符未打开。 close()
它会出错。
答案 1 :(得分:8)
这取决于确切的错误性质。使用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/
最简单的方法是假设套接字在任何情况下都不再可用并关闭它。
答案 2 :(得分:2)
POLLNVAL
表示文件描述符值无效。它通常表示程序中存在错误,但如果您关闭了文件描述符并且之后没有打开任何可能重用了描述符的文件,则可以依赖poll
返回POLLNVAL
。
POLLERR
类似于select
的错误事件。它表示read
或write
调用将返回错误条件(例如,I / O错误)。这不包括select
通过其errorfds
掩码发出信号的带外数据,但poll
信号通过POLLPRI
发出信号。
POLLHUP
基本上意味着连接另一端的内容已关闭其连接的结束。 POSIX将其描述为
设备已断开连接。此活动和POLLOUT是互斥的;如果发生挂断,则流永远不可写。
这对于终端来说已经足够清楚了:终端已经消失(产生SIGHUP的同一事件:调制解调器会话已经终止,终端仿真器窗口已经关闭等)。永远不会为常规文件发送POLLHUP
。对于管道和插座,it depends on the operating system。当管道写入端的程序关闭管道时Linux设置POLLHUP
,当套接字的另一端关闭套接字时设置POLLIN|POLLHUP
,但POLLIN
仅设置套接字关闭。当管道的写入端关闭管道时,最近* BSD设置POLLIN|POLLUP
,并且套接字的行为更加可变。
答案 3 :(得分:-1)
最小FIFO示例
一旦你了解这些情况何时发生,就应该很容易知道如何处理它们。
#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
在另一个shell上:
printf a >poll0.tmp
<强> POLLHUP 强>
如果您不修改来源:./poll.out
输出:
loop
POLLIN n=1 buf=a
loop
POLLHUP
loop
所以:
POLLIN
POLLHUP
关闭时,会发生printf
close(pfd.fd);
和pfd.fd *= -1;
清理了一切,我们停止接收POLLHUP
poll
永远挂起这是正常的操作。
您现在可以重新启动FIFO以等待下一个open
,或者如果您已完成则退出循环。
<强> POLLNAL 强>
如果你发表评论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生成POLLERR
。如果有办法让我知道。但是应该可以使用file_operations
设备驱动程序。
在Ubuntu 14.04中测试。