赞
踩
注意:
- //在event.c中, 这里面省略了些许不相关代码
- int
- event_base_loop(struct event_base *base, int flags)
- {
- /* Grab the lock. We will release it inside evsel.dispatch, and again
- * as we invoke user callbacks. */
- //获取锁, 且是在调用evsel->dispatch() 前释放的锁, 需要配合evsel->dispatch的多线程逻辑
- EVBASE_ACQUIRE_LOCK(base, th_base_lock);
-
- //一个base在一个时间段内只能被一个线程运行
- if (base->running_loop) {
- ... ...(error)
- }
-
- //如果在event_base_dispatch之前, 有对信号的event_add调用, 那么 base->sig.ev_signal_added就会为1
- //反之, 如果用户没有要求关注任何信号, 那么这个if就会被跳过了
- //这个函数的目的在于为libevent的信号模块设置全局变量, 比如指定接收信号的base是哪个, 要监听几个信号, IO复用中信号事件的管道一端是哪个
- if (base->sig.ev_signal_added && base->sig.ev_n_signals_added)
- evsig_set_base(base);
-
- done = 0;
-
-
- base->event_gotterm = base->event_break = 0;
-
- while (!done) {
- base->event_continue = 0;
-
- /* Terminate the loop if we have been asked to */
- if (base->event_gotterm) {
- break;
- }
-
- if (base->event_break) {
- break;
- }
-
- timeout_correct(base, &tv);
-
- tv_p = &tv;
- //如果此时没有已经激活的事件需要处理(如果对这里有疑惑, 那么还请继续往下看, 先假设是第一次启动base), 并且base不是非阻塞的, 此时就要为base指定一个超时时间
- //timeout_next函数就是用来指定新的超时时间的, 看此函数下面的解析
- if (!N_ACTIVE_CALLBACKS(base) && !(flags & EVLOOP_NONBLOCK)) {
- timeout_next(base, &tv_p);
- } else {
- /*
- * if we have active events, we just poll new events
- * without waiting.
- */
- evutil_timerclear(&tv);
- }
-
- /* If we have no events, we just exit */
- //没有事件, 且没有激活事件,说明没有事情要base做,即可退出
- if (!event_haveevents(base) && !N_ACTIVE_CALLBACKS(base)) {
- event_debug(("%s: no events registered.", __func__));
- retval = 1;
- goto done;
- }
-
- /* update last old time */
- gettime(base, &base->event_tv);
-
- clear_time_cache(base);
-
- //这就是核心的IO复用函数调用, 就涉及我们要讨论的处理激活事件的过程
- //所以看到这里, 我希望可以转到evsel->dispatch函数中去了解其中的内容, 接着继续回到这里
- //概括性的来说, evsel->dispatch的目的是在得知有数据要来后, 将对应的文件描述符激活
- res = evsel->dispatch(base, tv_p);
-
- if (res == -1) {
- ... ...(error)
- goto done;
- }
-
- upd
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。