news 2026/10/22 7:36:22

Linux网络(三十二): 告别 select 位图焦虑:一文吃透 poll 多路转接的接口设计、结构体分离与 O(n) 性能瓶颈

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Linux网络(三十二): 告别 select 位图焦虑:一文吃透 poll 多路转接的接口设计、结构体分离与 O(n) 性能瓶颈

◆ 博主名称: 小此方-CSDN博客
大家好,欢迎来到小此方的博客。
⭐️网络系列个人专栏: 【主题曲】计算机网络
⭐️此方的GitHub: github_此方
⭐️我们思考 (Rethink) · 我们重建 (Rebuild) · 我们记录 (Record)

文章目录

  • 概要&序論
  • 一、从 select 的痛点走向 poll:接口设计、结构体与事件机制
    • 1.1 poll 的函数原型
    • 1.2 深入理解 struct pollfd 结构体
    • 1.3 常用的事件类型
    • 1.4 poll 是如何解决 select 的痛点的?
      • 1.4.1 问题一:输入输出参数分离,无需重复重置
      • 1.4.2 问题二:彻底打破数量上限
      • 1.4.3 实用小技巧:忽略某个 fd
    • 1.5 实战插曲:如何查看一个进程的文件描述符?
  • 二、poll 的优缺点分析与性能瓶颈
    • 2.1 poll 相比 select 的核心优势
    • 2.2 无法逃避的性能瓶颈:poll 的缺点
    • 2.3 总结与过渡:为什么需要 epoll?

概要&序論

Hello大家好,我是此方。上一篇我们讲解了Select,本文我们来讲解Poll,看看Poll在Select的基础上又有哪些优化。

一、从 select 的痛点走向 poll:接口设计、结构体与事件机制

在上一节中,我们深度剖析了 select 的机制。虽然它是 IO 多路复用的老大哥,但它的痛点也极其明显:每次调用都要手动重置 fd_set 集合,而且还受限于 fd_set 的位图大小,无法支撑海量并发。为了解决这些问题,poll横空出世了。

poll的作用和定位与select一致,它依然只负责等,一次可以等待多个 fd,事件就绪后,就可以对上层进行事件通知。但它在接口和底层数据结构的设计上,做了一次极其优雅的升级。

1.1 poll 的函数原型

我们来看看poll的函数原型:

#include<poll.h>intpoll(structpollfd*fds,nfds_tnfds,inttimeout);

这个接口比select清爽太多了,只有三个参数:

  1. fds是数组的起始地址。
  2. nfds是数组元素的个数。
  3. timeout直接以毫秒为单位。如果传入 0 表示非阻塞,传入 -1 表示阻塞等待。

1.2 深入理解 struct pollfd 结构体

poll抛弃了select那种反人类的位图(bitmap)操作,转而使用了一个结构体数组。我们来看看这个结构体:

structpollfd{intfd;/* file descriptor */shortevents;/* requested events */shortrevents;/* returned events */};

这个设计极其绝妙,把输入和输出完美分离了:

  • events是事件位图,代表用户告诉内核你要帮我关心fd上面的events事件。
  • revents也是事件位图,代表poll成功返回时,内核告诉用户,你让我关心的fd上面的事件,哪些已经就绪了!

调用的时候,fd和events有效;成功返回时,fd和revents有效。

1.3 常用的事件类型

在poll的世界里,事件类型非常丰富,但作为初学者,别的我们先不要管,我们就记住这两个核心事件就够了:

  1. POLLIN:数据(包括普通数据和优先数据)可读。
  2. POLLOUT:数据(包括普通数据和优先数据)可写。

那要怎么设置和检查呢?

  • 设置监听读事件:events |= POLLIN
  • 检查是否就绪:revents & POLLIN

1.4 poll 是如何解决 select 的痛点的?

对比select,poll到底帮我们解决了哪些恶心的问题?

1.4.1 问题一:输入输出参数分离,无需重复重置

poll的输入输出参数彻底分离了,所以你不用再在 poll 之前进行参数重置了!你只需要初始化一次events,如果下次还要复用这个数组,直接再次调用poll即可。revents每次会被内核重新覆盖,不会影响下一次的监听逻辑。

1.4.2 问题二:彻底打破数量上限

poll 等待的 fd 个数,没有上限!

为什么呢?因为上限问题与poll这个系统调用本身无关了。原本select是直接在内核里写死了fd_set大小,限制了上限。但是现在,poll的上限直接由用户自己决定,用户甚至可以直接 malloc 开辟出来的动态数组传递进去。你想监听一万个还是十万个 fd,只需要把数组开得足够大即可。

1.4.3 实用小技巧:忽略某个 fd

如果某天你不想关心数组中的某个 fd 了,但又不想去移动数组元素,有个非常简单的办法:把该结构体里的fd设置为-1。在内核中,如果遇到fd == -1,内核就不关心这类 fd 的 events。

1.5 实战插曲:如何查看一个进程的文件描述符?

在编写poll服务器的代码时,我们经常需要查看底层到底打开了哪些 fd。在 Linux 终端下,你可以通过进程号来直接查看:

