该联机帮助页用于民意调查(2):
POLLHUP - 挂断(仅输出)
POLLNVAL - 无效请求:fd未打开(仅输出)
究竟有什么区别?编写一个简单的程序表明,如果我关闭文件描述符,POLLNVAL
将触发,然后尝试从关闭的fd读取。但是,我无法找到返回POLLHUP
的方法。
答案 0 :(得分:9)
POLLNVAL
相当于EBADF
:这意味着文件描述符实际上并不是指任何打开的文件,即它是close
d或永远不会打开。除非由于编程错误或故意尝试查询文件描述符是否无效,否则这种情况永远不会发生。外部条件,例如对等关闭其网络套接字或管道的末尾 - 永远不能将您的文件描述符关闭到您的套接字的末尾或管道。如果可以,这将导致基本上任何使用套接字/管道等的程序存在大量漏洞。
POLLHUP
表示您的文件描述符有效,但它处于以下状态:
设备已断开连接,或者管道或FIFO已被最后一个打开以进行写入的进程关闭。一旦设置,FIFO的挂起状态将持续存在,直到某个进程打开FIFO进行写入或直到FIFO的所有只读文件描述符都关闭为止。此活动和POLLOUT是互斥的;如果发生挂断,则流永远不可写。但是,此事件与POLLIN,POLLRDNORM,POLLRDBAND或POLLPRI不是互斥的。该标志仅在revents位掩码中有效;在活动成员中应忽略它。
来源:http://pubs.opengroup.org/onlinepubs/9699919799/functions/poll.html
如果您想查看POLLHUP
,只需打开pipe
,关闭阅读结束,然后使用poll
查询结尾。
答案 1 :(得分:2)
如果您的目标是编写一个触发POLLHUP
的程序,请尝试打开管道,关闭它的写入结束然后poll()
读取结束(代码从{{3修改) }}):
#include <unistd.h>
#include <stdio.h>
#include <poll.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
int main(void)
{
int p[2];
struct pollfd ufd;
if (pipe(p) < 0) {
perror("pipe");
return EXIT_FAILURE;
}
if (close(p[1]) < 0) { /* close the write fd */
perror("close");
return EXIT_FAILURE;
}
memset(&ufd, 0, sizeof ufd);
ufd.fd = p[0]; /* poll the read fd after the write fd is closed */
ufd.events = POLLIN;
if (poll(&ufd, 1, 1000) < 0) {
perror("poll");
return EXIT_FAILURE;
}
switch(ufd.revents & (POLLIN|POLLHUP)) {
case POLLIN: printf("POLLIN\n"); break;
case POLLHUP: printf("POLLHUP\n"); break;
case POLLIN|POLLHUP: printf("POLLIN|POLLHUP\n"); break;
case POLLERR: printf("POLLERR\n"); break;
default: printf("%#x\n", (unsigned)ufd.revents); break;
}
return EXIT_SUCCESS;
}
以上为我打印POLLHUP
。
答案 2 :(得分:1)
POLLNVAL
表示文件描述符值无效。它通常表示您的计划中存在错误,但如果您关闭了文件描述符并且从那时起您没有打开任何文件,那么您可以依赖poll
返回POLLNVAL
重用了描述符。
POLLHUP
基本上意味着连接另一端的内容已关闭其连接的结束。 POSIX将其描述为
设备已断开连接。此活动和POLLOUT是互斥的;如果发生挂断,则流永远不可写。
这对于终端来说已经足够清楚了:终端已经消失(产生SIGHUP的同一事件:调制解调器会话已经终止,终端仿真器窗口已经关闭等)。永远不会为常规文件发送POLLHUP
。对于管道和插座,it depends。当管道写入端的程序关闭管道时Linux设置POLLHUP
,当套接字的另一端关闭套接字时设置POLLIN|POLLHUP
,但POLLIN
仅设置套接字关闭。当管道的写入端关闭管道时,最近* BSD设置POLLIN|POLLUP
,并且套接字的行为更加可变。
要观察POLLHUP
,请从终端读取您的程序并关闭终端。或者,在Linux上,让您的程序从管道读取并关闭写入结束(例如sleep 1 | yourprogram
)。