POLLHUP与POLLNVAL,或什么是POLLHUP?

Lyc*_*cus 4 c unix pipe poll-syscall

该联机帮助页用于民意调查(2):

POLLHUP - 挂机(仅限输出)

POLLNVAL - 无效请求:fd未打开(仅输出)

究竟有什么区别?编写一个简单的程序会显示POLLNVAL如果我关闭文件描述符将触发,然后尝试从关闭的fd读取.但是,我无法弄清楚返回的方法POLLHUP.

R..*_*R.. 10

POLLNVAL相当于EBADF:它表示文件描述符实际上并不是指任何打开的文件,即它是closed或从不打开开始.除非由于编程错误或故意尝试查询文件描述符是否无效,否则这种情况永远不会发生.外部条件(例如对等体关闭网络套接字或管道的末尾)永远不会将文件描述符关闭到套接字或管道的末尾.如果可以,这将导致基本上任何使用套接字/管道/等的程序的大量漏洞.

POLLHUP另一方面,表示您的文件描述符有效,但它处于以下状态:

设备已断开连接,或者管道或FIFO已被最后一个打开以进行写入的进程关闭.一旦设置,FIFO的挂起状态将持续存在,直到某个进程打开FIFO进行写入或直到FIFO的所有只读文件描述符都关闭为止.此活动和POLLOUT是互斥的; 如果发生挂断,则流永远不可写.但是,此事件与POLLIN,POLLRDNORM,POLLRDBAND或POLLPRI不是互斥的.该标志仅在revents位掩码中有效; 在活动成员中应忽略它.

资料来源:http://pubs.opengroup.org/onlinepubs/9699919799/functions/poll.html

如果你想看POLLHUP,只需打开一个pipe,关闭阅读结束,并查询写作结束poll.

  • 在这个意义上,我看到 POLLHUP 的读写“切换”。我打开一个 FIFO 进行读取,然后进行轮询;这会优雅地阻塞,直到其他内容写入 FIFO。然后我得到 POLLIN 并读取数据。写入器关闭它的末尾,我再次轮询,打算等待另一个写入器打开 FIFO 并写入它——但我立即收到了一个 POLLHUP。(或者 POLLHUP | POLLIN,如果我重复轮询直到写入确实发生。)我猜我需要在再次轮询之前刷新我的文件描述符,以避免忙等待。 (2认同)

Alo*_*hal 5

如果您的目标是编写触发 的程序POLLHUP,请尝试打开管道,关闭其写入端然后poll()读取端(代码修改自http://www.greenend.org.uk/rjk/tech/民意调查.html):

#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;
}
Run Code Online (Sandbox Code Playgroud)

以上POLLHUP为我打印。

  • switch 语句中的掩码意味着“POLLERR”和“POLLHUP”情况永远不会被采用。 (2认同)
  • 这也不起作用,就好像设置了多个位一样,很多情况都会失败。选项是 1) 枚举所有情况,或 2) 仅使用 3 个 if 检查每个相关位 (2认同)