lighttpd io 多路复用分析

Posted voipmaker

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了lighttpd io 多路复用分析相关的知识,希望对你有一定的参考价值。




在web服务器中,主要就是向socket写数据和从socket读数据。通常,web服务器是IO密集型程序,这就要求在数据的读写上,web服务器必须能够具有很好的性能,不会因为某个socket的阻塞而致使其他socket也被阻塞,否则会大大降低服务器的性能。因此,大部分的web服务器都采用非阻塞IO进行数据的读写。lighttpd通过fdevent系统,采用类似OO中面向对象的方式将对IO事件的处理进行封装,对于不同的IO系统,提供一个统一的接口,其核心机制与libevent/libev库大同小异,都是采用了所谓的Reactor模式,也就是非阻塞IO加多路复用(non-blocking IO + IO multiplexing),lighttpd通过fdevent将各种操作系统上支持的io多路复用实现进行封装,常用的io多路复用技术包括select, poll,kqueue,epoll. select应该是最原始了,基本所有类unix系统都支持,然后是poll,poll是select的升级版,并不是所有类unix系统都支持,bsd系列没有实现,poll主要解决select对单进程最大fd数的限制,但仍然没改变其轮训的本性。kqueue 是bsd系列操作系统提供的解决select,poll的性能问题,最后是明星级的 epoll,是linux 2.6 版本以后实现的一个类kqueue的东东,流行的高性能web服务器(nginx,lighttpd),cache服务器(memcached,varnish)在linux下基本都用的epoll做io事件监听,当然,为了可移植性,大多实现都对上面各种io模型进行封装,用户可以通过配置方式灵活选择。



接下在看看lighttpd 中fdevent是怎么封装的以上各种io模型。


fdevent对外提供了io模型的通用接口,而具体实现则在相应的io模型文件中。




//统一的操作接口,与后面的函数声明对应。


int (*reset) (struct fdevents * ev);
void (*free) (struct fdevents * ev);
int (*event_add) (struct fdevents * ev, int fde_ndx, int fd, int events);
int (*event_del) (struct fdevents * ev, int fde_ndx, int fd);
int (*event_get_revent) (struct fdevents * ev, size_t ndx);
int (*event_get_fd) (struct fdevents * ev, size_t ndx);
int (*event_next_fdndx) (struct fdevents * ev, int ndx);
int (*poll) (struct fdevents * ev, int timeout_ms);
int (*fcntl_set) (struct fdevents * ev, int fd);





上面为fdevent结构内部的函数指针,具体实现在每个io模型对应的文件中,


如 epoll实现在 文件fdevent_linux_sysepoll.c中,这体现了面向对象的设计思想。

fdevent的接口很清晰,使用过程与libevent类似,在一个闭合循环内部:


 fdevent_init :初始化 ,对于epoll,调用epoll_create

 fdevent_register ,注册某fd上发生的事件对应的回调,比如server的fd.

 fdevent_add,添加某fd事件类型(in, out), 与fdevent_register 配对使用。



while(1)


 fdevent_poll ,等待io事件并触发上面设置的回调。


下面为lighttpd  初始化框架,没考虑 module及connection 建立后的状态机。


 1. network_init , 初始化socket(socket, bind, listen)

 2. fork process (初始化若干子进程)

3. fdevent_init (初始化事件triger模块,记住,fdevent在fork之后)

4. fdevent_register(注册server in事件回调)

5. 

while(!is_shutdown)

fdevent_poll();


 


以上是关于lighttpd io 多路复用分析的主要内容,如果未能解决你的问题,请参考以下文章

Libevent源码分析--- IO多路复用模型

Libevent源码分析--- IO多路复用模型

IO模型以及多路复用基本原理

Python IO多路复用select模块

IO多路复用 -- 2019-08-16 19:10:29

IO多路复用 -- 2019-08-16 19:17:42