7-4 并发编程IO多路复用常见考题

Posted WinvenChang

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了7-4 并发编程IO多路复用常见考题相关的知识,希望对你有一定的参考价值。

一、五种IO模型

Unix网络编程中提到了5种网络模型
1.Blocking IO(阻塞式IO)
2.Noblocding IO(非阻塞式IO)
3.IO multiplexing(IO多路复用)

两种不常用,一般使用IO多路复用比较多
1.Signal Driven IO(信息驱动IO)
2.Asynchronous IO(异步IO)

二、如何提升服务器的并发能力呢?

一些常见的提升并发能力的方式
1.多线程模型,创建新的线程处理请求
2.多进程模型,创建新的进程处理请求

(注意:线程/进程创建开销比较大,可以用线程池方式解决;线程和进程比较占用资源,难以同时创建太多)
3.IO多路复用,实现单进程同时处理多个socket请求

三、什么中IO多路复用?

操作系统提供的同时监听多个socket的机制
1.为了实现高并发需要一种机制并发处理多个socket
2.Linux常见的是select/poll/epoll
3.可以使用单线程进程处理多个socket

阻塞式IO流程图:

  • 内核等待数据
  • 数据从内核拷贝到用户进程

    IO多路复用流程图:
    select可以同时处理多个socket,有一个就绪应用程序代码就可以处理它

    IO多路复用代码格式:
while True:
	events = sel.select()
	for key, mask in events:
		callback = key.data
		callback(key.fileobj, mask)

四、select/poll/epoll区别

系统调用selectpollepoll
事件集合用户通过3个参数分别传入感兴趣的可读、可写及异常等事件,内核通过对这些参数的在线修改来反馈其中的就绪事件。这使得用户每次调用 select都要重置这3个参数统一处理所有事件类型,因此只需一个事件集参数。用户通过pollfd.events传入感兴趣的事件,内核通过修改pollfd.revents反馈其中就绪的事件内核通过一个事件表直接管理用户感兴趣的所有事件。因此每次调用epoll_wait时,无须反复传入用户感兴趣的事件。epoll_wait系统调用的参数events仅用来反馈就绪事件
反应程序索引就绪文件描述符的时间复杂度O(n)O(n)O(1)
最大支持文件描述符数一般有最大值限制6553565535
工作模式LTLT支持ET高效模式
内核实现和工作效率采用轮询方式来检测就绪事件,算法时间复杂度为O(n)采用轮询方式来检测就绪事件,算法时间复杂度为O(n)采用回调方式来检测就绪事件,算法时间复杂度为O(1)

五、Python如何实现IO多路复用?

Python封装了操作系统的IO多路复用
1.PythonIO多路复用基于操作系统实现(select/poll/epoll
2.Python2 select模块
3.Python3 selectors模块

selectors模块:

  • 事件类型:EVENT_READ, EVENT_WRITE
  • DefaultSelector:自动根据平台选取合适的IO模型
    • register(fileojb, events, data=None)
    • unregister(fileobj)
    • modify(fileobj, events, data=None)
    • select(timeout=None): returns[(key, events)]
    • close()

代码示例:

import selectors
import socket

sel = selectors.DefaultSelector()

def accept(sock, mask):
	conn, addr = sock.accept()   # should be ready
	print('accepted', conn, 'from', addr)
	conn.setblocking(False)
	sel.register(conn, selectors.EVENT_READ, read)

def read(conn, mask):
	data = conn.recv(1000)  # should be ready
	if data:
		print('echoing', repr(data), 'to', conn)
		conn.send(data)  # Hope it won't block
	else:
		print('closing', conn)
		sel.unregister(conn)
		conn.close()

sock = socket.socket()
sock.bind(('localhost', 1234))
sock.listen(100)
sock.setblocking(False)
sel.register(sock, selectors.EVENT_READ, accept)

while True:
	events = sel.select()
	for key, mask in events:
		callback = key.data
		callback(key.fileobj, mask)

以上是关于7-4 并发编程IO多路复用常见考题的主要内容,如果未能解决你的问题,请参考以下文章

python并发编程-多路复用IO

并发编程:IO多路复用。

Python并发编程-IO模型-IO多路复用实现SocketServer

并发编程 - IO模型 - 1.io模型/2.阻塞io/3.非阻塞io/4.多路复用io

并发编程 - IO模型 - 1.io模型/2.阻塞io/3.非阻塞io/4.多路复用io

python 复习—并发编程——IO多路复用协程