1.什么是IO模型
在计算机系统中,Input/Output(简称 I/O),英语缩写 I/O,是指输入/输出,与计算机中的程序运算(算法)相对。
I/O模型(I/O Model)是操作系统中的一个重要概念,它规定了应用程序与操作系统之间数据交换的方式。
1.1 IO模型的分类
IO模型主要分为五类:
阻塞IO
非阻塞IO
IO复用(select/poll/epoll)
信号驱动IO
异步IO(AIO)
2.阻塞IO模型
阻塞IO(Blocking IO),当一个进程调用了阻塞式 IO 的系统调用函数之后,内核会去查看数据是否准备好,如果数据没有准备好,那么内核就会将这个进程阻塞,当数据准备好并且拷贝到用户态缓冲区后,进程将被唤醒,阻塞状态解除。
下面是使用阻塞IO模型进行文件读写的代码:
def blocking_io():
with open('test.txt', 'rb') as f:
data = f.read()
time.sleep(1)
with open('test.txt', 'wb') as f:
f.write(data)
time.sleep(1)
上面这段代码是使用阻塞IO模型进行文件读写操作,使用方式非常简单,只需要使用 Python 内置函数 open 打开文件,并使用 read 和 write 方法进行读和写操作即可。该函数使用了 time.sleep() 函数模拟了 IO 等待的过程。
3.非阻塞IO模型
非阻塞IO(Non-blocking IO),当一个进程调用非阻塞 IO 的系统调用函数之后,内核立即返回,不会发生进程阻塞,即使数据没有准备好,也会立即返回一个错误码,由于进程不会阻塞,所以 CPU 可以不停地轮询读写操作是否完成,这种方式的缺点就是非常耗费 CPU 资源。
下面是使用非阻塞IO模型进行文件读写的代码:
def non_blocking_io():
f = open('test.txt', 'rb')
data = None
while not data:
try:
data = f.read()
except BlockingIOError:
time.sleep(0.1)
f.close()
f = open('test.txt', 'wb')
while data:
try:
written = f.write(data)
except BlockingIOError:
time.sleep(0.1)
else:
data = data[written:]
f.close()
上面这段代码是使用非阻塞 IO 模型进行文件读写操作,与阻塞 IO 模型不同的是,它在读取和写入数据时使用了 try except 语句,并使用 time.sleep() 函数来降低 CPU 的使用率。
4.IO多路复用模型
IO多路复用(I/O Multiplexing)允许在单个进程中同时处理多个文件描述符的输入/输出请求。通过使用 Select/Poll/Epoll 等系统调用,操作系统内核可以同时监视多个文件描述符的状态,然后在需要读写数据时通知应用程序处理,从而实现了单进程高并发请求的处理。
下面是使用IO多路复用模型进行文件读写的代码:
def io_multiplexing():
f = open('test.txt', 'rb')
p = select.poll()
p.register(f, select.POLLIN)
data = None
while not data:
events = p.poll()
for fd, event in events:
if event & select.POLLIN:
data = f.read()
f.close()
f = open('test.txt', 'wb')
while data:
events = p.poll()
for fd, event in events:
if event & select.POLLOUT:
written = f.write(data)
data = data[written:]
f.close()
上面这段代码是使用 IO 多路复用模型进行文件读写操作,首先使用 select.poll() 函数创建一个对文件描述符的轮询对象,然后使用注册函数 p.register() 注册要进行轮询的文件描述符 f,并设置轮询方式为 POLLIN,表示监测 FD 上是否有可读数据可读取。在轮询到数据可读时,使用 f.read() 读取数据并关闭文件,同时将数据写入同一个文件的同时,使用轮询器上面设置输出模式 POLLOUT 监测是否已就绪,如果就绪,使用 f.write() 函数向文件中写入数据。
5.参考文献
阻塞式与非阻塞式 IO,https://developer.ibm.com/zh/articles/1307_xiawc_io/
I/O多路复用模型,https://www.ibm.com/developerworks/cn/linux/l-async/