将对象放在共享内存中以便在.so中使用

时间:2014-03-07 21:52:24

标签: linux c++11 ipc shared-memory

将对象放在共享内存中是在我正在处理的项目中的一小部分共享对象(Linux库)中重用对象的首选方法。我之前从未使用过共享内存,所以我在这里有点失明。 ui / execute-bit-set应用程序实例化一些对象(首选项和其他工具)然后加载库并开始工作。各种各样的工具对象很小,数量不多。到目前为止,分配共享内存块和传输字符串已经成功。我现在需要确保libs可以访问由ui设置的util对象。

经过几天的研究,我想出了这个简单的模型。 (我将示例类命名为“POD”,尽管它是一个合适的类。请忽略它......)

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

using namespace std;

class PODject
{
public:
PODject() { cout << "Init POD" << endl; }
~PODject() { cout << "Destroy POD" << endl; }
string WhoAmI(void) { return "I am the POD"; }
};

int
main(int argc, char** argv)
{
PODject* pBuf = NULL;
void *shared_memory = (void*)0;
int shmid;
key_t mykey = 73867;

shmid = shmget((key_t)mykey, sizeof(PODject), 0666 | IPC_CREAT);

if (shmid == -1) {
    cerr << "shmget failed" << endl;
    return(1);
}

shared_memory = shmat(shmid, (void *)0, 0);
if (shared_memory == (void *)-1) {
    cerr << "shmat failed" << endl;
    return(1);
}

pBuf = new (shared_memory) PODject;
if(pBuf) {
    cout << "before" << endl;
    cout << pBuf->WhoAmI() << endl;
    cout << "after" << endl;
            pBuf->~PODject();
}
else
    cout << "No object" << endl;

if (shmdt(shared_memory) == -1) {
    cerr << "shmdt failed" << endl;
    return(1);
}

if (shmctl(shmid, IPC_RMID, 0) == -1) {
    cerr << "shmctl(IPC_RMID) failed" << endl;
    return(1);
}

return(0);
}

令我惊讶的是,它在大门外工作:

$ ./a.out
Init POD
I am the POD
Destroy POD

我还没有在我的项目中实现这个模型,还在做研究。但是,使用共享内存进行此特定用途的信息非常稀少。我希望知识渊博的人会简单地批评这段代码并告诉我什么是遗漏的,如果有的话。我认为我的主要问题是;我一遍又一遍地读到在共享段上实例化类对象是有问题的,我没有发现它是这样。

1 个答案:

答案 0 :(得分:1)

将对象放入共享内存有几个难点。它们都与指针有关。您甚至不能在共享内存段中使用任何指针,因为它可能会加载到不同进程的不同位置。您必须非常确定所包含的对象不会malloc任何空间,因为该空间将在堆上而不在共享内存中,并且坏指针可能会对其他过程执行错误操作。它们不能具有虚函数,因为虚函数表可能位于本地进程内存中的不同位置。

例如,在对象中放入一个字符串是不好的,因为它为字符串分配了内存。

我见过大多数人都在解决这些问题,但这很痛苦。使用索引而不是指针可以提供帮助。

除此之外还有其他问题。您必须学会在进程之间使用互斥锁/互斥锁以避免竞争条件。