网络编程实战
盛延敏
前大众点评云平台首席架构师
44207 人已学习
新⼈⾸单¥59
登录后,你可以任选4讲全文学习
课程目录
已完结/共 40 讲
网络编程实战
15
15
1.0x
00:00/00:00
登录|注册

21 | poll:另一种I/O多路复用

timeout
nfds
fds
POLLNVAL
POLLHUP
POLLERR
POLLWRBAND
POLLWRNORM
POLLOUT
POLLRDBAND
POLLRDNORM
POLLPRI
POLLIN
返回值
参数
错误事件
可写事件
可读事件
revents
events
fd
改进连接描述字加入event_set
改进event_set数组大小
编写基于poll的服务器程序
poll的能力
客户端2
客户端1
处理已连接套接字的可读事件
处理连接建立事件
事件检测
初始化pollfd数组
poll函数原型
事件类型
pollfd结构
思考题
总结
实验
基于poll的服务器程序
poll函数介绍

该思维导图由 AI 生成,仅供参考

你好,我是盛延敏,这是网络编程实战第 21 讲,欢迎回来。
上一讲我们讲到了 I/O 多路复用技术,并以 select 为核心,展示了 I/O 多路复用技术的能力。select 方法是多个 UNIX 平台支持的非常常见的 I/O 多路复用技术,它通过描述符集合来表示检测的 I/O 对象,通过三个不同的描述符集合来描述 I/O 事件 :可读、可写和异常。但是 select 有一个缺点,那就是所支持的文件描述符的个数是有限的。在 Linux 系统中,select 的默认最大值为 1024。
那么有没有别的 I/O 多路复用技术可以突破文件描述符个数限制呢?当然有,这就是 poll 函数。这一讲,我们就来学习一下另一种 I/O 多路复用的技术:poll。

poll 函数介绍

poll 是除了 select 之外,另一种普遍使用的 I/O 多路复用技术,和 select 相比,它和内核交互的数据结构有所变化,另外,也突破了文件描述符的个数限制。
下面是 poll 函数的原型:
int poll(struct pollfd *fds, unsigned long nfds, int timeout);
   
返回值:若有就绪描述符则为其数目,若超时则为0,若出错则为-1
这个函数里面输入了三个参数,第一个参数是一个 pollfd 的数组。其中 pollfd 的结构如下:
struct pollfd {
int fd; /* file descriptor */
short events; /* events to look for */
short revents; /* events returned */
};
这个结构体由三个部分组成,首先是描述符 fd,然后是描述符上待检测的事件类型 events,注意这里的 events 可以表示多个不同的事件,具体的实现可以通过使用二进制掩码位操作来完成,例如,POLLIN 和 POLLOUT 可以表示读和写事件。
确认放弃笔记?
放弃后所记笔记将不保留。
新功能上线,你的历史笔记已初始化为私密笔记,是否一键批量公开?
批量公开的笔记不会为你同步至部落
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
  • 深入了解
  • 翻译
    • 英语
    • 中文简体
    • 中文繁体
    • 法语
    • 德语
    • 日语
    • 韩语
    • 俄语
    • 西班牙语
    • 阿拉伯语
  • 解释
  • 总结

基于poll的I/O多路复用技术是本文的重点。文章首先介绍了poll函数相对于select函数的优势,它通过描述符集合来表示检测的I/O对象,突破了文件描述符个数的限制。与select不同,poll函数的结果保留在revents字段中,避免了每次检测都需要重置待检测的描述字和感兴趣的事件。此外,文章还详细介绍了poll函数的返回值和参数timeout的含义,以及对比了poll函数和select函数的不同之处。通过编写基于poll的服务器程序,读者可以深入了解poll的用法和其在高并发场景下的优势。 在实验部分,作者通过telnet客户端连接到服务器程序,展示了基于poll的服务器程序的I/O复用能力。多个客户端输入的字符互不影响,且一个客户端断开连接不会影响其他客户端。最后,文章提出了两个思考题,引导读者深入思考和交流。 总的来说,本文通过介绍poll函数及其在服务器程序中的应用,展示了其在高并发场景下的优势和灵活性。读者可以通过本文快速了解poll技术特点,并在实际应用中加以思考和探索。

仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《网络编程实战》
新⼈⾸单¥59
立即购买
登录 后留言

全部留言(31)

  • 最新
  • 精选
  • 夏目
    老师,我还是没明白poll和select的本质区别是什么,能否指点一下

    作者回复: 两者只是编程接口的区别,从内核实现角度来讲,其实本质实现是差不多的,poll客服了select有限文件描述字的缺陷,适用的范围更广一些。

    2019-11-15
    5
    27
  • 徐凯
    1.采用动态分配数组的方式 2.如果内存不够 进行realloc 或者申请一块更大的内存 然后把源数组拷贝过来

    作者回复: 鼓励动手来一个。

    2019-09-25
    20
  • 阿卡牛
    还有种信号驱动型I/O,老师可以讲解吗

    作者回复: 让内核在描述符就绪时发送SIGIO信号通知我们,这种模型为信号驱动式I/O(signal-driven I/O),说实话,这个模型在实战中用的是比较少的,作为一个知识点知道就可以了。

    2019-10-24
    12
  • Hale
    能讲讲为什么不用POLLIN来判断套接字可读?

    作者回复: POLLIN包括了OOB等带外数据的检测,POLLRDNORM则不包括这部分。 #define POLLIN 0x0001 /* any readable data available */ #define POLLRDNORM 0x0040 /* non-OOB/URG data available */

    2019-09-26
    4
    10
  • D
    老师可否简单讲下底层实现,比如底层是数组,队列,红黑树等。

    作者回复: 好问题,我收集一下素材。

    2019-09-25
    3
    9
  • fedwing
    老师,请教个问题,我看ready_number在29行的if里如果有会--,后面read for循环里,如果处理也--,我是不是可以这样理解,events_set[0]表示listen的套接字,这个套接字里如果有pollin,那么肯定是新连接(而不是普通套接字的读数据),所以这时就是获取对应的连接的文件描述符,将其加入到event_set数组里,用于后续poll的时候,多检测一个文件描述符,如果ready_number在前面的处理--后,还大于0,则表示events_set里其他的文件描述符也有待检测的事件触发,这些就是常规的双端连接对应的套接字,它们pollin的话,就是我们常规意义里的read数据了。

    作者回复: 是的。

    2020-08-12
    2
    5
  • Geek_68d3d2
    老师我看网络编程里面使用了各种函数,函数里面各种参数,您那里有没有什么文档参考手册啥的可供我们需要时翻阅,光靠脑子记,记不来啊。您平常都是怎么写代码啊,这些函数都是背下来了吗。

    作者回复: Linux下"man xxx",windows下看MSDN,当然,有一些常见的是要记下来的。

    2019-12-11
    5
  • Simple life
    我搞不懂,accept后的fd要加入event_set,然后再遍历取出,直接拿来读写不行吗?

    作者回复: 因为我们在同时处理多个I/O,一旦一个fd经过accept处理后加入event_set,之后就可以通过一个poll调用来获取多个不同的fd来加以处理。这是event_set的意义。

    2020-07-31
    3
    3
  • Tesla
    老师 poll不改变传入检测的event的状态,而是返回revent,是出于什么目的呢?

    作者回复: 这个设计很合理,一个是输入参数,一个是输出参数,只不多在同一个结构体内。如果只有一个参数,既是输入,也是输出,反到有点奇怪。

    2020-03-05
    2
  • 传说中的成大大
    我还是不太明白select和poll进行事件注册的区别,希望老师再给我指点指点

    作者回复: 区别是编程的接口不一样,原理基本一致,但是select一般来说有文件句柄的现在,poll则没有。我觉得你可以看代码体会一下。

    2019-09-30
    2
收起评论
显示
设置
留言
31
收藏
沉浸
阅读
分享
手机端
快捷键
回顶部