为什么需要设计实现 epoll
系统自带的epoll管理的是系统的 fd,要想实现用户态协议栈,管理用户态的fd,就需要设计实现用户态 epoll。
epoll中存放着大量的需要被管理的 fd 集合,被查找频率高。当 A 客户端连接上来后,协议栈中会创建一个TCB,accept()会产生一个fd,TCB会查找通知对应 fd 。 应用程序 增删改查对应的 fd 也是查找频率高的动作。
epoll 的数据结构:
epoll_item 红黑树和就绪队列共用一个节点、epoll_pool 包含红黑树和就绪队列。
有了这些基础数据结构,开始设计实现epoll。
具体实现 3 个接口
用户态 和 epoll 的交互
伪代码:
epoll_create() {
初始化 spin_lock 、条件变量 、epoll_pool 初始化
}
epoll_wait(int epfd, struct epoll_event * events, int maxevents, int timeout) {
if(timeout > 0) {
pthread_cond_timewait ( time_wait); //延时等待
} else if ( timeout < 0 ){
pthread_cond_wait();
}
//从就绪队列拷贝到数组中
pthread_spin_lock();
while(! list.empty() {
memcpy(&events[i ++], &epi->event, sizeof(epi->event));
}
}
epoll_ctl() {
get_hostinfo_fromid(int socket); //根据 fd 返回 tcp、udp、文件、epoll 等具体的 控制块 。
增加 {
加锁 spin_lock
将 epoll_item 插入红黑树中
}
删除
修改
}
协议栈 和 epoll 交互
listen 、接收、发送 、close时加入回调函数:从红黑树拷贝到就绪列表中
回调函数:epoll_event_callback(struct eventpoll* ep, int sockfd, uint32 _t event)