在线观看www成人影院-在线观看www日本免费网站-在线观看www视频-在线观看操-欧美18在线-欧美1级

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

一文詳解epoll的實現原理

xCb1_yikoulinux ? 來源:一口Linux ? 作者:一口Linux ? 2022-08-01 13:28 ? 次閱讀

前言

本文以四個方面介紹epoll的實現原理,1.epoll的數據結構;2.協議棧如何與epoll通信;3.epoll線程安全如何加鎖;4.ET與LT的實現。

epoll的數據結構

多種數據結構進行決策

epoll至少需要兩個集合

  1. 所有fd的總集

  2. 就緒fd的集合

那么這個總集選用什么數據結構存儲呢?我們知道,一個fd,其底層對應一個TCB。那么也就是說key=fd,val=TCB,是一個典型的kv型數據結構,對于kv型數據結構我們可以使用以下三種進行存儲。

1. hash2. 紅黑樹3. b/b+tree

如果使用hash進行存儲,其優點是查詢速度很快,O(1)。但是在我們調用epoll_create()的時候,hash底層的數組創建多大合適呢?如果我們有百萬的fd,那么這個數組越大越好,如果我們僅僅十幾個fd需要管理,在創建數組的時候,太大的空間就很浪費。而這個fd我們又不能預先知道有多少,所以hash是不合適的。

b/b+tree是多叉樹,一個結點可以存多個key,主要是用于降低層高,用于磁盤索引的,所以在我們這個內存場景下也是不適合的。

在內存索引的場景下我們一般使用紅黑樹來作為首選的數據結構,首先紅黑樹的查找速度很快,O(log(N))。其次在調用epoll_create()的時候,只需要創建一個紅黑樹樹根即可,無需浪費額外的空間。

那么就緒集合用什么數據結構呢,首先就緒集合不是以查找為主的,就緒集合的作用是將里面的元素拷貝給用戶進行處理,所以集合里的元素沒有優先級,那么就可以采用線性的數據結構,使用隊列來存儲,先進先出,先就緒的先處理。

  1. 所有fd的總集 -----> 紅黑樹

  2. 就緒fd的集合 -----> 隊列

紅黑樹和就緒隊列的關系

紅黑樹的結點和就緒隊列的結點的同一個節點,所謂的加入就緒隊列,就是將結點的前后指針聯系到一起。所以就緒了不是將紅黑樹結點delete掉然后加入隊列。他們是同一個結點,不需要delete。

2f225f1a-1153-11ed-ba43-dac502259ad0.jpg

2f59eea8-1153-11ed-ba43-dac502259ad0.png

協議棧如何與epoll模塊通信

epoll的工作環境

應用程序只能通過三個api接口來操作epoll。當一個io準備就緒的時候,epoll是怎么知道io準備就緒了呢?是由協議棧將數據解析出來觸發回調通知epoll的。也就是說可以把epoll的工作環境看出三部分,左邊應用程序的api,中間的epoll,右邊是協議棧的回調(協議棧當然不能直接操作epoll,中間的vfs在此不是重點,就直接省略vfs這一層了)。

2f766b8c-1153-11ed-ba43-dac502259ad0.png

協議棧觸發回調通知epoll的時機

socket有兩類,一類是監聽listenfd,一類是客戶端clientfd。對于sockfd而言,我們一般比較關注EPOLLIN和EPOLLOUT這兩個事件,所以如果是listenfd,我們通常的做法就是accept。對于clientfd來說,如果可讀我們就recv,如果可寫我們就send。

協議棧將數據解析出來觸發回調通知epoll。epoll是怎么知道哪個io就緒了呢?我們從ip頭可以解析出源ip,目的ip和協議,從tcp頭可以解析出源端口和目的端口,此時五元組就湊齊了。socket fd --- < 源IP地址 , 源端口 , 目的IP地址 , 目的端口 , 協議 > 一個fd就是一個五元組,知道了fd,我們就能從紅黑樹中找到對應的結點。

那么這個回調函數做什么事情呢?我們傳入fd和具體事件這兩個參數,然后做下面兩個操作

1. 通過fd找到對應的結點

2. 把結點加入到就緒隊列

1、協議棧中,在三次握手完成之后,會往全連接隊列中添加一個TCB結點,然后觸發一個回調函數,通知到epoll里面有個EPOLLIN事件

2f815416-1153-11ed-ba43-dac502259ad0.jpg

2、客戶端發送一個數據包,協議棧接收后回復ACK,之后觸發一個回調函數,通知到epoll里面有個EPOLLIN事件

2fa506f4-1153-11ed-ba43-dac502259ad0.jpg

3、每個連接的TCB里面都有一個sendbuf,在對端接收到數據并返回ACK以后,sendbuf就可以將這部分確認接收的數據清空,此時sendbuf里面就有剩余空間,此時觸發一個回調函數,通知到epoll里面有個EPOLLOUT事件

2fc4a93c-1153-11ed-ba43-dac502259ad0.png

4、當對端發送close,在接收到fin后回復ACK,此時會調用回調函數,通知到epoll有個EPOLLIN事件

2fd8dfb0-1153-11ed-ba43-dac502259ad0.jpg

5、當接收到rst標志位的時候,回復ack之后也會觸發回調函數,通知epoll有一個EPOLLERR事件

2ff34f26-1153-11ed-ba43-dac502259ad0.png

通知的時機總結

一個有5個通知的地方

1. 三次握手完成之后2. 接收數據回復ACK之后3. 發送數據收到ACK之后4. 接收FIN回復ACK之后 5. 接收RST回復ACK之后

從回調機制看epoll 與 select/poll的區別

由于select和poll沒有本質的區別,所以下面統一稱為poll。

//  poll跟select類似, 其實poll就是把select三個文件描述符集合變成一個集合了。int select(int nfds, fd_set * readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);int poll(struct pollfd *fds, nfds_t nfds, int timeout);

我們看到每次調用poll,都需要把總集fds拷貝到內核態,檢測完之后,再有內核態拷貝的用戶態,這就是poll。而epoll不是這樣,epoll只要有新的io就調用epoll_ctl()加入到紅黑樹里面,一旦有觸發就用epoll_wait()將有事件的結點帶出來,可以看到他們的第一個區別:poll總是拷貝總集,如果有100w個fd,只有兩三個就緒呢?這會造成大量資源浪費;而epoll總是將需要拷貝的東西進行拷貝,沒有浪費。

第二個區別:我們從上面知道了epoll的事件都是由協議棧進行回調然后加入到就緒隊列的,而poll呢?內核如何檢測poll的io是否就緒?只能通過遍歷的方法判斷,所以poll檢測io通過遍歷的方法也是比較慢的。

所以兩者的區別:

  1. select/poll需要把總集copy到內核,而epoll不用

  2. 實現原理上面,select/poll 需要循環遍歷總集是否有就緒,而epoll是那個結點就緒了就加入就緒隊列里面。

注意:poll不一定就比epoll慢,在io量小的情況下,poll是比epoll快的,而在大io量下,epoll絕對是有主導地位的。至于有多少個io才算多,其實也很難說,一般認為500或者1024為分界點(我亂說的) 。

epoll線程安全如何加鎖

3個api做什么事情

  1. epoll_create() ===》創建紅黑樹的根節點

  2. epoll_ctl() ===》add,del,mod 增加、刪除、修改結點

  3. epoll_wait() ===》把就緒隊列的結點copy到用戶態放到events里面,跟recv函數很像

3014e2ee-1153-11ed-ba43-dac502259ad0.png

分析加鎖

