十四、并发编程之I/O模型

http://www.cnblogs.com/linhaifeng/articles/7454717.html

1、模型介绍

1.1 IO种类

(1)* blocking IO 阻塞IO

(2)* nonblocking IO 非阻塞IO

(3)* IO multiplexing 多路复用IO

(4)* signal driven IO 信号驱动IO

(5)* asynchronous IO 异步IO

1.2 IO发生时的对象和步骤

对于一个network IO (这里我们以read举例),它会涉及到两个系统对象,一个是调用这个IO的process (or thread),另一个就是系统内核(kernel)。

1.3 IO经历的阶段

(1)等待数据准备

(2)将数据从内核(操作系统内存)拷贝到进程(应用程序内存)中

2、阻塞IO

在linux中,默认情况下所有的socket都是blocking,一个典型的读操作流程大概是这样:

blocking IO的特点就是在IO执行的两个阶段(等待数据和拷贝数据两个阶段)都被block了。

3、非阻塞IO

3.1 流程

Linux下,可以通过设置socket使其变为non-blocking。当对一个non-blocking socket执行读操作时,流程是这个样子:

在非阻塞式IO中,用户进程其实是需要不断的主动询问kernel数据准备好了没有。  但是非阻塞IO模型绝不被推荐。

3.2 实例

#服务端fromsocket import*

importtime

s=socket(AF_INET,SOCK_STREAM)

s.bind(('127.0.0.1',8080))

s.listen(5)

s.setblocking(False) #设置socket的接口为非阻塞conn_l=[]

del_l=[]

while True:

try:

conn,addr=s.accept()

conn_l.append(conn)

exceptBlockingIOError:

print(conn_l)

forconn inconn_l:

try:

data=conn.recv(1024)

if notdata:

del_l.append(conn)

continueconn.send(data.upper())

exceptBlockingIOError:

passexceptConnectionResetError:

del_l.append(conn)

forconn indel_l:

conn_l.remove(conn)

conn.close()

del_l=[]

#客户端fromsocket import*

c=socket(AF_INET,SOCK_STREAM)

c.connect(('127.0.0.1',8080))

while True:

msg=input('>>: ')

if notmsg:continuec.send(msg.encode('utf-8'))

data=c.recv(1024)

print(data.decode('utf-8'))

3.3 优缺点

优点:能够在等待任务完成的时间里干其他活了

缺点:

#1. 循环调用recv()将大幅度推高CPU占用率;这也是我们在代码中留一句time.sleep(2)的原因,否则在低配主机下极容易出现卡机情况

#2. 任务完成的响应延迟增大了,因为每过一段时间才去轮询一次read操作,而任务可能在两次轮询之间的任意时间完成。这会导致整体数据吞吐量的降低。

4、多路复用IO

4.1 流程

有些地方也称这种IO方式为事件驱动IO(event driven IO)。我们都知道,select/epoll的好处就在于单个process就可以同时处理多个网络连接的IO。它的基本原理就是select/epoll这个function会不断的轮询所负责的所有socket,当某个socket有数据到达了,就通知用户进程。它的流程如图:

当用户进程调用了select,那么整个进程会被block,而同时,kernel会“监视”所有select负责的socket,当任何一个socket中的数据准备好了,select就会返回。这个时候用户进程再调用read操作,将数据从kernel拷贝到用户进程。

强调:

1. 如果处理的连接数不是很高的话,使用select/epoll的web server不一定比使用multi-threading + blocking IO的web server性能更好,可能延迟还更大。select/epoll的优势并不是对于单个连接能处理得更快,而是在于能处理更多的连接。

2. 在多路复用模型中,对于每一个socket,一般都设置成为non-blocking,但是,如上图所示,整个用户的process其实是一直被block的。只不过process是被select这个函数block,而不是被socket IO给block。

结论: select的优势在于可以处理多个连接,不适用于单个连接

4.2 实例

#服务端fromsocket import*

importselect

s=socket(AF_INET,SOCK_STREAM)

s.setsockopt(SOL_SOCKET,SO_REUSEADDR,1)

s.bind(('127.0.0.1',8081))

s.listen(5)

s.setblocking(False) #设置socket的接口为非阻塞read_l=[s,]

while True:

r_l,w_l,x_l=select.select(read_l,[],[])

print(r_l)

forready_obj inr_l:

ifready_obj == s:

conn,addr=ready_obj.accept() #此时的ready_obj等于sread_l.append(conn)

else:

try:

data=ready_obj.recv(1024) #此时的ready_obj等于connif notdata:

ready_obj.close()

read_l.remove(ready_obj)

continueready_obj.send(data.upper())

exceptConnectionResetError:

ready_obj.close()

read_l.remove(ready_obj)

#客户端fromsocket import*

c=socket(AF_INET,SOCK_STREAM)

c.connect(('127.0.0.1',8081))

