初探 IO 多路复用
多路复用是什么
维基百科定义:
多路复用(Multiplexing,又称“多工”)是一个通信和计算机网络领域的专业术语,在没有歧义的情况下,“多路复用”也可被称为“复用”。多路复用通常表示在一个信道上传输多路信号或数据流的过程和技术。因为多路复用能够将多个低速信道整合到一个高速信道进行传输,从而有效地利用了高速信道。通过使用多路复用,通信运营商可以避免维护多条线路,从而有效地节约运营成本
按技术分类和应用场景
- 时分复用(TDM)TDM: T-1 有限线路 和 GSM 移动手机,STDM: LAN and 网络连接
- 频分复用 (FDM)FM 调频收音机 有线电视
- 码分复用(CDM)数字电视 收音机 3G蜂窝移动通信网
- 空分复用(SDM)
工作过程
首先,各个低速信道的信号通过多路复用器(MUX,多工器)组合成一路可以在高速信道传输的信号。在这个信号通过高速信道到达接收端之后,再由分路器(DEMUX,解多工器)将高速信道传输的信号转换成多个低速信道的信号,并且转发给对应的低速信道。
IO 多路复用实现原理
select, poll, epoll 都是I/O多路复用的具体的实现,他们出现是有先后顺序的。
select是第一个实现,很快就暴露出了很多问题。
- 会修改传入的参数数组
- 任何一个sock(I/O stream)出现了数据,select 会返回,但不会告诉你是哪个sock上有数据
- select 只能监视1024个链接
- select 不是线程安全的
poll 修复了select的很多问题,比如
- 去掉了1024个链接的限制
- 不再修改传入数组
epoll 是I/O 多路复用最新的一个实现
- epoll 现在是线程安全的
- 不仅告诉你sock组里面数据,还会告诉你具体哪个sock有数据
epoll 的问题:只有linux支持。比如BSD上面对应的实现是kqueue。
select poll epoll 对比表格epoll的性能几乎不受监测的fd数目的影响,且没有最大监测fd数量的限制,各方面性能明显优于select和poll,但是当这种情况下,epoll的性能并不会优于select和poll,甚至更差:在所有并发的连接中,全部连接都是活跃连接
所以:当监测的fd数目较小,且各个fd都比较活跃,建议使用select或者poll
当监测的fd数目非常大,成千上万,且单位时间只有其中的一部分fd处于就绪状态,这个时候使用epoll能够明显提升性能,比如ngix web服务器就是使用epoll实现的。
常用应用场景
- 客户端要处理多个socket
- 客户端同时处理连接和用户输入,比如聊天室
- TCP服务器要同时处理监听socket和连接socket
- 服务器同时处理TCP和UDP
- 服务器要监听多个端口
与多进程和多线程技术相比,I/O多路复用技术的最大优势是系统开销小,系统不必创建进程/线程,也不必维护这些进程/线程,从而大大减小了系统的开销。
举例
- I/O框架libevent
- 基于libevent和协程的python网络框架gevent
- python的高性能web框架tornado
- redis文件事件处理器
- nginx,apache事件模型
参考:
多路复用-维基百科
IO多路复用(IO Multiplexing)
IO 多路复用是什么意思? - 罗志宇的回答 - 知乎
I/O多路复用——概述与应用场景
基于表格形式的select,poll,epoll对比-IO多路复用函数的应用场景
Python之路【第七篇续】:I/O多路复用
multiplexing
Multiplexing: An Intro to How it Works
Chapter 6. I/O Multiplexing: The select
and poll
Functions