epoll實現理解

????????根據前文高性能網絡設計推演中,epoll作為一個“大殺器”為網絡開發提供強大的支持。Linux系統上IO多路復用方案有select、poll、epoll。其中epoll的性能表現最優,且支持的并發量最大。本文大概介紹epoll的底層實現。

一、示例引入

了解epoll開發,最基本的暴露給應用層用戶開發使用的有三個方法:

  • epoll_create:創建一個 epoll 對象

  • epoll_ctl:向 epoll 對象中添加要管理的連接

  • epoll_wait:等待其管理的連接上的 IO 事件

一個簡單的使用流程樣例如下:

int main(){listen(lfd, ...);
?cfd1 = accept(...);cfd2 = accept(...);efd = epoll_create(...);
?epoll_ctl(efd, EPOLL_CTL_ADD, cfd1, ...);epoll_ctl(efd, EPOLL_CTL_ADD, cfd2, ...);epoll_wait(efd, ...)
}

二、關鍵數據結構eventpoll

????????對于應用層epoll三個接口方法不再贅述,主要介紹一下eventpoll。其中eventpoll標識了一個epoll,對于一個進程可以管理多個連接fd,然后由epoll實現事件監聽,并返回響應。都是圍繞eventpoll所完成。以下為eventpoll源碼:

/** This structure is stored inside the "private_data" member of the file* structure and represents the main data structure for the eventpoll* interface.*/
struct eventpoll {/** This mutex is used to ensure that files are not removed* while epoll is using them. This is held during the event* collection loop, the file cleanup path, the epoll file exit* code and the ctl operations.*/struct mutex mtx;
?/* Wait queue used by sys_epoll_wait() */wait_queue_head_t wq;
?/* Wait queue used by file->poll() */wait_queue_head_t poll_wait;
?/* List of ready file descriptors */struct list_head rdllist;
?/* Lock which protects rdllist and ovflist */rwlock_t lock;
?/* RB tree root used to store monitored fd structs */struct rb_root_cached rbr;
?/** This is a single linked list that chains all the "struct epitem" that* happened while transferring ready events to userspace w/out* holding ->lock.*/struct epitem *ovflist;
?/* wakeup_source used when ep_scan_ready_list is running */struct wakeup_source *ws;
?/* The user that created the eventpoll descriptor */struct user_struct *user;
?struct file *file;
?/* used to optimize loop detection check */int visited;struct list_head visited_list_link;
?
#ifdef CONFIG_NET_RX_BUSY_POLL/* used to track busy poll napi_id */unsigned int napi_id;
#endif
};
?

對于eventpoll需關注三個關鍵變量:

1、struct rb_root_cached rbr;

2、struct list_head rdllist;

3、wait_queue_head_t wq;

????????通過源碼中注釋可以了解其中作用:rbr為紅黑樹,rdllist為就緒隊列,wq為等待隊列。這是三種數據結構,對應到epoll中的功能而言,rbr為一顆紅黑樹,他維護了對epoll需要監聽的事件集合。rdllist維護了就緒事件集合,當有事件就緒后就會掛到rdllist上通知應用層程序處理。wq為維護的實現epoll線程的阻塞狀態。因為epoll_wait執行時,如果沒有事件就緒,此時會讓出cpu從而阻塞該線程,此時就會將該線程掛到wq上,后續就緒事件來臨時就會重新運行該線程。

????????對于rdllist和wq都選用隊列的數據結構比較好理解,因為此時的場景就是一個處理任務的場景,符合隊列“先進先出”的特性。所以選用隊列。

????????而對于紅黑樹的選擇原因是綜合了各方面的最優解。其中對于查詢效率,在整個epoll的event中有很多查詢場景,所以維護整體事件集合的數據結構需要較高的查詢效率,但是對應查詢效率更好的還有hashmap。這里就需要綜合事件集合的修改以及內存開銷這兩個問題。對于紅黑樹不需要連續的內存空間進行存儲,而hashmap需要連續的空間,并且對于應用層數量不定的事件內存的開辟大小就是一個問題。如果過小,后續添加就需要重新開辟連續空間并拷貝,如果過大就會導致內存空間的浪費。而且對于事件集合的修改而言紅黑樹也要更加方便,并且無hash沖突問題。綜上紅黑樹是最優解。

三、具體流程

????????對于epoll的實現介紹,本文從應用層角度和內核態角度分別簡單介紹,即“三+一“。應用層三個接口實現和內核層一個關鍵接口實現。(此處并非內核層只有一個接口,而是個人認為十分關鍵的一個實現,從而能夠支持整體epoll的功能實現)

????????應用層角度:三個接口:epoll_create、epoll_ctl、epoll_wait

????????1、epoll_create:該接口關鍵功能為初始化eventpoll數據結構,具體為上文提到的rbr、rdllist等。然后返回一個epoll_fd。應用層后續可以通過該句柄實現對epoll的操作。

