libevent 事件loop分析

本文详细解析了Libevent事件库的初始化过程及事件循环机制,包括核心数据结构event_base的定义,事件初始化函数event_init的工作原理,以及主事件循环函数event_dispatch的具体实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 

event_init初 始化libevent事件全局对象current_base
初始化全局current_base是一个进程的个全局的变量
 
struct event_base *
event_init(void)
{
 struct event_base *base = event_base_new();
 
 if (base != NULL)
  current_base = base;   <-----------
 
 return (base);
}
 
 
对libevent全局控制事件结构分析
struct event_base {
 const struct eventop *evsel ;       对libevent操作函数集合结构ops
 void *evbase;
 int event_count;  /* counts number of total events */  事件计数
 int event_count_active; /* counts number of active events */
 
 int event_gotterm;  /* Set to terminate loop */     主循环停止标记
 int event_break;  /* Set to terminate loop immediately */
 
 /* active event management */               活动事件管理
 struct event_list **activequeues ;        活动事件链表
 int nactivequeues;
 
 /* signal handling info */             信号处理
 struct evsignal_info sig;
 
 struct event_list eventqueue ;            事件队列

 struct timeval event_tv ;                事件时间
 
 struct min_heap timeheap ;               时间堆
 
 struct timeval tv_cache ;
};
 
main函数事件循环函数
 
 400x /*
 401x  * Wait continously for events.  We exit only if no events are left.
 402x  */
 403x
 404x int
 405x
event_dispatch (void)
 406x {
 407t>        return (event_loop (0));
 408x }
 
 
事件循环包裹函数,将全局的变量current_base 传入事件循环函数
int
event_loop (int flags)
{
 return event_base_loop(current_base , flags);     <-----------
}
 
 
current_base参数传入了
int
event_base_loop (struct event_base *base, int flags)
{
 const struct eventop *evsel = base->evsel;
 void *evbase = base->evbase;
 struct timeval tv;
 struct timeval *tv_p;
 int res, done;
 
 if (&base->sig.ev_signal_added)  如果加了信号处理
  evsignal_base = base;

 done = 0;
 while (!done) {
  /* Terminate the loop if we have been asked to */
  if (base->event_gotterm) {
如果循环退出标记,退出
   base->event_gotterm = 0;
   break;
  }
 
  if (base->event_break) {  如果事件中断,退出
   base->event_break = 0;
   break;
  }
 
  /* You cannot use this interface for multi-threaded apps */
  while (event_gotsig) {
   event_gotsig = 0;
   if (event_sigcb) {
    res = (*event_sigcb)();
    if (res == -1) {
     errno = EINTR;
     return (-1);
    }
   }
  }
  获取时间----比较当前事件时间和缓存累计时间
  timeout_correct (base, &tv );
 
  tv_p = &tv  获取时间epoll_wait的timeout时间  < -------------------------
 
    如果没有活动事件,指的是时间堆计数
  if (!base->event_count_active && !(flags & EVLOOP_NONBLOCK)) {
   
timeout_next(base, &tv_p);
  }
  else
  {
   /*  有活动事件,轮询新事件
    * if we have active events, we just poll new events
    * without waiting.
    */
   evutil_timerclear(&tv); tv值设置为0
  }
  
  /* If we have no events, we just exit */
  if (!event_haveevents(base)) { 没有epoll事件则退出loop  (base->event_count >  0) 
   event_debug(("%s: no events registered.", __func__));
   return (1);
  }
 
  /* update last old time */ 系统使用了tv_cache缓存累计时间,超过一秒更新到当前系统时间
  gettime(base, &base->event_tv);
 
  /* clear time cache */
  base->tv_cache.tv_sec = 0;
 开始进入epoll_wait函数,这里要注意到   tv_p 是上面  < -------------------------
  res = evsel->dispatch (base, evbase, tv_p );
 
  if (res == -1) 有错误则退出
   return (-1);

  gettime(base, &base->tv_cache);
 
  timeout_process(base);
 
  if (base->event_count_active) {
   event_process_active(base);
   if (!base->event_count_active && (flags & EVLOOP_ONCE))
    done = 1;
  } else if (flags & EVLOOP_NONBLOCK)
   done = 1;
 }
 
 event_debug(("%s: asked to terminate loop.", __func__));
 return (0);
}
 
struct eventop {
 const char *name;
 void *(*init)(struct event_base *);
 int (*add)(void *, struct event *);
 int (*del)(void *, struct event *);
 
int (*dispatch)(struct event_base *, void *, struct timeval *);
 void (*dealloc)(struct event_base *, void *);
 /* set if we need to reinitialize the event base */
 int need_reinit;
};
 
static int
epoll_dispatch (struct event_base *base, void *arg, struct timeval *tv)
{
 struct epollop *epollop = arg;
 struct epoll_event *events = epollop->events;
 struct evepoll *evep ;
 int i, res, timeout = -1;
 
 if (tv != NULL) 有超时时间,则换算成epoll_wait的时间
  timeout = tv->tv_sec * 1000 + (tv->tv_usec + 999) / 1000;
 
 if (timeout > MAX_EPOLL_TIMEOUT_MSEC) {
  /* Linux kernels can wait forever if the timeout is too big;
   * see comment on MAX_EPOLL_TIMEOUT_MSEC. */
  timeout = MAX_EPOLL_TIMEOUT_MSEC;
 }
 
 res = epoll_wait(epollop->epfd, events, epollop->nevents, timeout ); < -------------------------
 
 if (res == -1) {
  if (errno != EINTR) {
   event_warn("epoll_wait");
   return (-1);
  }
 
  evsignal_process (base);   信号处理函数
  return (0);
 }
 else if (base->sig.evsignal_caught) {
  
evsignal_process(base);
 }
 
 event_debug(("%s: epoll_wait reports %d", __func__, res));
 
 for (i = 0; i < res; i++) {
  int what = events[i].events;
  struct event *evread = NULL, *evwrite = NULL;
 
  evep = (struct evepoll *)events[i].data.ptr; --------> struct evepoll* ----->  struct event* rw
 
  if (what & (EPOLLHUP|EPOLLERR)) {
   evread = evep->evread;
   evwrite = evep->evwrite;
  } else {
   if (what & EPOLLIN) {
    evread = evep ->evread;
   }
 
   if (what & EPOLLOUT) {
    evwrite = evep ->evwrite;
   }
  }
 
  if (!(evread||evwrite))
   continue;
 
  if (evread != NULL)
   
event_active (evread, EV_READ, 1);
  if (evwrite != NULL)
   event_active (evwrite, EV_WRITE, 1);
 }
 
 return (0);
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值