io 多路复用 select poll epoll


IO  output  input

我们把内存中数据的交换操作都可以称之为IO操作。比如,文件的读写,向终端的输入输出,网络信息的传入和获取
io操作和cpu计算不同,因为需要数据的交换所以速度较慢。
所以对于一个程序来说如何更好的解决IO传输速率的问题往往决定着程序的执行效率
具有大量IO操作的程序称之为IO密集型程序
具有较多cpu运算操作的程序称之为计算密集型程序
IO分类
阻塞IO   非阻塞IO   IO多路复用  (事件驱动IO,异步IO)
阻塞IO(效率非常低的)
默认情况IO即为阻塞的
阻塞IO在一定条件下会结束阻塞
条件阻塞:因为不满足某种条件,使进程处于等待态。当等待条件被触发时即结束阻塞状态。比如accept,recv
传输阻塞:数据在交换的过程中,需要通过内核进行读写。这个读写过程需要一定的时间,这个时间也是处于阻塞的状态。
解决方法:
针对条件阻塞:
将阻塞条件设置为非阻塞,不再等待条件达到 ---->  非阻塞io

针对传输阻塞:在内核处理IO操作的时间里,应用层程序不再等待,而是继续执行自己的任务,等到内核处理IO结束会告知应用层程序,此时再进行应用层的IO处理  ---> 多路复用  事件驱动  异步  协程

非阻塞IO
非阻塞IO在遇到原本的阻塞时不再阻塞,但是如果想处理相应的事件就必须不断轮询,需要消耗一定的资源。
sockfd.setblocking(False) 设置sockfd套接字为非阻塞套接字
(默认为True 则为阻塞)
IO多路复用
win ---> select 
linux/unix   ---> select  poll   epoll
1.同时监测多个IO事件
2.当监测的IO时间被触发则返回处理相应的时间
3.当监测的io时间都没有准备好时,可以选择等待(也可以以非阻塞模式不进行等待)
4.IO多路复用在内核中实际上是一种轮询,需要消耗系统资源。
  效率相对阻塞的等待非常高,但是不是真正的异步。
io 多路复用 select poll epollio 多路复用 select poll epoll
poll 实现IO多路复用
POLLIN  POLLOUT  POLLERR  POLLUP    POLLPRI  POLLVAL
rlist   wlist    elist    断开连接  紧急处理  无效数据
epoll
epoll 效率比poll和select高
协程
微线程 (本质就是单线程程序)
优点:
创建协程资源消耗 少少少
可用于高并发的IO处理
无需上下文切换的开销
无需资源争夺,保证对数据的原子操作
缺点:
无法利用多核资源
一旦阻塞会阻塞整个程序的运行
底层实现使用yield关键字,通过yield可以模拟协程的过程

常见模块greenlet

sudo pip3 install greenlet

gevent

sudo pip3 install gevent

io 多路复用 select poll epoll

跳转