21 | poll:另一种I/O多路复用
21 | poll:另一种I/O多路复用
讲述:冯永吉
时长11:15大小10.30M
poll 函数介绍
基于 poll 的服务器程序
实验
总结
思考题
赞 12
提建议
精选留言(30)
- 夏目2019-11-15老师,我还是没明白poll和select的本质区别是什么,能否指点一下
作者回复: 两者只是编程接口的区别,从内核实现角度来讲,其实本质实现是差不多的,poll客服了select有限文件描述字的缺陷,适用的范围更广一些。
共 5 条评论26 - 徐凯2019-09-251.采用动态分配数组的方式 2.如果内存不够 进行realloc 或者申请一块更大的内存 然后把源数组拷贝过来
作者回复: 鼓励动手来一个。
20 - 阿卡牛2019-10-24还有种信号驱动型I/O,老师可以讲解吗
作者回复: 让内核在描述符就绪时发送SIGIO信号通知我们,这种模型为信号驱动式I/O(signal-driven I/O),说实话,这个模型在实战中用的是比较少的,作为一个知识点知道就可以了。
11 - Hale2019-09-26能讲讲为什么不用POLLIN来判断套接字可读?
作者回复: POLLIN包括了OOB等带外数据的检测,POLLRDNORM则不包括这部分。 #define POLLIN 0x0001 /* any readable data available */ #define POLLRDNORM 0x0040 /* non-OOB/URG data available */
共 4 条评论9 - D2019-09-25老师可否简单讲下底层实现,比如底层是数组,队列,红黑树等。
作者回复: 好问题,我收集一下素材。
共 3 条评论9 - fedwing2020-08-12老师,请教个问题,我看ready_number在29行的if里如果有会--,后面read for循环里,如果处理也--,我是不是可以这样理解,events_set[0]表示listen的套接字,这个套接字里如果有pollin,那么肯定是新连接(而不是普通套接字的读数据),所以这时就是获取对应的连接的文件描述符,将其加入到event_set数组里,用于后续poll的时候,多检测一个文件描述符,如果ready_number在前面的处理--后,还大于0,则表示events_set里其他的文件描述符也有待检测的事件触发,这些就是常规的双端连接对应的套接字,它们pollin的话,就是我们常规意义里的read数据了。展开
作者回复: 是的。
共 2 条评论5 - Geek_68d3d22019-12-11老师我看网络编程里面使用了各种函数,函数里面各种参数,您那里有没有什么文档参考手册啥的可供我们需要时翻阅,光靠脑子记,记不来啊。您平常都是怎么写代码啊,这些函数都是背下来了吗。
作者回复: Linux下"man xxx",windows下看MSDN,当然,有一些常见的是要记下来的。
5 - Simple life2020-07-31我搞不懂,accept后的fd要加入event_set,然后再遍历取出,直接拿来读写不行吗?
作者回复: 因为我们在同时处理多个I/O,一旦一个fd经过accept处理后加入event_set,之后就可以通过一个poll调用来获取多个不同的fd来加以处理。这是event_set的意义。
共 3 条评论3 - Tesla2020-03-05老师 poll不改变传入检测的event的状态,而是返回revent,是出于什么目的呢?
作者回复: 这个设计很合理,一个是输入参数,一个是输出参数,只不多在同一个结构体内。如果只有一个参数,既是输入,也是输出,反到有点奇怪。
2 - 传说中的成大大2019-09-30第一问: 我觉得需要改进的原因在于他是一个固定死了的值,而很多时候我们都要考虑到扩容的问题,所以可以把所有的描述符push_back到一个vector等类似的容器当中,直接对容器取size就可以获得数量 第二问:把新连接上来的connfd添加进去,对上面问题的容器进行一次取size操作就行了 通过前面两个问题 我产生了第三个问题 我们都知道select 每次循环都需要向内核重新注册一次需要关心的描述符, 在Poll当中他是怎么处理的呢?也是每次都要注册一次吗?新增了描述放到集合当中肯定也需要通知内核啊 !展开
作者回复: poll也是每次向内核注册了一个描述符集合,做法没有区别。你看到的这段代码,就是新增的描述符 //找到一个可以记录该连接套接字的位置 for (i = 1; i < INIT_SIZE; i++) { if (event_set[i].fd < 0) { event_set[i].fd = connected_fd; event_set[i].events = POLLRDNORM; break; } }
2 - LDxy2019-09-25为什么程序里使用POLLRDNORM而不是POLLIN呢?这两者又何不同?
作者回复: #define POLLRDNORM 0x0040 /* non-OOB/URG data available */ #define POLLIN 0x0001 /* any readable data available */
2 - 郑祖煌2020-07-031)第一道,可以用vector存储所有的连接描述符,然后当需要调用poll的时候,再用vector.size获取数组的大小,然后再创建出fd_set tmp[vector.size]存储所有需要的fd,将他传入到poll函数中。1
- panda2020-02-04老师,什么情况下会使套接字数目多余select数目呢,我所理解的是一般服务端对一个套接字就会开一个线程,客户端一个进程也不会创建出很多套接字,感觉都不会导致数量过多的情况,求指点
作者回复: 是这样的,当你写一个服务端程序,需要监听超过1024个客户端连接时,就会超过这个限制。客户端是没有问题的。
1 - JJj2020-01-16请问下,如果select同时关注可读、可写、异常。那是不是最多支持关注3*1024个IO事件
作者回复: 你这样理解倒也是可以的。一个描述字可以对应三种不同的事件。
1 - 传说中的成大大2019-09-30我还是不太明白select和poll进行事件注册的区别,希望老师再给我指点指点
作者回复: 区别是编程的接口不一样,原理基本一致,但是select一般来说有文件句柄的现在,poll则没有。我觉得你可以看代码体会一下。
1 - Jimmy Xiong2019-09-28请问老师,例子的全代码(可以直接运行起来)哪里可以找得到?
作者回复: https://github.com/froghui/yolanda
1 - pippin2022-03-03套接字和文件描述符有什么区别
作者回复: 在Linux系统里,所有都是文件,所以套接字也是文件描述符。当然,文件描述符,也可以有别的,比如说文件、目录等。
- 菜鸡互啄2021-12-09老师 28行不是太明白 如果listen_fd有可读事件 为什么说明有连接要accept了?
作者回复: 因为listen_fd是监听套接字。
1 - 你已经长大了,别皮2021-11-28老师服务器程序在49-68处理连接事件时,此时如果有新连接来,ready_number是否会++,这样是否会死循环?还是内核会存储起来,等待下一次poll时再往上报?
作者回复: 等待下一次poll。
- huadanian2021-11-21请问一下老师,上面代码第53行用于判断的revents的值,在第54行的read之后,是否需要清除掉,否则之后的循环会不会重复判断这个revents的值??
作者回复: 不需要。每次poll之后,revents的值都是全新从内核拷贝到用户空间的。但是如果这个连接已经close了,需要把对应的fd置为-1。