深入解析Linux poll()系统调用

🔄 Linux poll() 系统调用详解


一、poll 是干什么的?

poll 是 Linux(及 POSIX 标准)中用于实现 I/O 多路复用(I/O Multiplexing) 的系统调用,它的核心作用是:

让一个线程能够同时监视多个文件描述符(file descriptors),并等待其中任意一个变为“就绪”状态(可读、可写或出现异常),而无需阻塞在单个 I/O 操作上。

换句话说,poll 实现了“一个线程处理多个 I/O 事件”的能力,是构建并发网络程序的重要工具之一。

它本质上是 select 的改进版,解决了 select 的一些关键限制,同时为后续更高效的 epoll 奠定了基础。


二、为什么需要 poll?它解决了什么问题?

1. select 的局限性

  • 文件描述符数量限制select 最多只能监听 1024 个 fd(由 FD_SETSIZE 决定)。

  • 使用位图(bitmap)管理 fd 集合:操作繁琐,需用宏(FD_SET, FD_ISSET 等)。

  • 每次调用必须重置集合:性能开销大,且易出错。

  • 需传入最大 fd + 1:效率低,扫描范围可能很大。

2. poll 的解决方案

poll 在设计上直接针对 select 的缺陷进行优化:

优点

  • 无 fd 数量硬限制:使用动态数组,理论上只受系统资源限制。

  • 使用数组结构管理 fd:更直观、灵活。

  • 无需重置整个集合结构:只需复用 struct pollfd 数组。

  • 不依赖位图或最大 fd:避免无效扫描。

pollselectepoll 之间的重要过渡机制,兼具兼容性与扩展性。


三、poll 的函数原型

#include <poll.h>​int poll(struct pollfd *fds, nfds_t nfds, int timeout);

返回值:

  • 成功:返回就绪的文件描述符数量(> 0)

  • 超时:返回 0

  • 出错:返回 -1,并设置 errno


四、参数详解

