Linux后台服务器编程。
分类: C/C++
2014-11-11 21:25:42
这两天事情不多,简单看了下boost.asio的源码,因为asio采用proactor模式,而windows下的IOCP本身就是这个模式的体现,所以将精力集中在了asio在linux下的实现(asio在windows下采用了IOCP,linux下用epoll,还有其它的一些实现如kqueue,select等).
在高性能服务器并发模型设计中,Reactor和Proactor是两个经常用到的设计模式,前者用于同步IO,后者用于异步IO,前者在IO操作就绪的情况下通知用户,用户再采取实际的IO操作,后者是在IO操作完成后通知用户,举个简单的例子,比如说你有一封信到了邮局,Reactor模式就是邮局的人到你家来告诉你说你有信件,然后你到邮局去拿,而Proactor模式则是邮局的把信件送到了你家.在我看来IOCP的设计就是Proactor模式的完美体现,而epoll则很容易实现Reactor模式,asio设计为跨平台,并且在linux下采用epoll,我的印象中linux对异步IO的支持没有windows那么完善(看看IOCP和epoll模型的区别就知道),那么asio是怎么用epoll机制实现proactor模式的呢,刚开始想的是应该在应用层做了一层封装,就是asio内部应该有某个循环调用epoll_wait,当有IO事件就绪时帮用户做一些操作(比如把数据拷贝到我们提交的缓冲区),然后在操作完成的时候调用我们的handler(后来看代码基本是这样).OK,不说废话了.
几个重要的类:
io_service: 这是asio中最重要的一个类,任何其它类基本都需要这个类作为成员类构造,这个类主要实现了proactor模式,它有一个成员io_service_impl,就是它的实现,这个实现根据平台的不同而不同,如下:
#if defined(BOOST_ASIO_HAS_IOCP)
namespace detail { typedef win_iocp_io_service io_service_impl; }
#else
namespace detail { typedef task_io_service io_service_impl; }
#endif
如果IOCP可用采用IOCP的实现,否则采用后者.
task_io_service:作为proactor模式在非win下的具体实现,主要功能有对IO是否就绪的不停扫描,以及事件到达后对线程池的统筹协作等,它的几个比较重要的成员如reactor(这是一个typedef定义的同义词,不同非win平台有不同的实现),op_queue
epoll_reactor:上面reactor在linux下的实现,采用的是epoll机制,对IO是否就绪不停扫描,我们熟悉的epoll_wait就在这个类的run函数里面,具体的过程是1发现IO就绪,2取得相应回调压入task_io_service的op_queue成员里面,3循环直到一次epoll_wait返回的就绪事件全部处理.
basic_stream_socket
basic_socket_acceptor
reactive_socket_service:前面说过这个类真正实现了上面两个套接字的具体功能,具体干了些什么呢,我们不妨想一下,我们在调用一些异步IO操作的时候,提供了操作的具体类型和套接字,它如果要起作用还必须和epoll关联起来,这样我们的事件多路分发器才会关注我们提交的事件,而这个类正是做这项工作的,在我们的异步调用中,它会封装我们提交的回调函数,并注册我们我们感兴趣的事件到epoll中(它是有epoll_reactor引用的哦,有了它,一切事情都好办了....)
OK,再来看看一个asio工作的一个流程(以linux下epoll实现为例):
1,用户初始化一个io_service对象.相当于初始化了网络,包括reactor,也就是操作系统提供的同步事件多路分发器(linux下epoll的初始化),io_service在这个分发器的基础上封装实现proactor模式;
2,用户根据应用要求构造basic_stream_socket
3.用户调用io_service的run函数(如上面说到的,这个函数会调用具体实现类的run函数,linux下会调用task_io_service的run函数,这个函数首先会检查op_queue是不是有事情做,有几个的话会唤醒调用了io_service.run的线程,如果只有一个则自己去做,同时解锁,让另外的线程接替自己来轮询,如果op_queue为空的话会调用epoll_wait,看看是否有新到达的事件,有一点需要注意的是,如果需要使服务器一直轮询,就必须保持至少有一个未完成的异步IO请求,否则run函数就要返回了)
这仅仅是一个大体的框架,还有许多实现的细节以后慢慢去体会,Keep Learnning!!