如果有3個線程同時操作epoll,有哪些地方需要加鎖?我們用戶層面一共就只有3個api可以使用:

  1. 如果同時調用 epoll_create() ,那就是創建三顆紅黑樹,沒有涉及到資源競爭,沒有關系。

  2. 如果同時調用 epoll_ctl() ,對同一顆紅黑樹進行,增刪改,這就涉及到資源競爭需要加鎖了,此時我們對整棵樹進行加鎖。

  3. 如果同時調用epoll_wait() ,其操作的是就緒隊列,所以需要對就緒隊列進行加鎖。

我們要扣住epoll的工作環境,在應用程序調用 epoll_ctl() ,協議棧會不會有回調操作紅黑樹結點?調用epoll_wait() copy出來的時候,協議棧會不會操作操作紅黑樹結點加入就緒隊列?綜上所述:

epoll_ctl() 對紅黑樹加鎖epoll_wait()對就緒隊列加鎖回調函數()   對紅黑樹加鎖,對就緒隊列加鎖

那么紅黑樹加什么鎖,就緒隊列加什么鎖呢?

對于紅黑樹這種節點比較多的時候,采用互斥鎖來加鎖。就緒隊列就跟生產者消費者一樣,結點是從協議棧回調函數來生產的,消費是epoll_wait()來消費。那么對于隊列而言,用自旋鎖(對于隊列而言,插入刪除比較簡單,cpu自旋等待比讓出的成本更低,所以用自旋鎖)。

ET與LT如何實現

  • ET邊沿觸發,只觸發一次

  • LT水平觸發,如果沒有讀完就一直觸發

代碼如何實現ET和LT的效果呢?水平觸發和邊沿觸發不是故意設計出來的,這是自然而然,水到渠成的功能。水平觸發和邊沿觸發代碼只需要改一點點就能實現。從協議棧檢測到接收數據,就調用一次回調,這就是ET,接收到數據,調用一次回調。而LT水平觸發,檢測到recvbuf里面有數據就調用回調。所以ET和LT就是在使用回調的次數上面的差異。

那么具體如何實現呢?協議棧流程里面觸發回調,是天然的符合ET只觸發一次的。那么如果是LT,在recv之后,如果緩沖區還有數據那么加入到就緒隊列。那么如果是LT,在send之后,如果緩沖區還有空間那么加入到就緒隊列。那么這樣就能實現LT了。

302505de-1153-11ed-ba43-dac502259ad0.png


審核編輯:湯梓紅


聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 存儲
    +關注

    關注

    13

    文章

    4355

    瀏覽量

    86175
  • 數據結構
    +關注

    關注

    3

    文章

    573

    瀏覽量

    40232
  • epoll
    +關注

    關注

    0

    文章

    28

    瀏覽量

    2984

原文標題:從4個方面分析epoll的實現原理

