python io包_python_day11_IO模型

事件驱动编程思想

范式: 一种写代码的方式 ,这里程序的执行是由外部事件来决定的。它的特点是包含一个事件循环,当外部事件发生时使用回调机制来触发相应的处理。

触发事件发送到队列,然后提取事件任务,发送到执行任务函数

当CPU指令集为 0的时候对应的是内核态(拥有硬件,软件所有权限), 1为用户态

用户态: 用户所运行的程序,

内核态: 操作系统

进程阻塞:正在执行的进程,由于期待的事件未发生,如请求系统资源失败,等待某种操作的完成,则由系统自动执行阻塞,使进程进入阻塞状态, 进程阻塞是不占用CPU资源的

缓存I/O : 标准IO操作数据流向路径:数据——流缓存区——内核缓存区——磁盘

数据--> 用户态 --> 内核态 --> 对端 内核态 --> 用户态 --> 对应应用程序 --> 数据

IO模型

阻塞

非阻塞

IO多路复用

异步IO

1、阻塞IO 全程阻塞 缺点:CPU不能做其它事情 优点: 数据同步

例: 比如以socket为例,当服务启动之后,accept发起一个系统调用,由用户态到内核态,操作系统(内核态)一直等待数据(程序阻塞),当启动client端连接到s端,内核态接收到数据,数据从内核态复制到用户态,最后返回给conn

缺点: 阻塞跟同步类似,都是你发我收, 我发你收 ,CPU将会一直阻塞,

##### 阻塞IO

'''IO 每次连接都只能连接一次,如果有其它客户端需要连接就需要等待本次连接断开'''# server.py

import socket

so=socket.socket(socket.AF_INET,socket.SOCK_STREAM)

ipport=('127.0.0.1',9001)

so.bind(ipport)

so.listen(5)

while True:

conn,data=so.accept()

print(conn)

2、非阻塞IO

setblocking(False)

例: 服务端发起系统调用,查看内核态是否有数据,如果有就直接返回,如果也直接返回但会隔一段时间就会重新再去内核态在查看。

缺点: 系统调用发送太多,占据大量的数据资源, 当数据在前1秒发送时,而服务端正在阻塞就会导致数据无法及时处理

##### 非阻塞IO

''' setblocking socket等待用户进行连接,如果没有客户端进行连接,将会每隔一段时间查询一次内核态里是否有数据 '''import socket

import time

so=socket.socket(socket.AF_INET,socket.SOCK_STREAM)

ipport=('127.0.0.1',9001)

so.bind(ipport)

so.listen(5)

so.setblocking(False)

while True:

try:

conn,data=so.accept()

print(conn)

except Exception as F:

print(F)

time.sleep(5)

# 同阻塞client.py

3、IO多路调用

select.select([bindname,],[],[],5)

input output errorput 每隔几秒钟监听

select发起系统调用,内核态当发现有数据时返回给select,然后server端再发送一次recvfrom##### IO多路复用 server端

import socket

import selectors

import json

ipport=('127.0.0.1',9001)

sel=selectors.DefaultSelector()

sock=socket.socket()

sock.bind(ipport)

sock.listen(5)

class UpDown:

def put(self,obj,**data):

print('ok')

print(data)

obj.send('ok'.encode('utf-8'))

def accept(obj,mask):

# 与客户端建立连接 就跟socket 配置的 socket.accept是一个意思,只不过这里配置的是异步io可以同步连接多个客户端

conn,addr=obj.accept()

# print('client informaster: ',conn,'client addr: ',addr)

# 注册客户端conn文件描述符对象,并绑定read函数

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

def read(obj,mask):

try:

data = obj.recv(1024)

obj.send(data)

except Exception as E:

sel.unregister(obj)

obj.close()

sel.register(sock,selectors.EVENT_READ,accept)

while 1:

# 监听

events=sel.select()

# 如果没有客户端连接就是为空

# 客户端第一次连接获取的是sock对象,绑定accept函数并执行,

# 客户端发送数据 绑定read函数再进行数据的接收或发送操作

for key,mask in events:

print(key.data)

# 获取socket文件描述符,并获取register注册函数accept (sel.register(sock, selectors.EVENT_READ,accept))

conn=key.data

# key.fileobj方法 获取的是客户端的socket文件描述符对象

# mask不知道有啥用 可以不配置它

conn(key.fileobj,mask)

# 客户端 (只实现了简单的发送接收,错误处理没弄)import socket

so=socket.socket(socket.AF_INET,socket.SOCK_STREAM)

ipport=('127.0.0.1',9001)

so.connect(ipport)

while True:

inp=input('>>>>>: ')

so.send(inp.encode('utf-8'))

data=so.recv(1024)

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

触发方式: 两种

1、 水平触发

只有高电平(1)或低电平(0)时才触发通知,只要在这两种状态就能得到通知,上面提到的只要有数据可读(描述符就绪)那么水平触发的epooll就立即返回

2、 边缘触发

只有电平发生变化(高电平到低电平,或电低平到高电平)的时候才触发通知,

3、IO多路复用优势:同时可以监听多个连接

IO多路复用: 单线程下实现的并发, 原理:利用IO空闲时间

select: 效率最慢 windows下只有这个, linux三个都有,最大量只有1024个连接

poll:

epoll: 效率最快,

只要有一点点阻塞就是同步IO

4、异步IO

异步最大特点: 全程无阻塞,但系统内核运行会很忙碌

用户进程 发起调用,没有数据立刻返回,进程继续执行, 内核会一直等待数据,当内核收到数据,会将数据复制到用户态并直接返回给进程

阻塞与非阻塞区别

阻塞,全程阻塞

非阻塞,只在数据从内核态到用户态那一段时间内阻塞

同步IO与异步IO

同步IO: 只要有阻塞的就是同步IO

异步IO: 不带一丝阻塞的就是异步IO

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值