天天看點

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