(轉)徹底學會使用epoll(一)——ET模式實現分析

注:之前寫過兩篇關于epoll實現的文章,但是感覺懂得了實現原理并不一定會使用,所以又決定寫這一系列文章,希望能夠對epoll有比較清楚的認識。是請大家轉載務必注明出處,算是對我勞動成果的一點點尊重吧。另外,文中如果有不全面或者不正確的地方還請大家指出。也可以私信或者發郵件:lvyilong316@163.com

1.?ET模式實現分析

1.1?ET和LT的實現區別

????首先給出下面一張圖,這張圖是從我之前的一篇博文——epoll實現分析中摘取并細化的。這張圖對理解ET模式已經epoll的工作過程只管重要,當然我自己總結出來后也感覺有的小成就,在這里與大家分享。

注:上圖的poll不要理解成和select相似那個poll,這是通過epoll_ctl調用的。

下面簡要分析一下epoll的工作過程:

(1)?epoll_wait調用ep_poll,當rdlist為空(無就緒fd)時掛起當前進程,知道rdlist不空時進程才被喚醒。

(2)?文件fd狀態改變(buffer由不可讀變為可讀或由不可寫變為可寫),導致相應fd上的回調函數ep_poll_callback()被調用。

(3)?ep_poll_callback將相應fd對應epitem加入rdlist,導致rdlist不空,進程被喚醒,epoll_wait得以繼續執行。

(4)?ep_events_transfer函數將rdlist中的epitem拷貝到txlist中,并將rdlist清空。

(5)?ep_send_events函數(很關鍵),它掃描txlist中的每個epitem,調用其關聯fd對用的poll方法(圖中藍線)。此時對poll的調用僅僅是取得fd上較新的events(防止之前events被更新),之后將取得的events和相應的fd發送到用戶空間(封裝在struct?epoll_event,從epoll_wait返回)。之后如果這個epitem對應的fd是LT模式監聽且取得的events是用戶所關心的,則將其重新加入回rdlist(圖中藍線),否則(ET模式)不在加入rdlist。

具體代碼:

/*?掃描整個txlist鏈表...?*/

for?(eventcnt?=?0,?uevent?=?esed->events;

?????!list_empty(head)?&&?eventcnt?<?esed->maxevents;)?{

/*?取出第一個成員?*/

epi?=?list_first_entry(head,?struct?epitem,?rdllink);

/*?然后從鏈表里面移除?*/

list_del_init(&epi->rdllink);

/*?讀取events,?

?*?注意events我們ep_poll_callback()里面已經取過一次了,?為啥還要再取?

?*?1.?我們當然希望能拿到此刻的最新數據,?events是會變的~

?*?2.?不是所有的poll實現,?都通過等待隊列傳遞了events,?有可能某些驅動壓根沒傳

?*?必須主動去讀取.?*/

revents?=?epi->ffd.file->f_op->poll(epi->ffd.file,?NULL)?&

epi->event.events;

?

if?(revents)?{

/*?將當前的事件和用戶傳入的數據都copy給用戶空間,

?*?就是epoll_wait()后應用程序能讀到的那一堆數據.?*/

if?(__put_user(revents,?&uevent->events)?||

????__put_user(epi->event.data,?&uevent->data))?{

/*?如果copy過程中發生錯誤,?會中斷鏈表的掃描,

?*?并把當前發生錯誤的epitem重新插入到ready?list.

?*?剩下的沒處理的epitem也不會丟棄,?在ep_scan_ready_list()

?*?中它們也會被重新插入到ready?list?*/

list_add(&epi->rdllink,?head);

return?eventcnt???eventcnt?:?-EFAULT;

}

eventcnt++;

uevent++;

if?(epi->event.events?&?EPOLLONESHOT)

epi->event.events?&=?EP_PRIVATE_BITS;

else?if?(!(epi->event.events?&?EPOLLET))?{

/*

?*?If?this?file?has?been?added?with?Level

?*?Trigger?mode,?we?need?to?insert?back?inside

?*?the?ready?list,?so?that?the?next?call?to

?*?epoll_wait()?will?check?again?the?events

?*?availability.?At?this?point,?noone?can?insert

?*?into?ep->rdllist?besides?us.?The?epoll_ctl()

?*?callers?are?locked?out?by

?*?ep_scan_ready_list()?holding?"mtx"?and?the

?*?poll?callback?will?queue?them?in?ep->ovflist.

?*/

/*?嘿嘿,?EPOLLET和非ET的區別就在這一步之差呀~

?*?如果是ET,?epitem是不會再進入到readly?list,

?*?除非fd再次發生了狀態改變,?ep_poll_callback被調用.

?*?如果是非ET,?不管你還有沒有有效的事件或者數據,

?*?都會被重新插入到ready?list,?再下一次epoll_wait

?*?時,?會立即返回,?并通知給用戶空間.?當然如果這個

?*?被監聽的fds確實沒事件也沒數據了,?epoll_wait會返回一個0,

?*?空轉一次.

?*/

list_add_tail(&epi->rdllink,?&ep->rdllist);

}

}

}

