IO模型介绍:

* blocking IO 阻塞IO
* nonblocking IO 非阻塞IO
* IO multiplexing IO多路复用
* signal driven IO 信号驱动IO ()
* asynchronous IO 异步IO

IO模型介绍:


 为了更好地了解IO模型,我们需要事先回顾下:同步、异步、阻塞、非阻塞

同步(synchronous) IO和异步(asynchronous) IO,阻塞(blocking) IO和非阻塞(non-blocking)IO分别是什么,到底有什么区别?这个问题其实不同的人给出的答案都可能不同,比如wiki,就认为asynchronous IO和non-blocking IO是一个东西。这其实是因为不同的人的知识背景不同,并且在讨论这个问题的时候上下文(context)也不相同。所以,为了更好的回答这个问题,我先限定一下本文的上下文。

本文讨论的背景是Linux环境下的network IO。本文最重要的参考文献是Richard Stevens的“UNIX® Network Programming Volume 1, Third Edition: The Sockets Networking ”,6.2节“I/O Models ”,Stevens在这节中详细说明了各种IO的特点和区别,如果英文够好的话,推荐直接阅读。Stevens的文风是有名的深入浅出,所以不用担心看不懂。本文中的流程图也是截取自参考文献。

Stevens在文章中一共比较了五种IO Model:
    * blocking IO           阻塞IO
    * nonblocking IO      非阻塞IO
    * IO multiplexing      IO多路复用
    * signal driven IO     信号驱动IO
    * asynchronous IO    异步IO
    由signal driven IO(信号驱动IO)在实际中并不常用,所以主要介绍其余四种IO Model。

再说一下IO发生时涉及的对象和步骤。对于一个network IO (这里我们以read举例),它会涉及到两个系统对象,一个是调用这个IO的process (or thread),另一个就是系统内核(kernel)。当一个read操作发生时,该操作会经历两个阶段:

#1)等待数据准备 (Waiting for the data to be ready)
#2)将数据从内核拷贝到进程中(Copying the data from the kernel to the process)

  记住这两点很重要,因为这些IO模型的区别就是在两个阶段上各有不同的情况。

#同步:提交一个任务之后,要等待这个任务执行完毕
#比如去银行存钱,要取完号才能存钱
#异步:只管提交任务,不等待这个任务执行完毕,就可以做其他事情
#可以边存钱,边玩手机
#阻塞:recv recvfrom accpt 取号的时候,等待人很多
#非阻塞: #很多种情况了 #recv 等待数据准备,等待数据从内核拷贝到进程
#send 讲用户要发送的信息copy到操作系统 发送的时候的网络延迟
#主动方所以阻塞很小

小理解

景老师笔记: IO多路复用

一.阻塞IO:

#图在 有道词典 20181001 IO模型
#1.tcp/udp recv的时候—系统调用—内核操作系统数据没有准备好—等待数据------->数据准备好了,copy数据,将操作系统中的数据,复制,并且返回给进程
#两个重要节点:1.数据准备,2.将信息从内核拷贝到进程 #阻塞IO特点:程序被阻塞着,接收不了其他任务
#进程和线程,没有解决阻塞的这段时间,只是在开启多个进程/线程,该等还是在等,每个线程都受到了阻塞的影响
#协程只是一定程度上的解决这个问题,但是还是在等待

二.非阻塞IO:

#图在有道词典20181001 IO模型

#非阻塞IO
#用户端:
#recv ----> 告诉系统我要收数据了 ----> 系统告诉你没数据---->然后程序没有阻塞住,可以继续往后执行,但是也没收到数据
#过段时间,继续追问
#recv----> 然后系统继续告诉你没有数据,重复上面过程
#假设,一直在请求,请求了很多次,直到
#recv----> 有数据了,----> 从操作系统copy到进程中,然后告诉用户,有数据了 # 但是非阻塞IO模型绝不被推荐。
# 我们不能否则其优点:能够在等待任务完成的时间里干其他活了(包括提交其他任务,也就是 “后台” 可以有多个任务在“”同时“”执行)。 # 但是也难掩其缺点:
#1. 循环调用recv()将大幅度推高CPU占用率;这也是我们在代码中留一句time.sleep(2)的原因,否则在低配主机下极容易出现卡机情况
#2. 任务完成的响应延迟增大了,因为每过一段时间才去轮询一次read操作,而任务可能在两次轮询之间的任意时间完成。这会导致整体数据吞吐量的降低。
# 此外,在这个方案中recv()更多的是起到检测“操作是否完成”的作用,
# 实际操作系统提供了更为高效的检测“操作是否完成“作用的接口,例如select()多路复用模式,可以一次检测多个连接是否活跃。

