Linux 命令 poll 和 ppoll 详解 + 实例


  作者:Linux猿

简介:CSDN博客专家,华为云享专家,Linux、C/C++、云计算、物联网、面试、刷题、算法尽管咨询我,关注我,有问题私聊!

关注专栏: 数据结构和算法成神路【精讲】优质好文持续更新中……

欢迎小伙伴们点赞、收藏⭐、留言


本文主要对 Linux 命令 poll 和 ppoll 命令进行详细讲解,最后会以实例的方式进行说明,下面一起来看下吧!

一、基本概念

poll 和 ppoll 可以同时监听多个文件描述符上的事件,poll 函数和 ppoll 函数之间的关系类似于 select 和 pselect。

二、poll 和 ppoll 函数

2.1 poll 函数

头文件:

#include 

声明:

int poll(struct pollfd *fds, nfds_t nfds, int timeout);

其中,各参数为:

(1)struct pollfd *fds

  该参数是待监控事件的集合,struct pollfd 结构如下所示:

struct pollfd {
    int   fd;     //文件描述符
    short events; //需求的事件类型
    short revents;//返回的事件类型
};

字段 fd 包含打开文件的文件描述符。如果为负数,则忽略相应的时间字段,并返回 0,。如果此字段指定为零,则 fd 的所有事件都将被忽略,并且 revents 返回 0。

其中,events 和 revents 事件类型有如下种类:

#define POLLIN            0x0001 //有数据需要读取
#define POLLPRI          0x0002 //
#define POLLOUT        0x0004 //可以写入数据
#define POLLERR        0x0008 //调用出错,仅在revents中出现
#define POLLHUP        0x0010 //调用中断,仅在revents中出现
#define POLLNVAL       0x0020 //无效的请求,仅在revents中出现

(2)nfds_t nfds

  监听事件的个数,表示 fds 数组的长度。

(3)int timeout

阻塞时间,单位是毫秒,函数调用一直等待,直到发生下列三种情况之一:

  • 有事件发生;
  • 等待超时;
  • 调用被中断;

2.2 ppoll 函数

poll 函数和 ppoll 函数之间的关系类似于 select 和 pselect。

头文件:

#define _GNU_SOURCE
#include 
#include 

函数声明:

 int ppoll(struct pollfd *fds, nfds_t nfds, const struct timespec *tmo_p, const sigset_t *sigmask);

函数执行成功返回正数,表示发生事件的描述符的数量;如果返回值为 0,表示调用超时,且没有文件描述符就绪;如果返回 -1,表示出错。 

三、实例

下面来看下实例,如下所示:

#include 
#include 
#include 
#include 
#include 
#include 

#define errExit(msg)   do  { perror(msg); exit(EXIT_FAILURE); } while (0)

int main(int argc, char *argv[])
{
    int nfds, num_open_fds;
    struct pollfd *pfds;

    if (argc < 2)
    {
        fprintf(stderr, "Usage: %s file...\n", argv[0]);
        exit(EXIT_FAILURE);
    }

    num_open_fds = nfds = argc - 1;
    pfds = calloc(nfds, sizeof(struct pollfd));
    if (pfds == NULL)
        errExit("malloc");

    /* Open each file on command line, and add it 'pfds' array. */

    for (int j = 0; j < nfds; j++)
    {
        pfds[j].fd = open(argv[j + 1], O_RDONLY);
        if (pfds[j].fd == -1)
            errExit("open");

        printf("Opened \"%s\" on fd %d\n", argv[j + 1], pfds[j].fd);

        pfds[j].events = POLLIN;
    }

    /* Keep calling poll() as long as at least one file descriptor is
       open. */

    while (num_open_fds > 0)
    {
        int ready;

        printf("About to poll()\n");
        ready = poll(pfds, nfds, -1);
        if (ready == -1)
            errExit("poll");

        printf("Ready: %d\n", ready);

        /* Deal with array returned by poll(). */

        for (int j = 0; j < nfds; j++)
        {
            char buf[10];

            if (pfds[j].revents != 0)
            {
                printf("  fd=%d; events: %s%s%s\n", pfds[j].fd,
                       (pfds[j].revents & POLLIN) ? "POLLIN " : "",
                       (pfds[j].revents & POLLHUP) ? "POLLHUP " : "",
                       (pfds[j].revents & POLLERR) ? "POLLERR " : "");

                if (pfds[j].revents & POLLIN)
                {
                    ssize_t s = read(pfds[j].fd, buf, sizeof(buf));
                    if (s == -1)
                        errExit("read");
                    printf("    read %zd bytes: %.*s\n",
                           s, (int)s, buf);
                }
                else
                { /* POLLERR | POLLHUP */
                    printf("    closing fd %d\n", pfds[j].fd);
                    if (close(pfds[j].fd) == -1)
                        errExit("close");
                    num_open_fds--;
                }
            }
        }
    }

    printf("All file descriptors closed; bye\n");
    exit(EXIT_SUCCESS);
}

编译程序:

gcc -o main main.c

CSDN博客专家,华为云享专家,Linux、C/C++、云计算、物联网、面试、刷题、算法尽管咨询我,关注我,有问题私聊!

感觉有帮助记得「一键三连支持下哦!有问题可在评论区留言,感谢大家的一路支持!猿哥将持续输出「优质文章回馈大家!


你可能感兴趣的:(Linux,技术,linux,运维,服务器)