libevent & Reactor模式

整個libevent本身就是一個Reactor模式;Reactor是一種事件驅(qū)動機(jī)制,應(yīng)用程序提供相應(yīng)的接口并且注冊到Reactor中,如果相應(yīng)的事件發(fā)生,Reactor將主動調(diào)用應(yīng)用程序的接口。

Reactor框架需要包含幾個組件:事件源,Reactor框架,IO多路復(fù)用機(jī)制,事件處理程序。

事件源:linux上是文件描述符,

IO多路復(fù)用:epoll,select等;程序?qū)㈥P(guān)心的fd以及事件(read,write)注冊到IO多路復(fù)用上(epoll),事件到達(dá)后,epoll發(fā)出通知。

Reactor反應(yīng)器:libevent中就是指event_base結(jié)構(gòu)體。

事件處理程序:對應(yīng)libevent中,就是event結(jié)構(gòu)體。



libevent初始化Reactor:?

struct event_base* reactor = event_base_new();

函數(shù)實現(xiàn)內(nèi)容是 對結(jié)構(gòu)體struct event_base的初始化操作:malloc內(nèi)存,選擇適當(dāng)?shù)腎O多路復(fù)用(此處以epoll為例),調(diào)用IO多路復(fù)用的初始化操作,epoll的初始化操作(epoll_init),調(diào)用epoll_create創(chuàng)建一個RB樹頭節(jié)點。

事件處理程序:event

使用event_new 或者event_assign函數(shù) 獲得一個event,二者的區(qū)別是event_new 內(nèi)部對結(jié)構(gòu)體event進(jìn)行申請空間后再調(diào)用event_assign操作。


event_new實現(xiàn)

event_assign(struct event *ev, struct event_base *base, evutil_socket_t fd, short events, void (*callback)(evutil_socket_t, short, void *), void *arg)

函數(shù)event_assign完成的功能是對event結(jié)構(gòu)體的初始化工作


event_assign函數(shù)

以上對base_event和event 進(jìn)行了初始化相關(guān)操作,二者還沒有進(jìn)行關(guān)聯(lián)起來,調(diào)用event_add函數(shù)是將最終是將此event添加到epoll中的紅黑樹中,event_add--->event_add_internal -----> evmap_io_add---->evsel->add


這個add函數(shù)調(diào)用的是之前關(guān)聯(lián)的epoll中的epoll_nochangelist_add,最終是調(diào)用epoll_ctl將此event添加到之前申請的RB樹中,

epoll_nochangelist_add 調(diào)用epoll_apply_one_change函數(shù),epoll_apply_one_change函數(shù)核心完成功能如下:


epoll添加操作

至此,將一個event注冊到event_base中了,接下來調(diào)用event_base_loop 函數(shù),等待事件的到來,然后調(diào)用相關(guān)的回調(diào)函數(shù)。

int event_base_loop(struct event_base *base, int flags)

內(nèi)部調(diào)用 evsel->dispatch函數(shù),對應(yīng)epoll中的epoll_dispatch函數(shù),


event_base_loop中調(diào)用


epoll_diapatch中調(diào)用


可以看到loop中最終使用epoll_wait等待事件的到來了,有事件到來時進(jìn)行調(diào)用回調(diào)函數(shù)。

事件返回 的集合,linux下epoll鎖使用的是一個evmap_io列表,記錄給定的fd上可讀或者可寫的所有事件,以及每個事件的數(shù)量。

res返回后,調(diào)用evmap_io_active??激活在event_base上等待給定fd的一組事件。

event_base_loop 中 res = evsel->dispatch(base, tv_p); 返回激活的數(shù)量,激活事件存放到了event_base結(jié)構(gòu)體中的activequeues隊列中,


循環(huán)激活隊列執(zhí)行回調(diào)函數(shù)

最后循環(huán)隊列執(zhí)行回調(diào)函數(shù)。


evnt_process_active_single_queu
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容