深入解析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
英文地址,請注明出處:http://en.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;篩選重復項…