libevent解析(一)
libevent解析(一)
Fire_thief 发表于4年前
libevent解析(一)
  • 发表于 4年前
  • 阅读 140
  • 收藏 3
  • 点赞 0
  • 评论 0

腾讯云 技术升级10大核心产品年终让利>>>   

    在linux下开发网络服务程序一直在用libevent,对于我来说如果不把一个库的源代码看得八九不离十,我很难说服自己肆无忌惮地使用它。可能这是技术强迫症患者典型的症状。到今天我还是不敢说对libevent熟悉得滚瓜烂熟,即使它的代码精炼易读。但是每次回过头来重新梳理这些源代码时总会有新的收获。所以,把对libevent的使用或者分析心得记录下来,是一件很有必要的事。

    libevent是一个基于事件驱动的网络库模型,支持多种I/O多路复用:epoll,poll,select,kqueue等等。libevent由于是基于事件驱动的,所以在代码中看见大量的函数指针就很理所当然了。由于其的轻量级和高性能,就有相当部分的项目使用它:memcached, NetChat等等,其中典型的当属memcached,我很早就分析过它的网络实现部分,是很经典的libevent的用法,以至于我以后使用libevent的时候不自觉的参照memcached,并乐此不疲。libevent的轻量级不只是体现在它是C语言实现的,还体现在它专注于网络方面,不像ACE那样臃肿。而封装后既不失使用的方便性又不失使用的灵活性。

    由于使用libevent已有一段时间,就不以一个初学者的眼光通过简单的实例一步步深入分析,而是以一个过看来人的眼光从整个框架到细节来逐层分析。我也希望通过这次分析加深对其的认识,吸收精华为其所用。

    libevent使用的是Reactor模型,这是典型的时间驱动模型。下面是网上搜到的一段对Reactor的解释:

Reactor模型有几个基本组成:事件源,多路复用机制, 事件触发的处理程序, Reactor框架。

事件源:在linux上文件描述符,在windows上是Handle或者Socket。

多路复用机制(event demultiplexer):一般指I/O多路复用机制,有系统特性提供,比如epoll,select,poll,kqueue等等。

Reactor框架:对事件操作的接口,操作包括将事件注册,注销到I/O多路复用中。并在I/O多路复用器上阻塞等待事件发生,在调用相应的回调函数处理。这里的事件对应事件源中的可读可写事件。

事件触发的处理程序:当事件发生后需要处理的回调函数。

在libevent中需要关心的事件有三种:I/O读写,定时器,信号。

I/O读写只需将读写对应的文件描述的可读或可写事件注册到I/O多路复用中就可以实现对其监控。

定时器有两种方法,第一种就是和Muduo一样利用新版linux提供的timerfd_create()函数创建了一个文件描述符用于描述定时器,并将文件描述符的可读事件注册到I/O多路复用器中,但是考虑到兼容性,libevent肯定不会考虑。第二种方法根据I/O多路复用器在指定时间到达时可以超时返回的特性来实现

信号在libevent中实现得比较复杂,而且网上介绍得也比较少。首先信号肯定不能像定时器那样通过复用器的超时返回实现,因为系统没提供相应接口,其次系统也没有提供相应api来创建文件描述符来描述信号。但是总得有事件源来描述一下信号才能将其事件注册到I/O多路复用器中。万变不离其宗,现在还是要回到文件描述符上,如果现在能有一个文件描述符在指定信号发生时会有可读可写事件就行了,所以很容易想到pipe或者socketpair。用socketpair创建一对未命名的、相互连接的UNIX域套接字。这对套接字中的一个作为事件源将其可读事件注册到I/O多路复用器中,而另一个则在自定义的信号处理函数中被写入数据。这样当信号发生时套接字被写入数据而注册到I/O多路复用器中的一个套接字就会触发可读事件,这样就比较完美地实现了io,定时器,信号的统一。当然对于信号的处理需要注意很多你需要关注的不仅要区分信号还要对信号的发生次数有一个记录,不能遗漏。


共有 人打赏支持
粉丝 0
博文 6
码字总数 7916
×
Fire_thief
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
* 金额(元)
¥1 ¥5 ¥10 ¥20 其他金额
打赏人
留言
* 支付类型
微信扫码支付
打赏金额:
已支付成功
打赏金额: