Libevent第二弹

使用libevent首先要创建一个event_base来保存真个运行的环境。event_base_new函数调用的是event_base_new_with_config函数。

然后创建event对应的事件,同时对事件进行相应的初始化。event_new函数转调用的是event_assign函数。

然后就是将event添加到event_base中,使用的函数时event_add。

然后就进入主循环进行监听了,event_base_loop函数,由于会对event_base中保存的队列进行修改,如果在多线程模式下,是需要使用锁机制来进行同步操作。

简单的说,查看监听的文件描述符是否是一个activate状态,如果是activate的状态就将其添加到activate队列当中,然后交给后续进行处理。后续会将该文件描述符上面对应的所有的事件统一的放入到优先级队列当中,event_base维护了一个优先级队列的数组。并且事件相应的状态也会变成activate的状态。

最后剩下的就是处理优先级队列中的激活时间的队列了。因为已经添加到了优先级队列当中,因此,可以直接以遍历数组的形式来直接处理优先级队列上面的事件。

核心就是直接调用但是注册事件时候的回调函数就可以了。

优先级队列的设置应该在程序运行之前,因为一旦程序开始运行了,就不能再次设置优先级数组的大小了。这是在event_priority_set函数中规定的。

event事件的状态是在不断的进行变迁,将event插入到优先级队列中的时候之前的就绪状态设置成为activate状态。默认优先级是取优先级的中位数。

上面描述的是传统的套接字文件描述符的处理,libevent的强大之处在与可以同时处理信号事件和定时器事件。

LIbevent是如何做到的呢? 是采用统一事件源的方式,也就是说将信号处理事件变成IO处理事件。

当一个信号发生的时候,会调用信号处理的回调函数,就会在回调函数中向一个管道中写数据,同时将这个管道提前加入到IO复用函数中,这个时候这个管道就可读了。就监测并捕获了这个信号,然后在进行对应的处理即可。libevent内部使用的是socketpair类型。

libevent会为所有信号创建一个event来进行监控,根据向socketpait中写入的值的不同来区分不同的信号事件的发生。可能会向这个socketpair中同时多次写入信号,因此需要遍历这个socketpair。并记录对应信号是否发生以及发生的次数。

和IO一样,当信号事件发生了以后,会将信号时间放置到优先级队列中去,并且内部处理信号的优先级是最高的。执行信号就直接调用回调函数,因为一个信号可能会发生多次,因此需要使用循环执行信号的回调函数。

当其他线程想要往event_base中添加一个新的事件的时候吗,如何来通知evnet_base来处理这个event呢,毕竟event_base还没有将这个新的事件添加到自己所管辖的event队列中,因为也没有方法可以获得新event的状态,这个时候libevent的处理方式就和信号处理类型相似,信号处理会有一个专用的event来处理信号事件,同样,event的通知事件也采用相通的方式。

有3中通讯方式,分别是 eventfd、pipe 和 socketpair 中选择一种通信方式。创建好了以后添加到event_base中,并且设置为最高的优先级。

在没有事件处理的情况下,主线程是处于休眠状态的,如果新添加了一个event就会向,这个检测event中写一个字节,由于event_base监控了event这个事件,因此可以捕获到事件的发生,在处理这个事件的同时可以处理新添加的事件。我是觉得这种处理方式简直了。往对应文件描述符中写入一个字节,event_base 就会被唤醒,然后调用这个管道对应 event 的回调函数。当然,在 event_base 醒来的时候,还能看到其他东西。这也是 Libevent 提供唤醒功能的原因。不过如果想要libevent支持这种机制就需要在一开始的时候提供多线程使用的选项。

猜你喜欢

转载自www.cnblogs.com/randyniu/p/9495056.html