好吧,神马都init好了,loop毕竟是个环呐,在哪跑起来呢,ok,他是ev_run的工作:

int ev_run (EV_P_ int flags)
{
#if EV_FEATURE_API
++loop_depth;
#endif assert (("libev: ev_loop recursion during release detected", loop_done != EVBREAK_RECURSE)); loop_done = EVBREAK_CANCEL; EV_INVOKE_PENDING; /* in case we recurse, ensure ordering stays nice and clean */ do
{
#if EV_VERIFY >= 2
ev_verify (EV_A);
#endif #ifndef _WIN32
if (expect_false (curpid)) /* penalise the forking check even more */
if (expect_false (getpid () != curpid))
{
curpid = getpid ();
postfork = ;
}
#endif #if EV_FORK_ENABLE
/* we might have forked, so queue fork handlers */
if (expect_false (postfork))
if (forkcnt)
{
queue_events (EV_A_ (W *)forks, forkcnt, EV_FORK);
EV_INVOKE_PENDING;
}
#endif #if EV_PREPARE_ENABLE
/* queue prepare watchers (and execute them) */
if (expect_false (preparecnt))
{
queue_events (EV_A_ (W *)prepares, preparecnt, EV_PREPARE);
EV_INVOKE_PENDING;
}
#endif if (expect_false (loop_done))
break; /* we might have forked, so reify kernel state if necessary */
if (expect_false (postfork))
loop_fork (EV_A); /* update fd-related kernel structures */
fd_reify (EV_A); /* calculate blocking time */
{
ev_tstamp waittime = .;
ev_tstamp sleeptime = .; /* remember old timestamp for io_blocktime calculation */
ev_tstamp prev_mn_now = mn_now; /* update time to cancel out callback processing overhead */
time_update (EV_A_ 1e100); /* from now on, we want a pipe-wake-up */
pipe_write_wanted = ; ECB_MEMORY_FENCE; /* make sure pipe_write_wanted is visible before we check for potential skips */ if (expect_true (!(flags & EVRUN_NOWAIT || idleall || !activecnt || pipe_write_skipped)))
{
waittime = MAX_BLOCKTIME; if (timercnt)
{
ev_tstamp to = ANHE_at (timers [HEAP0]) - mn_now;
if (waittime > to) waittime = to;
} #if EV_PERIODIC_ENABLE
if (periodiccnt)
{
ev_tstamp to = ANHE_at (periodics [HEAP0]) - ev_rt_now;
if (waittime > to) waittime = to;
}
#endif /* don't let timeouts decrease the waittime below timeout_blocktime */
if (expect_false (waittime < timeout_blocktime))
waittime = timeout_blocktime; /* at this point, we NEED to wait, so we have to ensure */
/* to pass a minimum nonzero value to the backend */
if (expect_false (waittime < backend_mintime))
waittime = backend_mintime; /* extra check because io_blocktime is commonly 0 */
if (expect_false (io_blocktime))
{
sleeptime = io_blocktime - (mn_now - prev_mn_now); if (sleeptime > waittime - backend_mintime)
sleeptime = waittime - backend_mintime; if (expect_true (sleeptime > .))
{
ev_sleep (sleeptime);
waittime -= sleeptime;
}
}
} #if EV_FEATURE_API
++loop_count;
#endif
assert ((loop_done = EVBREAK_RECURSE, )); /* assert for side effect */
backend_poll (EV_A_ waittime);
assert ((loop_done = EVBREAK_CANCEL, )); /* assert for side effect */ pipe_write_wanted = ; /* just an optimisation, no fence needed */ ECB_MEMORY_FENCE_ACQUIRE;
if (pipe_write_skipped)
{
assert (("libev: pipe_w not active, but pipe not written", ev_is_active (&pipe_w)));
ev_feed_event (EV_A_ &pipe_w, EV_CUSTOM);
} /* update ev_rt_now, do magic */
time_update (EV_A_ waittime + sleeptime);
} /* queue pending timers and reschedule them */
timers_reify (EV_A); /* relative timers called last */
#if EV_PERIODIC_ENABLE
periodics_reify (EV_A); /* absolute timers called first */
#endif #if EV_IDLE_ENABLE
/* queue idle watchers unless other events are pending */
idle_reify (EV_A);
#endif #if EV_CHECK_ENABLE
/* queue check watchers, to be executed first */
if (expect_false (checkcnt))
queue_events (EV_A_ (W *)checks, checkcnt, EV_CHECK);
#endif EV_INVOKE_PENDING;
}
while (expect_true (
activecnt
&& !loop_done
&& !(flags & (EVRUN_ONCE | EVRUN_NOWAIT))
)); if (loop_done == EVBREAK_ONE)
loop_done = EVBREAK_CANCEL; #if EV_FEATURE_API
--loop_depth;
#endif return activecnt;
}

