事件驱动与异步IO

Posted momo8238

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了事件驱动与异步IO相关的知识,希望对你有一定的参考价值。

论事件驱动与异步IO

通常,我们写服务器处理模型的程序时,有以下几种模型:
(1)每收到一个请求,创建一个新的进程,来处理该请求;
(2)每收到一个请求,创建一个新的线程,来处理该请求;
(3)每收到一个请求,放入一个事件列表,让主进程通过非阻塞I/O方式来处理请求。(启动一个协程)
上面的几种方式,各有千秋,
第(1)中方法,由于创建新的进程的开销比较大,所以,会导致服务器性能比较差,但实现比较简单。
第(2)种方式,由于要涉及到线程的同步,有可能会面临死锁等问题。
第(3)种方式,在写应用程序代码时,逻辑比前面两种都复杂。
综合考虑各方面因素,一般普遍认为第(3)种方式是大多数网络服务器采用的方式。
 

看图说话讲事件驱动模型

在UI编程中,常常要对鼠标点击进行相应,首先如何检测到鼠标点击呢?

方式一:创建一个线程,该线程一直循环检测是否有鼠标点击,那么这个方式有以下几个缺点: 1. CPU资源浪费,可能鼠标点击的频率非常小,但是扫描线程还是会一直循环检测,这会造成很多的CPU资源浪费;如果扫描鼠标点击的接口是阻塞的呢? 2. 如果是堵塞的,又会出现下面这样的问题,如果我们不但要扫描鼠标点击,还要扫描键盘是否按下,由于扫描鼠标时被堵塞了,那么可能永远不会去扫描键盘; 3. 如果一个循环需要扫描的设备非常多,这又会引来响应时间的问题; 所以,该方式是非常不好的。


方式二:就是事件驱动模型 目前大部分的UI编程都是事件驱动模型,如很多UI平台都会提供onClick()事件,这个事件就代表鼠标按下事件。事件驱动模型大体思路如下: 1. 有一个事件(消息)队列; 2. 鼠标按下时,往这个队列中增加一个点击事件(消息); 3. 有个循环,不断从队列取出事件,根据不同的事件,调用不同的函数,如onClick()、onKeyDown()等; 4. 事件(消息)一般都各自保存各自的处理函数指针,这样,每个消息都有独立的处理函数;

我只管往里面扔任务就可以了。

 

 

注册一个事件的时候,还可以增加一个回调函数。可以自己定义回调函数,做完这个动作的下一步干什么。

事件驱动编程是一种编程范式,这里程序的执行流由外部事件来决定。它的特点是包含一个事件循环,当外部事件发生时使用回调机制来触发相应的处理。另外两种常见的编程范式是(单线程)同步以及多线程编程。

让我们用例子来比较和对比一下单线程、多线程以及事件驱动编程模型(三种常用的网络编程范式)

A-单线程:完全线程执行三个任务,最耗时间。

B-多线程:同时起3个线程,但在每个线程里面,还是有自己的IO会被卡住。效率也是比较低。

C-协程:把所有的IO都挤掉了。(IO操作是由操作系统完成的。那么我怎么才能知道什么时候IO操作完成了呢。)

                一出现IO操作,我就注册一个IO事件,然后交给操作系统,操作系统有一个队列,操作完了以后,返回结果,

                 并且通过回调函数通知你。

 

下图展示了随着时间的推移,这三种模式下程序所做的工作。这个程序有3个任务需要完成,每个任务都在等待I/O操作时阻塞自身。阻塞在I/O操作上所花费的时间已经用灰色框标示出来了。

 

 IO操作实际上是由操作系统的IO接口完成的,告诉操作系统,你处理完了的时候,调用一下回调函数。这个回调函数就会通知我。

一出现IO操作,我就注册一个IO事件交给操作系统。操作系统里面有个队列,处理完了以后返回结果并且通过回调函数通知你。

 

 2. IO多路复用

    要访问的数据--------->内存里的内核空间---->内存里的用户空间。

二 IO模式

刚才说了,对于一次IO访问(以read举例),数据会先被拷贝到操作系统内核的缓冲区中,然后才会从操作系统内核的缓冲区拷贝到应用程序的地址空间。所以说,当一个read操作发生时,它会经历两个阶段: 1. 等待数据准备 (Waiting for the data to be ready) 2. 将数据从内核拷贝到进程中 (Copying the data from the kernel to the process)

正式因为这两个阶段,linux系统产生了下面五种网络模式的方案。 - 阻塞 I/O(blocking IO) - 非阻塞 I/O(nonblocking IO) - I/O 多路复用( IO multiplexing) - 信号驱动 I/O( signal driven IO) - 异步 I/O(asynchronous IO)

 

blocking I/O模式: 当没有数据返回的时候,就一直处于等待状态。

Nonblocking I/O 模式: 当没有数据返回的时候,就先通过。所以可以提高效率。

 

 

 

以上是关于事件驱动与异步IO的主要内容,如果未能解决你的问题,请参考以下文章

python下:事件驱动与 阻塞IO非阻塞IOIO多路复用异步IO

# 进程/线程/协程 # IO:同步/异步/阻塞/非阻塞 # greenlet gevent # 事件驱动与异步IO # SelectPollEpoll异步IO 以及selectors模块 # (示

论事件驱动与异步IO

Python 协程/异步IO/SelectPollEpoll异步IO与事件驱动

linux五种IO模型与事件驱动模型

同步异步事件驱动