【转】IO多路复用之poll
原文: https://blog.51cto.com/lingdandan/1783952
____________________________________________
poll提供的功能与select类似,与select在本质上没有多大差别,管理多个描述符也是进行轮询,但poll比select的优点是,不限制所能监视的描述符的数目,但随着所监视描述符的数目的增加,性能也会下降
函数原型:
#include <poll.h>
int poll(struct pollfd *fds, nfds_t nfds, int timeout);
返回值:成功时,poll()返回结构体中revents域不为0的文件描述符个数;如果在超时前没有任何事件发生,返回0;失败返回-1
参数:
fds:结构体指针,该结构体结构如下:
struct pollfd{
int fd; //所感兴趣的文件描述符
short events; //用于指定等待的事件
short revents; //用于指定poll返回时,在该文件描述符上实际发生了的事件
};
每一个pollfd结构体制定了一个被监视文件描述符,可传递多个该结构体,指示poll监视多个文件描述符
nfds:要监视的描述符的个数
timeout:单位(微秒),timeout指定等待的毫秒数,无论I/O是否准备好,poll都会返回,指定为负数值表示无限超时,使poll()一直挂起直到一个指定事件发生;timeout为0指示poll调用立即返回并列出准备好I/O的文件描述符,但并不等待其它的事件,立即返回
events域中请求的任何事件都可能在revents域中返回。合法的事件如下:
POLLIN 有数据可读
POLLPRI 有紧迫数据可读
POLLOUT 写数据不会导致阻塞
POLLRDNORM 有普通数据可读。
POLLRDBAND 有优先数据可读。
POLLWRNORM 写普通数据不会导致阻塞。
POLLWRBAND 写优先数据不会导致阻塞。
POLLMSGSIGPOLL 消息可用。
此外,revents域中还可能返回下列事件:
POLLER 指定的文件描述符发生错误。
POLLHUP 指定的文件描述符挂起事件。
POLLNVAL 指定的文件描述符非法。
这些事件在events域中无意义,因为它们在合适的时候总是会从revents中返回。
POLLIN | POLLPRI等价于select()的读事件,POLLOUT |POLLWRBAND等价于select()的写事件。POLLIN等价于POLLRDNORM |POLLRDBAND,而POLLOUT则等价于POLLWRNORM。例如,要同时监视一个文件描述符是否可读和可写,我们可以设置 events为POLLIN |POLLOUT。在poll返回时,我们可以检查revents中的标志,对应于文件描述符请求的events结构体。如果POLLIN事件被设置,则文件描述符可以被读取而不阻塞。如果POLLOUT被设置,则文件描述符可以写入而不导致阻塞。这些标志并不是互斥的:它们可能被同时设置,表示这个文件描述符的读取和写入操作都会正常返回而不阻塞。
示例代码如下:
编写一个echo server程序,功能是客户端向服务器发送信息,服务器接收输出并原样发送回给客户端,客户端接收到输出到终端
server_poll.c
client_poll.c
运行结果:
服务器端运行结果:
客户端1运行结果:
客户端2运行结果:
最后还有一点,poll()会自动把revents域设置为0,不需要我们手动的去设置
测试程序如下:
以下程序片段只是在上面代码的基础上添加了几行代码,为看的更清楚,我用红色注释了这几行代码
运行出来的结果如下:
现在对上面运行结果进行分析,为简单起见,我们只关注四个结构体,所以以四行为单位
可看到第一次(前四行)的revents都为随机值
第二次(次四行)poll()函数把fd=3的描述符中revents设置为0
第四次poll()函数把fd=3的描述符中revents设置为1(因为此时监听到了客户端请求)所以接下来有:
get a connection...1.0.0.0:0 这条消息
第五次fd=3的revents还是为1,因为此时还没有执行poll(),fd=4的revents是随机值
第六次fd=3和fd=4的events都为1,它们都添加了读事件,而fd=3的revents被poll设置为了0,fd=4的revents为1(因为客户端发送了条消息,使读事件发生,因此有下面一条消息:)
client# hello
第七次和第六次的一致,因为还未被poll()设置
第八次和第七次的一致,但此时fd=4的revents=1是因为客户端按下了Ctrl+c,所以接下来会有:
client shutdown
第九次把fd=4从数组中去掉
《完》
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 25岁的心里话
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
2019-12-09 【转】An introduction to using and visualizing channels in Go
2019-12-09 【转】 Anatomy of Channels in Go - Concurrency in Go
2016-12-09 php composer 安装
2016-12-09 服务器主从切换
2016-12-09 php-redis 下载地址
2016-12-09 【转】RestQL:现代化的 API 开发方式
2015-12-09 Html 中表单提交的一些知识总结——防止表单自动提交,以及submit和button提交表单的区别