zoukankan      html  css  js  c++  java
  • 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
    ", __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
    ", 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];


  • 相关阅读:
    python数据结构之树(二叉树的遍历)
    python数据结构之树(概述)
    python面向对象高级:定制类
    python面向对象高级:Mixin多重继承
    frp
    CentOS7 安装远程桌面
    Java-JVM 锁优化
    Java-内存模型 synchronized 的内存语义
    Java-内存模型 final 和 volatile 的内存语义
    Java-内存模型(JSR-133)
  • 原文地址:https://www.cnblogs.com/haoxing990/p/6910676.html
Copyright © 2011-2022 走看看