写一篇总结,来加深印象。
Symbian OS内核和内存管理单元为每个进程实现不同的内存映射地址空间,同时防止无关进程重写另一个进程的内存。唯一能够“看到”整个物理内存的进程是内核进程自身。所有的线程都是内核服务器的客户,并且正是内核帮助进程和它们所包含的线程之间进行通信。
这段话让我有点恍然大悟,客户端部分的RSessionBase和服务器部分的CSession2可以理解是对KerrnelServer的C/S调用。
所有的服务器都是从CActive派生而来――它们都是活动对象。
StartL()方法将它们添加到活动规划器中,并且启动它们等待它们的初次请求。
实际上由RunL()的实现负责在会话上调用ServiceL()。
当内核通过信号通知服务器的TRequestStatus(表示已从客户传入请示)时执行。
由此可基本确定,服务器的实现为:
它是一个AO,创建AS(ActiveScheduler),并加入。
StartL()方法伪码大概为:
{ //调用异步请求:异步请求的服务提供者是:操作系统内核(KerrnelServer)服务,只要有客户线程发出SendService请求,异步服务就完成。 //异步服务完成后,改变iStatus值,启动服务线程,调用AO::RunL,CServer2在RunL中调用CSession2::Service(),处理客户端请求。 AO::Request(iStatus); AS::Start();//活动调度器进行事件异步请求完成等待,并调度 }
下面给出了服务器服务于异步请求的基本过程,假设已经启动了所讨论的服务器。
1、 客户通过RSession派生对象建立与服务器的连接,该对象表示客户端的API
2、 服务器创建与客户会话关联的新会话对象
3、 客户通过客户端的API建立请求
4、 根据具体的请求,客户API将与请求关联的所有数据包装为整数、描述符或包描述符。
5、 客户API调用SendReceiveL(),该函数带有适当的函数ID和参数指针。
6、 内核完成服务器的iStatus成员。
7、 调用服务器的RunL(),通过内核将从客户处接收到的消息传递给会话的ServiceL()方法。
8、 根据消息中函数ID值,会话的ServiceL()调用适当的服务处理器。
9、 使用适当的ReadL(),服务处理程序从客户的地址空间中复制数据。
10、 服务处理程序服务请求
11、 使用适当的WriteL(),服务处理器将数据复制到客户地址空间。
12、 服务处理器在消息上以适当错误码,调用Complete()。
13、 内核增加客户线程的信号量,并且将TRequestStatus设置为Complete()中指定的值。
14、 客户线程的活动规划器调用客户的RunL()方法。
15、 客户的RunL()通过客户API执行对返回数据的所有处理。