看到了那么多ifdef有木有想shi的赶脚,尼玛。对于win32下,我们来精简下,哈哈:

 int
ev_run (EV_P_ int flags)
{
assert (("libev: ev_loop recursion during release detected", loop_done != EVBREAK_RECURSE)); loop_done = EVBREAK_CANCEL;
 //激活已经pending的事件
EV_INVOKE_PENDING; /* in case we recurse, ensure ordering stays nice and clean */ do
{
if (expect_false (curpid)) /* penalise the forking check even more */
if (expect_false (getpid () != curpid))
{
curpid = getpid ();
postfork = ;
} if (expect_false (loop_done))
break; /* update fd-related kernel structures */
fd_reify (EV_A);//把更改的事件进行更新 /* calculate blocking time */
{
ev_tstamp waittime = .;
ev_tstamp sleeptime = .; /* remember old timestamp for io_blocktime calculation */
ev_tstamp prev_mn_now = mn_now; /* update time to cancel out callback processing overhead */
time_update (EV_A_ 1e100); /* from now on, we want a pipe-wake-up */
pipe_write_wanted = ; ECB_MEMORY_FENCE; /* make sure pipe_write_wanted is visible before we check for potential skips */ if (expect_true (!(flags & EVRUN_NOWAIT || idleall || !activecnt || pipe_write_skipped)))
{
waittime = MAX_BLOCKTIME; if (timercnt)
{
ev_tstamp to = ANHE_at (timers [HEAP0]) - mn_now;
if (waittime > to) waittime = to;
} /* don't let timeouts decrease the waittime below timeout_blocktime */
if (expect_false (waittime < timeout_blocktime))
waittime = timeout_blocktime; /* at this point, we NEED to wait, so we have to ensure */
/* to pass a minimum nonzero value to the backend */
if (expect_false (waittime < backend_mintime))
waittime = backend_mintime; /* extra check because io_blocktime is commonly 0 */
if (expect_false (io_blocktime))
{
sleeptime = io_blocktime - (mn_now - prev_mn_now); if (sleeptime > waittime - backend_mintime)
sleeptime = waittime - backend_mintime; if (expect_true (sleeptime > .))
{
ev_sleep (sleeptime); //以上这么大一堆,都是在计算必要的sleep事件,其实就是阻塞嘛
waittime -= sleeptime;
}
}
} assert ((loop_done = EVBREAK_RECURSE, )); /* assert for side effect */
backend_poll (EV_A_ waittime);//这里开始调用上层封装的epool,select进行轮询,收集pending事件
assert ((loop_done = EVBREAK_CANCEL, )); /* assert for side effect */ pipe_write_wanted = ; /* just an optimisation, no fence needed */ ECB_MEMORY_FENCE_ACQUIRE;
if (pipe_write_skipped)
{
assert (("libev: pipe_w not active, but pipe not written", ev_is_active (&pipe_w)));
ev_feed_event (EV_A_ &pipe_w, EV_CUSTOM);
} /* update ev_rt_now, do magic */
time_update (EV_A_ waittime + sleeptime);
} /* queue pending timers and reschedule them */
timers_reify (EV_A); /* relative timers called last *///对pending的timer事件进行收集 EV_INVOKE_PENDING; //遍历所有pending事件
}
while (expect_true (
activecnt
&& !loop_done
&& !(flags & (EVRUN_ONCE | EVRUN_NOWAIT))
)); if (loop_done == EVBREAK_ONE)
loop_done = EVBREAK_CANCEL; return activecnt;
}

所有总结下,ev_run是libev的核心,

他主要做了五件事情:

1.更新更改的FD事件

2.进行必要的sleep

3.backend_poll收集pending的IO事件

