共享内存段内的指针

时间:2012-05-27 19:50:43

标签: c linux shared-memory

我已经尝试了几个小时了,谷歌所有我想到的东西,但我会发疯。

我有一个结构:

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-&gt;行和collumns赋值,并为所有矩阵赋值0.

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

调试程序我看到两个指针,mat和IDs_row都为null。如何在共享内存段中为它们提供正确的值??

我尝试删除char *指针,只是尝试一下,然后分段错误错误发生在连接到所述共享内存的另一个程序中,只检查了矩阵内的值(检查 - &gt;行和 - &gt; collumns成功了)

2 个答案:

答案 0 :(得分:8)

首先,将绝对指针放在共享内存段中可怕的主意 - 这些指针只在填充其值的过程中有效。共享内存段无法保证在每个进程中附加到同一虚拟地址。相反 - 它们附加在系统认为可以在调用shmaddr == NULL时指定shmat()的地方。您可以在调用shmat()时指定相同的虚拟地址,但您需要确保在所有参与进程中的其他内容区域上没有映射任何其他内容。这很难以便携方式进行。你最想做的是:

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

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

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

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

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

答案 1 :(得分:6)

ctrl = (mem *)shmat(shmemid, 0, 0); 

这只会为ctrl指针指定有效内存,而不是ctrl->matctrl->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);