共享库,对象构造函数和fork()行为

Joe*_*ish 1 c++ linux fork shared

g ++(Ubuntu 4.4.3-4ubuntu5)4.4.3.编辑清晰.

我有一个共享库,我想在第一次加载时做一些事情,并且每当没有更多的引用时.

我尝试了两种方法,结果相同.第一个是使用此链接的建议.第二种方法是在库中创建一个类的全局实例.

每个都是一样的.然后我构建了一个测试程序,该程序使用库和fork()关闭进程.事实证明构造函数只被调用一次,但析构函数被调用两次 - 每个进程一次.

这是共享库和fork()的预期行为,还是我在这里做错了什么?让dtors调用每个进程并且ctor只调用一次似乎非常危险.

共享库(g ++ -fPIC -c -o myshare.o myshare.cpp/g ++ -shared -o libmyshare.so myshare.o):

class SharedMemAccess
{
public:
    SharedMemAccess();
    ~SharedMemAccess();
};

static SharedMemAccess g_sharedMem;

SharedMemAccess::SharedMemAccess()
{    
    LOGDEBUG("Constructor\n");return;
}

SharedMemAccess::~SharedMemAccess()
{
    LOGDEBUG("Destructor\n");return;
}
Run Code Online (Sandbox Code Playgroud)

测试驱动程序(g ++ -c -o main.o main.cpp/g ++ main.o -lmyshare -o test):

int main()
{    
    LOGDEBUG("In main\n");

    pid_t rc = fork();  
    if (rc == -1)      LOGDEBUG("fork failed\n");
    else if (rc == 0)  ChildProcess();
    else               ParentProcess();

    return 0;
}

void ChildProcess()
{
    LOGDEBUG("Child process spawned.\n");    
    usleep(10 * 1000 * 1000);    
    LOGDEBUG("Child process exiting.\n");
}

void ParentProcess()
{
    LOGDEBUG("Parent process spawned.\n");
    usleep(5 * 1000 * 1000);
    LOGDEBUG("Parent process exiting.\n");
}
Run Code Online (Sandbox Code Playgroud)

输出:

16:10:28 SharedMemAccess(  59): Constructor
16:10:28 main(  25): In main
16:10:28 ParentProcess(  62): Parent process spawned.
16:10:28 ChildProcess(  47): Child process spawned.
16:10:33 ParentProcess(  72): Parent process exiting.
16:10:33 ~SharedMemAccess( 133): Destructor
16:10:38 ChildProcess(  57): Child process exiting.
16:10:38 ~SharedMemAccess( 133): Destructor
Run Code Online (Sandbox Code Playgroud)

谢谢,

-Joe

Nic*_*ght 5

那不是"共享记忆".您只是在非常衰减的意义上"共享"对象 - fork()正在复制父已经构造的对象,作为复制整个父进程的一部分.

作为大多数操作系统中的实现细节,您将获得写时复制语义(因此在一个进程尝试以某种方式改变页面之前将使用相同的内存物理位),但是来自一个进程的更改将不会是另一方面是可见的,从程序员的角度来看,父对象的实例完全不同于孩子的实例.COW语义仅用于性能和效率优化.

您可以通过一些谷歌搜索来了解共享内存/对象的实际方法.Beej的IPC指南对一种形式的共享内存进行了很好的介绍.

但是,实际共享内存的语义不会精确地匹配普通C++对象构造/销毁的语义.

  • @JoeFish:好吧,为了缩小我的答案,是的,这是预期的行为.在C++标准的约束下,确实没有任何其他行为可能.要有任何其他行为,需要C++标准知道诸如进程之类的事情 - 事实并非如此. (2认同)