【问题标题】:C Socket/Client fork(), share struct memoryC Socket/Client fork(),共享结构内存
【发布时间】:2015-02-08 18:32:49
【问题描述】:

我正在尝试在我的 C 服务器上共享结构的内存,得到以下代码

// Before the main
struct Esami {
    char nome[20];
    char cognome[20];
    char matricola[20];
    char voto[20];
};

struct Appelli {
    int stato;
    char dipartimento[20];
    char cdl[20];
    char nomeEsame[20];
    char data[20];
    struct Esami esame[10];
    int numEsamiRegistrati;
} *appello[100];

这就是我在 fork 中所做的:

// After creating socket, bind(), listen() and so on..
if ((pid = fork()) == 0) {
    shmid = shmget(2009, sizeof(appello), 0666 | IPC_CREAT);
    *appello = shmat(shmid, 0, 0);
    close (listenfd); // Closes the parent socket
    // Operations on this struct (like the one I explained below)
    exit(0);
}

我尝试使用箭头运算符访问结构的字段,但是程序可能会出现内存错误,所以如果我填充一个字段并尝试例如

printf("Dipartimento: %s", appello[0]-> dipartimento);

服务器程序崩溃:不再读取来自客户端的所有其他输入。我设法让它与单个结构变量(如 *appello)一起工作,但是一旦我开始使用数组(*appello[100]),我就会遇到这个问题。

问题是:如何将这个结构数组的内存段共享给每个连接到服务器的客户端?

请注意,我正在尝试理解一个大学练习,我必须使用共享内存和 fork 来解决它。

【问题讨论】:

  • 你为什么不在socket上serialize你的数据结构呢?另请参阅this answer 相关问题...

标签: c sockets struct fork shared-memory


【解决方案1】:

首先只是对您的示例的评论:

`printf("Dipartimento: %s", appello[0]-> dipartimento);`    
 this space does not belong in any form ^  

注意:,对于下面的 cmets,我没有您的结构成员 struct Esami esame[10]; 的定义,因此必须在所有插图中简化您的结构的表示.

下一点,为了说明不同的方法,更改:

struct Appelli {
    int stato;
    ....
    int numEsamiRegistrati;
} *appello[100];  

typedef struct {
    int stato;
    ....
    int numEsamiRegistrati;
} APPELLO;
APPELLO appello[100], *pAppello;

在 main()(或代码的任何可执行部分)执行此初始化:

pAppello, = &appello[0];//initializes your pointer to a copy of struct  
pAppello = malloc(sizeof(APPELLO));  

然后,当使用 指针时,引用成员如下:

pAppello->cdl;//use -> for pointer 

当使用 数组时,像这样引用成员:

appello[0].cdl;//use . for non-pointer   

如果你想要一个指针数组,那么用不同的方式初始化:

pAppello = &appello[0];//initializes your pointer to a copy of struct  
pAppello = malloc(sizeof(APPELLO)*100); //provides 100 instances of pAppello

现在,你有一个指向结构的指针数组,你将再次 使用. 访问其成员:

pAppello[0].cdl;

更多阅读这里是一个很好的tutorial on C structures

【讨论】:

  • 感谢您的友好回答,我用结构“Esame”更新了我的问题,但是从您的代码中,我仍然不明白我是否正确分配了内存段以便在所有分叉进程
  • @wiredmark - 您是否阅读并理解此 page 上的内容?这是关键:成功的 shmat() 调用会更新 shmid_ds 结构的成员。此结构已定义,但您已经创建了自己的结构。
  • 关于您的记忆问题 - 我不确定我是否理解,但我会试一试:通过创建指向 @ 的指针数组987654333@,您应该能够使用每个实例来存储您创建的每个进程的信息。在示例中,我们创建了一个包含 100 个的数组,因此您应该能够存储多达 100 个不同进程的信息。 pAppello[0].cdl; 代表第一个进程,pAppello[1].cdl; 代表第二个进程,一直到 pAppello[99].cdl; 代表第 100 个进程。