第八章第一节 I/O框架库概述
前言
前面三章详细地介绍了Linux服务器程序必须处理的三类事件:I/O事件、信号、定时事件;在处理这三类事件时网络程序要考虑如下三个问题。
- 统一事件源。
- 可移植性。不同的操作系统具有不同的I/O复用方式;Solaris采用/dev/poll文件、FreeBSD采用kqueue机制、Linux采用epoll系列系统调用;
- 并发。在多进程/线程环境下,网络程序需要考虑各执行实体如何协同处理客户连接、信号与定时器;
开源社区提供了诸多优秀的I/O框架库——ACE、ASIO与Libevent。下面介绍相对轻量级的Libevent框架库。
I/O框架库概述
I/O框架库一库函数的形式,封装了较为底层的系统调用,想应用程序提供一组更便于使用的接口。这些库函数经受住了真实网络环境下的高压测试,以及时间的考验。
句柄Handle
I/O框架库处理的对象(I/O事件,信号与定时事件)统一称为事件源。一个事件源绑定一个句柄;例如,在Linux环境下,I/O事件对应的句柄是文件描述符,信号事件对应的句柄是信号值。
事件多路分发器
I/O框架库将系统支持的各种I/O复用系统调用封装成统一的接口——事件多路分发器EventDemultiplexer。事件多路分发器的demultiplex方法是等待事件的核心函数,其内部调用的是select、poll、epoll_wait等函数。
此外,事件多路分发器还需要实现register_event与remove_event方法,以便应用程序向事件多路分发器添加事件与删除事件。
(具体)事件处理器
事件处理器执行事件对应的业务逻辑,它通常包含一个或多个handle_event回调函数。I/O框架库提供的事件处理器只是一个接口,应用程序需要继承该接口来实现具体的事件处理器,即具体事件处理器。
此外,事件处理器还提供get_handle方法,它返回与该事件处理器关联的句柄。
Reactor
Reactor是I/O框架库的核心。它提供如下几个方法。
- handle_events。handle_events方法执行事件循环,重复如下过程:等待事件,然后依次处理所有就绪事件对应的事件处理器;
- register_handler。register_handler方法调用事件多路分发器的register_event方法来向事件多路分发器中注册一个事件;
- remove_handler。remove_handler方法调用事件多路分发器的remove_event方法来删除事件多路分发器中的一个事件;
小结
I/O框架库的工作时序图如下。