????????2、epoll_ctl:根據操作的不同(增加、刪除、修改)對epitem節點進行操作。epitem節點標識了一個監聽的句柄的某個事件。其中EPOLL_CTL_ADD為添加,最重要的是建立socket句柄與epoll的關聯,即注冊ep_poll_callback回調函數到sock->sk_wq。并將eptime掛到socket->wq->wait_queue_head上。后續當socket句柄可讀或者可寫時,會執行該回調函數以通知eventpoll,將該epitem掛到rdllist隊列,如果此時epoll線程是阻塞的話也會將該線程從wq中喚醒。

????????3、epoll_wait:該操作會遍歷rdllist就緒隊列,如果就緒隊列有就緒事件,則正常返回由應用層進行處理。否則會阻塞當前線程并將線程掛到eventpoll->wq上,然后讓出CPU使用進入阻塞態。

????????4、當數據來臨時,數據由網卡->網卡驅動->Linux內核協議棧(ip、tcp/udp等)調用sock_def_wakup喚醒該sock的wait_queue上的eptime,然后回調ep_poll_callback。由回調函數將epitme掛到eventpoll->rdllist,如果之前epoll_wait阻塞了當前線程,則一并喚醒當前線程。

????????5、ep_send_events實現從eventpoll->rdllist中取出就緒事件,并返回應用層event數組。后續由應用層處理就緒事件。

更多內容可參考:0voice · GitHub?

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/86512.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/86512.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/86512.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

協議轉換賦能光伏制造:DeviceNET轉PROFINET網關的通信質檢實踐

協議轉換賦能光伏制造:DeviceNET轉PROFINET網關的通信質檢實踐 某光伏電池片生產線創新性地將網關作為計算節點,通過搭載DeviceNET-PROFINET智能網關-穩聯技術WL-PN-DVNM,在協議轉換層直接運行AI質檢模型。DeviceNET端采集的高清圖像數據經網…

學習永無止境