說明:

l?epoll_wait返回的條件是rdlist不空,而使rdlist不空的途徑有兩個,分別對應圖中的紅線和藍線。

l?ET和LT模式下的epitem都可以通過紅線方式加入rdlist從而喚醒epoll_wait,但LT模式下的epitem還可以通過藍線方式重新加入rdlist喚醒epoll_wait。所以ET模式下,fd就緒(通過紅線加入rdlist)只會被通知一次,而LT模式下只要滿足相應讀寫條件就返回就緒(通過藍線加入rdlist)。

l?ET事件發生僅通知一次的原因是只被添加到rdlist中一次,而LT可以有多次添加的機會。

1.2?兩種加入rdlist途徑的不同

下面我們來分析一下圖中兩種將epitem加入rdlist方式(也就是紅線和藍線)的區別。

l?紅線:fd狀態改變是才會觸發。那么什么情況會導致fd狀態的改變呢?

對于讀取操作:

(1)?當buffer由不可讀狀態變為可讀的時候,即由空變為不空的時候。

(2)?當有新數據到達時,即buffer中的待讀內容變多的時候。

對于寫操作:

(1)?當buffer由不可寫變為可寫的時候,即由滿狀態變為不滿狀態的時候。

(2)?當有舊數據被發送走時,即buffer中待寫的內容變少得時候。

l?藍線:fd的events中有相應的時間(位置1)即會觸發。那么什么情況下會改變events的相應位呢?

對于讀操作:

(1)?buffer中有數據可讀的時候,即buffer不空的時候fd的events的可讀為就置1。

對于寫操作:

(1)?buffer中有空間可寫的時候,即buffer不滿的時候fd的events的可寫位就置1。

?

說明:紅線是時間驅動被動觸發,藍線是函數查詢主動觸發。

?

原文:http://blog.chinaunix.net/xmlrpc.php?r=blog/article&uid=28541347&id=4273856

轉載于:https://www.cnblogs.com/hznet/p/6097098.html

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

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

相關文章

MFC的消息映射有什么作用

絕對以下這三個解釋的比較簡潔&#xff0c;特此做個記錄&#xff01;以感謝回答的這些人&#xff01; MFC的消息映射有什么作用: Windows操作系統主要是有消息來處理的&#xff0c;每個程序都有自己的消息隊列&#xff0c;并且這些消息是有優先級的&#xff0c;也就是誰會先…

線性表的鏈式存儲結構

鏈式存儲結構的定義 1.概念定義&#xff1a; - n個結點離散分配 - 彼此通過指針相連 - 每個結點只有一個前驅結點和一個后繼結點 - 首結點沒有前驅結點&#xff0c;尾結點沒有后繼結點 2.專業術語 -首結點&#xff1a;第一個有有效數據的結點 -尾結點&#xff1a;最后一個有有效…

Apache 設置http跳轉至HTTPS訪問

為什么80%的碼農都做不了架構師&#xff1f;>>> <VirtualHost>...</VirtualHost> 中添加如下配置 <IfModule mod_rewrite.c>RewriteEngine onRewriteCond %{SERVER_PORT} 80RewriteRule ^(.*)$ https://域名/$1 [R301,L] </IfModule> 轉…

JAVA線程概念

一、程序與進程 1、程序&#xff1a;一段靜態的代碼。 2、進程&#xff1a;程序的一次動態執行過程&#xff0c;它對應從代碼加載、執行到執行完畢的一個完整過程。 3、進程也稱任務&#xff0c;支持多個進程同時執行的OS就被稱為多進程OS或多任務OS。 二、進程與線程 在一…

(二)功耗的分析

前面學習了進行低功耗的目的個功耗的構成&#xff0c;今天就來分享一下功耗的分析。由于是面向數字IC前端設計的學習&#xff0c;所以這里的功耗分析是基于DC中的power compiler工具&#xff1b;更精確的功耗分析可以采用PT&#xff0c;關于PT的功耗分析可以查閱其他資料&#…

Hibernate創建hqll時報錯

Hibernate 問題,在執行Query session.createQuery(hql) 報錯誤 出錯截圖&#xff1a; 這條語句在java運行環境下&#xff0c;直接連數據庫不出錯&#xff0c;如果在hiberante,struts環境下就出錯 出錯原因&#xff1a;jar包沖突&#xff0c;struts2和hibernate框架中都有antlr包…

.NET Core TDD 前傳: 編寫易于測試的代碼 -- 全局狀態

第1篇: 講述了如何創造"縫". "縫"(seam)是需要知道的概念. 第2篇, 避免在構建對象時寫出不易測試的代碼. 第3篇, 依賴項和迪米特法則. 本文是第4篇, 將介紹全局狀態引起的問題. 全局狀態 全局狀態, 也可以叫做應用程序狀態, 它是一組變量, 這些變量維護著…

(三)系統與架構級低功耗設計

