select/poll/epoll多路转接
1.poll1.1 是什么为什么1.2 怎么做比如我们关心文件描述符0,34的读事件fd_set就是11001高位省略如果3和4都检测到了读事件就绪返回的时候因为0没就绪就把文件描述符对应比特置0返回的readfds就是11000也就是把设置为1的比特没有就绪的置0readfds作为输入输入型参数会相互影响1.我们一般不会同时关注读写事件一般是先读后写或者先写后读2.对读事件来讲一般默认是不就绪写事件默认就绪对于写事件一般不会常设按需设置3.后续代码暂时只关注读事件实验echoserver1.一个tcp服务器最开始有一个fd监听socket随着连接增多fd增多2.listen sockfd直接调用accept(等获取连接)本质当做IO来看listensock等待工作交给select来检测读事件是否就绪1.3 原理select优点聚合IO提高效率多路转接的优点select 基于多路转接的就绪事件通知机制 事件派发 基于事件进行编程的模式内核实现简化版使用select实现简单server代码https://gitee.com/sunanfeng/linux-code-replication/blob/master/test_10_12/Select/SelectServer.hpp2.pollselect主要问题可等待的文件描述符个数有限循环遍历参数耦合poll解决了可等待的文件描述符个数有限和参数耦合poll只负责等等num个fd就绪事件通知机制作用等同于select有意思的是poll的代码把数组设为4096个元素大小超过了进程能打开的文件描述符个数这就引出一个问题select在我的云服务器上完全够用了进程打开的文件描述符个数也是有限的要把问题分开来看进程可打开文件描述符个数有限不是select参数设置导致可等待的文件描述符个数有限的理由这是接口的问题因为进程可打开的文件描述符个数和平台有关如果是企业级的一般是65535API要有能力处理文件描述符数量巨大的情况epoll能解决但是epoll要做更多事情就比较重一般select和poll适用于轻量级文件描述符个数有限如果文件描述符个数多就用epoll不过是各司其职各找其位罢了按照man手册的说法epoll是为处理大批量句柄做了改进的poll在2.5.44内核中被引进的(epoll(4) is a new API introduced in Linux kernel 2.5.44)几乎具备一切优点公认Linux2.6及以后版本性能最好的多路I/O就绪通知方法函数签名3.epoll3.1 原理epoll_ctl会把激活函数设置到fd的传输层回调硬件上从网络里收到了数据网卡通过硬件中断告诉OS有数据OS把数据从外设搬到内存形成sk_buff自底向上交付到传输层把sk_buff链入到recvive_queueOS会自动判断回调指针是否为空非空就调用把红黑树节点-就绪节点epoll_create的size参数为了向后兼容新的程序能够在老的机器上跑size刚开始是用户告诉内核大概需要多少文件描述符1内核好开辟空间可以动态扩展现在不需要内核直接动态开辟但是为了兼容还要传size0epoll_ctl和wait一定会涉及到内核和用户空间的拷贝eventepoll的红黑树类似select/poll的数组vscode代码8000行之上代码可能会卡remote sshremote wsl 虚拟机/OS等待的fd约定epoll效率越高由于聚合fd越多单位时间内等的比重降低检测O(1)处理就绪事件O(N)没有mmap映射3.2 工作模式LT和ET最早来源于数字电路与计算机硬件中断LT是高电平为1也就是信号的值ET是上升沿为1也就是信号的变化为有效信号计数器后来计算机设计时感觉epoll的通知机制和ET和LT很像沿用包括示波器也是