架构:如何为访问共享资源的多个 COM 接口提供服务
我有一个建筑问题。我有一个项目,概念上是这样的:
这看起来很简单,但也有一些问题。通过一个部分虚构的例子来介绍一些背景。这是一个 ASCOM 驱动程序,它控制一些电机、传感器和一些电源开关。硬件设备可以旋转天文台圆顶并报告其位置、打开和关闭快门以及打开和关闭各种观测仪器(望远镜、相机、聚焦器等)的电源。
硬件抽象层处理通过串行链路发送和接收命令以及随之而来的任何时序和排序问题。表示层可以调用 HAL 中的方法来使硬件执行某些操作,这可能会在串行端口上生成一系列命令和响应,或者根本不生成任何命令和响应。未经请求的数据也可以到达串行端口并完全在 HAL 内处理。
“表示层”由多个 COM 接口组成。一个接口 (IDome) 负责控制球罩和快门,另一个接口 (IPower) 负责对各种设备进行电源控制。这是标准,无法更改。
当两个不同的程序想要访问该设备时就会出现问题。例如,一个程序可能想要通过 IDome 接口控制球机,另一个程序可能想要使用 IPower 接口控制电源。在当前的实现中,这会导致在不同的进程中创建整个程序集的两个实例,其中一个由于串行端口上的争用而失败,该端口只能允许一个连接。
我需要找到一种将HAL和表示层解耦的方法,使得COM接口可以被多个进程加载,而HAL只加载一次并为表示层的所有实例提供服务。
目前,所有这些“层”都包含在单个 .NET 程序集中,如果可能的话,我希望保持这种方式。
什么模式适合这种情况?非常感谢任何和所有建议。
I have an architectural question. I have a project that is conceptually something like this:
This seems quite straightforward but there are wrinkles. Some background, by way of a partly fictitious example. This is an ASCOM driver which controls some motors, sensors and some power switches. The hardware device can rotate an observatory dome and report its position, open and close the shutter and turn the power on and off to the various observing instruments (telescope, camera, focuser, etc).
The Hardware Abstraction Layer deals with sending and receiving commands over a serial link and with any timing and sequencing issues that come with that. The presentation layer can call a method in the HAL to make the hardware do something, that might generate a whole series of commands and responses on the serial port, or none at all. Unsolicited data can also arrive at the serial port and is dealt with completely within the HAL.
The 'presentation layer' is composed of several COM interfaces. One interface (IDome) deals with controlling the dome and shutter, another (IPower) deals with the power control to the various devices. This is a standard and can't be changed.
The problem comes when two different programs want to access the device. For example, one program might want to control the dome via the IDome interface, another might want to control the power using the IPower interface. In the current implementation, this results in two instances of the whole assembly being created in different processes and one fails because of contention on the serial port, which can only allow one connection.
I need to find a way of decoupling the HAL and the presentation layer, such that the COM interfaces can be loaded by multiple processes, while the HAL only loads once and serves all the instances of the presentation layer.
Currently all of these 'layers' are contained within a single .NET assembly and I'd prefer to keep it that way if possible.
What patterns are good for this situation? Any and all suggestions greatly appreciated.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
一种选择是让需要成为单例(HAL)的东西实际上成为盒子上的单例。例如,您可以将 HAL 逻辑移至 Windows 服务中,表示层可以通过进程间通信(管道或 TCP 套接字)进行通信。为了确保只有一个服务实例启动,您可以强制使用静态服务名称,但也可以通过让服务采用系统范围的互斥锁来防止服务实例在多个用户会话下运行。
One option would be to make what needs to be a singleton (the HAL) actually a singleton on the box. For example, you could move the HAL logic into a windows service and the presentation layer can communicate via interprocess communications (pipe or tcp sockets). To ensure that only one instance of the service starts up, you can enforce a static service name but you can also protect against instances of the service running under multiple user sessions by having the service take a system wide mutex.
您也许可以使用DCOM。这个想法是将您的 CLSID 注册为进程外服务器(可以选择使用 COM+)。当您的客户端创建这些 CLSID 的实例时,它们都将在“代理进程”中创建,并且 Windows 将透明地编组客户端进程与此代理进程之间的调用。
请注意,要执行此操作,您必须具有 'proxy/stub DLL' 用于您的接口。如果编译包含接口定义的 IDL 文件,它将为此类代理/存根 DLL 生成 C 代码。然后,您必须注册此 DLL 以进行进程外通信,以便与您的自定义接口正常工作。
或者,您可以在 HAL 级别应用相同的进程外激活模型 - 即,为 HAL 创建 COM 接口,将 HAL 的 CLSID 注册为进程外服务器,并让内部组件通过以下方式进行通信: DCOM。这样做的优点是您可以控制接口 CLSID,并且可以注册您自己的代理/存根 DLL,而不会与其他供应商的代理/存根 DLL 发生冲突。
You may be able to use DCOM. The idea is to register your CLSIDs as out of process servers (optionally using COM+). When your clients create instances of these CLSIDs, they will all be created in a "surrogate process", and Windows will transparently marshal calls between the client processes and this surrogate process.
Note that to do this, you must have a 'proxy/stub DLL' for your interface. If you compile an IDL file containing your interface definitions, it will produce C code for such a proxy/stub DLL. You must then register this DLL for out of process communication to work properly with your custom interfaces.
Alternately, you can apply the same out-of-process activation model at the HAL level - that is, create a COM interface for the HAL, register the HAL's CLSID as an out-of-process server, and have your internal components communicate over DCOM. This has the advantage that you'll have control of the interface CLSID, and can register your own proxy/stub DLL without possibly colliding with some other vendor's proxy/stub DLL.
就模式而言,您需要一个代理来控制对 HAL 的所有访问,这是给定的。
就控制访问而言,多个 UI 控制一组资源是否有意义?假设您也确实想要,代理将使用可以解决冲突等的逻辑。
或者,代理有两个逻辑部分,一个接受输入,另一个报告当前值,以便多个订阅者客户端(UI) )可以及时了解 HAL 所在的位置。事件驱动的方法在这里可以很好地工作,还可以看看发布/订阅模式。对于单一控制,请查看锁定模式。
在所有情况下,代理都是应用控制逻辑的地方,但代码结构本身会比这更复杂。
In terms of pattern you want a proxy that controls all access to the HAL, that's a given.
In terms of control access, does it make sense for multiple UIs to have control over one set of resources? Assuming you do want too there would be logic used by the proxy that would resolve conflicts etc.
Alternatively you'd have two logical parts to the proxy, one that accepted input, and the other that reported current values so that multiple subscriber clients (UIs) could keep up to date with where the HAL is at. An event driven approach would work well here, also have a look at publish/subscribe patterns. For single control have look at locking patterns.
In all cases the proxy is where the control logic is applied, but the code structure itself would be more complex than that.