libev源碼分析1

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個數。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章