标签:实现 状态 接受 指定 poll epo png twisted head
数据复制的过程中不会消耗CPU
# 1 内存分为内核缓冲区和用户缓冲区
# 2 用户的应用程序不能直接操作内核缓冲区,需要将数据从内核拷贝到用户才能使用
# 3 而IO操作、网络请求加载到内存的数据一开始是放在内核缓冲区的
用户进程从发起请求,到最终拿到数据前,一直挂起等待; 数据会由用户进程完成拷贝
‘‘‘
举个例子:一个人去 商店买一把菜刀,
他到商店问老板有没有菜刀(发起系统调用)
如果有(表示在内核缓冲区有需要的数据)
老板直接把菜刀给买家(从内核缓冲区拷贝到用户缓冲区)
这个过程买家一直在等待
如果没有,商店老板会向工厂下订单(IO操作,等待数据准备好)
工厂把菜刀运给老板(进入到内核缓冲区)
老板把菜刀给买家(从内核缓冲区拷贝到用户缓冲区)
这个过程买家一直在等待
是同步io
‘‘‘
用户进程发起请求,如果数据没有准备好,那么立刻告知用户进程未准备好;此时用户进程可选择继续发起请求、或者先去做其他事情,稍后再回来继续发请求,直到被告知数据准备完毕,可以开始接收为止; 数据会由用户进程完成拷贝
‘‘‘
举个例子:一个人去 商店买一把菜刀,
他到商店问老板有没有菜刀(发起系统调用)
老板说没有,在向工厂进货(返回状态)
买家去别地方玩了会,又回来问,菜刀到了么(发起系统调用)
老板说还没有(返回状态)
买家又去玩了会(不断轮询)
最后一次再问,菜刀有了(数据准备好了)
老板把菜刀递给买家(从内核缓冲区拷贝到用户缓冲区)
整个过程轮询+等待:轮询时没有等待,可以做其他事,从内核缓冲区拷贝到用户缓冲区需要等待
是同步io
‘‘‘
类似BIO,只不过找了一个代理,来挂起等待,并能同时监听多个请求; 数据会由用户进程完成拷贝
‘‘‘
举个例子:多个人去 一个商店买菜刀,
多个人给老板打电话,说我要买菜刀(发起系统调用)
老板把每个人都记录下来(放到select中)
老板去工厂进货(IO操作)
有货了,再挨个通知买到的人,来取刀(通知/返回可读条件)
买家来到商店等待,老板把到给买家(从内核缓冲区拷贝到用户缓冲区)
多路复用:老板可以同时接受很多请求(select模型最大1024个,epoll模型),
但是老板把到给买家这个过程,还需要等待,
是同步io
‘‘‘
发起请求立刻得到回复,不用挂起等待; 数据会由内核进程主动完成拷贝
‘‘‘
举个例子:还是买菜刀
现在是网上下单到商店(系统调用)
商店确认(返回)
商店去进货(io操作)
商店收到货把货发个卖家(从内核缓冲区拷贝到用户缓冲区)
买家收到货(指定信号)
整个过程无等待
异步io
‘‘‘
注意:
Reactor模式,基于同步I/O实现
- Proactor模式,基于异步I/O实现
Reactor模式通常采用IO多路复用机制进行具体实现
- kqueue、epoll、poll、select等机制
Proactor模式通常采用OS Asynchronous IO(AIO)的异步机制进行实现
- 前提是对应操作系统支持AIO,比如支持异步IO的linux(不太成熟)、具备IOCP的windows server(非常成熟)
Reactor模式和Proactor模式都是事件驱动,主要实现步骤:
使用过程中,用户通常只负责定义事件和事件处理器并将其注册以及一开始的事件循环的启动,这个过程就会是以异步的形式执行任务。
Reactor模型处理耗时长的操作会造成事件分发的阻塞,影响到后续事件的处理;
Proactor模型实现逻辑复杂;依赖操作系统对异步的支持,目前实现了纯异步操作的操作系统少,实现优秀的如windows IOCP,但由于其windows系统用于服务器的局限性,目前应用范围较小;而Unix/Linux系统对纯异步的支持有限,因而应用事件驱动的主流还是基于select/epoll等实现的reactor模式
Python中:如asyncio、gevent、tornado、twisted等异步模块都是依据事件驱动模型设计,更多的都是使用reactor模型,其中部分也支持proactor模式,当然需要根据当前运行的操作系统环境来进行手动配置
标签:实现 状态 接受 指定 poll epo png twisted head
原文地址:https://www.cnblogs.com/guyouyin123/p/12700416.html