I/O模型
- 阻塞式IO
- 非阻塞式IO
- I/O多路复用(select,poll,epoll)
- 信号驱动式IO
- 异步IO(POISX的aio_系类函数)
上述1,2,3,4都属于同步IO模型,因为其中真正的IO操作都阻塞用户进程
只有5才是异步IO
需要了解:
用户进行IO操作要内核要历经两个阶段:
- 等待数据包准备好
- 将数据从内核复制到用户空间
真正的IO操作是阶段二
上述1,2,3,4 四个IO模型不同的地方在于阶段一的内核处理方式
阶段一完成后使用,内核通知用户进程;用户进程轮询知道完成;直接等待等方式
然后阶段二都在阻塞中,所以认为是同步模型
异步IO是开始阶段一时候告知内核在阶段二完成后直接按照我的设定的方式返回数据
需要重点掌握: IO多路复用
应用场景
1.服务器既要处理UDP又要TCP
2.TCP服务器既要 监听套接字也要处理 已经连接的套接字(类似服务器高并发的实现)
3.客户端处理多个套接字(类似与python 协程并发爬虫之类的)
多路复用三件套 select,poll,epoll
操作系统给我提供一些中断的方式通知应用程序,如select,poll,epoll
python 通过selectors 封装了这三个函数,通过当前系统自动选择最合适的方法
epoll|kqueue|devpoll > poll > select.
python使用例子
import selectors
import socket
sel = selectors.DefaultSelector()
def accept(sock, mask):
conn, addr = sock.accept() # Should be ready
print('accepted', conn, 'from', addr)
conn.setblocking(False)
sel.register(conn, selectors.EVENT_READ, read)
def read(conn, mask):
data = conn.recv(1000) # Should be ready
if data:
print('echoing', repr(data), 'to', conn)
conn.send(data) # Hope it won't block
else:
print('closing', conn)
sel.unregister(conn)
conn.close()
sock = socket.socket()
sock.bind(('localhost', 1234))
sock.listen(100)
sock.setblocking(False)
sel.register(sock, selectors.EVENT_READ, accept)
while True:
events = sel.select()
for key, mask in events:
callback = key.data
callback(key.fileobj, mask)
通过上面的例子看出来,我们需要轮询,查看是否有读写异常事件发生
select + 事件循环 + 回掉函数