已掌握以下每個,有屬于自己的一套架構方式: vue.element-ui:后臺管理 vue.uni-app:H5,小程序,Android,IOS php:??RESTful,服務,業務邏輯(如電商…

永磁無刷電機旋轉原理

目錄 1. 磁場的基本知識 2. 角速度,線速度,工程轉速 3.力和力矩 4. 慣量,轉動慣量 5. 電機的四種狀態 5.1 空載 5.2 帶載 5.3 滿載 5.4 堵轉 6. 功和功率 1. 磁場的基本知識 無頭無尾,轉了一圈,就叫有旋…

Ubuntu 物理桌面遠程訪問教程(基于 RealVNC / mstsc)

Ubuntu 物理桌面遠程訪問教程(基于 RealVNC / mstsc) 適用對象:任意安裝了 GNOME GDM 的 Ubuntu 系統 目標:遠程連接系統默認物理桌面 :0,無虛擬桌面、無 Xfce,真實 GNOME 桌面環境 1. 準備條件 Ubuntu 系…

Vue3 工程化實戰

Vue3 工程化實戰 引言:構建工具的演進與選擇 在前端工程化領域,構建工具的選擇直接影響開發效率與項目性能。隨著Vue3的普及,構建工具生態也發生了顯著變化:傳統vue-cli逐漸進入維護模式,而新一代構建工具Vite憑借其…

調用phantomjs(前端)插件生成ECharts圖片

package com.demo.common.utils; //json格式化工具,可以其他工具類 import cn.hutool.json.JSONUtil; import lombok.extern. public class FileUtil { /** * 調用phantomjs(前端)插件生成ECharts圖片 * @param path 根路徑 * @param option ECharts配置J…

React Hooks詳解

React Hooks 常考內容 React Hooks 是 React 16.8 引入的重要特性,用于在函數組件中使用狀態和其他 React 特性。以下是面試中常考的核心內容: 基礎 Hook useState: 用于管理組件內部狀態,返回狀態變量和更新狀態的函數。useEffect: 處理副…

c++17標準std::filesystem常用函數

std::filesystem 是 C17 引入的標準庫&#xff0c;用于處理文件系統操作&#xff0c;提供了跨平臺的文件和目錄操作能力。以下是一些常用的函數和類&#xff1a; 一、路徑操作&#xff08;std::filesystem::path&#xff09; cpp 運行 #include <filesystem> namespa…

非結構化文檔的自動化敏感標識方法技術解析

在數字化時代&#xff0c;企業與組織面臨的數據形態正發生深刻變革。據統計&#xff0c;非結構化數據占企業數據總量的 80% 以上&#xff0c;涵蓋文本、郵件、PDF、日志、社交媒體內容等多種形式。這些數據中往往蘊含著大量敏感信息&#xff0c;如個人身份信息、商業機密、醫療…

c語言中的字符類型

字符類型 char char是一種整數&#xff0c;也是一種特殊的類型&#xff1a;字符。 #include <stdio.h> int main(){char c,d;c 1; //把整數1賦值給變量cd 1; //把字符‘1’賦值給變量dif (c d){printf("相等");}else{printf("不相等\n");…

Cribl stream 管道對時間的改變時區

先說一下時區的重要性&#xff0c;要是cribl 時區是UTC&#xff0c;但是過來數據是GTM8 就是中國時區&#xff0c;那么數據過來&#xff0c;就可能在后端的Splunk 沒有顯示&#xff0c;那么解決這個問題&#xff0c;cribl 管道引入了auto timestamp 的功能&#xff1a; 注意到&…

深度學習:PyTorch卷積神經網絡(1)

本文目錄&#xff1a; 一、CNN概述二、CNN日常應用三、CNN的卷積層&#xff08;一 &#xff09;基本介紹&#xff08;二&#xff09;卷積層計算1.對輸入數據的要求2.卷積核核心參數3.計算過程4.特征圖尺寸計算5.1、多通道卷積計算5.2、多卷積核計算6.PyTorch卷積層API 前言&…

linux網絡編程socket套接字

套接字概念 Socket本身有“插座”的意思&#xff0c;在Linux環境下&#xff0c;用于表示進程間網絡通信的特殊文件類型。本質為內核借助緩沖區形成的偽文件。 既然是文件&#xff0c;那么理所當然的&#xff0c;我們可以使用文件描述符引用套接字。與管道類似的&#xff0c;L…

Python 數據分析與可視化 Day 5 - 數據可視化入門(Matplotlib Seaborn)

&#x1f3af; 今日目標 掌握 Matplotlib 的基本繪圖方法&#xff08;折線圖、柱狀圖、餅圖&#xff09;掌握 Seaborn 的高級繪圖方法&#xff08;分類圖、分布圖、箱線圖&#xff09;熟悉圖像美化&#xff08;標題、標簽、顏色、風格&#xff09;完成一組學生成績數據的可視化…

CephFS “Client Failing to Respond to Cache Pressure“ 告警分析

告警含義 當出現 Client failing to respond to cache pressure 警告時,表明: 元數據服務器 (MDS) 要求客戶端釋放緩存的元數據(如 inode Capabilities)客戶端未能及時響應 釋放請求核心觸發機制 MDS 通過以下周期性流程管理緩存 階段操作觸發條件Cache Trim 周期每隔 mds…

生成式人工智能實戰 | 生成對抗網絡(Generative Adversarial Network, GAN)

生成式人工智能實戰 | 生成對抗網絡 0. 前言1. 生成對抗網絡2. 模型構建2.1 生成器2.2 判別器 3. 模型訓練3.1 數據加載3.2 訓練流程 0. 前言 生成對抗網絡 (Generative Adversarial Networks, GAN) 是一種由兩個相互競爭的神經網絡組成的深度學習模型&#xff0c;它由一個生成…

緩存與加速技術實踐-MongoDB數據庫應用

一.什么是MongoDB MongoDB 是一個文檔型數據庫&#xff0c;數據以類似 JSON 的文檔形式存儲。 MongoDB 的設計理念是為了應對大數據量、高性能和靈活性需求。 MongoDB 使用集合&#xff08;Collections&#xff09;來組織文檔&#xff08;Documents&#xff09;&#xff0…

聲網對話式AI把“答疑機器人”變成“有思維的助教”

作為一家專注初高中學生的線上教育平臺&#xff0c;我們精心打磨的系統化課程收獲了不少認可&#xff0c;但課后無人答疑的難題卻始終橫亙在前。學生課后遇到疑惑&#xff0c;要么只能默默憋在心里&#xff0c;要么就得苦苦等待下一節課&#xff0c;家長們也頻繁抱怨 “花了錢&…

常見的排序方法

目錄 1. 插入排序 2. 希爾排序 3. 選擇排序 4. 堆排序 5. 冒泡排序 6. 快速排序 1. 快速排序的實現 1. 思路&#xff08;以從小到大排序為例&#xff09; 2. 選取基準元素的方法&#xff08;Hoare&#xff09; 3. 選取基準元素的方法&#xff08;挖坑法&#xff09; …

【matlab定位例程】基于AOA和TDOA混合的定位方法,背景為三維空間,自適應錨點數量,附下載鏈接

文章目錄 代碼概述代碼功能概述核心算法原理AOA定位模型TDOA定位迭代算法混合定位策略關鍵技術創新 運行結果4個錨點的情況40個錨點的情況 MATLAB源代碼 代碼概述 代碼功能概述 本代碼實現了一種三維空間中的混合定位算法&#xff0c;結合到達角&#xff08; A O A AOA AOA&a…