1. 程式人生 > >libev學習筆記(持續更新)

libev學習筆記(持續更新)

2014-09-03

--

==libev學習筆記 == 


參考:
1. http://pod.tst.eu/http://cvs.schmorp.de/libev/ev.pod
2. 


簡介:
libev - a high performance full-featured event loop written in C


libev是Marc Lehmann用C寫的高效能事件迴圈庫。通過libev,可以靈活地把各種事件組織管理起來,如:時鐘、io、訊號等。libev在業界內也是廣受好評,不少專案都採用它來做底層的事件迴圈。
libev所實現的功能就是一個強大的reactor,可以notify的事件主要包括下面這些:


ev_io                 // IO可讀可寫
ev_stat               // 檔案屬性變化
ev_signal             // 訊號處理
ev_timer              // 相對定時器
ev_periodic           // 絕對定時器
ev_child              // 子程序狀態變化
ev_fork               // fork事件
ev_cleanup            // event loop退出觸發事件
ev_idle               // event loop空閒觸發事件
ev_embed              // 嵌入另一個後臺迴圈
ev_prepare            // event loop之前事件
ev_check              // event loop之後事件
ev_async              // 執行緒間非同步事件


1. 一些巨集定義:
/* support multiple event loops */
#if EV_MULTIPLICITY
struct ev_loop;
# define EV_P  struct ev_loop *loop               /* a loop as sole parameter in a declaration */
# define EV_P_ EV_P,                              /* a loop as first of multiple parameters */
# define EV_A  loop                               /* a loop as sole argument to a function call */
# define EV_A_ EV_A,                              /* a loop as first of multiple arguments */


ev_loop是主迴圈,而EV_MULTIPLICITY是一個條件編譯的巨集,表明是否支援有多個ev_loop例項存在,一般來說,每個執行緒中有且僅有一個ev_loop例項。
如果整個程式是單執行緒的,程式中使用全域性預設的ev_loop即可,不需要在函式中傳參。而在多執行緒中呼叫函式很多時候都要指定函式操作的loop。
比如啟動一個io事件,呼叫的函式是void ev_io_start (EV_P_ ev_io *w),如果沒有定義EV_MULTIPLICITY,將會編譯成ev_io_start(io *w),
否則會編譯成ev_io_start(struct ev_loop *loop, ev_io *w)。 對於每一種事件,都有結構體ev_TYPE與之對應,比如ev_io,ev_timer等。
為了統一事件結構,libev在C中使用結構體佈局實現了多型,可以將ev_watcher結構體看做所有ev_TYPE結構體的基類,它包含了所有ev_TYPE中相同的欄位。


2. libev設定使用者自定義資料: 
void ev_set_userdata (loop, void *data)  /* set userdata=data */
void *ev_userdata (loop)/* return userdata */


3. ev_loop_fork(loop):
/* support multiple event loops */
while(i < PROCESS_NUM){
int pid = fork();
if(pid == 0){
ev_loop_fork(loop);
}
}


4. ev_io:
ev_io的主要使命就是監聽並響應指定檔案描述fd上的讀寫事件。對fd的監聽工作,主要委託給底層的io庫來完成。libev對目前比較流行的io庫都提供了支援,如:select, epoll以及windows的iocp等。在這裡libev使用了Adaptor模式,
通過統一的適配層隱藏了底層io庫的細節。


手冊上ev_io的介紹:
I/O watchers check whether a file descriptor is readable or writable in each iteration of the event loop, or, more precisely, when reading would not block the process and writing would at least be able to write some data. This behaviour is called level-triggering because you keep receiving events as long as the condition persists.

/* invoked when fd is either EV_READable or EV_WRITEable */
/* revent EV_READ, EV_WRITE */
typedef struct ev_io
{
 EV_WATCHER_LIST (ev_io)


 int fd;     /* ro */
 int events; /* ro */
} ev_io;


5. ev_io_init(ev, cb, fd, events):
#define ev_io_init(ev,cb,fd,events)          do { ev_init ((ev), (cb)); ev_io_set ((ev),(fd),(events)); } while (0)


   例如:
ev_io* read_ev_io = (ev_io*) malloc(sizeof(ev_io));
ev_io_init(read_ev_io, mysql_libev_read_callback, mysql_get_file_descriptor(mysql), EV_READ);


6. ev_io_start(loop, ev):
   接上例:
    ev_io_start(loop, read_ev_io)


7. ev_io_stop(loop, ev):
   接上例:
ev_io_stop(loop, read_ev_io)