具有结构数组的共享内存
Shared memory with array of structs
我正在使用结构数组在两个进程之间共享数据。当我尝试访问共享内存到父进程时,3 秒后的程序会引发 Segmentation fault
错误。为什么数据没有正确共享?
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#define LEN 3
typedef struct {
int val;
} val_t;
int
main (int argc, char *argv[])
{
key_t key;
int shmid, i, size;
val_t **val;
if ((key = ftok(argv[0], 'D')) == -1) {
perror("ftok");
exit(1);
}
size = sizeof(val_t *) * LEN;
if (fork() == 0) {
if ((shmid = shmget(key, size, IPC_CREAT | IPC_EXCL | 0666)) == -1) {
perror("shmget");
exit(1);
}
val = (val_t **) shmat(shmid, 0, 0);
if (val == (val_t **)(-1)) {
perror("shmat");
exit(1);
}
for (i = 0; i < LEN; i++) {
val[i] = (val_t *) malloc(sizeof(val_t));
val[i]->val = i;
}
while (val[0]->val != 3)
sleep(1);
if (shmdt(val) == -1) {
perror("shmdt");
exit(1);
}
shmctl(shmid, IPC_RMID, NULL);
}
else {
sleep(3);
if ((shmid = shmget(key, size, IPC_EXCL)) == -1) {
perror("shmget");
exit(1);
}
val = (val_t **) shmat(shmid, 0, 0);
if (val == (val_t **)(-1)) {
perror("shmat");
exit(1);
}
printf("%d\n", val[0]->val);
val[0]->val = 3;
if (shmdt(val) == -1) {
perror("shmdt");
exit(1);
}
}
return 0;
}
您想在进程之间共享 struct
,但您只共享结构的 指针 。如果那些指向在 fork 之前分配和初始化的 struct
s 那么它们在两个进程中都是有效的,但会指向 struct
s 的不同副本(malloc()
仅分配私有内存,从不共享)。然而,事实上,指针仅在 child 中有效,即执行 malloc()
.
的指针
因此,分配一个结构数组而不是指针数组:
val_t *val;
/* ... */
size = sizeof(val_t) * LEN;
/* ... */
val = (val_t *) shmat(shmid, 0, 0);
如果你这样做,而且,就不需要malloc()
(或free()
)个人struct
s。
在,
val = (val_t **) shmat(shmid, 0, 0);
val
指向共享内存中类型为 val_t*
的数组。此 可以 在附加到同一共享内存段的另一个进程中访问。
但是在
val[i] = (val_t *) malloc(sizeof(val_t));
val[i]
指向进程私有的 malloc()
分配的内存。这个指针不能在不同的进程中被访问。因此,当您在子进程中执行此操作时 Segmentation fault
。
val[0]->val = 3;
问题是您没有共享一个结构数组,而是共享一个指向结构的指针数组,而这些指针指向您使用 malloc 分配的 non-shared 内存。您想要的代码更像:
val_t *val;
size = sizeof(val_t) * LEN;
if (fork() == 0) {
if ((shmid = shmget(key, size, IPC_CREAT | IPC_EXCL | 0666)) == -1) {
perror("shmget");
exit(1); }
val = (val_t *) shmat(shmid, 0, 0);
if (val == (val_t *)(-1)) {
perror("shmat");
exit(1); }
for (i = 0; i < LEN; i++) {
val[i].val = i; }
也就是说,使用结构数组,而不是结构指针数组。
请注意,这仅在您的结构(以及您的共享内存)从不中有任何指针时才有效——即使指针指向共享内存,它可能在不同的进程中位于不同的地址。
我正在使用结构数组在两个进程之间共享数据。当我尝试访问共享内存到父进程时,3 秒后的程序会引发 Segmentation fault
错误。为什么数据没有正确共享?
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#define LEN 3
typedef struct {
int val;
} val_t;
int
main (int argc, char *argv[])
{
key_t key;
int shmid, i, size;
val_t **val;
if ((key = ftok(argv[0], 'D')) == -1) {
perror("ftok");
exit(1);
}
size = sizeof(val_t *) * LEN;
if (fork() == 0) {
if ((shmid = shmget(key, size, IPC_CREAT | IPC_EXCL | 0666)) == -1) {
perror("shmget");
exit(1);
}
val = (val_t **) shmat(shmid, 0, 0);
if (val == (val_t **)(-1)) {
perror("shmat");
exit(1);
}
for (i = 0; i < LEN; i++) {
val[i] = (val_t *) malloc(sizeof(val_t));
val[i]->val = i;
}
while (val[0]->val != 3)
sleep(1);
if (shmdt(val) == -1) {
perror("shmdt");
exit(1);
}
shmctl(shmid, IPC_RMID, NULL);
}
else {
sleep(3);
if ((shmid = shmget(key, size, IPC_EXCL)) == -1) {
perror("shmget");
exit(1);
}
val = (val_t **) shmat(shmid, 0, 0);
if (val == (val_t **)(-1)) {
perror("shmat");
exit(1);
}
printf("%d\n", val[0]->val);
val[0]->val = 3;
if (shmdt(val) == -1) {
perror("shmdt");
exit(1);
}
}
return 0;
}
您想在进程之间共享 struct
,但您只共享结构的 指针 。如果那些指向在 fork 之前分配和初始化的 struct
s 那么它们在两个进程中都是有效的,但会指向 struct
s 的不同副本(malloc()
仅分配私有内存,从不共享)。然而,事实上,指针仅在 child 中有效,即执行 malloc()
.
因此,分配一个结构数组而不是指针数组:
val_t *val;
/* ... */
size = sizeof(val_t) * LEN;
/* ... */
val = (val_t *) shmat(shmid, 0, 0);
如果你这样做,而且,就不需要malloc()
(或free()
)个人struct
s。
在,
val = (val_t **) shmat(shmid, 0, 0);
val
指向共享内存中类型为 val_t*
的数组。此 可以 在附加到同一共享内存段的另一个进程中访问。
但是在
val[i] = (val_t *) malloc(sizeof(val_t));
val[i]
指向进程私有的 malloc()
分配的内存。这个指针不能在不同的进程中被访问。因此,当您在子进程中执行此操作时 Segmentation fault
。
val[0]->val = 3;
问题是您没有共享一个结构数组,而是共享一个指向结构的指针数组,而这些指针指向您使用 malloc 分配的 non-shared 内存。您想要的代码更像:
val_t *val;
size = sizeof(val_t) * LEN;
if (fork() == 0) {
if ((shmid = shmget(key, size, IPC_CREAT | IPC_EXCL | 0666)) == -1) {
perror("shmget");
exit(1); }
val = (val_t *) shmat(shmid, 0, 0);
if (val == (val_t *)(-1)) {
perror("shmat");
exit(1); }
for (i = 0; i < LEN; i++) {
val[i].val = i; }
也就是说,使用结构数组,而不是结构指针数组。
请注意,这仅在您的结构(以及您的共享内存)从不中有任何指针时才有效——即使指针指向共享内存,它可能在不同的进程中位于不同的地址。