libevent 事件loop分析
来源:互联网 发布:淘宝客服怎么登陆千牛 编辑:程序博客网 时间:2024/04/29 09:07
event_init初 始化libevent事件全局对象current_base
初始化全局current_base是一个进程的个全局的变量
struct event_base *
event_init(void)
{
struct event_base *base = event_base_new();
event_init(void)
{
struct event_base *base = event_base_new();
if (base != NULL)
current_base = base; <-----------
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 */
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 */
int event_break; /* Set to terminate loop immediately */
/* active event management */ 活动事件管理
struct event_list **activequeues ; 活动事件链表
int nactivequeues;
struct event_list **activequeues ; 活动事件链表
int nactivequeues;
/* signal handling info */ 信号处理
struct evsignal_info sig;
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 }
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); <-----------
}
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;
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;
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;
}
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);
}
}
}
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);
}
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);
}
/* 有活动事件,轮询新事件
* 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);
gettime(base, & base->event_tv);
/* clear time cache */
base->tv_cache.tv_sec = 0;
base->tv_cache.tv_sec = 0;
开始进入epoll_wait函数,这里要注意到 tv_p 是上面 < -------------------------
res = evsel->dispatch (base, evbase, tv_p );
if (res == -1) 有错误则退出
return (-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_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);
}
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;
};
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;
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;
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;
}
/* 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);
}
if (errno != EINTR) {
event_warn("epoll_wait");
return (-1);
}
evsignal_process (base); 信号处理函数
return (0);
}
return (0);
}
else if (base->sig.evsignal_caught) {
evsignal_process(base);
}
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;
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;
}
evread = evep->evread;
evwrite = evep->evwrite;
} else {
if (what & EPOLLIN) {
evread = evep ->evread;
}
if (what & EPOLLOUT) {
evwrite = evep ->evwrite;
}
}
evwrite = evep ->evwrite;
}
}
if (!(evread||evwrite))
continue;
continue;
if (evread != NULL)
event_active (evread, EV_READ, 1);
if (evwrite != NULL)
event_active (evwrite, EV_WRITE, 1);
}
event_active (evread, EV_READ, 1);
if (evwrite != NULL)
event_active (evwrite, EV_WRITE, 1);
}
return (0);
}
}
0 0
- libevent 事件loop分析
- libevent 事件loop分析
- libevent事件处理框架分析
- libevent事件处理框架分析
- libevent事件处理框架分析
- Libevent:4event loop
- libevent源码分析--libevent库对信号事件的处理
- Libevent源码分析(四)--- libevent事件机制
- libevent项目分析(四) -- 事件驱动
- libevent源码分析--事件处理框架
- libevent源码分析--事件处理框架
- libevent源码分析--I/O事件
- libevent源码分析之事件激活
- libevent源码分析--事件处理框架
- libevent源码学习-----事件驱动流程分析
- Libevent分析
- libevent项目分析 (二) -- I/O多路复用基础 .事件驱动
- libevent源码分析---基本使用场景和事件流程
- zoj 1232 Adventure of Super Mario (Floyd+dp)
- CentOS6.5_x64安装VNCserver
- Linux命令:find与exec参数的用法
- layoutSubviews与drawRect
- Java 如何实现非阻塞的安全通信?
- libevent 事件loop分析
- WebService CXF 中的拦截器(Interceptor)
- IT人士必去的10个网站
- SpringMVC文件上传
- JDK的一些安装配置
- 三个微内核和四个名字的故事
- GitHub详细教程
- EggUI计划——项目架构
- hdu4975 网络流解方程组(网络流+dfs判环或矩阵DP)