当前位置导航:炫浪网>>网络学院>>编程开发>>C++教程>>C++进阶与实例

在 Linux 中使用共享对象

    充分利用共享内存并不总是容易的。在本文中,IBM 的 Sachin Agrawal 与我们共享了他的 C++ 专门技术,展示了面向对象如何去利用一个独特而实用的进程间通信通道的关键优势。

    就时间和空间而言,共享内存可能是所有现代操作系统都具备的最高效的进程间通信通道。共享内存 同时将地址空间映射到多个进程:一个进程只需依附到共享内存并像使用普通内存一样使用它,就可以开始与其他进程进行通信。

    不过,在面向对象编程领域中,进程更倾向于使用共享对象而不是原始的信息。通过对象,不需要再对对象中容纳的信息进行序列化、传输和反序列化。共享对象也驻留在共享内存中,尽管这种对象“属于”创建它们的进程,但是系统中的所有进程都可以访问它们。因此,共享对象中的所有信息都应该是严格与特定进程无关的。

    这与当前所有流行的编译器所采用的 C++ 模型是直接矛盾的:C++ 对象中总是包含指向各种 Vee-Table 和子对象的指针,这些是 与特定进程相关的。要让这种对象可以共享,您需要确保在所有进程中这些指针的目标都驻留在相同的地址。

    在一个小的示例的帮助下,本文展示了在哪些情况下 C++ 模型可以成功使用共享内存模型,哪些情况下不能,以及可能从哪里着手。讨论和示例程序都只限于非静态数据成员和虚函数。其他情形不像它们这样与 C++ 对象模型关系密切:静态的和非静态非虚拟的成员函数在共享环境中没有任何问题。每个进程的静态成员不驻留在共享内存中(因此没有问题),而共享的静态成员的问题与这里讨论到的问题类似。

    环境假定

    本文仅局限于用于 32 位 x86 Interl 体系结构的 Red Hat Linux 7.1,使用版本 2.95 的 GNU C++ 编译器及相关工具来编译和测试程序。不过,您同样可以将所有的思想应用到任意的机器体系结构、操作系统和编译器组合。

    示例程序

    示例程序由两个客户机构成:shm_client1 和 shm_client2,使用由共享对象库 shm_server 提供的共享对象服务。对象定义在 common.h 中:

    清单 1. common.h 中的定义

    #ifndef __COMMON_H__
       #define __COMMON_H__

       class A {
       public:
           int m_nA;
           virtual void WhoAmI();

           static void * m_sArena;
           void * operator new (unsigned int);
       };

       class B : public A {
       public:
           int m_nB;
           virtual void WhoAmI();
       };

       class C : virtual public A {
       public:
           int m_nC;
           virtual void WhoAmI();
       };

       void GetObjects(A ** pA, B ** pB, C ** pC);

       #endif //__COMMON_H__

 

    清单 1 定义了三个类(A、B 和 C),它们有一个共同的虚函数 WhoAmI()。基类 A 有一个名为 m_nA 的成员。定义静态成员 m_sArena 和重载操作 new() 是为了可以在共享内存中构造对象。类 B 简单地从 A 继承,类 C 从 A 虚拟地继承。为了确保 A、B 和 C 的大小明显不同,定义了 B::m_nB 和 C::m_nC。这样就简化了 A::operator new() 的实现。GetObjects() 接口返回共享对象的指针。

    共享库的实现在 shm_server.cpp 中:
    清单 2. 库 - shm_server.cpp

    #include <sys/types.h>
       #include <sys/ipc.h>
       #include <sys/shm.h>
       #include <errno.h>
       #include <stdio.h>
       #include <iostream>

       #include "common.h"

       void * A::m_sArena = NULL;

       void * A::operator new (unsigned int size)
       {
           switch (size)
           {
           case sizeof(A):
               return m_sArena;

           case sizeof(B):
               return (void *)((int)m_sArena + 1024);

           case sizeof(C):
               return (void *)((int)m_sArena + 2048);

           default:
               cerr << __FILE__ << ":" << __LINE__ << " Critical error" <<
    endl;
           }
       }

       void A::WhoAmI() {
           cout << "Object type: A" << endl;
       }


       void B::WhoAmI() {
           cout << "Object type: B" << endl;
       }


       void C::WhoAmI() {
           cout << "Object type: C" << endl;
       }


       void GetObjects(A ** pA, B ** pB, C ** pC) {
           *pA = (A *)A::m_sArena;
           *pB = (B *)((int)A::m_sArena + 1024);
           *pC = (C *)((int)A::m_sArena + 2048);
       }


       class Initializer {
       public:
           int m_shmid;
           Initializer();

           static Initializer m_sInitializer;
       };

       Initializer Initializer::m_sInitializer;

 

共3页 首页 上一页 1 2 3 下一页 尾页 跳转到
相关内容
赞助商链接