我有一个Node类,它包含两个嵌套类,Server和Client,以及指向每个类的实例的指针。
我在父进程中对我的Node执行一些init方法,但希望嵌套的Server和Client实例独立行动。
我目前的方法使用shmget和shmat。 我之前使用mmap做了一次非成功的尝试。
#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
我看到Node的地址是一样的。那很好。但是为什么每个孩子的'test'值的变化都没有反映在父流程中?
我的猜测是正在进行上下文切换,因此每个进程都有自己的副本加载到同一地址。
如何更改此设置以便每个进程访问thisNode的完全相同的副本?
更新:
我试过避免双指针,我改变了一些小事。我遇到了贴装新操作符,并认为这样可以让我在shmat提供的地址分配我的对象。
#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;
}
程序运行顺利,但我仍然可以获得与以前相同的输出。
我也在每个子进程中尝试了ftok,shmget,shmat序列但是没有效果。是否有一种机制可以用来强制我的类在共享内存段中分配所有数据?
我觉得可以做到这一点,但我不知道如何并且认为它可能很难。有什么想法吗?
答案 0 :(得分:0)
您不共享节点对象,每个进程都有自己的节点副本。它们在分叉时是相同的,但是一个过程中的变化不会反映在另一个过程中。要实现这一点,您必须实际实例化共享内存中的节点对象。你需要做一个新的&#39;