设为首页 友情链接
在线留言 发表文章
加入收藏 广告联系

刺猬首页

| 专案技术 | 网络技术 | 图形图象 | 网络编程 | 网页设计 | 操作系统 | 服务器 | 技术白皮书 | 在线实验室 | 刺猬论坛 |
小说专版  | 数据库 | 设计赏析 | 存储频道 | 网络安全 | 私服架设 |  Solaris | 网站评估 | PC维护技巧 | 下载中心 | 博 客 |
专   题: | Linux | java | cisco | 防病毒 | 刀片 | SOA | iscsi | ASP.NET | SQL | Oracle |
您现在的位置: IT公社 IT community >> Linux专题 >> Linux应用技巧 >> 教程正文 用户登录 新用户注册
专 题 栏 目
最 新 热 门
最 新 推 荐
相 关 文 章
如何判定你是否具备有学…
如何改进系统命令行工具
Linux如何显示FAT等分区…
如何自动登录linux
Linux系统中如何让程序开…
Linux系统下如何查看已经…
FreeBSD如何通过代理上网…
Linux笔记本如何延长电池…
如何制作Linux操作系统下…
如何在Linux系统下用DMA…
  如何在RedHatLinux中使用共享对象         
如何在RedHatLinux中使用共享对象
 

充分利用共享内存并不总是容易的。在本文中,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;
  
    Initializer::Initializer()
    {
      key_t key = 1234;
      bool bCreated = false;
  
      m_shmid = shmget(key, 3*1024, 0666);
  
      if (-1 == m_shmid) {
  
        if (ENOENT != errno) {
          cerr << __FILE__ << ":" << __LINE__ << " Critical error" <<
  endl;
          return;
        }
  
        m_shmid = shmget(key, 3*1024, IPC_CREAT | 0666);
  
        if (-1 == m_shmid) {
          cerr << __FILE__ << ":" << __LINE__ << " Critical error" <<
  endl;
          return;
        }
  
        cout << "Created the shared memory" << endl;
        bCreated = true;
      }
  
      A::m_sArena = shmat(m_shmid, NULL, 0);
  
      if (-1 == (int)A::m_sArena) {
        cerr << __FILE__ << ":" << __LINE__ << " Critical error" <<
  endl;
        return;
      }
  
      if (bCreated) {
        // Construct objects on the shared memory
        A * pA;
        pA = new A;
        pA->m_nA = 1;
        pA = new B;
        pA->m_nA = 2;
        pA = new C;
        pA->m_nA = 3;
      }
  
      return;
    }
  
  让我们更详细地研究清单 2:
  第 9-25 行:operator new ()
  
  同一个重载的操作符让您可以在共享内存中构造类 A、B 和 C 的对象。对象 A 直接从共享内存的起始处开始。对象 B 从偏移量 1024 处开始,C 从偏移量 2048 处开始。
  
  第 26-34 行:虚函数
  虚函数简单地向标准输出写一行文本。
  
  第 35-39 行:GetObjects
  GetObjects() 返回指向共享对象的指针。
  
  第 40-46 行:初始化器(Initializer)
  这个类存储共享内存标识符。它的构造函数创建共享内存及其中的对象。如果共享内存已经存在,它就只是依附到现有的共享内存。静态成员 m_sInitializer 确保在使用共享库的客户机模块的 main() 函数之前调用构造函数。
  
  第 48-82 行:Initializer::Initializer()
  如果原来没有共享内存,则创建,并在其中创建共享对象。如果共享内存已经存在,对象的构造就会被跳过。Initializer::m_shmid 记录标识符,A::m_sArena 记录共享内存地址。
  
  即使所有进程都不再使用它了,共享内存也不会被销毁。这样就让您可以显式地使用 ipcs 命令来销毁它,或者使用 ipcs 命令进行一些速查。
  
  客户机进程的实现在 shm_client.cpp 中:
  清单 3. 客户机 - shm_client.cpp
  
  #include "common.h"
  
    #include <iostream>
    #include <stdlib.h>
  
    int main (int argc, char * argv[])
    {
      int jumpTo = 0;
  
      if (1 < argc) {
        jumpTo = strtol(argv[1], NULL, 10);
      }
  
      if ((1 > jumpTo) || (6 < jumpTo)) {
        jumpTo = 1;
      }
  
      A * pA;
      B * pB;
      C * pC;
  
      GetObjects(&pA, &pB, &pC);
  
      cout << (int)pA << "\t";
      cout << (int)pB << "\t";
      cout << (int)pC << "\n";
  
      switch (jumpTo) {
      case 1:
        cout << pA->m_nA << endl;
  
      ca

Linux联盟收集整理

频道声明:本频道的文章除部分特别声明禁止转载的专稿外,可以自由转载.但请务必注明出出处和原始作者 文章版权归本频道与文章作者所有.对于被频道转载文章的个人和网站,我们表示深深的谢意。

原始作者:佚名 录入时间:2007-1-3 0:17:38
信息来源:不详 投稿信箱:itqoo@126.com
教程录入:itqoo    责任编辑:itqoo 
  • 上一个教程:

  • 下一个教程:
  • 【字体: 】【发表评论】【加入收藏】【告诉好友】【打印此文】【关闭窗口
      网友评论:(只显示最新10条。评论内容只代表网友观点,与本站立场无关!)
    - 关于我们 - 合作伙伴 - 友情链接 - 广告刊登 - 投稿热线 - 在线留言版权声明联系方式 -
    IT公社版权所有 粤ICP备05127012号
    Copyrigh@2005-2006 itqoo.com.Inc All Rights Reserved  推荐分辨率 1024*768
    联系站长:E-Mail:itqoo@126.com     MSN:urchincc@hotmail.com    QQ:点击这里给我发消息
    特别感谢:亿太网络提供空间支持