码迷,mamicode.com
首页 > 其他好文 > 详细

Proactor模式(二)

时间:2015-02-11 07:08:24      阅读:200      评论:0      收藏:0      [点我收藏+]

标签:

上次写Blog的时候Proactor并没有说的十分清楚。

这次用aio_read工作流程来举个例子:

  1. 主线程调用aio_read函数向内核注册fd的读完成事件以及buffer,期望读取多少字节,偏移是多少和怎么回馈给应用程序(Linux上一般都是信号)。

  2. 主程序继续执行自己的业务,不需要等待aio_read。这时候aio_read存在两种可能性,一种是数据已经读入buffer,另一种书数据还没读入buffer。

  3. 当fd的数据读取到用户缓冲区之后,内核立刻通知程序数据读取完成(Linux上一般是信号),需要程序进行处理。

在Erlang中并没有使用aio系列函数,而是使用的模拟Proactor。

先让我说下什么是模拟Proactor,模拟Proactor就是使用一个线程不断的使用select/epoll/kevent等函数等待IO事件,并且当IO事件发生后完成所对应的读写操作,并且通过队列的方式将结果送到工作线程上

为什么Erlang选择了模拟Proactor模式,这个和Erlang的整个模型是息息相关的。Erlang使用的是actor模型,所有的东西都被映射为Erlang的进程,这些进程之间的通信是通过消息进行的。Erlang为了执行它自己的Erlang进程,就需要将Erlang进程和物理线程关联起来,就要自己实现调度,而这个调度是在用户层完成的。所以Erlang的scheduler本身是一个没有阻塞行为的线程(除休眠状态外),它不断的去检查Erlang进程队列,如果发现有Erlang进程可执行,就执行该任务的OPcode或者BIF来完成相应的功能。那么这时候就产生了一个问题,网络IO的select操作,文件读写的阻塞操作会阻碍scheduler检查Erlang的进程队列,那该怎么办?Erlang的大神很自然的想到了模拟Proactor模式。Erlang的inet是一个内连驱动,内部实现了一个队列,当一个Erlang进程发起IO操作的时候,就将这个操作进行一下封装放入这个队列中,等待IO线程被唤醒的时候去执行。当数据读取成功后,IO线程将所有的数据读取好作为一个消息放入相对应的Erlang进程的信箱中,这样当scheduler去再次检查这个进程的时候,就可以进行后续的业务处理。这样IO和业务处理就被很好的分离开来。



Proactor模式(二)

标签:

原文地址:http://my.oschina.net/u/236698/blog/377513

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!