日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

(转)彻底学会使用epoll(一)——ET模式实现分析

發(fā)布時(shí)間:2023/12/13 编程问答 22 豆豆
生活随笔 收集整理的這篇文章主要介紹了 (转)彻底学会使用epoll(一)——ET模式实现分析 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

注:之前寫過(guò)兩篇關(guān)于epoll實(shí)現(xiàn)的文章,但是感覺(jué)懂得了實(shí)現(xiàn)原理并不一定會(huì)使用,所以又決定寫這一系列文章,希望能夠?qū)poll有比較清楚的認(rèn)識(shí)。是請(qǐng)大家轉(zhuǎn)載務(wù)必注明出處,算是對(duì)我勞動(dòng)成果的一點(diǎn)點(diǎn)尊重吧。另外,文中如果有不全面或者不正確的地方還請(qǐng)大家指出。也可以私信或者發(fā)郵件:lvyilong316@163.com

1.?ET模式實(shí)現(xiàn)分析

1.1?ET和LT的實(shí)現(xiàn)區(qū)別

????首先給出下面一張圖,這張圖是從我之前的一篇博文——epoll實(shí)現(xiàn)分析中摘取并細(xì)化的。這張圖對(duì)理解ET模式已經(jīng)epoll的工作過(guò)程只管重要,當(dāng)然我自己總結(jié)出來(lái)后也感覺(jué)有的小成就,在這里與大家分享。

注:上圖的poll不要理解成和select相似那個(gè)poll,這是通過(guò)epoll_ctl調(diào)用的。

下面簡(jiǎn)要分析一下epoll的工作過(guò)程:

(1)?epoll_wait調(diào)用ep_poll,當(dāng)rdlist為空(無(wú)就緒fd)時(shí)掛起當(dāng)前進(jìn)程,知道rdlist不空時(shí)進(jìn)程才被喚醒。

(2)?文件fd狀態(tài)改變(buffer由不可讀變?yōu)榭勺x或由不可寫變?yōu)榭蓪?#xff09;,導(dǎo)致相應(yīng)fd上的回調(diào)函數(shù)ep_poll_callback()被調(diào)用。

(3)?ep_poll_callback將相應(yīng)fd對(duì)應(yīng)epitem加入rdlist,導(dǎo)致rdlist不空,進(jìn)程被喚醒,epoll_wait得以繼續(xù)執(zhí)行。

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

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

具體代碼:

/*?掃描整個(gè)txlist鏈表...?*/

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

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

/*?取出第一個(gè)成員?*/

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

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

list_del_init(&epi->rdllink);

/*?讀取events,?

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

?*?1.?我們當(dāng)然希望能拿到此刻的最新數(shù)據(jù),?events是會(huì)變的~

?*?2.?不是所有的poll實(shí)現(xiàn),?都通過(guò)等待隊(duì)列傳遞了events,?有可能某些驅(qū)動(dòng)壓根沒(méi)傳

?*?必須主動(dòng)去讀取.?*/

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

epi->event.events;

?

if?(revents)?{

/*?將當(dāng)前的事件和用戶傳入的數(shù)據(jù)都copy給用戶空間,

?*?就是epoll_wait()后應(yīng)用程序能讀到的那一堆數(shù)據(jù).?*/

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

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

/*?如果copy過(guò)程中發(fā)生錯(cuò)誤,?會(huì)中斷鏈表的掃描,

?*?并把當(dāng)前發(fā)生錯(cuò)誤的epitem重新插入到ready?list.

?*?剩下的沒(méi)處理的epitem也不會(huì)丟棄,?在ep_scan_ready_list()

?*?中它們也會(huì)被重新插入到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的區(qū)別就在這一步之差呀~

?*?如果是ET,?epitem是不會(huì)再進(jìn)入到readly?list,

?*?除非fd再次發(fā)生了狀態(tài)改變,?ep_poll_callback被調(diào)用.

?*?如果是非ET,?不管你還有沒(méi)有有效的事件或者數(shù)據(jù),

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

?*?時(shí),?會(huì)立即返回,?并通知給用戶空間.?當(dāng)然如果這個(gè)

?*?被監(jiān)聽的fds確實(shí)沒(méi)事件也沒(méi)數(shù)據(jù)了,?epoll_wait會(huì)返回一個(gè)0,

?*?空轉(zhuǎn)一次.

?*/

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

}

}

}

說(shuō)明:

l?epoll_wait返回的條件是rdlist不空,而使rdlist不空的途徑有兩個(gè),分別對(duì)應(yīng)圖中的紅線和藍(lán)線。

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

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

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

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

l?紅線:fd狀態(tài)改變是才會(huì)觸發(fā)。那么什么情況會(huì)導(dǎo)致fd狀態(tài)的改變呢?

對(duì)于讀取操作:

(1)?當(dāng)buffer由不可讀狀態(tài)變?yōu)榭勺x的時(shí)候,即由空變?yōu)椴豢盏臅r(shí)候。

(2)?當(dāng)有新數(shù)據(jù)到達(dá)時(shí),即buffer中的待讀內(nèi)容變多的時(shí)候。

對(duì)于寫操作:

(1)?當(dāng)buffer由不可寫變?yōu)榭蓪懙臅r(shí)候,即由滿狀態(tài)變?yōu)椴粷M狀態(tài)的時(shí)候。

(2)?當(dāng)有舊數(shù)據(jù)被發(fā)送走時(shí),即buffer中待寫的內(nèi)容變少得時(shí)候。

l?藍(lán)線:fd的events中有相應(yīng)的時(shí)間(位置1)即會(huì)觸發(fā)。那么什么情況下會(huì)改變events的相應(yīng)位呢?

對(duì)于讀操作:

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

對(duì)于寫操作:

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

?

說(shuō)明:紅線是時(shí)間驅(qū)動(dòng)被動(dòng)觸發(fā),藍(lán)線是函數(shù)查詢主動(dòng)觸發(fā)。

?

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

轉(zhuǎn)載于:https://www.cnblogs.com/hznet/p/6097098.html

總結(jié)

以上是生活随笔為你收集整理的(转)彻底学会使用epoll(一)——ET模式实现分析的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。