文章目录
一、Poller模块:描述符IO事件监控模块
二、提供的功能
对任意的描述符进行IO事件监控。
三、实现思想
(一)功能
对任意的描述符进行IO事件监控。
(二)意义
对epoll进行的封装,让对描述符进行事件监控的操作更加简单。
(三)功能设计
- 添加事件监控------ channel模块
- 修改事件监控
- 移除事件监控
- 取消定时任务
四、封装思想
cpp
封装思想: 1. 必须拥有一个epoll的操作句柄
2. 拥有一个struct epoll_event 结构数组,监控保存所有的活跃事件!
3. 使用hash表管理描述符与描述符对应的事件管理Channnel对象!
逻辑流程:
1. 对描述符进行监控,通过Channnel才能知道描述符监控什么事件
2. 当描述符就绪了,通过描述符在hash表中找到对应的Channel(得到了Channel才知道什么事件如何处理)当描述符就绪了,返回就绪描述符对应的Channel
五、代码
(一)框架
cpp
框架:
class Poller {
private:
int _epfd;
struct epoll_event_evs[xxx];
std::unordered_map<int,Channel*> mp;
private:
// 1. 判断要更新事件的描述符是否存在
// 2. 针对epoll直接操作(添加,修改,移除)
public:
// 1. 添加或者更新描述符所监控的事件
void Update(Channel* channel);
// 2. 移除描述符所监控的事件
void Remove(Channel* )
// 3. 开始监控,获取就绪Channel
};
*/
/*
(二)完整代码
cpp
#define MAX_EPOLLEVENTS 1024
// Poller模块是对epoll进⾏封装的⼀个模块,主要实现epoll的IO事件添加,修改,移除,获取活跃连接功能。
class Poller {
private:
int _epfd;
struct epoll_event _evs[MAX_EPOLLEVENTS];
std::unordered_map<int,Channel*> _channels;
private:
// 对epoll直接操作
void Update(Channel* channel,int op) {
int fd = channel->Fd();
struct epoll_event ev;
ev.data.fd = fd;
ev.events = channel->Events();
int ret = epoll_ctl(_epfd,op,fd,&ev);
if (ret < 0) {
ERR_LOG("EPOLLCTL FAILED!!!");
abort(); // 推出程序!!
}
}
// 判断一个Channel是否已经添加到了事件监控
bool hashChannel(Channel* channel) {
auto it = _channels.find(channel -> Fd());
if (it == _channels.end()) {
return false;
}
return true;
}
public:
Poller() {
_epfd = epoll_create(MAX_EPOLLEVENTS);
if (_epfd < 0) {
ERR_LOG("EPOLL CREATE FAILED!!");
abort();//退出程序
}
}
// 添加或者修改监控事件
void UpdateEvent(Channel* channel) { // 有描述符也有事件
bool ret = hashChannel(channel);
if (ret == false) {
_channels.insert(std::make_pair(channel->Fd(),channel));
return Update(channel,EPOLL_CTL_ADD); // 不存在添加
}
return Update(channel,EPOLL_CTL_MOD); // 存在了更新
}
// 移除监控事件
void removeEvent(Channel *channel) {
auto it = _channels.find(channel->Fd());
if (it != _channels.end()) {
_channels.erase(it);
}
Update(channel, EPOLL_CTL_DEL);
}
// 开始监控,返回活跃链接!
void Poll(std::vector<Channel*> *active) {
// int epoll_wait(int epfd, struct epoll_event *evs, int maxevents, int timeout)
int nfds = epoll_wait(_epfd, _evs, MAX_EPOLLEVENTS, -1);
if (nfds < 0) {
if (errno == EINTR) {
return ;
}
ERR_LOG("EPOLL WAIT ERROR:%s\n", strerror(errno));
abort();//退出程序
}
for (int i = 0; i < nfds; i++) {
auto it = _channels.find(_evs[i].data.fd);
assert(it != _channels.end());
it->second->setRevents(_evs[i].events);//设置实际就绪的事件
active->push_back(it->second);
}
return;
}
};