IO操作
在内存中存在数据交换的操作都可以认为是IO操作
# 和终端交互 : input print
# 和磁盘交互 : read write
# 和网络交互 : recv send
IO密集型程序
在程序执行过程中存在大量IO操作,而cpu运算操作较少,消耗cpu较少,运行效率较低
计算密集型程序(cpu密集型程序)
在程序执行中cpu运算较多,IO操作相对较少,消耗cpu大,运行速度快
阻塞IO与非阻塞IO
阻塞IO是IO的默认形态,是效率较低的一种IO情形
阻塞情况
- 因某种条件没有达成造成的阻塞
例如:accept
,input
,recv
- 处理IO数据传输时间较长形成的阻塞
例如:网络传输过程,文件读写过程
非阻塞IO
- 通过修改IO事件的属性,使其变为非阻塞状态。(让一些条件阻塞函数不再阻塞)
- 非阻塞IO往往和循环判断一起使用
设置非阻塞状态
将套接子对象设置为非阻塞状态,当有客户端连接进来时,即可出来客户端请求
超时检测
将原本阻塞的函数设置一个最长阻塞时间。如果时间内条件达成则正常运行,如果仍然阻塞则视为超时,继续向下运行或产生异常。
# 将套接字设置为非阻塞状态
s.setblocking(False)
# 设置套接字的超时时间
s.settimeout(sec)
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
select方案
import select
# 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
# 注意 :
# wlist中如果有IO事件则select立即回返回为ws
# 在处理IO过程中不要处理一个客户端长期占有服务端使服务端无法运行到select的情况
# IO多路复用占用计算机资源少,IO效率高
poll方案
- 创建
poll
对象
import select
p = select.poll()
- 通过文件描述符找到对应的IO对象
# poll 的返回值没有IO对象
# 用字典以键值对的形式保存文件描述符对应的IO对象
{s.fileno() : s}
- 添加注册事件
# 添加注册事件
p.register(s,POLLIN | POLLERR)
# 常见事件:
# POLLIN POLLOUT POLLERR POLLHUP POLLNVAL
# rlist wlist xlist 断开 无效数据
# 从关注事件中移除
p.unregister(s)
- 阻塞等待IO发生
# 功能:阻塞等待IO发生
# 返回值:
# events 是一个列表,列表中给每一个元素都是一个元组,代表一个发生的IO事件
# [(fileno,event),(),()....]
# fileno:就绪IO的文件描述符
# event:具体就绪事件
events = p.poll()
- 处理具体的IO事件
epoll方案
使用方法基本与poll
方法相同
- 将生产对象
poll()
改为epoll()
- 将所有
poll
对象事件改为epoll
对象事件
poll与epoll的区别
-
epoll
的效率要比poll
和select
高 -
epoll
的事件触发方式更多