47异步编程_selectors

 

创新互联建站专注于怀宁网站建设服务及定制,我们拥有丰富的企业做网站经验。 热诚为您提供怀宁营销型网站建设,怀宁网站制作、怀宁网页设计、怀宁网站官网定制、重庆小程序开发公司服务,打造怀宁网络公司原创品牌,更为您提供怀宁网站排名全网营销落地服务。

目录

异步编程:...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多路复用:

IO过程分2阶段:

数据准备阶段,内核从输入设备读写数据(淘米、放锅里煮);

内核空间复制回用户进程缓冲区阶段,进程从内核复制数据(盛饭,从内核这个饭锅里把饭装到碗里来);

 

注:

sendfile,disk缓冲区-->内核缓冲区(网络缓冲区)-->发出;

0拷贝,网络缓冲区上有disk缓冲区的快捷方式,直接从disk缓冲区发出;

 

sync同步IO模型:

阻塞IO、非阻塞IO、IO多路复用;

 

阻塞IO,sync blocking IO:

47异步编程_selectors

进程等待(阻塞),直到读写完成,全程等待;

 

非阻塞IO,sync non-blocking IO:

47异步编程_selectors

进程调用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;

47异步编程_selectors

以select为例,将关注的IO操作告诉select函数并调用,进程阻塞,内核监视select关注的fd文件描述符,被关注的任何一个fd对应的IO准备好了数据,select返回,在使用read将数据复制到用户进程;

例,食堂供应很多菜(众多的IO),你需要吃某三菜一汤,大师傅(OS)说要现做,需要等,你只好等待,其中一样菜好了,大师傅叫你过来,你得自己找找看哪一样菜好了,请服务员把做好的菜打给你,而epoll是有菜准备好了,大师傅喊你去几号窗口直接打菜,不用自己找菜了;

 

async异步IO:

linux的aio系统调用,从kernel version2.6开始支持;

47异步编程_selectors

2阶段都是异步,高并发时用;

进程发起异步IO请求,立即返回,内核完成IO的两个阶段,内核给进程发一个信号;

例,来打饭,跟大师傅说饭好了叫我,饭菜准备好了,窗口服务员把饭盛好了打电话叫你,两阶段都是异步的,在整个过程中,进程都可以忙别的,等好了才过来;

例,今天不想出去到饭店吃了,点外卖,饭菜在饭店做好了(第1阶段),快递员把饭送到你家门口(第2阶段);

 

 

 

py中的IO multiplexing——selectors:

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=, fd=172, events=1, data=)

[(SelectorKey(fileobj=, fd=172, events=1, data=), 1)]

SelectorKey(fileobj=, fd=172, events=1, data=) 1

[(SelectorKey(fileobj=, fd=216, events=1, data=), 1)]

SelectorKey(fileobj=, fd=216, events=1, data=) 1

nimeide

 

 

例:

ChatServer改为IO多路复用方式;

 

注:

if mask == selectors.EVENT_READ:   #不严格

if (mask & selectors.EVENT_READ) == selectors.EVENT_READ:   #严格写法,如果r和w同时满足,进来3则不作处理

 

 

 

 


分享文章:47异步编程_selectors
本文路径:http://ybzwz.com/article/gghesh.html