1. 程式人生 > >libev原始碼分析(二)---ev_io

libev原始碼分析(二)---ev_io

 1.ev_io結構

typedef struct ev_io{
  
  EV_WATCHER_LIST (ev_io)
 
  int fd;    /* 檔案描述符 */
  int events; /* 事件型別 */

} ev_io;

2 . 作用
ev_io是我們最常用的一個watcher。因為專案中,時間迴圈的應用場景大部分也都集中在io的讀寫方面。

從ev_io的宣告中我們可以看到它繼承了WATCHER_LIST,並且有兩個新欄位,fd和events。不難理解fd就是用來儲存所監聽的檔案描述符的,而events則是記錄了我們所要監聽的時間,一般為讀、寫。

3 .相關函式

 ev_init (ev_io *ev,callback)  ; 

 ev_io_set(ev_io *ev, int fd, int events);

 ev_io_init(ev_io *ev, callback,int fd, int events);

ev_io_init等價於呼叫ev_init,再呼叫ev_io_set。其功能是將回調函式、檔案描述符以及所監聽的事件繫結到watcher上。

根據實踐經驗,我覺得最好還是少呼叫ev_io_init。因為ev_init只能對watcher執行一次,但我們卻可能經常需要重置watcher,這時如果我們再次呼叫ev_io_init而不是呼叫ev_io_set對watcher進行重置,就可能會使程式core掉。我會在以後提到這個問題。

ev_io_start(EV_P_ ev_io * w);

ev_io_start的作用就是將已經初始化好的watcher繫結到事件監聽主迴圈ev_loop上。在這個過程中:

l  首先會檢查正確性,在這裡用到了一個巨集EV_FREQUENT_CHECK,其具體內容就是進行各種檢查,就不仔細討論了。

l  呼叫ev_start將監視器active置為啟動,同時設定優先順序等。

l  呼叫array_needsize檢查anfds的大小是否足夠放入新的fd,如果不夠realloc。

l  呼叫wlist_add將fd插入anfds中。

l  最後呼叫fd_change註冊行為改變的函式,改函式把所有新的fd或者所監聽的事件有改變的fd存放到fdchanges陣列中,在適當的時候呼叫底層事件模型進行修改。

ev_io_stop(EV_P_ ev_io * w);

ev_io_stop的作用正好與ev_io_start相反,就是把watcher從ev_loop中去除。起流程基本如下:

l  首先從pendings中清楚watcher對應的即將被觸發的事件。

l  呼叫EV_FREQUENT_CHECK進行檢查。

l  呼叫wlist_del從anfds中清除相關fd。

l  呼叫ev_stop將watcher的active置為0。

l  呼叫fd_change註冊fd行為變化。