libevent 信號事件實現方式

學會使用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];
相關文章
相關標籤/搜索