当前位置: 首页 > 知识库问答 >
问题:

在分叉进程之间共享运行时创建的对象

公良英资
2023-03-14

我有一个节点类,它包含两个嵌套类,服务器和客户机,以及指向每个类实例的指针。

#include "../hdr/g04.h"
#include <sys/shm.h>
#include <sys/wait.h>

void fatal(string s) {
    cerr << "Error: " << s << " . . .\n";
    exit(-1);   
}

int main() {

    int shmkey = 12345, shmid;
    Node **nodeLocation, *thisNode;
    pid_t client_pid, server_pid;

    // get a shared mem segment
    if ((shmid = shmget(shmkey, sizeof(Node *), IPC_CREAT | 0666)) < 0)
        fatal("shmget");
    if ((nodeLocation = (Node **) shmat(shmid, NULL, 0)) == (Node **) - 1)
        fatal("shmat");

    // instantiate the Node
    // assign shared memory address
    thisNode = new Node();
    *nodeLocation = thisNode;

    // Node configuration / initialization
    if (configure(*thisNode) < 0) fatal("configuration");
    if (thisNode->read_seeds() < 0) fatal("seed file");
    if (thisNode->read_catalogue() < 0) fatal("catalogue");
    thisNode->init();

    // test
    thisNode->server->test = 10;
    cout << "parent: " << thisNode 
        << "\n\t" << thisNode->server->test << endl;


    // create a client operations process
    if ((client_pid = fork()) < 0) fatal("fork");
    if (client_pid == 0) {

        // test
        thisNode->server->test = 20;
        cout << "client: " << thisNode 
            << "\n\t" << thisNode->server->test << endl;

        // do client stuff
        exit(0);
    }

    // test
    wait(NULL);
    cout << "parent: " << thisNode 
        << "\n\t" << thisNode->server->test << endl;


    // create a server operations process
    if ((server_pid = fork()) < 0) fatal("fork");
    if (server_pid == 0) {

        // test
        thisNode->server->test = 30;
        cout << "server: " << thisNode 
            << "\n\t" << thisNode->server->test << endl;

        // do server stuff
        exit(0);
    }

    // test
    wait(NULL);
    cout << "parent: " << thisNode 
        << "\n\t" << thisNode->server->test << endl;


    delete thisNode;
    return 0;
}
parent: 0x7f2532683390
        10
client: 0x7f2532683390
        20
parent: 0x7f2532683390
        10
server: 0x7f2532683390
        30
parent: 0x7f2532683390
        10
parent: 0x7f2532683390
        10
client: 0x7f2532683390
        20
parent: 0x7f2532683390
        20
server: 0x7f2532683390
        30
parent: 0x7f2532683390
        30

我的猜测是上下文切换正在发生,因此每个进程都有自己的副本被加载到相同的地址中。

我如何改变这一点,使每个进程访问该节点的完全相同的副本?

更新:

#include <sys/shm.h>
#include <sys/wait.h>
#include <sys/mman.h>
#include <errno.h>

void fatal(string s) {
    if (errno)
        perror(s.c_str());
    else
        cerr << "Error: " << s << " . . .\n";
    exit(-1);   
}

void test(string proc, Node *thisNode) {
    cout << proc << thisNode 
        << "\n\t" << thisNode->server->test << endl;
}

