epoll的实现原理
epoll是Linux IO多路复用的管理机制。
一 epoll的数据结构
epoll主要由两个结构体:总集和就绪队列。总集指的是epoll中存储的全部fd节点。就绪队列指的是IO操作已经准备就绪的epoll节点。
总集所选择的数据结构是红黑树。和hash相比,红黑树容易扩充,和B/B+树相比,红黑树的搜索效率比较高。因此红黑树最适合作为总集的数据结构。
就绪队列的数据结构是队列。
在epoll中,每个fd只有一个节点。当把某个红黑树的节点放入就绪队列时,不需要复制它,只需要改变此节点的指针就好。
总集的数据结构代码如下:
#define RB_ENTRY(type) \
struct { \
struct type *rbe_left; /* left element */ \
struct type *rbe_right; /* right element */ \
struct type *rbe_parent; /* parent element */ \
int rbe_color; /* node color */ \
}
#define LIST_ENTRY(type) \
struct { \
struct type *le_next; /* next element */ \
struct type **le_prev; /* address of previous next element */ \
}
struct epitem {
RB_ENTRY(epitem) rbn;
LIST_ENTRY(epitem) rdlink;
int rdy; //exist in list
int sockfd;
struct epoll_event event;
};
二 协议栈、epoll模块和应用层通信
协议栈通过回调函数调到epoll,主要步骤有2个:
1.通过fd查找对应节点。
2.通过fd
epoll_create(1);在内核里创建一个总集的数据结构
epoll_ctl();
epoll和poll/select的区别:
1.使用:select/poll需要把总集拷贝到内核中,epoll不用。
1.实现原理:select/poll,循环遍历总集,是否需要有就绪epoll。
三 epoll如何加锁
四 et与lt如何实现
如果用户空间的epoll_wait()一次最多只能copy50个,而协议栈中有100个,那么会自动拷贝两次。