學會使用libevent,才能真正的掌握其是實現原理,咱們先從一個簡短的測試用例開始:緩存
1 #include <sys/types.h> 2 #include <sys/stat.h> 3 #include <sys/queue.h> 4 #include <unistd.h> 5 #include <sys/time.h> 6 7 #include <signal.h> 8 #include <fcntl.h> 9 #include <stdlib.h> 10 #include <stdio.h> 11 #include <string.h> 12 #include <errno.h> 13 #include <event.h> 14 15 16 int called = 0; 17 static void signall_cb(int fd, short event, void *arg) 18 { 19 struct event *signal = arg; 20 printf("%s: got signal %d\n", __func__, EVENT_SIGNAL(signal)); 21 if (called >= 2) 22 event_del(signal); 23 called++; 24 } 25 int main (int argc, char **argv) 26 { 27 struct event signal_int; 28 /* Initalize the event library */ 29 event_init(); 30 /* Initalize one event */ 31 event_set(&signal_int, SIGINT, EV_SIGNAL|EV_PERSIST, signall_cb, &signal_int); 32 event_add(&signal_int, NULL); 33 event_dispatch(); 34 return (0); 35 }
該代碼的大致意思是:添加一個信號中斷事件,經過CTRL+C,產生中斷信號,再調用中斷處理函數。函數
首先分析的是函數是event_init函數,現帖出其具體實現方式測試
194 struct event_base * 195 event_base_new(void) 196 { 197 int i; 198 struct event_base *base; 199 200 if ((base = calloc(1, sizeof(struct event_base))) == NULL) 201 event_err(1, "%s: calloc", __func__); 202 203 event_sigcb = NULL; 204 event_gotsig = 0; 205 206 detect_monotonic(); 207 /*若是第一次使用初始化,須要將時間緩存保留,在event_base中保留了一個事件*/ 208 gettime(base, &base->event_tv); 209 /*初始化最小堆,這個堆裏存儲的是時間,在I/O複用的函數裏是使用最小堆中堆頂的值 210 做爲等待的時間參數,這裏只介紹epoll_wait做爲I/O複用的方法,這個值就是函數的最後 211 一個參數,當等待的時間結束,函數返回,也就表明着多是定時事件被激活 212 這樣也將定時事件集合到I/O事件*/ 213 min_heap_ctor(&base->timeheap); 214 /*宏做爲初始化的,eventqueue是一個event_list,這裏面存儲着這個event_base所關注的 215 全部事件*/ 216 TAILQ_INIT(&base->eventqueue); 217 /*這一對套接字是爲了將信號事件融合到I/O事件中所特有的,將其中一個套接字添加到被關注的 218 行列中,信號事件是經過這一對套接字上來傳遞的,信號到達,其中一個套接字上有I/O事件, 219 那麼信號到達能夠讓I/O返回,這樣即可將信號事件添加到激活隊列中去........*/ 220 base->sig.ev_signal_pair[0] = -1; 221 base->sig.ev_signal_pair[1] = -1; 222 223 base->evbase = NULL; 224 /*尋找合適的I/O複用機制,在這裏說明,libevent庫使用的I/O機制是在編譯的時候肯定的 225 其實evbase和某一個複用機制的關係就像類和對象的關係同樣,複用機制是evbase的具體實現 226 */ 227 printf("default is selected %d %d %d\n", HAVE_EPOLL, :qHAVE_POLL, HAVE_SELECT); 228 229 /*eventops 是一個全局的結構體,結構體中都是不一樣內核所支持的幾種I/O複用機制*/ 230 for (i = 0; eventops[i] && !base->evbase; i++) { 231 base->evsel = eventops[i];