前面講解了使用EDA工具&#xff08;主要是power compiler&#xff09;進行功耗分析的流程&#xff0c;這里我們將介紹在數字IC中進行低功耗設計的方法&#xff0c;同時也結合EDA工具&#xff08;主要是Design Compiler&#xff09;如何實現。我們的講解的低功耗設計主要是自頂向…

python---統計列表中數字出現的次數

1 import collections 2 3 a [1,2,3,1,2,3,4,1,2,5,4,6,7,7,8,9,6,2,23,4,2,1,5,6,7,8,2] 4 b collections.Counter(a) 5 for c in b&#xff1a; print c,b[c] 轉載于:https://www.cnblogs.com/lxs1314/p/7236321.html

MFC入門(一)——MFC是一個編程框架

MFC (Microsoft Foundation Class Library)中的各種類結合起來構成了一個應用程序框架&#xff0c;它的目的就是讓程序員在此基礎上來建立Windows下的應用程序&#xff0c;這是一種相對SDK來說更為簡單的方法。因為總體上&#xff0c;MFC框架定義了應用程序的輪廓&#xff0c;并…

2.數據結構筆記學習--線性表基本操作

線性表的結構定義&#xff1a; 順序表的結構定義&#xff1a; typedef struct {int data[maxSize]; //存放順序表元素的數組&#xff0c;一般用 int A[maxSize];int length; //存放順序表的長度,一般用 int n; }SeqList; 單鏈表結點定義&#xff1a; typedef struct L…

(四)RTL級低功耗設計

前面介紹了系統級的低功耗設計&#xff0c;換句話說就是在系統級降低功耗可以考慮的方面。系統級的低功耗設計&#xff0c;主要是由系統級設計、具有豐富經驗的人員實現&#xff0c;雖然還輪不到我們設計&#xff0c;我們了解一下還是比較好的。我們前端設計人員的重點不在系統…

Unity3D 游戲前端開發技能樹(思維導圖)

如果做游戲也是一種游戲,那么這個游戲的自由度實在是太高了.(導圖源文件鏈接&#xff1a;http://pan.baidu.com/s/1eSHpH5o 密碼&#xff1a;qzl5) 最近要用思維導圖軟件Xmind把自己的思路好好捋一捋,算是溫故知新吧. 轉載于:https://www.cnblogs.com/qiaogaojian/p/6098962.ht…

js forEach

&#xfeff;&#xfeff;forEach()函數從頭到尾把數組遍歷一遍。有三個參數各自是&#xff1a;數組元素。元素的索引&#xff0c;數組本身&#xff08;假設是一個參數就是數組元素&#xff0c;也就是數組的值。var data[1,2,3,4,5,6]; var sum0; data.forEach(function(v){//當…

SQL Server 死鎖的告警監控

原文:SQL Server 死鎖的告警監控今天這篇文章總結一下如何監控SQL Server的死鎖&#xff0c;其實以前寫過MS SQL 監控錯誤日志的告警信息&#xff0c;這篇文章著重介紹如何監控數據庫的死鎖&#xff0c;當然這篇文章不分析死鎖產生的原因、以及如何解決死鎖。死鎖&#xff08;D…

關于web性能一些特性匯總

關于web性能一些特性匯總 DOMContentLoaded & load load事件是window對象上的事件。指的是網頁資源已經加載完畢&#xff08;包括但不限于DOM、圖片、音頻、腳本、插件資源以及CSS&#xff09;。 DOMContentLoaded事件是document對象上的事件。指的是DOM已經加載完畢。IE中…

(五)門級電路低功耗設計優化

&#xff08;1&#xff09;門級電路的功耗優化綜述 門級電路的功耗優化(Gate Level Power Optimization&#xff0c;簡稱GLPO)是從已經映射的門級網表開始&#xff0c;對設計進行功耗的優化以滿足功耗的約束&#xff0c;同時設計保持其性能&#xff0c;即滿足設計規則和時序的要…

SQL三大范式

第一范式(1NF) (必須有主鍵&#xff0c;列不可分) 數據庫表中的任何字段都是單一屬性的&#xff0c;不可再分 create table aa(id int,NameAge varchar(100)) insert aa values(1,無限-女 ) 沒有達到第一范式 create table aa(id int,name varcahr(10),age char(2)) insert aa …

Spring3向Spring4升級過程中quartz修改

為什么80%的碼農都做不了架構師&#xff1f;>>> 問題 nested exception is org.springframework.beans.factory.CannotLoadBeanClassException: Cannot find class [org.springframework.scheduling.quartz.CronTriggerBean] for bean with name ... 原因 org.spri…

Socket編程知識必學/SELECT 編程

Select在Socket編程中還是比較重要的&#xff0c;可是對于初學Socket的人來說都不太愛用Select寫程序&#xff0c;他們只是習慣寫諸如 connect、accept、recv或recvfrom這樣的阻塞程序&#xff08;所謂阻塞方式block&#xff0c;顧名思義&#xff0c;就是進程或是線程執行到這些…