zoukankan      html  css  js  c++  java
  • poll相关

    IO多路复用。

    1. 定义

    #include <poll.h>
    
    struct pollfd {
        int   fd;         /* file descriptor */
        short events;     /* requested events */
        short revents;    /* returned events */
    };
    
    int poll(struct pollfd *fds, nfds_t nfds, int timeout);
    
    #define _GNU_SOURCE         /* See feature_test_macros(7) */
    #include <poll.h>
    
    struct timespec {
        long    tv_sec;         /* seconds */
        long    tv_nsec;        /* nanoseconds */
    };
    
    int ppoll(struct pollfd *fds, nfds_t nfds,
            const struct timespec *timeout_ts, const sigset_t *sigmask);
    

    2. 基本使用

    select(2)类似,等待一组文件描述符上的事件。

    如果 fd 是负数,poll(2) 会忽略 events,并且返回的revents是0,可以在单次poll(2)调用中,忽略某一个fd
    events 是入参,输入对fd上感兴趣的事件,是个bitmask,0表示对所有事件都不感兴趣。

    revents是出参,表示哪些事件发生了,也是个bitmask,可能会比 events 多出来三个值 POLLER, POLLHUP, POLLNVAL

    timeout是ms,表示poll(2)最少会阻塞的时间,0表示非阻塞,立刻返回,即使没有事件发生也会返回;负数表示一直阻塞,直到有事件发生。

    bitmask可以有的值为:

    • POLLIN: 有数据可以读
    • POLLPRI: 紧急数据可读(TCP上的带外数据等)
    • POLLOUT: 数据可写,这时候进行写操作不会阻塞
    • POLLRDHUP(>=2.6.17): 流式socket的对端断开连接或者关闭了写操作。比如有 _GNU_SOURCE 宏才能使用该定义
    • POLLERR(out): 有错误发生
    • POLLHUP(out): 挂起。写端关闭,在读端poll()时,会出现该错误。
    • POLLNVAL(out): 非法请求,fd未打开。等价于EBADF。

    ppoll(2) 允许应用安全的等待fd上事件发生,或者捕获了信号。类似 select(2)pselect(2) 的关系。
    这样的调用:

    ready = ppoll(&fds, nfds, timeout_ts, &sigmask);
    

    等价于 原子性 的执行:

    sigset_t origmask;
    int timeout;
    
    timeout = (timeout_ts == NULL) ? -1 :
                (timeout_ts.tv_sec * 1000 + timeout_ts.tv_nsec / 1000000);
    sigprocmask(SIG_SETMASK, &sigmask, &origmask);
    ready = poll(&fds, nfds, timeout);
    sigprocmask(SIG_SETMASK, &origmask, NULL);
    

    3. 返回值

    大于0: 成功,有事件发生的fd的个数(这些fd上的 revents 非0)。
    0: 超时,没有事件发生
    -1: 失败,需要检查对应的errno。

    errno:

    • EFAULT: 参数数组地址无效
    • EINTR: 有信号发生
    • EINVAL: nfds 值超出了 RLIMIT_NOFILE 的值
    • ENOMEM: 没有内存来申请fd表

    4. 其他

    有些实现定义了 timeout 参数无穷大值 INFTIM,值为-1, glibc 没有定义。

    linux提供的 ppoll(2) 系统调用接口会更新 timeout_ts 参数,glibc封装的时候不会更新,需要注意

    5. 关于POLLHUP

    这里稍详细的解释了POLLHUP: https://pubs.opengroup.org/onlinepubs/9699919799/functions/poll.html

    POLLHUP
    A device has been disconnected, or a pipe or FIFO has been closed by the last process that had it open for writing. Once set, the hangup state of a FIFO shall persist until some process opens the FIFO for writing or until all read-only file descriptors for the FIFO are closed. This event and POLLOUT are mutually-exclusive; a stream can never be writable if a hangup has occurred. However, this event and POLLIN, POLLRDNORM, POLLRDBAND, or POLLPRI are not mutually-exclusive. This flag is only valid in the revents bitmask; it shall be ignored in the events member.
    POLLNVAL

    也就是写端关闭,在读端进行poll()时,会报出这个错,然后在写端重新打开后,该fd还会正常,有人提供了个示例,演示了如何触发 POLLHUP

    // 打开pipe, 关闭写端,在读端进行poll()
    
    #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
    "); break;
            case POLLHUP: printf("POLLHUP
    "); break;
            case POLLIN|POLLHUP: printf("POLLIN|POLLHUP
    "); break;
            case POLLERR: printf("POLLERR
    "); break;
            default: printf("%#x
    ", (unsigned)ufd.revents); break;
        }
    
        return EXIT_SUCCESS;
    }
    
  • 相关阅读:
    VC 常见问题百问
    python windows 环境变量
    Check server headers and verify HTTP Status Codes
    Where are the AES 256bit cipher suites? Please someone help
    outlook 如何预订会议和会议室
    安装Axis2的eclipse插件后,未出现界面
    windows 环境变量
    python 时间日期处理汇集
    openldap学习笔记(使用openldap2.3.32)
    set p4 environment in windows
  • 原文地址:https://www.cnblogs.com/suntus/p/14908743.html
Copyright © 2011-2022 走看看