libev源码分析1

watcher初始化及启动
ev_io:
初始化:
    首先调用ev_init,设置watcher的初始化状态,包括:active = 0, pending = 0, priority = 0以及回调函数;
    再调用ev_io_set, 设置watcher所关注的文件描述符(fd)以及事件(event)。
    可以一次性调用ev_io_init进行上述两项的设置。
启动(ev_io_start):
    判断该watcher是否已经启动,如果是,则直接返回;
    断言该watcher关注的文件句柄以及事件是否设置正确;
    调用ev_start,对该watcher的优先级进行调整(系统默认的优先级范围-2 ~ +2),设置watcher的状态active为1,对相应消息循环中active watcher的个数加1;
    调用array_needsize,为相应的消息循环分配保存文件描述符的ANFD anfds(数组以文件描述符作为下标,相同文件描述符的watcher以链表连接)空间,anfdmax记录该数组的容量(需要时该容量自动扩充);
    调用wlist_add,将watcher添加到相应文件描述符的链表中;
    调用fd_change,设置新增加或改变的文件描述符,记录在fdchanges数组中,fdchangecnt记录数组下标,fdchangemax记录数组容量(需要时该容量自动扩充)。

ev_timer:
初始化:
    首先调用ev_init,设置watcher的初始化状态,包括:active = 0, pending = 0, priority = 0以及回调函数;
    再调用ev_timer_set, 设置watcher所关注的触发时间点(at)以及重复次数(repeat)。
    可以一次性调用ev_timer_init进行上述两项的设置。
启动(ev_timer_start):
    判断该watcher是否已经启动,如果是,则直接返回;
    设置定时器实际触发时间(at),at += loop->mn_now;
    将该消息循环中定时器个数(timercnt)加1;
    调用ev_start,对该watcher的优先级进行调整(系统默认的优先级范围-2 ~ +2),设置watcher的状态active为3(如果再向该消息循环中增加ev_timer,则下一个watcher的active值为上个watcher的active值加1),对相应消息循环中active watcher的个数加1;
    调用array_needsize,为相应的消息循环分配保存触发时间的ANNE timers(数组以active值作为下标)堆空间,timermax记录该数组的容量(需要时该容量自动扩充);
    调用ANNE_w和ANNE_at_cache,设置ANNE结构体的w(watcher)以及at(触发时间);
    调用upheap,以watch的active值对timers堆进行排序。

ev_run:
    增加该消息循环的调用次数,++(loop->loop_depth);
    重新设置消息循环的状态,loop->ev_break = EVBREAK_CANCEL;
    在首次循环之前,调用所有pending watcher的回调;
循环:
    如果使用了EVFLAG_FORKCHECK,则检查是否产生了新的子进程;
    如果检测到新的子进程,则所有fork watchers加入到pending消息队列并调用回调;
    将所有的prepare watchers加入到pending消息队列并调用回调;
    如果调用了ev_break, 则消息循环结束;
    如果产生了forked消息,重新设置内核状态防止进程之间相互影响;
    更新所有未解决的改变的内核状态;
    更新事件循环时间(ev_now());
    计算该消息循环需要block或sleep多长时间或者不sleep(有激活的idle watchers,设置了EVRUN_NOWAIT或根据就没有任何激活的watchers);
    Sleep if the I/O and timer collect interval say so(?);
    增加该消息循环循环次数,++(loop->loopcount);
    阻塞进程,调用后端相应操作系统提供的事件检测机制,等待事件发生;
    将所有未解决的I/O(fd)事件加入到pending队列;
    更新事件循环时间(ev_now())并进行可能的时间调整;
    将所有超时的定时器(timer)加入到pending队列;
    将所有超时的周期(periodics)加入到pending队列;
    将所有优先级大于pending队列中的idle watchers加入到pending队列;
    将所有check watchers加入到pending队列;
    以反序调用所有加入pending队列的watchers(例如:首先是check watchers)。信号和fork watchers是以I/O watcher的方式进行声明,所以也会在这里得到处理;
    如果ev_break被调用,或设置了EVRUN_ONCE|EVRUN_NOWAIT,或没有激活的watchers,则消息循环结束,否则继续循环;
结束:
    如果消息循环状态为EVBREAK_ONE,则重新设置为EVBREAK_CANCEL;
    减少该消息循环的调用次数,--(loop->loop_depth);
    返回,该消息循环中处于active状态的watcher个数。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值