重庆分公司,新征程启航
为企业提供网站建设、域名注册、服务器等服务
创新互联建站专注于怀宁网站建设服务及定制,我们拥有丰富的企业做网站经验。 热诚为您提供怀宁营销型网站建设,怀宁网站制作、怀宁网页设计、怀宁网站官网定制、重庆小程序开发公司服务,打造怀宁网络公司原创品牌,更为您提供怀宁网站排名全网营销落地服务。
目录
异步编程:...1
同步、异步:...1
阻塞、非阻塞:...2
同步、异步与阻塞、非阻塞区别:...2
联系:...2
IO模型...2
py中的IO multiplexing——selectors:...5
你做完了,我才能做,同步,串行;我让你打饭,你不打好给我,我不走开,直到你打饭给了我;
你做你的,我做我的,异步,步调不一致;我让你打饭,你正打着,我不等你,但我会盯着你,你打完我过来拿走,异步并不保证多长时间打完饭;
函数或方法调用的时候,被调用者是否得到最终结果;
直接得到最终结果的,就是同步调用;
不直接得到最终结果的,就是异步调用;
某一方法是否在这个方法调用完时,是否能获得最终结果;
同步、异步区别:
同步,一直要执行到返回结果;
异步,直接返回了,但不是最终结果,调用者不能通过这种调用得到结果,还要通过被调用者,使用其它方式通知调用者,来取回最终结果;
函数或方法调用时,是否立刻返回;
不立即返回,就是阻塞调用;
立即返回,就是非阻塞调用;
time.sleep()和event.wait(),event.wait()要优于time.sleep(),wait会主动让出时间片,其它线程可以被调度,而sleep会占用时间片不让出;
它们不相关;
同步、异步,强调的是结果;
阻塞、非阻塞强调的是时间,是否等待;
注:调用者、被调用者;
同步阻塞,我啥事不干,就等你打饭给我,打饭是结果,而且我啥事不干一直等;
同步非阻塞,我等着你打饭给我,但我可以玩手机、看电视,打饭是结果,但我不一直等;
异步阻塞,我要打饭,你说等叫号,并没有返回饭给我,我啥事不干,就等着饭好了你叫我,叫号;
异步非阻塞,我要打饭,你说等叫号,并没有返回饭给我,我在旁边玩手机、看电视,饭打好了你叫我;
同步IO、异步IO、IO多路复用:
IO过程分2阶段:
数据准备阶段,内核从输入设备读写数据(淘米、放锅里煮);
内核空间复制回用户进程缓冲区阶段,进程从内核复制数据(盛饭,从内核这个饭锅里把饭装到碗里来);
注:
sendfile,disk缓冲区-->内核缓冲区(网络缓冲区)-->发出;
0拷贝,网络缓冲区上有disk缓冲区的快捷方式,直接从disk缓冲区发出;
sync同步IO模型:
阻塞IO、非阻塞IO、IO多路复用;
阻塞IO,sync blocking IO:
进程等待(阻塞),直到读写完成,全程等待;
非阻塞IO,sync non-blocking IO:
进程调用read操作,如果IO设备没有准备好,立即返回ERROR,进程不阻塞,用户可以再次发起系统调用,如果内核已准备好,就阻塞,然后复制数据到用户空间;
第1阶段数据没有准备好,就先忙别的,等会再来看看,检查数据是否准备好了的过程是非阻塞;systemcall后返回的是异常,直到return OK;
第2阶段是阻塞(sync blocking)的,即内核空间和用户空间之间复制数据是阻塞的;
淘米、煮饭我不等,我去玩会,盛饭过程我等着你装好饭,但是要等到盛好饭才算完事,这是同步的,结果就是盛好饭;
IO多路复用,multiplexing:
同时监控多个IO,有一个准备好了,就不需要等了,开始处理,提高同时处理IO的能力;同时多路在等,而不是等完一个再等下一个;2个阶段均是sync blocking;
select,所有平台支持,poll是select的升级;
epoll,linux kernel2.5+支持,对select和poll的增强,在监视的基础上,增加回调机制(通知机制);BSD、MAC的kqueue;win的iocp;
通常用multiplexing;
以select为例,将关注的IO操作告诉select函数并调用,进程阻塞,内核监视select关注的fd文件描述符,被关注的任何一个fd对应的IO准备好了数据,select返回,在使用read将数据复制到用户进程;
例,食堂供应很多菜(众多的IO),你需要吃某三菜一汤,大师傅(OS)说要现做,需要等,你只好等待,其中一样菜好了,大师傅叫你过来,你得自己找找看哪一样菜好了,请服务员把做好的菜打给你,而epoll是有菜准备好了,大师傅喊你去几号窗口直接打菜,不用自己找菜了;
async异步IO:
linux的aio系统调用,从kernel version2.6开始支持;
2阶段都是异步,高并发时用;
进程发起异步IO请求,立即返回,内核完成IO的两个阶段,内核给进程发一个信号;
例,来打饭,跟大师傅说饭好了叫我,饭菜准备好了,窗口服务员把饭盛好了打电话叫你,两阶段都是异步的,在整个过程中,进程都可以忙别的,等好了才过来;
例,今天不想出去到饭店吃了,点外卖,饭菜在饭店做好了(第1阶段),快递员把饭送到你家门口(第2阶段);
select库:
实现了select、poll系统调用,部分实现了epoll;
是底层的IO多路复用模块,类似网络编程的socket;
开发中选择:
1、完全跨平台,使用select、poll,但性能较差;
2、针对不同OS自行选择支持的技术,这样做会提高IO处理的性能;
selectors库:
py3.4提供,高级IO复用库;
类层次结构:
BaseSelector
SelectSelector
PollSelector
EpollSelector
DevpollSelector
KqueueSelector
selectors.DefaultSelector(),返回当前平台最有效、性能最高的实现;
但,此库没有实现win的iocp,将自动退化为select;
class BaseSelector(metaclass=ABCMeta):
@abstractmethod
def register(self, fileobj, events, data=None): #fileobj,被监视文件对象,如socket对象;events,该文件对象必须等待的事件;data,可选,与此文件对象相关联的不透明数据,如,可用来存储每个客户端的会话ID,本例中关联方法,就是让selector干什么事,可以是任意对象,如果是函数类似回调
events常量:
EVENT_READ,可读0x01,内核已准备好输入输出设备,可以开始读了;
EVENT_WRITE,可写0x10,内核已准备好,可以往里写了;
注:
# generic events, that must be mapped to implementation-specific ones
EVENT_READ = (1 << 0)
EVENT_WRITE = (1 << 1)
单线程+selectors,单线程下用selectors而不用多线程,条件不满足不能转为就绪态,则不会被cpu调度;
多线程+阻塞,在OS中多了线程资源而已;
selectors可解决网络IO、文件IO;
例:
selector = selectors.DefaultSelector()
def accept(sock: socket.socket):
conn, addrinfo = sock.accept()
conn.setblocking(False)
selector.register(conn, selectors.EVENT_READ, recv)
def recv(conn: socket.socket):
data = conn.recv(1024).strip().decode()
print(data)
msg = 'ack: {}'.format(data)
conn.send(msg.encode())
sock = socket.socket()
addr = ('127.0.0.1', 9999)
sock.bind(addr)
sock.listen()
sock.setblocking(False)
e = threading.Event()
key = selector.register(sock, selectors.EVENT_READ, accept)
print(key)
while not e.is_set():
events = selector.select()
if events:
print(type(events))
print(events)
for key,mask in events:
print(key, mask)
callback = key.data
callback(key.fileobj)
输出:
SelectorKey(fileobj=
[(SelectorKey(fileobj=
SelectorKey(fileobj=
[(SelectorKey(fileobj=
SelectorKey(fileobj=
nimeide
例:
ChatServer改为IO多路复用方式;
注:
if mask == selectors.EVENT_READ: #不严格
if (mask & selectors.EVENT_READ) == selectors.EVENT_READ: #严格写法,如果r和w同时满足,进来3则不作处理