libevent事件(三)---event_add和epoll_add
来源:互联网 发布:专业检测手机信号软件 编辑:程序博客网 时间:2024/05/29 17:54
libevent将定时事件、信号、描述符事件都集成到event中,并且分别维护了相关的链表。
因此,event_add
和event_delete
主要是操作链表,并且调用底层的api。
1. event_add函数
首先是超时事件,timer事件用一个小根堆来表示,这个堆中的最小时间可以用来select/poll/epoll参数的最大值.
另外,添加事件分为两个内容,首先会调用底层的add回调,它有可能是epoll_ctl()
,然后会将该event添加到注册事件的链表中
intevent_add(struct event *ev, const struct timeval *tv){ struct event_base *base = ev->ev_base;//event_base const struct eventop *evsel = base->evsel;//evsel为底层的操作 void *evbase = base->evbase; int res = 0; //为timer事件分配空间,min_heap_reserve的操作实际上是realloc if (tv != NULL && !(ev->ev_flags & EVLIST_TIMEOUT)) { if (min_heap_reserve(&base->timeheap, 1 + min_heap_size(&base->timeheap)) == -1) return (-1); /* ENOMEM == errno */ }//reserve //添加事件 if ((ev->ev_events & (EV_READ|EV_WRITE|EV_SIGNAL)) && !(ev->ev_flags & (EVLIST_INSERTED|EVLIST_ACTIVE))) { res = evsel->add(evbase, ev);//底层回调函数 if (res != -1) event_queue_insert(base, ev, EVLIST_INSERTED);//event插入队列 } /* * we should change the timout state only if the previous event * addition succeeded. */ if (res != -1 && tv != NULL) {//当上一步操作成功时,如果是timer事件将调整timer堆 struct timeval now; /* * we already reserved memory above for the case where we * are not replacing an exisiting timeout. */ //表明event已经在timer堆中了,删除旧的 if (ev->ev_flags & EVLIST_TIMEOUT) event_queue_remove(base, ev, EVLIST_TIMEOUT); /* Check if it is active due to a timeout. Rescheduling * this timeout before the callback can be executed * removes it from the active list. */ if ((ev->ev_flags & EVLIST_ACTIVE) && (ev->ev_res & EV_TIMEOUT)) { /* See if we are just active executing this * event in a loop */ if (ev->ev_ncalls && ev->ev_pncalls) { /* Abort loop */ *ev->ev_pncalls = 0; } event_queue_remove(base, ev, EVLIST_ACTIVE); } gettime(base, &now);//计算时间并插入到timer的小根堆中 evutil_timeradd(&now, tv, &ev->ev_timeout);//宏定义:timeout= now + tv event_queue_insert(base, ev, EVLIST_TIMEOUT); } return (res);}
epoll_add函数
上文提到,相同的接口会调用特定的回调,以epoll为例,将调用封装的epoll_add
static intepoll_add(void *arg, struct event *ev){ struct epollop *epollop = arg; struct epoll_event epev = {0, {0}}; struct evepoll *evep; int fd, op, events; if (ev->ev_events & EV_SIGNAL) return (evsignal_add(ev)); fd = ev->ev_fd; if (fd >= epollop->nfds) { /* Extent the file descriptor array as necessary */ if (epoll_recalc(ev->ev_base, epollop, fd) == -1) return (-1); } evep = &epollop->fds[fd]; op = EPOLL_CTL_ADD; events = 0; if (evep->evread != NULL) { events |= EPOLLIN; op = EPOLL_CTL_MOD; } if (evep->evwrite != NULL) { events |= EPOLLOUT; op = EPOLL_CTL_MOD; } if (ev->ev_events & EV_READ) events |= EPOLLIN; if (ev->ev_events & EV_WRITE) events |= EPOLLOUT; epev.data.fd = fd; epev.events = events; if (epoll_ctl(epollop->epfd, op, ev->ev_fd, &epev) == -1) return (-1); /* Update events responsible */ if (ev->ev_events & EV_READ) evep->evread = ev; if (ev->ev_events & EV_WRITE) evep->evwrite = ev; return (0);}
首先来看传进来的两个参数,在event_add
中有如下调用evsel->add(evbase,ev)
,这个时候就明白evbase的作用了,在event_base_new
调用中,
有base->evbase=base->evsel->init(base)
,回调函数将最终调用epoll_init
创建一个struct epollop
结构体,并返回指针,为什么要这么做?
本质上来说,还是为了可移植性,对于select也会有struct selectop这样的结构体
再看epoll_add
函数,将封装的struct event
和struct epollop
结构体,转化为epoll认识的struct epoll_event
中
1 0
- libevent事件(三)---event_add和epoll_add
- [libevent]epoll_add()
- [libevent]event_add()
- libevent源码分析--epoll_add()函数
- [libevent源码分析] event_add
- [libevent源码分析] event_add
- libevent源码分析--event_add()函数
- event_add
- libevent源码分析--epoll中的几个函数 epoll_init epoll_add epoll_dispatch
- Libevent参考手册:与事件循环一起工作(三)
- libevent(三)事件注册与循环监听
- libevent高性能网络库源码分析——事件(event)及其接口(三)
- libevent库介绍--事件和数据缓冲
- Libevent源码分析(四)--- libevent事件机制
- Libevent源码学习(三) 事件内部流程解析上部
- 委托和事件(三)
- libevent项目分析(四) -- 事件驱动
- libevent事件(二)---event源码
- hdu3001 三进制 状态压缩dp
- <Linux>Linux内核启动分析(二)——start_kernel
- CSDN日报20170420 ——《开发和产品之间的恩怨从何来?》
- 前端实现tooltip的常见实现方式
- 【HTNML】美化自定义列表
- libevent事件(三)---event_add和epoll_add
- 微信支付 常见报错
- BZOJ 1787 [Ahoi2008]Meet 紧急集合——LCA
- 高性能JavaScript 重绘与重排
- skynet任务调度分析
- 链队列
- 经典蓝牙的基本操作
- 斯坦福「AI百年研究」首份报告:2030年的人工智能与生活
- HDU 5783 Divide the Sequence