项目模块五:poller模块
一、模块目的
通过 epoll 来实现对描述符的IO事件监控。
二、模块设计
1、成员变量
epoll 描述符:int _epfd;
就绪事件的存储容器:struct epoll_event _evs[SIZE];
epoll_event ev;
ev.data.fd 表示关心的特定的描述符
ev.events 表示关心特定描述符的特定事件
sockfd 与 channel 指针的对应哈希表:unordered_map<int, Channel*> _channels;
2、成员函数
(1)私有函数1:对 epoll 的直接操作 void Update(Channel *channel, int op)
int epoll_ctl(int epfd, int op, int fd, struct epoll_event *ev);
(2)私有函数2:判断 channel 是否已经被监控 bool HasChannel(Channel *channel)
return _channels.find(channel->Sockfd()) == _channels.end() ? false : true;
(3)公有函数1:构造函数用来创建 _epfd
int epoll_create(int size);
size 已经不用,传一个大于0的数即可。
(4)公有函数2:添加 / 修改关心事件 void UpdateEvent(Channel *channel)
先看 channel 是否存在,存在就用 EPOLL_CTL_MOD
不存在要先添加到哈希表再用 EPOLL_CTL_ADD
(5)公有函数3:删除监控 void RemoveEvent(Channel *channel)
先删除哈希表节点再调用 Update 函数
(6)公有函数4:等待事件就绪并加入活跃队列 void Pool(vector<Channel*> *active)
int epoll_wait(int epfd, struct epoll_event *evs, int maxevents, int timeout);
返回的是等待了几个事件就绪,evs 是输出型参数,得到就绪的结构体 epoll_event,里面存有对应的描述符和就绪事件,timeout 填 -1 表示阻塞等待事件就绪。
具体流程:
先得到返回值:int nfds = epoll_wait(_epfd, _evs, sizeof _evs, -1);
再 for 循环处理:
for(int i = 0; i < nfds; i++)
{
// 先获得目标迭代器
auto it = _channels.find(_evs[i].data.fd);
// 再添加就绪事件
it->second->SetRevent(_evs[i].events);
// 最后添加活跃队列
active->push_back(it->second);
}