libevent源码分析--epoll_add()函数

首先看看add函数实在event_add函数中调用的,肯定是evsel->add的方式调用的。

259 static int

260 epoll_add(void *arg, struct event *ev)
261 {
262     struct epollop *epollop = arg;
263     struct epoll_event epev = {0, {0}};
264     struct evepoll *evep;
265     int fd, op, events;
266
267     if (ev->ev_events & EV_SIGNAL)
268         return (evsignal_add(ev));
269
270     fd = ev->ev_fd;
271     if (fd >= epollop->nfds) {
272         /* Extent the file descriptor array as necessary */
273         if (epoll_recalc(ev->ev_base, epollop, fd) == -1)
274             return (-1);
275     }
276     evep = &epollop->fds[fd];
277     op = EPOLL_CTL_ADD;
278     events = 0;
279     if (evep->evread != NULL) {
280         events |= EPOLLIN;
281         op = EPOLL_CTL_MOD;
282     }
283     if (evep->evwrite != NULL) {
284         events |= EPOLLOUT;
285         op = EPOLL_CTL_MOD;
286     }
287
288     if (ev->ev_events & EV_READ)
289         events |= EPOLLIN;
290     if (ev->ev_events & EV_WRITE)
291         events |= EPOLLOUT;
292
293     epev.data.fd = fd;
294     epev.events = events;
295     if (epoll_ctl(epollop->epfd, op, ev->ev_fd, &epev) == -1)
296             return (-1);
297
298     /* Update events responsible */
299     if (ev->ev_events & EV_READ)
300         evep->evread = ev;
301     if (ev->ev_events & EV_WRITE)
302         evep->evwrite = ev;
303
304     return (0);
305 }

这个时候传递的是两个参数,第一个参数是void*,但是在event_add中使用的是evsel->add(evbase,ev);这个时候就明白了evbase的用处,同时再回忆一下evsel,是一个struct eventop,而这里的epoll_add中将第一个参数转化为struct epollop,而struct  epollop就是上篇文章中主要介绍的那个,就是epoll_init主要初始化的一个结构体,咱们看看在event_init()中调用evsel->init返回的东西是什么,返回的即使void*,正好,也就是说,一种I/O复用机制对应一个这样的结构体,在select对应的就是struct selectop结构体。其实这也没有什么课奇怪的!

event_add就是将struct event类型的ev转化为epoll机制认识的struct epoll_event ,并将其存放到struct epollop,这么说,在上层框架中封装了具体实现,且看且分析。267行判断ev的类型,如果是EV_SIGNAL,直接将这个ev添加到信号队列中。

271判断ev的描述符,不行的话重新申请空间。注意276行,在struct epollop结构体中有一个字段fds,这个就是指向了nfds个struct evepoll,而struct evepoll都是可读可写的struct event.

从276到292都是为了一个struct epoll_event封装做准备,这里的变量名是epev。

根据fds取出evepoll,也就是276行,赋值给evep,再根据函数第二个参数组合 到293行组合好了一个struct epoll_event epev。然后添加到epfd中。

然后299行到结束更新这个evep的相关内容。其实epoll_del和add很相似,这里不多加累述,下面分析另一个重要的函数epoll_dispatch()

你可能感兴趣的:(libevent)