while True:

msg=input('>>: ')

if notmsg:continuec.send(msg.encode('utf-8'))

data=c.recv(1024)

print(data.decode('utf-8'))

4.3 优缺点

优点:

#相比其他模型,使用select()的事件驱动模型只用单线程(进程)执行,占用资源少,不消耗太多CPU,同时能够为多客户端提供服务。如果试图建立一个简单的事件驱动的服务器程序,这个模型有一定的参考价值。

缺点:

#首先select()接口并不是实现“事件驱动”的最好选择。因为当需要探测的句柄值较大时,select()接口本身需要消耗大量时间去轮询各个句柄。很多操作系统提供了更为高效的接口,如linux提供了epoll,BSD提供了kqueue,Solaris提供了/dev/poll,…。如果需要实现更高效的服务器程序,类似epoll这样的接口更被推荐。遗憾的是不同的操作系统特供的epoll接口有很大差异,所以使用类似于epoll的接口实现具有较好跨平台能力的服务器会比较困难。

#其次,该模型将事件探测和事件响应夹杂在一起,一旦事件响应的执行体庞大,则对整个模型是灾难性的。

5、异步IO

Linux下的asynchronous IO其实用得不多,从内核2.6版本才开始引入。先看一下它的流程:

用户进程发起read操作之后,立刻就可以开始去做其它的事。而另一方面,从kernel的角度,当它受到一个asynchronous read之后,首先它会立刻返回,所以不会对用户进程产生任何block。然后,kernel会等待数据准备完成,然后将数据拷贝到用户内存,当这一切都完成之后,kernel会给用户进程发送一个signal,告诉它read操作完成了。

6、selectors模块

select,poll,epoll这三种IO多路复用模型在不同的平台有着不同的支持,而epoll在windows下就不支持,好在我们有selectors模块,帮我们默认选择当前平台下最合适的

#服务端fromsocket import*

importselectors

sel=selectors.DefaultSelector()

defaccept(server_fileobj,mask):

conn,addr=server_fileobj.accept()

sel.register(conn,selectors.EVENT_READ,read)

defread(conn,mask):

try:

data=conn.recv(1024)

if notdata:

print('closing',conn)

sel.unregister(conn)

conn.close()

returnconn.send(data.upper()+b'_SB')

exceptException:

print('closing', conn)

sel.unregister(conn)

conn.close()

server_fileobj=socket(AF_INET,SOCK_STREAM)

server_fileobj.setsockopt(SOL_SOCKET,SO_REUSEADDR,1)

server_fileobj.bind(('127.0.0.1',8088))

server_fileobj.listen(5)

server_fileobj.setblocking(False) #设置socket的接口为非阻塞sel.register(server_fileobj,selectors.EVENT_READ,accept) #相当于网select的读列表里append了一个文件句柄server_fileobj,并且绑定了一个回调函数acceptwhile True:

events=sel.select() #检测所有的fileobj,是否有完成wait data的forsel_obj,mask inevents:

callback=sel_obj.data #callback=accpetcallback(sel_obj.fileobj,mask) #accpet(server_fileobj,1)#客户端fromsocket import*

c=socket(AF_INET,SOCK_STREAM)

c.connect(('127.0.0.1',8088))

while True:

msg=input('>>: ')

if notmsg:continuec.send(msg.encode('utf-8'))

data=c.recv(1024)

print(data.decode('utf-8'))

7、socketsever模块

服务端:

importsocketserver

classMyTCPhandler(socketserver.BaseRequestHandler):

defhandle(self):

# print(self)# print(self.request) #self.request=connwhile True:

try:

print(self.client_address)

print(self.server) #objdata=self.request.recv(1024)

if notdata:breakself.request.send(data.upper())

exceptConnectionResetError:

breakif__name__ == '__main__':

print('starting...')

obj=socketserver.ThreadingTCPServer(('127.0.0.1',8080),MyTCPhandler)

#bind_and_activate=True#socketserver.ForkingTCPServerobj.serve_forever() #连接循环'''t=Thread(target=MyTCPhandler().handle)t.start()'''# obj.server_address #('127.0.0.1',8080)# obj.RequestHandlerClass #MyTCPhandler# obj.socket #s对象

客户端:

fromsocket import*

c=socket(AF_INET,SOCK_STREAM)

c.connect(('127.0.0.1',8080))

while True:

msg=input('>>: ').strip()

if notmsg:continuec.send(msg.encode('utf-8'))

data=c.recv(1024)

print(data.decode('utf-8'))

8、并发编程总结(重点)

1 生产者消费者模型

2 开启进程、开启线程

3 进程池、线程池(回调机制)

4 GIL全局解释器锁

