Redis源码剖析(二)io多路复用函数及事件驱动流程

作为服务器监听客户端请求的方法,io多路复用起到了不可忽略的作用,利用io复用监听的方法叫Reactor模式,在前一篇也提到过,使用io复用是现在常用的提高并发性的方法,而且效果显著。

通常io多路复用连同事件回调是一起出现的,在将文件描述符(套接字)注册到io多路复用函数中时,同时也需要保存当这个文件描述符被激活时调用的函数(称作回调函数),这样,使用者无需考虑何时事件被激活又何时调用相应处理函数,只管注册即可,执行回调函数的任务由Reactor接管,极大提高了并发性

在C语言中,回调函数通常是以函数指针的形式出现的(参考libevent)

在C++语言中,回调函数可以是函数指针,但是通常会是通过std::bind绑定的std::function对象,当然随着C++11的出现,也可以以lambda代替std::bind

既然Redis是C语言实现的,就老老实实使用函数指针好了,不过在此之前,先简单复习一下io多路复用函数

io多路复用函数

Linux平台三种io多路复用函数的区别

在不同的平台(linux,window),存在着不同的io复用函数,以Linux平台为例,就有select,poll,epoll三种,这三种的区别主要在于监听事件的底层方法不同,从而导致效率的差异

  • select是早期Linux引入的io复用函数,底层采用轮询的方法判断每个文件描述符是否被激活。所谓轮询就是一遍遍的遍历,依次判断每一个文件描述符的状态,效率可想而知,慢
  • poll是在select之后引入的,使用方法上稍微简单于select,但是仍然没有摆脱轮询带来的问题
  • epoll作为轮询的终结者,底层没有采用轮询的方法,而是基于事件回调的。简单的说,就是在内核中当文件描述符被激活时都会调用一个回调函数,epoll根据回调函数直接定位文件描述符,极大提高了效率,同时也减轻了CPU的负担,不用一遍遍轮询

当然,除了效率问题,三者在使用上也是存在诸多差异

select接口

/* 
 * maxfds    : 最大的文件描述符 + 1
 * readfs    : 可读事件集
 * writefds  : 可写事件集
 * exceptfds : 其它(错误)事件集
 * tvptr     : 超时时间
 */
int select(int maxfds, fd_set* readfds, fd_set* writefds, fd_set* exceptfds, struct timeval* tvptr);

其中fd_set结构保存的是需要监听的文件描述符,select将可读,可写,其它(错误)事件分开监听,返回被激活描述符的个数。但是仍需要一个一个遍历使用FD_ISSET判断是否被激活

poll接口

/* 
 * fdarray[] : 监听事件集
 * nfds      : 监听事件个数
 * timeout   : 超时时间
 */
int poll(struct pollfd fdarray[], nfds_t nfds, int timeout);

在pollfd结构中保存需要监听的文件描述符,需要监听的事件,激活原因。使用起来比select简便的多

epoll接口

/* 
 * epollfd   : epoll文件描述符,用于监听所有的注册事件
 * events    : 保存所有激活事件
 * maxevents : events最大可容纳的激活事件个数
 * timeout   : 超时时间
 */
int epoll_wait(int epollfd, struct epoll_event* events, int maxevents, int timeout);

epoll_event结构保存了监听的文件描述符,监听的事件以及激活原因,与select和poll不同的是,epoll_wait直接将所有激活的事件保存在events中,这样就不需要一个个遍历判断哪个激活了

Redis对io多路复用的封装

接下来以epoll为例,了解Redis内部是如何封装io多路复用的

为了将所有io复用统一,Redis为所有io复用统一了类型名aeApiState,对于epoll而言,类型成员就是调用epoll_wait所需要的参数

//ae_epoll.c
typedef struct aeApiState {
    int epfd; //epollfd,文件描述符
    struct epoll_event *events; //保存激活的事件(epoll_event)
} aeApiState;
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值