共享内存与结构数组

时间:2015-12-30 18:00:10

标签: c ipc shared-memory

我在两个进程之间使用一组结构来共享数据。当我尝试访问父进程的共享内存时,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;
}

3 个答案:

答案 0 :(得分:2)

问题是你没有共享一个结构数组,你正在共享一个指向结构的指针数组,而这些指针指向你用malloc分配的非共享内存。您希望代码更像:

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; }

也就是说,使用结构数组,而不是指向结构的指针数组。

请注意,这只会在你的结构(以及你的共享内存)永远不会中有任何指针的情况下起作用 - 即使指针指向共享内存,也可能是在不同过程中的不同地址。

答案 1 :(得分:1)

您希望在进程之间共享struct,而是只共享指针到结构。如果指向struct的那些在fork之前被分配和初始化的那些,那么它们在两个进程中都是有效的,但是会指向struct的不同副本(malloc()仅分配私有记忆,永不共享)。但是,实际上,指针仅在子节点中有效,即执行malloc()的节点。

因此,不是指针数组,而是分配一个结构数组:

val_t *val;

/* ... */

size = sizeof(val_t) * LEN;

/* ... */

val = (val_t *) shmat(shmid, 0, 0);

如果以这种方式执行此操作,则无需malloc()(或free())个人struct

答案 2 :(得分:1)

在,

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;