FAQ 帮你理解COM进程外服务器EXE


COM库通过注册表获得组件信息,如果是EXE,则以客户端的权限启动该EXE,如果是服务,则委托服务管理器启动服务。

进程外组件启动时会把所有类厂接口创建好并通过调用CoRegisterClassObject把这些接口进行全局登记,登记过后其他进程就能访问这些类厂接口,当服务器需要关闭时(服务器锁引用计数为0)再调用 CoRevokeClassObject 取消登记并退出进程(服务程序可能不退出)。

客户端请求类厂接口时,COM库首先查找全局登记表中是否已经存在该接口,不存在就创建EXE组件进程,如果存在,还要判断该组件是不是SINGLETON模式,如果不是,直接返回类厂接口,如果是,重新启动一个EXE组件进程。

实际情况比上面的描述更复杂,但是足以帮助你理解其启动原理。

 

 

程的空间对于外部来说是不可见的,当然,通过注入就另说了。那么一个客户端如何能得到另一个进程里面的对象呢??
======================
这个问题问得好。后面的所有问题其实都是由这个问题引申出来的。进程空间确实对外部不可见,进程通信需要使用某种方式来完成,比如共享内存、管道、套接字等等,但如果COM系统直接把这些通信方式让用户来完成,显然就失去了COM易用透明的基础,这时出现了列集(MARSHALL)的概念。所谓列集,就是把各种无序的数据整理成有序的数据,既然数据有序了,自然适合用共享内存、管道、套接字来传递数据(它们都是以有序数据为基础的)。有序数据传递到对端,再被还原成原始的无序状态,这个过程成为散列(UNMARSHALL)。请着重看看COM原理的介绍。

sub/proxy机制提供了一个假的对象,那么假的对象又如何与实际的服务器对象通信?
======================
代理存根确实是假的对象,让使用者感觉该对象就在自己身边,随时都可以直接触摸到它。假对象与真对象之间可能近在咫尺,也可能相隔十万公里,对假对象的使用都是通过接口的方法调用来完成,假对象会把调用的上下文环境和各种参数全部列集(上面提到过)成有序数据,然后选择某种通信方式传递给对端,对端散列数据还原成假的调用者,然后由假的调用者去调用真实的对象方法。返回结果的过程也是一样的。当然,为了模仿得更逼真,调用者必须被阻塞直到返回结果。

这肯定是进程间通信的问题,那么是用的什么呢?共享内存? RPC? 对于跨主机调用来说,用RPC好,那么对于本机跨进程通信难道也是用的RPC?? 那样的话效率是个问题。
======================
这个问题也问到要点了。进程间通信具体用哪种方式,多数情况下由系统自动选择,也能自己定义,但是没必要,因为系统选择的方式已经优化得非常好了。RPC只是一个框架,不是一种具体的通信方式,因为它也要用到大家耳熟能详的方式来完成具体的通信。对于跨机器的远程调用,RPC似乎没有太多选择,除了网络还是网络;对于本机跨进程通信,RPC就变身成LPC了(这就是优化的结果),选择方式也是多种多样的,哪种通信方式都能用,效率不会成为大问题,只不过LPC过于底层,大家都感觉不到它的存在。事实上,SendMessage这个用得非常广泛的API本身就使用了LPC,0-WM_USER之间的所有系统内置消息在被发送时都会进行列集处理,这就是为什么你可以在任何地方给其他进程的窗口发送消息,而无需担心作为参数的指针传不过去,比如本进程分配的字符串,可以顺利地传递给其他进程窗口。当然如果是大于WM_USER的自定义消息,请别传递指针,因为系统不会帮你列集。

回到问题的最开始,你已经无需再问这些问题了“CoRegisterClassObject把这些接口进行全局登记,登记了什么东西??登记在哪里的? 全局对象登记表是到底是个什么东西?它用了什么方式登记下了另一个进程的对象?”,因为上面的原理能回答这些问题,剩下的事情就是继续去啃COM原理,一次啃不动下次再啃。

 

看了你的解释,很受用,我是否可以这样理解: 对于进程外服务器,COM提供了一套通信协议,我们不用去管这个协议是什么,也不用管是本地通信还是远程通信,反正都是通过了sub/proxy机制去调用一个接口的方法,这个方法的调用呢,被COM转换成了一个消息(我姑且这样认识吧),并发送给了进程外服务器,进程外服务器响应这个消息,并返回结果。
列集的作用就是把这些消息的参数序列化。其实对于进程外服务器,我们从来都没有得到过一个真正的对象。

 

看了你的解释,很受用,我是否可以这样理解: 对于进程外服务器,COM提供了一套通信协议,我们不用去管这个协议是什么,也不用管是本地通信还是远程通信,反正都是通过了sub/proxy机制去调用一个接口的方法,这个方法的调用呢,被COM转换成了一个消息(我姑且这样认识吧),并发送给了进程外服务器,进程外服务器响应这个消息,并返回结果。
列集的作用就是把这些消息的参数序列化。其实对于进程外服务器,我们从来都没有得到过一个真正的对象。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值