非阻塞IO框架,例子及解释:

import socket
sk = socket.socket()
sk.bind(('127.0.0.1',8088))
sk.setblocking(False) #~~~~~~~~~~~~~~将阻塞设置为不阻塞
sk.listen()
conn_lst = []
del_lst = []
while True:
try:
conn,addr = sk.accept()
print('建立了连接',addr)
conn_lst.append(conn)
# msg = conn.recv(1024).decode('utf8') #注释1
# print(msg)
except BlockingIOError:
for con in conn_lst: #循环反复的获取con
try:
msg = con.recv(1024) # 这里还是非阻塞,还是会报错
if msg == b'': # 但是如果一直从一个关闭的client获取数据,会一直打印空
del_lst.append(con) #不能 conn_lst.remove(con) 不能再for循环中列表里的元素,index会错误
continue #当con传过来为空,就不执行后面的语句了,要进行下一个循环
print(msg)
con.send(b'bye')
except BlockingIOError:pass
for con in del_lst:
con.close()
conn_lst.remove(con)
del_lst.clear() #注释1:
#此处有两种情况,第一种由于我此时是不阻塞的(setblocking)client端以非常快速的和我聊天,导致while循环就没效果了,别人接收不了请求了
#但是如果只快速的发了一句,然后server就只能接收这一句,接下来就会因为非阻塞,然后这个conn就被内存给冲掉了
#第二种由于此时是阻塞的,client如果慢了一点给我传消息,我马上会跳过,并且报错BlockingIOError #解决方法:
#建立一个conn列表,把每次连接成功的conn,放到列表里。并且把recv放到 except语句后,因为没信息就会报错。
#然后for循环这个conn列表,一直去尝试获取,conn是否发了消息过来
#从而让本来本内存刷掉的conn,可以一直被尝试获取
#但是此是for循环的列表里,recv还是非阻塞的,所以要继续异常处理

server端

import time
import socket
import threading def func():
sk = socket.socket()
sk.connect(('127.0.0.1', 8088))
sk.send(b'hello')
time.sleep(0.1)
print(sk.recv(1024))
sk.close() for i in range(20):
threading.Thread(target=func).start()

client端

三.IO多路复用:(select模块)

#select 模块
#图在有道
# IO多路复用:操作系统级别的,windows的select机制,不是我们代码提供的 # 流程:
#1.有个代理(select模块),可以帮助你监听一个对象。而且这个代理可以监听多个对象 conn1,2,3,4...
#可以接受数据的对象,比如 socket.accept conn.recv
#发生一次系统调用,
#2.然后这个代理,会替你等待 socket对象 被连接,如果没有人来连,会一直阻塞 (从而监听对象就可以不阻塞了)
#3.阻塞到有client来连接,然后把 反馈信息 给帮忙监听的对象,比如accept
#2-3步骤,是操作系统帮你循环监听列表,查看每一项是否有可读事件(但不是很高效) #4.然后accept知道了有数据来了,再次产生一次系统调用,找操作系统要数据
#5.系统就复制数据,传给了一开始索要数据的对象 #注意: 1~3步骤才是IO多路复用,4~5步就是 对象正常获取数据的步骤了 #监听方式:
#windows 只有 select机制
#linux :
# select机制: 都是操作系统轮询每一个被监听的对象,看是否有读操作
#poll机制: 和select机制一样,但是poll好在可以监听的对象,比select机制多
#比如select可以监听500个,poll可以监听1000个
#随着监听项的增多,会导致监听效率降低。(比如监听列表有1000个,当我监听完第3个了,第2个来消息了,)
#epoll机制:
#给监听的每一个对象,都绑定了一个回调函数
#每当有可读事件,回调函数就马上进行信息反馈,而不用等待轮询
#很高效,可以在Linux上用
# selectors模块,自动帮你选择,你最适用的监听机制,根本不需要关心

IO多路复用框架,例子及解释:

import socket
import select sk = socket.socket()
sk.bind(('127.0.0.1',8080))
sk.setblocking(False)
sk.listen() read_lst = [sk] while True:
r_lst,w_lst,x_lst = select.select(read_lst,[],[]) #read_lst中的监听对象,只有有回应的,才会出现在 r_lst
print('***',r_lst) # 注释1
for i in r_lst:
if i is sk:
conn,addr = sk.accept()
read_lst.append(conn)
else:
ret = i.recv(1024)
if ret == b'':
i.close()
read_lst.remove(i) # 此时 r_lst和read_lst是两个不同内存空间,可以remove
continue
print(ret)
i.send(b'goodbye') #注释1
#此时经历过一次连接后,read_lst本来是有着 [conn,sk], 然后此时如果有人给我发消息,也就是我此时 conn.recv了
#由于 select模块, 此时的r_lst只有 conn了,因为没有人连接我,sk也就不会出现在 r_lst里

server端

import time
import socket
import threading def func():
sk = socket.socket()
sk.connect(('127.0.0.1',8080))
sk.send(b'hello')
time.sleep(3)
print(sk.recv(1024))
sk.close() for i in range(20):
threading.Thread(target=func).start()

client端

四.异步IO:

#异步IO
#步骤
#1. 阻塞对象,recv,accept,告诉系统,我要数据,然后接着就去干别的事了,不阻塞
#2.操作系统就在那边阻塞等待着数据,等到直到有数据传来了
#3.然后操作系统,直接将数据传给用户。
# (!!)但是python在这一步,没有提供这个copy data没有提供python对操作系统的接口
#所以不能用python代码实现,真正的异步IO模型
#但是c语言可以,我们可以使用很多异步框架来实现
#4.用户收到数据了。 #django就不是异步框架
#异步框架:没有waitdata和copydata的阻塞阶段,可以响应更多请求
# twisted框架
#tornado框架
# tornado 和 twisted,作为异步框架,是大同小异的。
# 只不过tornado 轻量级一些,twisted 重量级一些。在其他方面,也是互有长短。
# 经过实测,发现这两个框架,I/O性能差不多,对计算资源的占用相差较多!
# 如果追求整体性能的话,推荐使用twisted。

