IO密集型程序 : 在程序执行过程中存在大量IO操作,而cpu运算操作较少。消耗cpu较少,运行效率较低
计算密集型程序(cpu密集型程序):在程序执行中cpu运算较多,IO操作相对较少。消耗cpu大,运行速度快
IO分类:
阻塞IO非阻塞IOIO多路复用阻塞IO:是IO的默认形态,是效率较低的一种IO情形。
阻塞情况:
因为某种条件没有达成造成的阻塞
e.g. accept input recv
处理IO数据传输时间较长形成的阻塞
e.g. 网络传输过程,文件读写过程
非阻塞IO :通过修改IO事件的属性,使其变为非阻塞状态。比如:超时检测
*非阻塞IO往往和循环判断一起使用
IO多路复用
定义 : 同时监控多个IO事件,当哪个IO事件准备就绪就执行哪个IO事件。以此形成可用同时操作多个IO的并发行为,避免一个IO阻塞,造成所有IO都无法执行。
IO多路复用的编程实现
将IO设置为关注IO将关注IO提交给内核监测处理内核给我们反馈准备就绪的IO具体方案: select ——> windows linux unix
poll ——> linux unix
epoll ——> linux unix
from select import * rs,ws,xs = select(rlist, wlist, xlist[, timeout]) 功能: 监控IO事件,阻塞等待IO事件发生 参数: rlist 列表 存放我们监控等待处理的IO事件 wlist 列表 存放我们要主动操作的IO事件 xlist 列表 我们要关注出错处理的IO事件 timeout 超时时间 返回值:rs 列表 rlist中准备就绪的IO ws 列表 wlist中准备就绪的IO xs 列表 xlist中准备就绪的IO 注意 : 1. rlist有已经准备就绪的IO事件,select会立即返回给rs 2. IO多路复用占用计算机资源少,io效率高 poll 1.创建poll对象 p = poll() 2.添加注册事件 p.register(s,POLLIN | POLLERR) POLLIN POLLOUT POLLERR POLLHUP POLLNVAL rlist wlist xlist 断开 无效数据 p.unregister(s) 从关注事件中移除 3. 阻塞等待IO发生 events = p.poll() 功能 : 阻塞等待IO发生 返回值 : events 是一个列表,列表中给每一个元素都是一个元组,代表一个发生的IO事件 [(fileno,event),(fileno,event),(fileno,event)...] fileno: 就绪IO的文件描述符 event: 具体就绪IO事件 * 需要通过文件描述符(fileno)找到对应的IO对象,所以需要建立映射关系 {s.fileno() : s} 4. 处理具体的IO epoll方法 使用方法:基本与poll方法相同 epoll 和 poll的区别: 1. epoll 的效率要比 poll和select 高 2. epoll 的事件触发方式更多 from socket import * from select import * #创建套接字作为我们关注的IO s = socket() s.setsockopt(SOL_SOCKET,SO_REUSEADDR,1) s.bind(('0.0.0.0',8888)) s.listen(5) #创建poll对象 p = poll() #fileno ---> IO对象的字典 fdmap = {s.fileno():s} #注册关注的IO p.register(s,POLLIN | POLLERR) while True: #进行IO监控 events = p.poll() for fd,event in events: if fd == s.fileno(): c,addr = fdmap[fd].accept() print("Connect from",addr) #添加新的关注事件 p.register(c,POLLIN | POLLHUP) fdmap[c.fileno()] = c elif event & POLLIN: data = fdmap[fd].recv(1024) if not data: #客户端退出,从关注事件移除 p.unregister(fd) fdmap[fd].close() del fdmap[fd] else: print(data.decode()) fdmap[fd].send(b'Receive')