参数类型说明
fdsstruct pollfd *指向 pollfd 结构体数组的指针,每个元素代表一个待监听的 fd。
nfdsnfds_t(通常是 unsigned long数组中元素的个数(即要监听的 fd 总数)。
timeoutint等待超时时间(毫秒)。决定 poll 是阻塞、非阻塞还是限时等待。

五、核心数据结构

1. struct pollfd —— 文件描述符事件结构

struct pollfd {int   fd;       // 要监听的文件描述符short events;   // 用户关心的事件类型(输入)short revents;  // 内核返回的就绪事件(输出)};
常见事件类型(eventsrevents):
事件说明
POLLIN数据可读(包括普通数据和优先级数据)
POLLRDNORM普通数据可读(通常与 POLLIN 等价)
POLLRDBAND优先级数据可读(带外数据 OOB)
POLLOUT数据可写
POLLWRNORM普通数据可写(通常与 POLLOUT 等价)
POLLERR错误发生(自动检测,无需设置 events
POLLHUP对端挂起或关闭连接(hang up)
POLLNVAL文件描述符无效(未打开)

⚠️ 注意:

  • events:由用户设置,表示关心哪些事件

  • revents:由内核填充,表示实际发生的事件

  • 即使未在 events 中设置 POLLERRPOLLHUP,只要发生,revents 中也会包含。


2. timeout 参数的三种用法

情况设置方式行为
永久阻塞timeout = -1一直等待,直到有 fd 就绪
非阻塞timeout = 0立即返回,用于轮询
限时等待timeout = 5000最多等待 5000 毫秒(5 秒)

六、poll 的工作流程(典型用法)

 #include <poll.h>#include <unistd.h>#include <stdio.h>​#define MAX_FDS 10​struct pollfd fds[MAX_FDS];int nfds = 0; // 当前监听的 fd 数量​// 假设已有 listen_fd 和一些 conn_fd​// 1. 初始化:将监听 socket 加入fds[nfds].fd = listen_fd;fds[nfds].events = POLLIN;nfds++;​// 主循环while (1) {// 2. 调用 pollint ready = poll(fds, nfds, 5000); // 等待 5 秒​if (ready == -1) {perror("poll");break;} else if (ready == 0) {printf("Timeout: no fd ready\n");continue;}​// 3. 遍历所有注册的 fd,检查 reventsfor (int i = 0; i < nfds; i++) {if (fds[i].revents & POLLIN) {if (fds[i].fd == listen_fd) {// 新连接到达int conn_fd = accept(listen_fd, NULL, NULL);// 将新连接加入 poll 数组fds[nfds].fd = conn_fd;fds[nfds].events = POLLIN;nfds++;} else {// 已连接 socket 有数据可读char buffer[1024];int n = read(fds[i].fd, buffer, sizeof(buffer));if (n > 0) {write(fds[i].fd, buffer, n); // echo} else {// 客户端关闭或出错close(fds[i].fd);// 从数组中移除(可前移覆盖)fds[i] = fds[--nfds];i--; // 重新检查当前位置}}}​if (fds[i].revents & POLLHUP) {printf("FD %d hung up\n", fds[i].fd);close(fds[i].fd);fds[i] = fds[--nfds];i--;}​if (fds[i].revents & POLLERR) {fprintf(stderr, "Error on FD %d\n", fds[i].fd);close(fds[i].fd);fds[i] = fds[--nfds];i--;}}}

🔁 关键点

  • poll 不会修改 events,但会修改 revents

  • 每次调用后需检查 revents 判断事件类型。

  • 删除 fd 时需手动维护数组(如前移覆盖)。


七、poll 解决的核心问题

问题poll 如何解决
select 的 1024 fd 限制使用数组,无硬编码限制
select 的位图操作繁琐使用结构体数组,语义清晰
select 需传最大 fdpoll 直接传数组长度,无需扫描无效范围
跨平台兼容性POSIX 标准,支持 Linux、BSD、macOS 等

八、poll 的缺点(局限性)

缺点说明
1. 时间复杂度仍为 O(n)每次调用需遍历所有注册的 fd,即使只有一个就绪
2. 用户态/内核态拷贝开销每次调用都要复制整个 pollfd 数组到内核
3. 无边缘触发(ET)模式只支持水平触发(LT),可能重复通知
4. 需手动管理 fd 数组添加/删除 fd 需维护数组,逻辑复杂
5. 不支持就绪事件批量返回优化不像 epoll 有就绪链表机制

九、现代替代方案

机制优势
epoll() (Linux)O(1) 通知、支持 ET、高性能,Linux 首选
kqueue() (BSD/macOS)类似 epoll,功能强大,支持过滤器机制
io_uring (Linux 5.1+)异步 I/O + 多路复用一体化,下一代标准

✅ 推荐:

  • Linux 高并发:使用 epoll

  • 跨平台中等并发:使用 poll

  • 学习过渡:poll 是理解 epoll 的良好跳板


十、总结:poll 的定位

项目内容
本质POSIX I/O 多路复用系统调用
目的单线程监听多个 fd 的 I/O 事件
核心函数poll() + struct pollfd
核心结构pollfd 数组
触发模式仅支持水平触发(LT)
适用场景中等并发、跨平台兼容、学习 I/O 复用进阶
不适用场景超高并发(>1万连接)、极致性能要求
学习价值理解从 selectepoll 的演进路径

📌 一句话总结pollselect 的现代化替代,它通过数组结构摆脱了 fd 数量限制,提升了灵活性和可移植性,虽然性能仍不及 epoll,但它是构建跨平台高并发网络程序的重要工具,也是理解现代 I/O 复用机制的关键一环

🔥 进阶建议

  • 对比 pollepoll 的系统调用开销

  • 实现一个基于 poll 的简单 HTTP 服务器

  • 理解 polllibeventRedis 等项目中的使用

掌握 poll,你就掌握了从传统 I/O 模型迈向高性能网络编程的中间桥梁

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/news/918695.shtml
繁体地址,请注明出处:http://hk.pswp.cn/news/918695.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

文献阅读 | PLoS ONE | SRplot:一个免费的在线平台,用于数据可视化和图形

文献介绍文献题目&#xff1a; SRplot&#xff1a;一个免费的在线平台&#xff0c;用于数据可视化和图形 研究团队&#xff1a; Yewei Wang&#xff08;中南大学湘雅二医院&#xff09; 发表时间&#xff1a; 2023-11-09 发表期刊&#xff1a; PLoS ONE 影响因子&#xff1a; 3…

分布式与微服务宝典

分布式理论基础 1、分布式架构有哪些特点&#xff0c;优势和缺陷 特点&#xff1a;微服务架构的优点微服务架构的缺陷自由使用不同技术增加故障排除挑战每一个微服务都侧重于单一功能由于远程调用增加延迟支持单个可部署单元增加了配置与其他操作的工作量允许经常发布软件难以保…

利用生成式AI与大语言模型(LLM)革新自动化软件测试 —— 测试工程师必读深度解析

引言 自动化测试是现代软件工程的基石&#xff0c;然而&#xff0c;随着软件复杂度和迭代速度的飞速提升&#xff0c;传统自动化测试方法正面临越来越多的挑战。 近年来&#xff0c;生成式人工智能&#xff08;Generative AI&#xff09;和大语言模型&#xff08;LLM&#xff0…

JS 与 C++ 双向通信实战:基于 WebHostViewListener 的消息处理机制

前言在现代浏览器和桌面应用开发中&#xff0c;WebView 嵌入已经成为一种非常常见的 UI 技术方案。无论是基于 Chromium 的 CEF&#xff08;Chromium Embedded Framework&#xff09;、Qt WebEngine&#xff0c;还是自研浏览器内核&#xff0c;嵌入 WebView 都能带来极高的灵活…

模板打印技术——Office XLS 打印模板:为政务土地确权定制的纸张替换利器—仙盟创梦IDE

代码public static int cyberwin_replaceExcelandoutputPrint(string fisrcpathleurl, DataTable dtInfo, string despath){if (File.Exists(despath) true){//删除目标文件File.Delete(despath);}File.Copy(fisrcpathleurl, despath);string 目标文件 despath;MSEXCEL.Appli…

可直接运行的 Playwright C# 自动化模板

目录 目录结构 1. appsettings.json&#xff08;账号、URL、路径配置&#xff09; 2. Program.cs&#xff08;启动入口&#xff09; 3. SchedulerConfig.cs&#xff08;定时调度&#xff09; 4. SocialSecurityTask.cs&#xff08;自动报社保任务&#xff09; 5. QuerySo…

云平台监控-云原生环境Prometheus企业级监控实战

目录 一、基于 Kubernetes 的 Prometheus 监控方案概述 1. 核心组件及功能 2. 监控流程详解 3. 关键监控指标说明 二、Prometheus 与相关组件部署 1. 克隆项目代码 2. 安装 Prometheus Operator 3. 安装 Prometheus Stack 4. 查看容器运行状态 三、ServiceMonitor 配…

GPT-5 有点不太顺

GPT-5 有点不太顺 OpenAI 的新模型 GPT-5 盼了很久,结果一上线就问题不少。 发布会刚过,CEO 山姆・奥特曼就说,要给部分用户恢复 GPT-4o 这些老模型的使用权限,还承认 GPT-5 上线 “比预想的坎坷”。 简单题都做错了 不少用户发现,GPT-5 连一些简单问题都答不对,比之前…

《卷积神经网络(CNN):解锁视觉与多模态任务的深度学习核心》

1.概述卷积神经网络&#xff08;CNN&#xff09;是深度学习在计算机视觉领域的重要突破&#xff0c;专为处理网格状数据&#xff08;如图像&#xff09;设计&#xff0c;后也扩展到自然语言处理等领域。它解决了全连接网络处理大图像时计算代价高、特征保留差的问题&#xff0c…

React Native + Expo搭建APP项目+安卓模拟器

Expo 尝试一下就好&#xff0c;毕竟参考代码太少&#xff0c;相当于闭关造轮子&#xff0c;不建议。 一、需要的工具 1. node.js&#xff0c;推荐使用&#xff08;TLS版本&#xff09;&#xff0c;版本不是太低就行&#xff0c;测试用的v20.12.2的Node 2. 开发工具 VS CODE或…

第六十五章:AI的“精良食材”:图像标注、视频帧抽帧与字幕提取技巧

ai 数据处理前言&#xff1a;从“原始食材”到“AI盛宴”第一章&#xff1a;图像标注&#xff1a;为AI“指点江山”1.1 什么是图像标注&#xff1f;—— AI的“视觉标签”1.2 分类任务&#xff1a;图像的“身份识别”1.3 目标检测&#xff1a;图像的“区域识别”与“边界框”1.…

2025 开源语音合成模型全景解析:从工业级性能到创新架构的技术图谱

一、引言&#xff1a;开源浪潮下的语音合成技术跃迁 语音合成&#xff08;TTS&#xff09;作为人工智能领域的核心技术&#xff0c;近年来在开源社区的推动下取得了突破性进展。从早期的基于规则的拼接合成&#xff0c;到深度学习驱动的端到端模型&#xff0c;再到当前与大语言…

前端懒加载技术全面解析

懒加载(Lazy Loading)是一种优化前端性能的重要技术,核心思想是延迟加载非关键资源,只在需要时加载它们。 一、懒加载的基本原理 懒加载的核心思想是通过以下方式优化性能: 减少初始加载实践: 只加载首屏所需资源 节省带宽和内存: 避免加载用户可能不会查看的内容 提高…

B3DM,OSGB,PLY,OBJ,S3MB,I3S这几种格式有什么区别

B3DM、OSGB、PLY、OBJ、S3MB、I3S 都是三维模型/地理空间数据的文件格式&#xff0c;但它们的用途、结构和适用场景差别很大。1. B3DM&#xff08;Batched 3D Model&#xff09;来源/用途&#xff1a;属于 Cesium 3D Tiles 规范&#xff0c;用于在 Cesium、Mapbox 这种 WebGIS …

Matlab(4)

一、Basic plotting1.plot&#xff08;&#xff09;plot(x,y) &#xff1a;x图片中点的横坐标&#xff0c;y图片中点的纵坐标plot(y) &#xff1a;y图片中点的纵坐标&#xff0c;x图片中点的横坐标默认为1&#xff0c;2&#xff0c;3&#xff0c;4&#xff0c;5........plot(co…

Pycharm选好的env有包,但是IDE环境显示无包

一、异常现象 Pycharm选好的env&#xff08;yolov7&#xff09;&#xff1a; 有Numpy这个包&#xff1a; IDE环境愣是报没有&#xff1a; 二、尝试解决 2.1 重新启动pycharm 重新打开.py文件&#xff1a; 还是不行&#xff1a; 看看好使的windows上的pycharm参数&#xff1a…

深入理解 Linux 下的 GDB 调试工具

引言 在软件开发中&#xff0c;调试是一个不可避免且至关重要的环节。无论是简单的逻辑错误&#xff0c;还是复杂的内存泄漏问题&#xff0c;调试工具都能帮助我们快速定位并修复问题。而在 Linux 系统中&#xff0c;GDB&#xff08;GNU 调试器&#xff09;是最强大、最常用的…

让齿轮与斑马线共舞:汽车文化驿站及安全教育基地的展陈实践

当汽车文化驿站及安全教育基地的展陈项目图纸在绘图仪上初现轮廓时&#xff0c;我们就明确了一个核心命题&#xff1a;如何让 “速度与激情” 的汽车文化&#xff0c;与 “规则与敬畏” 的安全教育在同一空间里和谐共生&#xff0c;而非简单拼接。这不是两个独立展区的物理叠加…

Flask + Vue.js 物联网数字大屏实现方案

我将为您创建一个精美的物联网数字大屏,使用Flask作为后端提供数据,Vue.js作为前端展示,全部集成在单个HTML文件中实现。 设计思路 整体布局: 深色主题背景提高数据可视性 顶部标题栏显示系统名称和时间 中央区域分为多个数据卡片 底部显示系统状态信息 核心功能: 实…

Excel怎么筛选重复项?【图文详解】查找/删除重复项?查找重复项公式?如何去重?

一、问题背景 在使用 Excel 整理数据时&#xff0c;我们经常会遇到重复内容。这些重复项不仅会让表格显得杂乱&#xff0c;还可能影响数据统计的准确性。比如学生成绩表中重复的分数、员工信息表中重复的姓名等&#xff0c;都需要及时筛选出来处理。其实&#xff0c;筛选重复项…