1.3 消息传递与共享内存
到目前为止,我们关于协议(protocol)的讨论都基于一个假设:信息是在不同计算机的对等体之间传输。这类交换(传输)被称为“消息传递”。如果通信实体可以访问一块共享内存,就会导致另一种不同的信息交换方式。本节将讲述这两种机制,以及它们的利弊。
消息传递(message passing)明确地通过IPC机制来交换字节流(bytestream)和“面向记录(record-oriented)”的数据;关于IPC机制,我们将在第2章讲述。通常,应用程序开发者得定义这些信息的格式和内容,以及应用协议;参与者必须遵守这一协议,以交换信息。这一协议还定义了每个交换中可能的参与者的数量(例如,“点对点”(单播)、多播,或广播),以及参与者如何启动、管理和终止“消息传递”会话。
“消息传递”IPC机制通过IPC信道(channel),将数据以消息的形式从一个进程或线程传输给另一个进程或线程,如图1.3(1)所示。如果要传输的数据量很大,这些数据就会被分段,以

图1.3 消息传递与共享内存
消息序列的形式发送。如果有一个以上的进程接收数据,则每一条消息会发送多次,每一次针对一个接收者。很多流行的中间件体系结构,譬如,RPC、CORBA和“面向消息”中间件(MOM, message-oriented middleware),其内部都基于“消息传递”通信模型。
共享内存(shared memory)允许相同或不同主机上的多个进程访问、交换数据,就像数据位于每一个进程的本地地址空间一样。在网络应用程序中,如果数据必须被多个进程读取和(或)处理,那么,较之“消息传递”,“共享内存”设施将是一种更有效的通信机制。如果要在应用程序中使用原始(native)的OS“共享内存”机制,则应用程序不用定义“信息在实体间的传输方法”,它要定义如何定位(locate)和映射(map)共享内存区,还要定义“放在共享内存中”的数据结构。
共享内存有“本地(local)”和“分布式(distributed)”两种形式,如下文所述。
l 本地共享内存(Local shared memory)允许同一计算机上的进程拥有一个或多个共享内存区,这些内存区被映射为不同的虚拟地址范围。常见的共享内存机制有两种:
1. System V UNIX共享内存。shmget()系统函数创建一块新的共享内存区,或返回一块可用的共享内存区。进程可以通过shmat()系统函数将一块共享内存区挂接(attach)到它的虚拟地址空间上。
2. 内存映射文件。一个文件的“全部”或“局部”可以映射到一块虚拟内存区中,此虚拟
内存区被多个进程共享。内存映射文件的内容可以转储至永久存储器中,因而,它提供了一条“在执行程序之间保存和恢复信息”的捷径。
在这两种机制中,有了OS,多个进程可以将共享内存区映射到它们的地址空间中,如图1.3(2)所示。所有可以映射共享内存区的进程都可以直接读/写共享内存中的内容。
尽管共享内存很灵活,但是,通过共享内存进行多进程间通信,还是需要细致的编程。例如,应用程序开发者必须保证:共享数据不能被“竞态条件(race condition)”破坏。在第10章,我们将讲述系统范围(system-scope)同步机制,这种机制可以对一块共享内存区实施串行化(serialization)控制,使得共享信息能够以一种有序的方式被访问。同样,如果应用程序需要在共享内存中存储C++对象,也得认真设计,如副栏3所述。
|
副栏3:C++对象与共享内存 |
|
在C++中, new运算符可用来在共享内存中初始化C++对象。这一特性对concrete class(具体类)[Bja00]来说是可行的,因为每一个concrete class都包含“提供这一支持所需的全部操作”。concrete class中的所有方法(method)都是非虚方法(nonvirtual);也就是说,它们是被直接调用的,而不是通过函数指针间接调用。很多ACE wrapper facade都是concrete type(具体类型),原因参见附录A.6的论述。 相反,abstract type(抽象类型)包含虚方法,如果将其置于共享内存中,则在编写程序时将很棘手。通常,虚方法是间接调用的,它要借助一个“位于对象内存中”的函数指针表(vtable)。在每一个映射了共享内存的进程中,此共享内存区可能位于不同的虚拟内存区域(location)[BC94、Jor91]。而且,C++编译器/链接器不一定会将vtable放在各个进程的相同地址中。因此,vtable及其指向的函数可能会被映射到各个进程中的不同虚拟地址中,因而必定会在运行时产生问题。 |
l 分布式共享内存(DSM)是程序设计中的一种抽象,它扩展了OS虚拟内存机制[JM98],以供应用程序所需。虚拟内存提供了一组策略(policy),用于在需要时获取(fetching)、放置
(placing)、替换(replacing)一组内存页,从而给程序造成一种假象,认为自己拥有一块比实际物理内存大得多的地址空间。DSM在网络上扩展了虚拟内存的概念,以通过全局/共享内存中的数据进行透明的进程间通信。它体现了两种计算范式(computing paradigm)的结合:共享内存多处理器和分布式系统[PTM97]。
例如,在一些硬件/软件平台上,多台计算机被群集(cluster)为一套逻辑系统,系统中的内存在群集(cluster)中共享。应用程序通过共享内存通信,共享内存由网络计算机共同管理。DSM系统提供了相应的机制,以配合进程和网络节点的更新。通常,这种通信模型会在底层使用“消息传递”机制,用来协调数据交换,使读取者和写入者同步。
日志服务程序 => 在网络日志服务程序中,我们使用了一种实现在TCP/IP之上的“消息传递 ”IPC模型。一般来说,较之开发DSM机制并通过复杂的“分布式高速缓存一致性协议(distributed cache coherency protocol)”来管理它,使用消息传递 IPC更实际。由于DSM是一项高级研究课题,不常见于实际应用之中,所以,在本书中不会对其作进一步讨论。关于DSM方面的研究,介绍得比较好的是参考文献[NL91,PTM97]。