4.收集pending的timer事件

5.调用所有pending的事件

ok,就是这样了!但是还有很多细节啊,尼玛代码之虐心,非比寻常啊!

libev学习之ev_run的更多相关文章

  1. libev学习笔记

    转 libev的使用--结合Socket编程 作者:cxy450019566 之前自己学过一些libev编程的基础,这次写压测刚好用上了,才算真正动手写了些东西,在这里做一些总结.写这篇文章是为了用浅 ...

  2. libev 学习使用

    libev 简单的I/O库.  a high performance full featured event loop written in c libev 的大小也比 libevent 小得多并且自 ...

  3. 【转载】使用事件模型 & libev学习

    参考这篇文章: http://www.ibm.com/developerworks/cn/linux/l-cn-edntwk/ 这里面使用的是 libev ,不是libevent Nodejs就是采用 ...

  4. libev学习(一)

    一.libev简介 Libev是一个事件循环:你注册感兴趣的特定事件(比如一个文件可以读取时或者发生超时时),它将管理这些事件源,将这些事件反馈给你的程序.为了实现这些,至少要在你的进程(或线程)中执 ...

  5. Libev学习笔记4

    这一节首先分析Libev的定时器部分,然后分析signal部分. 对定时器的使用主要有两个函数: ev_timer_init (&timeout_watcher, timeout_cb, .) ...

  6. Libev学习笔记3

    设置完需要监听的事件之后,就开始event loop了.在Libev中,该工作由ev_run函数完成.它的大致流程如下: int ev_run (EV_P_ int flags) { do { /* ...

  7. Libev学习笔记2

    这一节根据官方文档给出的简单示例,深入代码内部,了解其实现机制.示例代码如下: int main (void) { struct ev_loop *loop = EV_DEFAULT; ev_io_i ...

  8. Libev学习笔记1

    和Libevent相似,Libev是一个高性事件驱动框架,据说性能比Libevent要高,bug比Libevent要少.Libev只是一个事件驱动框架,不是网络库,因为它的内部并没有任何socket编 ...

  9. libev学习代码

随机推荐

  1. Java并发(一)并发编程的挑战

    目录 一.上下文切换 1. 多线程一定快吗 2. 测试上下文切换次数和时长 3. 如何减少上下文切换 4. 减少上下文切换实战 二.死锁 三.资源限制的挑战 四.本章小结 并发编程的目的是为了让程序运 ...

  2. easyui combotree combobox 使用例子

    <html xmlns="http://www.w3.org/1999/xhtml"> <head runat="server"> &l ...

  3. Android源代码下载以及异常查找网站推荐

    源代码下载:https://github.com/ 异常查找:http://stackoverflow.com/

  4. 转自:strcmp函数实现及详解

    strcmp函数是C/C++中基本的函数,它对两个字符串进行比较,然后返回比较结果,函数形式如下:int strcmp(constchar*str1,constchar*str2);其中str1和st ...

  5. 初识 ServiceWorker

    初识ServiceWorker 初识ServiceWorker 在8月份的时候.W3C更新了一个叫Service Workers的API. 了解过HTML5中的Web Worker的人可能会对这个AP ...

  6. Trusted Cloud Summit(2018.08.14)

    时间:2018.08.14地点:北京国际会议中心

  7. 使用Fortify进行代码静态分析(系列文章)

    BUG级别:低 Code Correctness(代码正确性) 1.Class does not Implement Equals(类未能实现Equals方法) Dead Code(死亡代码) 1.U ...

  8. SQL Server 启动时发生错误1069:由于登录失败而无法启动

    解决方法:    (1). 我的电脑--控制面板--管理工具--服务--右键MSSQLSERVER--属性--登陆--登陆身份--选择"本地系统帐户".    (2). 我的电脑- ...

  9. Tarjan&&缩点简析

    由于昨天写计蒜客初赛的一道题,看出了是缩点,但一时忘记了另外一个叫什么s...的算法怎么写了,话说我为什么没有回去翻一下自己的blog然后今天就去学了更实用也更强力的Tarjan Tarjan的思想其 ...

  10. 汇编 AND 运算

     AND运算  逻辑与&&  按位与& 一.AND运算 1&&12=1; 12&&0=0; 0&&1=0; 0040100 ...