IPCv2实现机制 Monday, October 12, 2009

IPCInter-Process Communication的缩写,说的就是client-server框架。它可是symbian OS 上的元老之一。在Psion Series 5上就已经实现了,直到symbian OS v9.5都在不断的改进扩展新的功能。client-serverOS上随处可见,比如F32(文件服务)、ESOCKsocket服务)、大名鼎鼎的WSERVwindow 服务)以及ETEL(电话服务)等等。由于我现在使用9.5版本的symbian os,所以在这里只讨论IPCv2。老一点IPCv1就不专门说了。
       从使用client-server的角度来看,developer只需要关注4个接口类:CServer2CSession2RSessionBaseRSubSessionBase,其中前两个类的实例运行于user端的server端,后两个类实际上是提供给client使用的接口,运行于user端的client端。由此可见client-server框架非常便利,它的工作过程可以大体描述为:
1.        client使用全局唯一的server名字与server建立起连接,创建一个session
2.        如果server没有启动,就启动之。
3.        server一启动就是发出一个request检查kernel端消息队列是不是有待处理的消息。
4.        client发送消息给server。实际上将消息放入到kernel端的消息队列中。
5.        client等待消息的处理结果。
6.        一旦有消息,server就取出一个消息
7.        server处理消息
8.        server处理完消息后,通知client消息已经处理完。
注意,消息队列FIFO队列,并且server一次只能取出一个消息,不能并行处理。
IPCv2相对于IPCv1来说提供了更健全的安全机制和更便利的使用方式。Server的名字必须是以“!”开头的,kernel端将保证名字的合法性和唯一性;session不再绑定到特定client中的线程;在kernel端创建server以及client连接到这个server是异步进行的,这将保证client不会连接到恶意的serverserver通过送来的message中包含的handle访问client端的地址空间,而message包含的handle是经过server认证的;session可以在线程之间也可以在进程之间共享。
在上文中我们提高了4个类,还提到了User端、kernel端等,看着有些乱。下面我用一个图来表示这些概念,将它们一一对应起来。


这样是不是比较清楚些?从上图可以看出来只要实现了CServer2CSession2这两个类就实现了server。一般我们接触到的server都是一个exe,也就是说一般情况下server都是运行在独立的进程空间的。但是实际上只要支持AO机制的线程或者进程都可以用于实现server,这是由于CServer2派生于CActiveServer必须在client与之交互之前启动,有两种方式启动server
1、client组织代码启动server
2、在手机启动的过程中自动启动,比如ETEL。自动启动server都是在system boot过程中执行的,参见symbian手机启动过程
Server启动后马上创建CServer2对象,然后调用Start()使CServer2处于接收message的状态,同时在kernel会有一个对应的kernel server对象被创建。Kernel server对象拥有一个FIFO message队列,里面的message依次发送到CServer2对象。
无论如何client端都需要从RSessionBase派生一个类。就RSessionBase这个类本身来说主要做三件事情:a)创建与server交互的sessionb)与server交互;c)设置session共享的级别。而其派生类主要实现地是利用RSessionBase提供的基础接口与sever交互的功能,这与具体是需求有关系,每个不同的需求都会有不同的实现,这里就不讨论派生类了。
Client调用RSessionBase::CreateSession创建与server交互的session,并与server建立连接。这个过程中同时创建了kernel端的session对象,这个kernel对象也有一个FIFO message队列,比较奇怪吧?想想为什么。此时如果server还没有启动,CreateSession会失败,就需要client组织代码启动server。到这里大家明白了吧,RSessionBase封装的handle就是kernel session对象,clientserver交互的环境。在这个过程中还调用了NewSessionL()创建CSession2对象。
到现在为止clientserver连接起来,可以进行交互了。下面说说交互的过程。
Client调用Sendxxx这类函数与server交互,它们都使用了那个handle,将message首先放入了kernel session对象的消息队列,之所以放入到这里是因为client-server框架有一个非常重要承诺:就算server死掉了,client发送给servermessage都会有返回。随后kernel再将message转发到kernel server的消息队列中,此时kernel激活user端的CServer2对象,CServer2收到后,会将接受到的message发送给CSession2对象。随后的处理过程就是大家熟悉的过程了。
该到RSubSessionBase出场的时候了。我认为IPCv2的共享的特性主要体现在这个类上。大家对RFsRFile这两个类比较熟悉吧,RFs建立起于F32的连接,然后若干个RFile共享这个RFsF32进行交互。RSubSessionBase封装的handle实现与CSession2中,由用户定义。
不同进程之间共享session通过SetParameter实现的,具体过程以后讨论吧。

0 comments: