Epoll的理解
2021-04-15 23:14:32 2 举报
Epoll的理解
作者其他创作
大纲/内容
进程B
多路复用这个词多出现在网络编程,首先理解多路.多路:有多个客户端连接,一路就是一个连接复用:一个进程或线程处理上面所有的连接。如果不复用又需要同时服务多个客户端,需要多线程或多进程,这个就不是复用了
fdlist
epoll_ctl()
CPU
工作队列
等待队列
IRQ
select和poll的缺陷:每次调用都需要提供所有需要监听的socket文件描述符集合,由于主线程时轮询调用select/poll,这样就频繁的涉及到用户态和内核态的数据拷贝;返回值为int,不能确定哪些socket处于就绪状态,只能进行新的一轮遍历socket文件描述集合。
sfd
网卡
LT(Level Triger)水平触发
执行
读缓冲区
ET(edge-triggered)是高速工作方式,只支持no-block socket。在这种模式下,当描述符从未就绪变为就绪时,内核通过epoll告诉你。然后它会假设你知道文件描述符已经就绪,并且不会再为那个文件描述符发送更多的就绪通知,直到你做了某些操作导致那个文件描述符不再为就绪状态了(比如,你在发送,接收或者接收请求,或者发送接收的数据少于一定量时导致了一个EWOULDBLOCK 错误)。但是请注意,如果一直不对这个fd作IO操作(从而导致它再次变成未就绪),内核不会发送更多的通知(only once)。ET模式在很大程度上减少了epoll事件被重复触发的次数,因此效率要比LT模式高。epoll工作在ET模式的时候,必须使用非阻塞套接口,以避免由于一个文件句柄的阻塞读/阻塞写操作把处理多个文件描述符的任务饿死。
需要监听的socket fdlist红黑树结构
LT(level triggered)是缺省的工作方式,并且同时支持block和no-block socket。在这种做法中,内核告诉你一个文件描述符是否就绪了,然后你可以对这个就绪的fd进行IO操作。如果你不作任何操作,内核还是会继续通知你的。
就绪列表rdlist双向链表结构
中断程序
socket
ET(Edge Triger)水平触发
epoll_wait()
1.epoll_create函数会去创建eventpoll对象,eventpoll对象中维护了需要监听的socket文件描述符列表、就绪列表、以及进程等待队列。2.epoll_ctl()函数会把需要监听的socket添加到socket文件描述符列表中,同时会把eventpoll对象添加到这个socket对象的等待队列中。eventpoll这个等待列表的数据结构是红黑树。红黑树是一个自平衡的二叉查询树,查询复杂度为O(logN),添加删除也都很快。3.当执行到epoll_wait()函数时,如果就绪列表中没有数据,则挂起当前进程(将当前进程从工作队列移到eventpoll对象的等待队列中,挂起当前进程);如果有数据,则直接返回。4.网络中断响应。当客户端向服务端发送数据时,网卡接受到数据后,通过硬件的DMA把socket数据拷贝到内存,这步前是没有CPU参与的。然后网卡发出网络数据发送完毕中断事件,CPU接收到中断事件后,让出执行权去执行中断程序。中断程序首先会去读取并解析内存中的数据并复制到socket的读缓冲区,然后去检查socket的等待队列,此时队列中是eventpoll对象引用,然后将当前socket添加到eventpoll对象的就绪列表的末尾。同时也会检查eventpoll对象中等待队列中进程,把她们移动到工作队列,那么这个进程又可以获得CPU执行权。就绪列表使用了双向链表的数据结构,方便快速的插入。下一次执行到epoll_wait函数时,就绪列表就有数据了。
写缓冲区
eventpoll
typedef union epoll_data { void *ptr; int fd; uint32_t u32; uint64_t u64;} epoll_data_t;struct epoll_event { uint32_t events; /* Epoll events */ epoll_data_t data; /* User data variable */};
进程A
epfd
进程C
内核空间
在调用epoll_wait()函数时,会传入一个socket事件数组指针,在epoll_wait函数返回前,会将就绪的socket引用写入这个数组指针中,然后返回。epoll_wait()函数有一个超时参数,为0时相当于非阻塞。
epoll_create()
收藏
收藏
0 条评论
回复 删除
下一页