IO模型--阻塞IO,非阻塞IO,IO多路复用,异步IO的更多相关文章

  1. IO多路复用,同步,异步,阻塞和非阻塞 区别

    一.什么是socket?什么是I/O操作? 我们都知道unix(like)世界里,一切皆文件,而文件是什么呢?文件就是一串二进制流而已,不管socket,还是FIFO.管道.终端,对我们来说,一切都是 ...

  2. IO多路复用,同步,异步,阻塞和非阻塞 区别(转)

    转自:http://www.cnblogs.com/aspirant/p/6877350.html?utm_source=itdadao&utm_medium=referral 同步.异步 是 ...

  3. IO复用,AIO,BIO,NIO,同步,异步,阻塞和非阻塞 区别参考

    参考https://www.cnblogs.com/aspirant/p/6877350.html?utm_source=itdadao&utm_medium=referral IO复用,AI ...

  4. IO复用,AIO,BIO,NIO,同步,异步,阻塞和非阻塞 区别(百度)

    如果面试问到IO操作,这篇文章提到的问题,基本是必问,百度的面试官问我三个问题 (1)什么是NIO(Non-blocked IO),AIO,BIO (2) java IO 与 NIO(New IO)的 ...

  5. (转)IO复用,AIO,BIO,NIO,同步,异步,阻塞和非阻塞 区别

    本文来自:https://www.cnblogs.com/aspirant/p/6877350.html?utm_source=itdadao&utm_medium=referral,非常感谢 ...

  6. IO复用,AIO,BIO,NIO,同步,异步,阻塞和非阻塞 区别

    一.什么是socket?什么是I/O操作? 我们都知道unix(like)世界里,一切皆文件,而文件是什么呢?文件就是一串二进制流而已,不管socket,还是FIFO.管道.终端,对我们来说,一切都是 ...

  7. socket阻塞与非阻塞,同步与异步I/O模型

    作者:huangguisu 原文出处:http://blog.csdn.NET/hguisu/article/details/7453390 socket阻塞与非阻塞,同步与异步 1. 概念理解 在进 ...

  8. socket阻塞与非阻塞,同步与异步,select,pool,epool

    概念理解 一.与I/O相关的五个重要概念 1. 第一个概念:用户空间与内核空间 1. 现在操作系统都是采用虚拟存储器,那么对32位操作系统而言,它的寻址空间(虚拟存储空间)为4G(2的32次方) 2. ...

  9. 简述linux同步与异步、阻塞与非阻塞概念以及五种IO模型

    1.概念剖析 相信很多从事linux后台开发工作的都接触过同步&异步.阻塞&非阻塞这样的概念,也相信都曾经产生过误解,比如认为同步就是阻塞.异步就是非阻塞,下面我们先剖析下这几个概念分 ...

  10. 磁盘IO的性能指标 阻塞与非阻塞、同步与异步 I/O模型

    磁盘IO的性能指标 - 蝈蝈俊 - 博客园https://www.cnblogs.com/ghj1976/p/5611648.html 阻塞与非阻塞.同步与异步 I/O模型 - 蝈蝈俊.net - C ...

随机推荐

  1. linux delete file

    今天不小心生成了这么个文件名的文件-ep-ser 然后 rm -ep-ser就删除不了,它认为-e是option 后来,用rm ./-ep-ser就顺利删除了,哈哈,教训啊

  2. Asianux 7.3安装Oracle 11.2.0.4单实例体验

    环境:Asianux 7.3 需求:安装Oracle 11.2.0.4 单实例 背景:系统使用默认的最小安装部署,Oracle安装额外需要的包统一使用yum安装. 查看当前系统相关信息: [root@ ...

  3. 蓝桥杯近三年初赛题之一(15年b组)

    临近比赛,自己定时做了近三年的初赛题,不是很理想,10道题平均做对5+道.为了这次比赛,总共做了200题左右吧,估计去北京参加决赛有点难,不过不管怎样,对得起自己万余行代码就好. 一.15年初赛题(第 ...

  4. tensorflow 的数据管理

    tensorflow api操纵和管理的是numpy矩阵数据 例子: import tensorflow as tf import numpy as np vector_np = np.array([ ...

  5. Restful API接口调用的方法总结

    restful 接口调用的方法 https://www.cnblogs.com/taozhiye/p/6704659.html http://www.jb51.net/article/120589.h ...

  6. vue项目初始化时npm run dev报错webpack-dev-server解决方法

    vue项目初始化时npm run dev报错webpack-dev-server解决方法 原因:这是新版webpack存在的BUG,卸载现有的新版本webpack,装老版本就好webpack-dev- ...

  7. Template模板

     目标 模板介绍 模板变量 常用标签 常用过滤器 自定义过滤器 模板结构 加载静态文件 一 模板介绍 在之前的章节中,视图函数只是直接返回文本,而在实际生产环境中其实很少这样用,因为实际的页面大多是带 ...

  8. Java继承和组合

    为了保证父类有良好的封装性,不会被子类随意修改,设计父类通常应该遵循以下规则: 1.尽量隐藏父类的内部数据,尽量把父类的所有成员变量设置为 private 访问类型,不要让子类直接访问父类的成员变量: ...

  9. Technical poem

    Apartment Good apartment be booked the second it bring to market. low product sold to many man, and ...

  10. Springboot 使用PageHelper分页插件实现分页

    一.pom文件中引入依赖 二.application.properties中配置以下内容(二选一方案) 第一种:pagehelper.helper-dialect=mysqlpagehelper.re ...