int main() {

    Node *tmp = new Node();
    key_t shmkey;
    int shmid;
    Node *thisNode, *nodeLocation;
    pid_t client_pid, server_pid;

    if ((shmkey = ftok("shared_obj.dat", 'R')) == (key_t)-1)
        fatal("ftok: ");
    if ((shmid = shmget(shmkey, sizeof(*tmp), 0644 | IPC_CREAT)) < 0)
        fatal("shmget: ");
    if ((nodeLocation = (Node *) shmat(shmid, (void *)0, 0)) < 0)
        fatal("shmat: ");
    thisNode = new (nodeLocation) Node();


    // Node configuration / initialization
    if (configure(*thisNode) < 0) fatal("configuration");
    if (thisNode->read_seeds() < 0) fatal("seed file");
    if (thisNode->read_catalogue() < 0) fatal("catalogue");
    thisNode->init();

    // test
    thisNode->server->test = 10;
    test("parent: ", thisNode);

    // create a client operations process
    if ((client_pid = fork()) < 0) fatal("fork");
    if (client_pid == 0) {

        thisNode->server->test = 20;
        test("client: ", thisNode); 
        // do client stuff
        exit(0);
    }

    // test
    wait(NULL);
    test("parent: ", thisNode);


    // create a server operations process
    if ((server_pid = fork()) < 0) fatal("fork");
    if (server_pid == 0) {

        thisNode->server->test = 30;
        test("server: ", thisNode); 
        // do server stuff
        exit(0);
    }

    // test
    wait(NULL);
    test("parent: ", thisNode);


    // delete thisNode;
    return 0;
}

共有1个答案

从劲
2023-03-14

您没有共享节点对象,每个进程都有自己的节点副本。它们在分叉时间是相同的,但一个过程中的变化不会反映在另一个过程中。要做到这一点,您必须实际实例化共享内存中的节点对象。你需要做一个“放置新的”

https://isocpp.org/wiki/faq/dtors#放置-新建

 类似资料:
  • 问题内容: 我正在使用“线程”模块在Python中进行项目。 如何创建一个全局变量(在我的情况下,我需要为True或False),以便项目中的所有线程(大约4-6)都可以访问? 问题答案: 我们可以在线程类外部定义变量,并在类的方法内部全局声明它。 请参见下面的简单示例,它交替打印AB。两个变量和在两个线程和之间共享。打印,然后设置为30。打印,因为已在中进行了修改。然后设置为20,再次用于中。这

  • 问题内容: 我正在尝试使用部分函数,​​以便pool.map()可以定位具有多个参数(在本例中为Lock()对象)的函数。 这是示例代码(摘自我之前的问题的答案): 但是,当我运行此代码时,出现错误: 我在这里想念什么?如何在子流程之间共享锁? 问题答案: 您不能将普通对象传递给方法,因为它们不能被腌制。有两种方法可以解决此问题。一种是创建并传递一个: 不过,这有点重量级;使用需要产生另一个进程来

  • 问题内容: 通过回答此问题,可以回答所有其他三个问题。希望我能说清楚: 在通过多处理创建的某些过程中创建对象后: 如何将对该对象的 引用 传递给其他进程? (不是很重要)我如何确保持有参考书时此过程不会消失? 示例1(已解决) 例子2 假设返回一个具有可变状态的对象。这个相同的对象应该可以从其他进程访问。 例子3 我有一个带有打开文件和锁的对象-如何授予对其他进程的访问权限? 提醒 我不希望此特定

  • 问题内容: 我有以下问题。我编写了一个函数,该函数将列表作为输入并为列表中的每个元素创建一个字典。然后,我想将此字典追加到新列表中,以便获得字典列表。我正在尝试为此生成多个进程。我在这里的问题是,我希望不同的进程访问字典列表,因为它由其他进程更新,例如,一旦达到一定长度,就打印一些东西。 我的例子是这样的: 现在我的问题是每个过程都创建自己的过程。有没有一种方法可以在进程之间共享列表,以便所有字典

  • 问题内容: 我对进程之间具有文件句柄的共享资源有疑问。这是我的测试代码: 然后我得到如下图所示: 我认为当我将对象放入队列时,对象被序列化了,而文件句柄无法序列化,所以,我得到了: 有人对此有任何想法吗?如果要共享具有文件句柄属性的对象,该怎么办? 问题答案: 我不得不反对(总之,不仅仅会放在注释中;-) @Mark反复断言文件句柄不能“在运行的进程之间传递”-这在现实,现代中根本不是真的操作系统