• 十、网络编程之 poll 详解.md


    上一篇文章《网络编程之 select 详解》详细介绍了 select,而 poll 和 select 非常相似,本文将详细探讨 poll 的相关知识。

    网络编程之 poll 详解

    poll 函数

    poll 是 Linux 中的字符设备驱动中的一个函数。poll 和 select 的实现机制类似,本质上没有多大差别,也是管理多个套接字文件描述符,也是由内核进行轮询并根据描述符的状态进行处理,但是 poll() 没有最大文件 描述符数量的限制,勉强算是select()函数的升级版。poll 的函数原型如下:

    #include <poll.h>
    int poll(struct pollfd *fds, nfds_t nfds, int timeout);
    fds				是一个 pollfd 结构类型的数组的首地址,用于存放需要检测其状态的Socket描述符
    nfds 			监控数组中有多少文件描述符需要被监控
    timeout 		毫秒级等待
        			-1:阻塞等,#define INFTIM -1(Linux中没有定义此宏,可以自己定义) 			
       				 0:立即返回,不阻塞进程
       				 >0:等待指定毫秒数,如当前系统时间精度不够毫秒,向上取值
    
    struct pollfd {
        int fd; /* 文件描述符:用户设置关注的文件描述符(用户填充) */
        short events; /* 监控的事件:用户关注的事件类型(用户填充) */
        short revents; /* 监控事件中满足条件返回的事件:/由内核填充,就绪的事件类型 */
    };
    
    pollfd 结构监控的事件类型如下:
    	POLLIN			普通或带外优先数据可读,即POLLRDNORM | POLLRDBAND
    	POLLRDNORM		数据可读
    	POLLRDBAND		优先级带数据可读
    	POLLPRI 		高优先级可读数据
    	POLLOUT		普通或带外数据可写
    	POLLWRNORM		数据可写
    	POLLWRBAND		优先级带数据可写
    	POLLERR 		发生错误
    	POLLHUP 		发生挂起
    	POLLNVAL 		描述字不是一个打开的文件
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • select管理多个文件描述符是通过集合这种数据结构,而 poll 是通过数组(也可以理解为队列)。
    • 如果不再监控某个文件描述符时,可以把 pollfd 中 fd 设置为 -1,poll不再监控此pollfd,下次返回时,revents设置为0。

    poll 实例

    详细代码示例参考 GitHub 开源代码 “IO Multiplexin\poll"部分,下载链接

    poll 代码逻辑如下:

    1. 初始数组,event 设置为读,revent设置为空;
    2. 将数组拷贝到内核进行监听,发现有文件描述符变化,就将该文件描述符 revent 设置为读;
    3. 将数组返回给应用层并覆盖原来的数组;
    4. 遍历数组对比 event 和 revent 是否一致,如果一致就对文件进行读/写(所以相对于 select 需要删除集合元素,poll不需要删除数组元素)

    poll 特点

    相对于 Linux 下 select 和 epoll,poll 特点如下:

    • 相较于select而言,poll的优势:

      1. 传入、传出事件分离。无需每次调用时,重新设定监听事件(重新初始化)。
      2. 文件描述符上限,可突破1024限制。能监控的最大上限数可使用配置文件调整。
      3. 相比同步阻塞型 IO 模型,poll 用单线程(进程)执行,占用资源少,不消耗太多 CPU,同时能够为多客户端提供服务。
    • 缺点和select一样:

      • 大量遍历:只是返回变化的套接字文件描述符的个数,具体哪个变化需要遍历;
      • 不必要的拷贝:监听的文件描述集合在应用层和内核之间来回拷贝;
      • 大量并发时,少量触发(即只有少量描述符被触发)时遍历低效。

    推荐一个零声学院免费公开课程,个人觉得老师讲得不错,
    分享给大家:[Linux,Nginx,ZeroMQ,MySQL,Redis,
    fastdfs,MongoDB,ZK,流媒体,CDN,P2P,K8S,Docker,
    TCP/IP,协程,DPDK等技术内容,点击立即学习:服务器课程

  • 相关阅读:
    Java复习-25-单例设计模式
    Spring Cloud(五):Spring Cloud Alibaba Nacos 1.4.X 注册中心AP & CP架构Raft源码分析
    聊一聊前端面临的安全威胁与解决对策
    构建可扩展的应用:六边形架构详解与实践
    【LeetCode】12. 整数转罗马数字
    mac使用vpn时重启 导致百度和app store打不开
    Leetcode.2316 统计无向图中无法互相到达点对数
    php 安装rabbitmq:如何使用 PHP 安装 RabbitMQ?
    黄金价格查询易语言代码
    《统计学习方法》第五章决策树总结
  • 原文地址:https://blog.csdn.net/weixin_45004203/article/details/125536621