总结epoll

参考链接

epoll 的本质是什么?

总结

epoll本质的第一步 是知道网卡把从网线接收到的数据写进内存,第二步如何知道接收到了数据,是网卡写完以后给cpu发送一个中断信号,然后操作系统知道了再去执行网卡中断程序,第三步为什么recv或者accept这样的阻塞方法不占用cpu资源呢?可以从操作系统进程管理的角度来理解,假设有三个进程A B C同时运行着,那么他们都在工作队列里面,被cpu分时执行,这时候进程A创建了一个socket对象,对象包含发送缓冲区 接受缓冲区和等待队列,执行recv的时候操作系统会把进程A的引用从工作队列移入到等待队列,这样就不占用cpu资源了,等到socket接收到数据之后,操作系统再把进程A从等待队列移入工作队列,也就是唤醒进程A,此时接收缓冲区已经有数据了,recv方法就可以返回了。那么操作系统如何知道网络数据对应着哪个socket,实际上网络数据包里面包含ip和端口,操作系统会维护端口号到socket的索引结构。如何同时监听多个socket数据?最先的select采用一个数组,将所有监视的socket放进去轮询,接收缓冲区有数据了就唤醒,从等待队列移到工作队列,但是进程被唤醒之后,程序并不知道是哪个socket被唤醒了,所以悲剧的要遍历两次,内核一次程序一次,而且为了性能考虑最多只能1024个。epoll的优化,一是一次性先添加所有的需要监听的socket对象,然后再等待数据。二是不是程序不知道哪个socket有数据了么,那就操作系统维护一个列表rdlist,只要获取rdlist就知道哪个socket收到数据了。实际上是在socket和进程之间引入了一个中间层eventpoll,用eventpoll的成员变量来维护等待队列wq,就绪队列rdlist。就绪队列rdlist要快速插入删除,所以采用的是双向链表结构,索引要监视的socket,要方便添加删除还要方便搜索防止重复添加,所以采用的是红黑树。