My friends, my life, my style - James S.F. Hsieh

3/02/2009

Out-of-process COM server

大家應該很常撰寫 in-process COM server (COM DLL) 吧, 因為它簡單好用也符合大部分的使用狀況跟期望, 對於 out-of-process COM server (COM EXE) 就比較少有機會撰寫了. 其實有幾個主要的原因:
  1. Out-of-process COM server 必須完全實做正確的 IDL 與 Proxy/Stub: 因為只有正確寫作 IDL 才可能產生正確的 P/S, 跨行程的 Marshalling 才可能正常運作, 雖然 COM DLL 應該也要如此, 但多數人根本不遵守, 所以在 .NET 環境使用這些 COM 時, 將為非常痛苦.
  2. 跨行程的 Marshalling 有一定的限制: 很多人會在 COM 的界面上傳遞 HMODULE, Callback function pointer 等等, 然而這些 handle 是 process-wide 的物件, 跨了行程之後就不具意義了.
  3. 管理 Out-of-process COM server 並不容易: 通常使用 COM EXE 都有些特殊的目的, 譬如塑模出 System-wide 的 singleton COM object, 如果用 DLL 來實做可就非常複雜, 因為各個 COM object 在各自行程的記憶體空間中所以無法互相直接存取, 當然可以用 share-memory 或是 RPC 等行程通訊的方式互相合作塑模出 singleton COM object, 但這並不容易, 相較之下 COM EXE 就容易與值觀的多, 不過在控制 COM object 的反應時間與執行效率上就是門工夫了.
  4. Side by Side (SxS) 不可行: 畢竟 COM EXE server 的特性是任何一個 client 有需要這個 COM 的服務時, 都是由同一個 EXE process 來服務, 所以當第一次 COM EXE 被執行時, COM EXE 會利用 CoRegisterClassObject 的方式來註冊 Class object, 方式上跟 DOT 很類似, 而 Client 則是以 CoGetClassObject 的方式取得 Class object 的 Proxy, 而這些過程已經不只是向 Win32 Registry database 查表 DLL 的路徑然後 load DLL 而已, 簡單的說 SxS 比較像是模擬一個私有的 Registry database 來重新導向, 這自然對 COM EXE 無效.
  5. 相關文件過少: MSDN上 Out-of-process COM server 相關文件實在少的可憐

其實 Out-of-process COM server 有幾個好處

  1. 因為 client 跟 server 是兩個不同的 process, 所以 client 不能存取 server 私有的記憶體空間.
  2. 如果不幸兩者其中有支 process crash 了, 也不會直接的影響另一方的執行 (Fault isolation).
  3. Out-of-process COM server 可以在遠端的機器上運作.

壞處則是

  1. 效率不彰, 因為所有的資料都要利用 ORPC 來進行傳遞, RPC 的速度必定遠慢於 function invoke 千倍,
  2. 典型的 Out-of-process COM server 會以 main thread 利用 message loop 的方式推動運作,利用單一 thread 運作概念與實作上很簡單, 但是當 client 變多時, 反應速度勢必下降.

值得一提 DLL Server Surrogates 是個有趣的東西, Surrogate 可以使 in-process COM server 執行於 client 以外其他的 process 中, 這帶來強固性與安全性的好處, 當然, 效率上是必付出代價. 詳細可以參考 DLL Surrogates

Out-of-Process Server Implementation Helpers