python电路模型编程_14、python开发之路-并发编程之I/O模型相关推荐

  1. 高并发编程_高并发编程系列:全面剖析Java并发编程之AQS的核心实现

    在并发编程领域,AQS号称是并发同步组件的基石,很多并发同步组件都是基于AQS实现,所以想掌握好高并发编程,你需要掌握好AQS. 本篇主要通过对AQS的实现原理.数据模型.资源共享方式.获取锁的过程, ...

  2. 并发编程之Java内存模型

    在介绍Java内存模型之前,先来了解一下为什么要有内存模型,以及内存模型是什么.然后我们基于对内存模型的了解,学习Java内存模型以及并发编程的三大特性. 为什么要有内存模型 在计算机中,所有的运算操 ...

  3. 并发编程之 Java 内存模型 + volatile 关键字 + Happen-Before 规则

    前言 楼主这个标题其实有一种作死的味道,为什么呢,这三个东西其实可以分开为三篇文章来写,但是,楼主认为这三个东西又都是高度相关的,应当在一个知识点中.在一次学习中去理解这些东西.才能更好的理解 Jav ...

  4. 基于python的modbus协议编程_通往未来的网络可编程之路:Netconf协议与YANG Model

    近年来,随着全球云计算领域的不断发展与业务的不断增长,促使网络技术也不断发展,SDN技术应运而生,从最初的基于Openflow的转发与控制分离的核心思想,人们不断的去扩展SDN的外延,目前,人们可以达 ...

  5. Python之路 - 网络编程之Socket

    Python之路 - 网络编程之Socket C/S架构 ? Socket ? 基于TCP ? 基于UDP ? Socket对象方法 ? C/S架构 ? 在网络通信中 , 一般是一方求一方应 , 求的 ...

  6. Python并发编程之threading模块

    Python并发编程之threading模块 threading 模块 1. Timer对象 2. Lock对象 3. RLock 4. 信号量和有边界的信号量 5. 事件 6. 条件变量 7. 使用 ...

  7. 网络编程+go+java_GO语言的进阶之路-网络编程之socket

    GO语言的进阶之路-网络编程之socket 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.什么是socket; 在说socket之前,我们要对两个概念要有所了解,就是IP和端口 ...

  8. Java 并发编程之美:并发编程高级篇之一-chat

    借用 Java 并发编程实践中的话:编写正确的程序并不容易,而编写正常的并发程序就更难了.相比于顺序执行的情况,多线程的线程安全问题是微妙而且出乎意料的,因为在没有进行适当同步的情况下多线程中各个操作 ...

  9. Java 并发编程之美:并发编程高级篇之一

    借用 Java 并发编程实践中的话:编写正确的程序并不容易,而编写正常的并发程序就更难了.相比于顺序执行的情况,多线程的线程安全问题是微妙而且出乎意料的,因为在没有进行适当同步的情况下多线程中各个操作 ...

最新文章

  1. mysql4中出现的本地计算机 无法启动mysql服务 错误1067解决办法
  2. 超出网络bios会话限制_?老旧BIOS说再见,拯救者系列设置超简单
  3. Java模因拒绝死亡
  4. C语言: ---windows下VS Debug调试
  5. 『总结』CSS/CSS3常用样式与web移动端资源
  6. java生成iso9660工具_基于数据库的代码自动生成工具,生成JavaBean、生成数据库文档、生成前后端代码等(TableGo v7.0.0版)...
  7. Premiere Pro 2022安装教程(附详细图文教程)
  8. iframe使用方法
  9. 加速求解两个矩阵任意两行之间的pearson相关性
  10. 2011 imac 固态_老款iMac 安装SSD固态硬盘
  11. 事件模式归纳相关研究简述
  12. Chrome浏览器标签管理插件–OneTab
  13. linux用屏幕录制软件下载,vokoscreenNG(屏幕录制软件)下载_vokoscreenNG(屏幕录制软件)官方下载-太平洋下载中心...
  14. 首批接入司法数据的网贷平台已拒贷3万余失信被执行人
  15. HTTPS 相关问题
  16. 超简单!为图片和 PDF 上去掉水印
  17. 用Python写炸金花代码,学习python语言精品案例
  18. IP CAMERA 介绍
  19. 未明学院:经济形势不好时,这2种人最抢手
  20. MLX90640 红外热成像传感器测温模块开发笔记(三)

热门文章

  1. php怎么创建事务,php事务的实现方法介绍(代码示例)
  2. df 和 du 命令详解
  3. 5.1 HTML5表单的创建
  4. 九度oj 题目1376:最近零子序列
  5. 酷欧天气(CoolWeather)应用源码
  6. 使用weka进行Cross-validation实验
  7. UA MATH563 概率论的数学基础 中心极限定理15 Kolmogorov 0-1律
  8. UA SIE545 优化理论基础5 搜索与整数规划1 DFS算法
  9. mysql插入大量数据总结
  10. 图解在emu8086中学习几条汇编语言常用语句