原创,请注明出处:http://www.cnblogs.com/stonehat/p/6286235.html
Libevent 是一个事件驱动框架, 不能仅说他是一个网络库。
notejs就是采用与libevent类似的libev来做核心驱动的。
Libevent支持三种事件:io事件、信号事件、时间事件,并且事件的设置和使用方式是一样的。
libevent的核心原理是采用io多路复用的方式来单线程处理事件。至于为什么这么说,下面会分别对三种事件进行解释。
io事件: io事件包含socket可读、可写、断开、设备可读、可写等和IO相关的事件, libevent主要采用了epoll模型来进行i/o事件的多路复用(我说的是linux上,libevent也封装了select,poll模型,下面仅说采用epoll的情况)。 一句话解释epoll模型:就是在内核管理的设备或者资源上设置等待队列,当资源出现的时候,系统会通知epoll_wait唤醒,进行事件的处理。 总的来说, i/o事件的事件驱动依赖于操作系统。
时间事件: 时间事件,可以简单的解释一下, 如果我们想在500ms后执行一段代码,那么,就可以在libevent上面设置一个时间事件,代码封装到回调函数里面去。 如果看过epoll或者select的使用方式,你就会知道epoll_wait可以设置一个timeout,等待timeout这个时长,如果没有事件发生,也会返回。时间事件的处理就 将所有时间事件要等待时间最少的设置为timeout时间,这样,即使什么i/o事件也没有发生,也能在timeout后,处理该处理的时间事件。
信号事件: 简单的解释一下, 即使和i/o无关的信号,也可以作为一个事件进行处理,信号在linux中是进程间通信方式之一, A可以发出一个信号, B可以接受信号,B接受之后可以进行一些操作,问题是, libevent想把信号事件也统一一起处理, 其原理是, 将信号事件这种和I/O无关的事件转换为和I/O有关的,充分利用现有模型统一处理。事实上, 信号事件是采用一个client socket 和一个server socket, client socket只能写, server socket只能读, server sockert将recv到的client socket的文件描述符放到了epoll的事件集合中, 永远不删。 当收到系统信号的时候, 通过client socket进行发送, server socket收到数据,就会触发epoll_wait唤醒,如果发现这是server socket的事件,就会对信号事件进行遍历找到那个等待的。
ps:个人觉得libevent应该添加字符串信号啥的自定义信号, 好扩展
事件的结构:
时间事件:采用最小堆组织, 时间最少的在顶部, 插入和删除都是log(N),主要是方便找到最小等待时间,方便设置time_out时间。
I/O事件:双向链表。
信号事件: 双向链表
激活事件:是libevent 的epoll_wait唤醒后,得到的所有要处理的事件双向链表。
主循环:
libevent采用一个主循环来处理所有事件处理和事件等待。