08、LinuxC -- IO多路复用 poll函数

        监听集合没无动静,如果没有动静就阻塞,如果有动静就成功返回,返回值为集合中有动静的fd的数量。

poll 函数原型
        int poll(struct pollfd *fds, nfds_t nfds, int timeout);

参数:
        fds:这个参数写为struct pollfd fds[ ] 更好理解,第一个参数要求传递一个 struct poll fd 结构体数组。这个数组就相当于select的文件描述符集合,只不过select是使用fd_set来定义的,而poll的集合是一个数组。
struct pollfd的成员:
struct pollfd

{
         int   fd;      :文件描述符
         short events;  :设置我们希望发生的事件,比如读事件,这个需要我们自己设置
         short revents; :实际发生的事件,比如读事件,由poll机制自己设置
};

events   说明
1、POLLIN 普通或优先级带数据可读
2、POLLRDNORM  普通数据可读
3、POLLRDBAND  优先级带数据可读
4、POLLPRI高优先级数据可读
5、POLLOUT普通数据可写
6、POLLWRNORM  普通数据可写
7、POLLWRBAND  优先级带数据可写
8、POLLERR发生错误
9、POLLHUP发生挂起
10、POLLNVAL  描述字不是一个打开的文件

poll 监听时如果没有动静就阻塞,有动静就不再阻塞,返回有动静的fd的数量。

如何知道是那些fd有动静?
        如果文件描述符“发生的事件”==“实际事件”,就说明希望的事件来了,就是对fd进行相应的“读或写”操作。        
        

        nfds:数组的元素个数。
        timeout:超时时间,如果写的是
               -1:不设置超时,如果集合没有动静就一直阻塞下去,直到poll函数被信号中断(唤醒)或者集合有动静为止                      
               非-1值:比如3000(3000微妙),表示将超时时间设置为3秒也就是说poll超时时间的单位时微妙。   

返回值:

        返回-1:说明函数调用失败,errno被设置。

如果是被信号中断从而导致出错返回-1时,errno被设置为EINTR,
如果不想被中断,要么重启poll的调用,要么忽略或者屏蔽这些信号。                    
        0:超时时间到,而且没有文件描述符有动静。
        大于0:返回有响应的文件描述符的数量。

demo代码: 同时读键盘和鼠标

#include <stdio.h>
#include <stdlib.h>

#include <sys/stat.h>
#include <sys/types.h>
#include <sys/time.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <poll.h>

int main(int argc, char const *argv[])
{
    int fd;

    if ((fd = open("/dev/input/mouse0", O_RDWR | O_CREAT, 0655)) < 0)
    {
        perror("open file error!");
        exit(1);
    }

    struct pollfd fds[2];

    fds[0].fd = 0;
    fds[0].events = POLLIN;

    fds[1].fd = fd;
    fds[1].events = POLLIN;

    while (1)
    {
        int ret = poll(fds, 2, -1);
        for (int i = 0; i < 2; i++)
        {
            if (fds[i].events == fds[i].revents)
            {
                if (fds[i].fd == 0)
                {
                    char buffer[1024];

                    read(fds[i].fd, buffer, sizeof(buffer));

                    printf("buffer = %s\n", buffer);
                }

                else if (fds[i].fd == fd)
                {
                    int cor;

                    read(fds[i].fd, &cor, sizeof(cor));

                    printf("cor = %d\n", cor);
                }

                if (--ret == 0)
                {
                    break;
                }
            }
        }
    }

    return 0;
}

执行结果:

root@GodFather:/home/superlan/C_Language/advanced_IO_operation# ./a.out 
cor = 8486696
cor = 8480552
cor = 12255272
cor = 520
cor = 264
hello
buffer = hello

^C
root@GodFather:/home/superlan/C_Language/advanced_IO_operation# 

poll 的优缺点

        解决 select 监听文件描述符受限的问题,通过采用链表的方式保存文件描述符

优点

        poll 没有最大文件描述符限制(使用链表的方式存储 fd)

缺点:

        因为无法获取具体哪个文件描述符发生变化,只能进行全盘轮询,随着监听的文件描述符增多,效率下降;

        所监听的文件描述符都必须从用户空间传入内核空间进行监听,涉及到大量的数据拷贝,效率低。
 
 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值