文章出處:【微信號:yikoulinux,微信公眾號:一口Linux】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏

    評論

    相關推薦

    epoll的使用

    以下內容是參考華清遠見《linux/unix系統編程手冊》對epoll個個人總結,是我在華清遠見比較全面的總結。epoll的優點同I/O多路復用和信號驅動I/O
    發表于 05-11 13:22

    揭示EPOLL些原理性的東西

    我們對這些流的操作都是有意義的。(復雜度降低到了O(1))在討論epoll實現細節之前,先把epoll的相關操作列出:epoll_create 創建
    發表于 08-24 16:32

    poll&&epollepoll實現

    poll&&epollepoll實現
    發表于 05-14 14:34 ?2818次閱讀
    poll&&<b class='flag-5'>epoll</b>之<b class='flag-5'>epoll</b><b class='flag-5'>實現</b>

    詳解精密封裝技術

    詳解精密封裝技術
    的頭像 發表于 12-30 15:41 ?1710次閱讀

    詳解分立元件門電路

    詳解分立元件門電路
    的頭像 發表于 03-27 17:44 ?3376次閱讀
    <b class='flag-5'>一</b><b class='flag-5'>文</b><b class='flag-5'>詳解</b>分立元件門電路

    詳解pcb和smt的區別

    詳解pcb和smt的區別
    的頭像 發表于 10-08 09:31 ?3475次閱讀

    詳解pcb地孔的作用

    詳解pcb地孔的作用
    的頭像 發表于 10-30 16:02 ?1751次閱讀

    epoll實現多路復用

    本人用epoll實現多路復用,epoll觸發模式有兩種: ET(邊緣模式) LT(水平模式) LT模式 是標準模式,意味著每次epoll_wait()返回后,事件處理后,如果之后還有
    的頭像 發表于 11-09 10:15 ?556次閱讀
    用<b class='flag-5'>epoll</b>來<b class='flag-5'>實現</b>多路復用

    epoll實現原理

    今兒我們就從源碼入手,來幫助大家簡單理解epoll實現原理,并在后邊分析下,大家都說 epoll 性能好,那到底是好在哪里。
    的頭像 發表于 11-09 11:14 ?587次閱讀
    <b class='flag-5'>epoll</b> 的<b class='flag-5'>實現</b>原理

    epoll的基礎數據結構

    epoll的基礎數據結構 在開始研究源代碼之前,我們先看epoll 中使用的數據結構,分別是 eventpoll、epitem 和 eppoll_entry。 1、event
    的頭像 發表于 11-10 10:20 ?846次閱讀
    <b class='flag-5'>epoll</b>的基礎數據結構

    epoll源碼分析

    個函數進行源碼分析。 源碼來源 由于epoll實現內嵌在內核中,直接查看內核源碼的話會有些無關代碼影響閱讀。為此在GitHub上寫的簡化版TCP/IP協議棧,里面實現
    的頭像 發表于 11-13 11:49 ?1116次閱讀
    <b class='flag-5'>epoll</b>源碼分析

    Epoll封裝類實現

    )的事件,并將事件從內核通知到用戶區,實現對特定事件的響應處理,而epoll可認為是poll的改進版,在多個方面大幅度提高了性能(當然也是在監聽描述符多、活躍描述符少的條件下)。 epoll的主要特點有以下幾點: 1.支持
    的頭像 發表于 11-13 11:54 ?550次閱讀

    詳解pcb不良分析

    詳解pcb不良分析
    的頭像 發表于 11-29 17:12 ?1236次閱讀

    詳解pcb的msl等級

    詳解pcb的msl等級
    的頭像 發表于 12-13 16:52 ?1w次閱讀

    詳解pcb的組成和作用

    詳解pcb的組成和作用
    的頭像 發表于 12-18 10:48 ?1674次閱讀
    主站蜘蛛池模板: 黄视频免费网站 | 天天做天天爱天天爽 | 天天狠狠弄夜夜狠狠躁·太爽了 | 免费理论片在线观看播放 | 天天透天天干 | 五月天婷婷在线观看 | 午夜视频色 | 户外露出 自拍系列 | 免费一级毛片清高播放 | 欧美黄色xxx | 一区卡二区卡三区卡视频 | 美女视频黄的免费视频网页 | 在线播放91灌醉迷j高跟美女 | 天天操夜夜操 | aaaaa毛片| 网站在线观看你懂的 | 国产精品青草久久久久福利99 | 日韩理论电影2021第1页 | 亚洲伊人精品综合在合线 | 在线免费日韩 | 亚洲欧美v视色一区二区 | 午夜a视频 | 日本写真高清视频免费网站网 | 四虎影院永久在线 | 四虎影院国产 | 恐怖片大全恐怖片免费观看好看的恐怖片 | www.瑟瑟| 天天干天天插天天操 | 亚洲黄色天堂 | 在线视频这里只有精品 | 三级成人网 | 黄a毛片 | 亚洲视频在线一区二区三区 | 免费大片黄国产在线观看 | 最近2018中文字幕免费看在线 | 日本69sex护士wwxx | 最新丁香六月 | 午夜视频免费观看黄 | 夜间免费视频 | 日本三级全黄三级a | 色婷婷六月丁香七月婷婷 |