Socket之于操作系统/进程
Socket通信在操作系统层面主要体现在I/O多路复用上,即每个进程通过一定的逻辑去检测具体哪个文件描述符(fd)发生了I/O事件。这个逻辑主要有select、poll、epoll/kqueue这几种。
select的缺点在于两次拷贝耗时、轮询所有fd耗时,支持的文件描述符受限且太小,其优点在于跨平台支持。
poll的优点在于通过链表存储使得连接数(也就是文件描述符)没有限制,但仍然存在大量拷贝,且是水平触发,会出现当报告了fd没有被处理,会重复报告,很耗性能。
epoll是Linux操作系统中对poll进行改进,epoll分为ET与LT模式,具体如下:
LT:延迟处理,当检测到描述符事件通知应用程序,应用程序不立即处理该事件。那么下次会再次通知应用程序此事件。
ET:立即处理,当检测到描述符事件通知应用程序,应用程序会立即处理。
ET模式减少了epoll被重复触发的次数,效率比LT高。我们在使用ET的时候,必须采用非阻塞套接口,避免某文件句柄在阻塞读或阻塞写的时候将其他文件描述符的任务饿死。epoll的优点在于没有最大并发连接的限制,只有活跃可用的fd才会调用callback函数,内存拷贝是利用mmap()文件映射内存的方式加速与内核空间的消息传递,减少复制开销。(内核与用户空间共享一块内存)。
kqueue是Unix操作系统对poll进行的一些优化后的模式,kqueue与epoll非常相似,最初是2000年Jonathan Lemon在FreeBSD系统上开发的一个高性能的事件通知接口。
下面是上述函数的调用过程:
- select函数的调用过程
- 将fd_set从内核空间拷贝到用户空间
- 如果遍历完所有的fd都没有返回一个可读写的mask掩码,就会让select的进程进入休眠模式,直到发