12

我已经尝试了好几个小时,并用谷歌搜索了我想到的所有东西,但我快疯了。

我有一个结构:

typedef struct {
  int rows;
  int collumns;
  int* mat;
  char* IDs_row;
} mem;

直到以后我才知道 int* (一个矩阵)和 char* 的大小。

当我这样做时,我会像这样创建共享内存:

mem *ctrl;
int size = (2 + ((i-1)*num_cons))*sizeof(int) + i*26*sizeof(char); //I have the real size now
shmemid = shmget(KEY, size, IPC_CREAT | 0666);
if (shmemid < 0) {
    perror("Ha fallado la creacion de la memoria compartida.");
    exit(1);
}
ctrl = (mem *)shmat(shmemid, 0, 0);
if (ctrl <= (mem *)(0)) {
    perror("Ha fallado el acceso a memoria compartida");
    exit(2);
}

这里没问题。然后我给 ctrl->rows 和 collumns 一个值,并将 0 分配给所有矩阵。

但在那之后,我在 char* 和 bam 中写了一些东西,分段错误。

调试程序我看到指针 mat 和 IDs_row 都为空。如何在共享内存段内给他们正确的值?

我尝试删除 char* 指针,只是为了试一试,然后分段错误错误出现在连接到所述共享内存的另一个程序中,并且只是检查了矩阵内的值(检查 ->rows 和 ->columns 是成功)

4

2 回答 2

13

首先,将绝对指针放在共享内存段中是非常糟糕的想法——这些指针仅在填充其值的进程中有效。不保证共享内存段在每个进程中都附加到相同的虚拟地址。shmaddr == NULL相反,它们在调用时指定系统认为可能的位置shmat()。您可以在调用时指定相同的虚拟地址,shmat()但您可以确保在所有参与进程的该内存区域上没有映射任何其他内容。这很难以便携的方式完成。您最想做的是:

1)分配一个大的共享内存段来容纳mem结构和两个数据数组。然后,您不应该放置绝对指针,而是放置相对于内存块开头的指针,然后根据使用情况进行调整。

2) 分配三个不同的共享内存段,但不是放置指针,而是放置由返回的共享内存 IDshmget()

typedef struct {
  int rows;
  int collumns;
  int mat_id;
  int IDs_row_id;
} mem;

当您需要访问矩阵或 IDs 数组时,只需附加到存储在相​​应字段中的共享内存 ID。

请注意,尽管KEY在后续调用中使用相同的shmget()内容不会产生预期的结果,除非KEY == IPC_PRIVATE. mem最好对带有描述符(类型)的共享内存块和其他两个内存块使用固定键值,IPC_PRIVATE否则三个调用实际上将返回相同的共享内存块 - 第一个将创建它,然后接下来的两个将简单地返回其 ID,因为具有该键的块已经存在。

于 2012-05-28T08:58:50.360 回答
7
ctrl = (mem *)shmat(shmemid, 0, 0); 

这只会将有效内存分配给ctrl指针,而不是分配给ctrl->mator ctrl->IDs_row

你可能想要:

mem *ctrl;
shmemid = shmget(KEY, sizeof(ctrl), IPC_CREAT | 0666);
//allocate memory for the structure
ctrl = (mem *)shmat(shmemid, 0, 0);

//allocate memory for the int*
shmemid = shmget(KEY,((i-1)*num_cons))*sizeof(int), IPC_CREAT | 0666);
ctrl->mat = (int*)shmat(shmemid, 0, 0);

//allocate memory for the char*
shmemid = shmget(KEY,i*26*sizeof(char), IPC_CREAT | 0666);
ctrl->IDs_row = (char*)shmat(shmemid,0,0);
于 2012-05-27T19:55:13.763 回答