watcher初始化及啓動
ev_io:
初始化:
首先調用ev_init,設置watcher的初始化狀態,包括:active = 0, pending = 0, priority = 0以及回調函數;
再調用ev_io_set, 設置watcher所關注的文件描述符(fd)以及事件(event)。
可以一次性調用ev_io_init進行上述兩項的設置。
啓動(ev_io_start):
判斷該watcher是否已經啓動,如果是,則直接返回;
斷言該watcher關注的文件句柄以及事件是否設置正確;
調用ev_start,對該watcher的優先級進行調整(系統默認的優先級範圍-2 ~ +2),設置watcher的狀態active爲1,對相應消息循環中active watcher的個數加1;
調用array_needsize,爲相應的消息循環分配保存文件描述符的ANFD anfds(數組以文件描述符作爲下標,相同文件描述符的watcher以鏈表連接)空間,anfdmax記錄該數組的容量(需要時該容量自動擴充);
調用wlist_add,將watcher添加到相應文件描述符的鏈表中;
調用fd_change,設置新增加或改變的文件描述符,記錄在fdchanges數組中,fdchangecnt記錄數組下標,fdchangemax記錄數組容量(需要時該容量自動擴充)。
ev_timer:
初始化:
首先調用ev_init,設置watcher的初始化狀態,包括:active = 0, pending = 0, priority = 0以及回調函數;
再調用ev_timer_set, 設置watcher所關注的觸發時間點(at)以及重複次數(repeat)。
可以一次性調用ev_timer_init進行上述兩項的設置。
啓動(ev_timer_start):
判斷該watcher是否已經啓動,如果是,則直接返回;
設置定時器實際觸發時間(at),at += loop->mn_now;
將該消息循環中定時器個數(timercnt)加1;
調用ev_start,對該watcher的優先級進行調整(系統默認的優先級範圍-2 ~ +2),設置watcher的狀態active爲3(如果再向該消息循環中增加ev_timer,則下一個watcher的active值爲上個watcher的active值加1),對相應消息循環中active watcher的個數加1;
調用array_needsize,爲相應的消息循環分配保存觸發時間的ANNE timers(數組以active值作爲下標)堆空間,timermax記錄該數組的容量(需要時該容量自動擴充);
調用ANNE_w和ANNE_at_cache,設置ANNE結構體的w(watcher)以及at(觸發時間);
調用upheap,以watch的active值對timers堆進行排序。
ev_run:
增加該消息循環的調用次數,++(loop->loop_depth);
重新設置消息循環的狀態,loop->ev_break = EVBREAK_CANCEL;
在首次循環之前,調用所有pending watcher的回調;
循環:
如果使用了EVFLAG_FORKCHECK,則檢查是否產生了新的子進程;
如果檢測到新的子進程,則所有fork watchers加入到pending消息隊列並調用回調;
將所有的prepare watchers加入到pending消息隊列並調用回調;
如果調用了ev_break, 則消息循環結束;
如果產生了forked消息,重新設置內核狀態防止進程之間相互影響;
更新所有未解決的改變的內核狀態;
更新事件循環時間(ev_now());
計算該消息循環需要block或sleep多長時間或者不sleep(有激活的idle watchers,設置了EVRUN_NOWAIT或根據就沒有任何激活的watchers);
Sleep if the I/O and timer collect interval say so(?);
增加該消息循環循環次數,++(loop->loopcount);
阻塞進程,調用後端相應操作系統提供的事件檢測機制,等待事件發生;
將所有未解決的I/O(fd)事件加入到pending隊列;
更新事件循環時間(ev_now())並進行可能的時間調整;
將所有超時的定時器(timer)加入到pending隊列;
將所有超時的週期(periodics)加入到pending隊列;
將所有優先級大於pending隊列中的idle watchers加入到pending隊列;
將所有check watchers加入到pending隊列;
以反序調用所有加入pending隊列的watchers(例如:首先是check watchers)。信號和fork watchers是以I/O watcher的方式進行聲明,所以也會在這裏得到處理;
如果ev_break被調用,或設置了EVRUN_ONCE|EVRUN_NOWAIT,或沒有激活的watchers,則消息循環結束,否則繼續循環;
結束:
如果消息循環狀態爲EVBREAK_ONE,則重新設置爲EVBREAK_CANCEL;
減少該消息循環的調用次數,--(loop->loop_depth);
返回,該消息循環中處於active狀態的watcher個數。
libev源碼分析1
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章
給原版的openwrt安裝Passwall
osc_bzc91lgy
2021-01-30 11:11:55
libev 的幾篇文章
wangzongze1986
2020-02-23 20:16:12
lua web快速開發指南(6) - Cache、DB介紹
CandyMi
2019-06-16 02:55:06
lua web快速開發指南(3) - 初識httpd庫路由
CandyMi
2019-06-14 15:35:12
lua web快速開發指南(2) - cf的運行機制簡介與基於httpd庫的開發環境搭建
CandyMi
2019-06-14 15:35:12
lua web快速開發指南(1) - 初識cf框架
CandyMi
2019-06-14 15:35:12
lua web快速開發指南(5) - 利用template庫構建httpd模板引擎
CandyMi
2019-06-14 15:35:01
lua web快速開發指南(4) - 詳細瞭解httpd庫的作用
CandyMi
2019-06-14 15:35:01
libev 的幾篇文章
wangzongze1986
2020-02-23 20:16:12
Libev使用
Newtown-Gao
2020-02-21 18:05:41
使用 libevent 和 libev 提高網絡應用性能
Newtown-Gao
2020-02-21 18:05:38
libev庫的安裝及簡單測試實例
Dancer__Sky
2018-12-23 16:37:23
Libev源碼解析
shadou0109
2018-09-04 09:25:24
libev的使用——結合Socket編程
cinyaaaa
2018-09-03 18:05:25