7-4 并发编程IO多路复用常见考题
Posted WinvenChang
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了7-4 并发编程IO多路复用常见考题相关的知识,希望对你有一定的参考价值。
一、五种IO
模型
Unix
网络编程中提到了5
种网络模型
1.Blocking IO
(阻塞式IO
)
2.Noblocding IO
(非阻塞式IO
)
3.IO multiplexing
(IO
多路复用)
两种不常用,一般使用IO
多路复用比较多
1.Signal Driven IO
(信息驱动IO
)
2.Asynchronous IO
(异步IO
)
二、如何提升服务器的并发能力呢?
一些常见的提升并发能力的方式
1.多线程模型,创建新的线程处理请求
2.多进程模型,创建新的进程处理请求
(注意:线程/进程创建开销比较大,可以用线程池方式解决;线程和进程比较占用资源,难以同时创建太多)
3.IO
多路复用,实现单进程同时处理多个socket
请求
三、什么中IO
多路复用?
操作系统提供的同时监听多个socket
的机制
1.为了实现高并发需要一种机制并发处理多个socket
2.Linux
常见的是select
/poll
/epoll
3.可以使用单线程进程处理多个socket
阻塞式IO
流程图:
- 内核等待数据
- 数据从内核拷贝到用户进程
IO
多路复用流程图:
select
可以同时处理多个socket
,有一个就绪应用程序代码就可以处理它
IO
多路复用代码格式:
while True:
events = sel.select()
for key, mask in events:
callback = key.data
callback(key.fileobj, mask)
四、select
/poll
/epoll
区别
系统调用 | select | poll | epoll |
---|---|---|---|
事件集合 | 用户通过3 个参数分别传入感兴趣的可读、可写及异常等事件,内核通过对这些参数的在线修改来反馈其中的就绪事件。这使得用户每次调用 select 都要重置这3 个参数 | 统一处理所有事件类型,因此只需一个事件集参数。用户通过pollfd.events 传入感兴趣的事件,内核通过修改pollfd.revents 反馈其中就绪的事件 | 内核通过一个事件表直接管理用户感兴趣的所有事件。因此每次调用epoll_wait 时,无须反复传入用户感兴趣的事件。epoll_wait 系统调用的参数events 仅用来反馈就绪事件 |
反应程序索引就绪文件描述符的时间复杂度 | O(n) | O(n) | O(1) |
最大支持文件描述符数 | 一般有最大值限制 | 65535 | 65535 |
工作模式 | LT | LT | 支持ET 高效模式 |
内核实现和工作效率 | 采用轮询方式来检测就绪事件,算法时间复杂度为O(n) | 采用轮询方式来检测就绪事件,算法时间复杂度为O(n) | 采用回调方式来检测就绪事件,算法时间复杂度为O(1) |
五、Python
如何实现IO
多路复用?
Python
封装了操作系统的IO
多路复用
1.Python
的IO
多路复用基于操作系统实现(select
/poll
/epoll
)
2.Python2 select
模块
3.Python3 selectors
模块
selectors
模块:
- 事件类型:
EVENT_READ, EVENT_WRITE
DefaultSelector
:自动根据平台选取合适的IO
模型register(fileojb, events, data=None)
unregister(fileobj)
modify(fileobj, events, data=None)
select(timeout=None): returns[(key, events)]
close()
代码示例:
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)
以上是关于7-4 并发编程IO多路复用常见考题的主要内容,如果未能解决你的问题,请参考以下文章
Python并发编程-IO模型-IO多路复用实现SocketServer
并发编程 - IO模型 - 1.io模型/2.阻塞io/3.非阻塞io/4.多路复用io