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. openshift 容器云从入门到崩溃之九《容器监控-报警》

    容器状态监控 主要是监控POD的状态包括重启.不健康等等这些k8s api 状态本身会报出来,在配合zabbix报警 导入zabbix模板关联上oc master主机 <?xml version ...

  2. linux----------centos6.4安装完了以后敲ifconfig,没有局域网ip。解决如下

    1.vim /etc/sysconfig/network-scripts/ifcfg-eth0 进入linux然后进入这个文件里面如下: DEVICE=eth0 HWADDR=00:0C:29:92: ...

  3. wysiwyg 富文本编辑器(附带图片上传功能)

    Fist: 需要的文件 font 文件夹下面的也是需要的哟 Then: 引入文件 <link href="bootstrap/css/bootstrap.css" rel=& ...

  4. linux下直接复制文件内容到剪切板

    title: linux下直接复制文件内容到剪切板 date: 2017-11-23 17:00:06 tags: categories: Linux 首先安装xsel. xsel --input - ...

  5. Vue系列之 => webpack基础使用

    webpack安装方式 1,运行 npm i webpack -g 全局安装. 2,在项目根目录中运行 npm i webpack --save-dev 安装到项目依赖中 项目目录 进入src运行, ...

  6. MB SD Connect Compact 5 Error 95.53392.0 Solved

    MB SD Connect Compact 5 is new released from MB Star company ,and its original version here the copy ...

  7. Porsche Piwis Tester II V14.000 with CF30 Laptop at autonumen.com

    Porsche piwis tester ii is the latest professional tester for Porshe,the most poweful diagnose and o ...

  8. 论文笔记【二】Making Sense of Word Embeddings

    摘要 1.作者提出了一种新的简单有效的方法,用于学习词义嵌入word sense embedding 2.传统的两种方法:(1)直接从语料库中学习词义:(2)依赖词汇资源的语义库 研究方法的创新点:通 ...

  9. 谷歌浏览器怎样把网页全部内容保存为.mhtml文件?

    Chrome保存.mhtml网页文件的方法: 在 Chrome 地址栏中键入chrome://flags,回车, 在页面搜索栏输入mhtml 把“Save Page as MHTML”项修改为 Ena ...

  10. Android创建自定义的布局和控件

    Android的自带布局有framelayout.linerlayout.relativelayout,外加两个百分比布局,但是这些无法灵活的满足我们的需要,所以我们要自己自定义并引入自己的布局.首先 ...