# 假设你的进程号是 235849ls/proc/235849/fd-l

执行后,你能清晰地看到该进程打开的socket文件描述符、/dev/pts终端描述符等。这对于排查网络 IO 程序的资源泄漏有着极大的帮助。

既然poll已经解决了select的两大痛点,那它是不是就是完美的了?下一节,我们将把select改成poll服务器,并看看它依然存在的隐患。

我写了一个小Demo可供参考:Select,epoll,poll三大多路转接工具进行测试的demo代码

二、poll 的优缺点分析与性能瓶颈

我们在上一节中了解了poll的基本用法,也知道了它是为了解决select的痛点而诞生的。但在实际工程中,没有任何一种模型是完美的。我们来系统性地梳理一下poll的优势与它无法逃避的物理限制。

2.1 poll 相比 select 的核心优势

不同于 select 使用三个位图来表示三个 fdset 的方式,poll 使用一个pollfd指针实现。这带来了几个非常直观的好处:

  1. pollfd 结构包含了要监视的 event 和发生的 event,不再使用 select “参数-值”传递的方式。接口使用比 select 更方便。
  2. poll 并没有最大数量限制(但是数量过大后性能也是会下降)。

2.2 无法逃避的性能瓶颈:poll 的缺点

虽然poll摆脱了位图,也不用每次重置参数了,但当并发量真正上来的时候,它的致命缺陷就暴露了。

每次调用 poll 都需要把大量的pollfd结构从用户态拷贝到内核中。这算是一个特点,因为当你传的数据越多,这次搬运的成本就越高,这个开销是无法省去的。

更严重的是,poll 中监听的文件描述符数目增多时,它和 select 函数一样,poll 返回后,需要轮询pollfd来获取就绪的描述符。同时连接的大量客户端在一时刻可能只有很少的处于就绪状态,因此随着监视的描述符数量的增长,其效率也会线性下降。

这就是经典的O(n) 复杂度问题。假设你监听了 10 万个连接,但这一刻只有 1 个连接有数据到达,内核依然会遍历这 10 万个 fd,白白浪费 CPU 算力。

2.3 总结与过渡:为什么需要 epoll?

select和poll共同的硬伤在于:内核不保存你要监听的文件描述符集合,每次调用都要重新传入;而且内核是“盲找”的,每次都要遍历所有 fd 才能知道谁就绪了。

为了提升效率 —— 于是我们引入了epoll。它不仅能突破数据拷贝的瓶颈,还能做到只返回就绪的 fd,实现真正的 O(1) 事件通知!


好的本期内容就到这里,如果对你有帮助,还不要忘记点赞三联支持。我是此方,我们下期再见。bye!
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/22 7:35:13

特殊符号打不出来?小工具点一下即复制

软件介绍 公众号是图文类的自媒体&#xff0c;我平时写文章&#xff0c;经常会碰到要打带圈的数字、粗黑的圆点、箭头这类特殊符号的时候。为了方便&#xff0c;干脆就留了一款专门存特殊字符的软件在手边&#xff0c;也就是今天这款特殊字符输入器。 点一下就复制&#xff0c…

作者头像 李华
网站建设 2026/10/22 7:34:12

最新FinalShell下载安装 及使用教程(附安装包)

本文面向刚接触服务器的新手&#xff0c;介绍一款好用的国产 SSH 工具——FinalShell。它集 SSH 连接与文件传输于一体&#xff0c;操作简单、免费易用。接下来&#xff0c;我们将一步步带你完成下载、安装和连接服务器的全过程。 FinalShell&#xff1a;国产SSH工具&#xff…

作者头像 李华
网站建设 2026/10/22 7:34:11

DeepSeek 内部推理框架,开源了

DeepSeek 内部推理框架&#xff0c;开源了 这两个月大家的话题都在模型上。版本号、参数、榜单。 但有个东西比新模型更值得看一眼&#xff1a;DeepInfer。 它是 DeepSeek 大规模生产服务所依赖的高性能推理框架。这次开源的版本提供离线推理功能&#xff0c;同时带上了大规模服…

作者头像 李华
网站建设 2026/10/22 7:33:01

Agent开发薪资差距大揭秘:从15K到40K,能力断层如何跨越?

文章揭示了Agent开发岗位的薪资差距现象&#xff0c;指出能力断层是关键因素。文章将求职者分为三档&#xff1a;第一档&#xff08;15-20K&#xff09;能搭不能跑&#xff0c;主要依赖教程&#xff1b;第二档&#xff08;25-30K&#xff09;能跑能兜底&#xff0c;经历过线上事…

作者头像 李华
网站建设 2026/10/22 7:32:21

DeepSeek第一,MiniMax第二,国产Flash双子星杀疯了

国产Flash双子星&#xff0c;开始抢旗舰的饭碗 DeepSeek刚出牌&#xff0c;又一款王炸杀上来了&#xff01; 两天前&#xff0c;DeepSeek甩出V4.1 Flash-1017&#xff0c;把「许愿式编程」摆上台面。 才过一个周末&#xff0c;MiniMax就紧接着重磅出击&#xff0c;M3.1 Flas…

作者头像 李华