首页 > 代码库 > IO模型

IO模型

IO模型:

  对于一个network IO(这里我们以read举例),它会涉及到两个系统对象,一个是调用这个IO的process(or Thread),另一个就是系统内核(kernel),当一个read操作发生时,它会经历两个阶段:

  1.等待数据准备()

  2.将数据从内核拷贝到进程中

blocking IO(阻塞IO):

  blocking IO的特点就是在IO执行的两个阶段都被block了.

non-blocking IO(非阻塞IO):

  非阻塞的recvfrom系统调用之后,进程并没有被阻塞,内核马上返回给进程,如果数据还没有准备好,此时会返回一个error.进程在返回之后,可以干点别的事情,然后再发起recvfrom系统调用.循环往复的进行recvfrom系统调用,这个过程被称之为轮询,轮询检查内核数据,直到数据准备好,再拷贝数据到进程,进行数据处理.拷贝数据整个过程,进程仍然是处于阻塞状态.

  优点:能够在等待任务完成的时间里干其他活了(也就是后台,可以有多个任务在同时执行)

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

IO multiplexing(IO多路复用):

  select函数返回结果中如果有文件可读了,那么进程就可以通过调用accept()或recv()来让kernel将位于内核中准备到的数据copy到用户区.

  select的优势在于可以处理多个链接,不适用于单个链接

selectors模块:

 1 import selectors
 2 import socket
 3 
 4 sel = selectors.DefaultSelector()
 5 
 6 def accept(sock, mask):
 7     conn, addr = sock.accept()  # Should be ready
 8     print(accepted, conn, from, addr)
 9     conn.setblocking(False)
10     sel.register(conn, selectors.EVENT_READ, read)
11 
12 def read(conn, mask):
13     data = http://www.mamicode.com/conn.recv(1000)  # Should be ready
14     if data:
15         print(echoing, repr(data), to, conn)
16         conn.send(data)  # Hope it won‘t block
17     else:
18         print(closing, conn)
19         sel.unregister(conn)
20         conn.close()
21 
22 sock = socket.socket()
23 sock.bind((localhost, 1234))
24 sock.listen(100)
25 sock.setblocking(False)
26 sel.register(sock, selectors.EVENT_READ, accept)
27 
28 while True:
29     events = sel.select()
30     for key, mask in events:
31         callback = key.data
32         callback(key.fileobj, mask)

 

IO模型