简体   繁体   English

与结构数组共享内存

[英]Shared memory with array of structs

I'm using an array of structs for share data between two process. 我正在使用结构数组在两个进程之间共享数据。 The program after 3 secs raise an Segmentation fault error, when I try to access to the shared memory into the parent process. 当我尝试将共享内存访问到父进程中时,该程序在3秒钟后引发了Segmentation fault错误。 Why the data is not correctly shared? 为什么数据没有正确共享?

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

The problem is that you're not sharing an array of structs, you're sharing an array of pointers to structs, and those pointers point into non-shared memory you allocate with malloc. 问题是您没有共享结构数组,而是共享了指向结构的指针数组,并且这些指针指向使用malloc分配的非共享内存。 You want code more like: 您想要的代码更像:

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

That is, use an array of structs, rather than an array of pointers to structs. 也就是说,使用结构体数组,而不是结构体指针数组。

Note that this will only work as long as your structs (and thus your shared memory) never have any pointers in them -- even if the pointers were to point at shared memory, it might be at different addresses in the different processes. 请注意,这仅在您的结构(因此您的共享内存)中永远没有任何指针的情况下才起作用-即使这些指针指向共享内存,它也可能位于不同进程中的不同地址。

You want to share the struct s between processes, but instead you are sharing only pointers to structs. 您想在进程之间共享struct ,但是您只共享指向结构的指针 If those pointed to struct s that were allocated and initialized before the fork then they would be valid in both processes, but would point to different copies of the struct s ( malloc() allocates only private memory, never shared). 如果那些指向在派生之前分配和初始化的struct的对象,则它们在两个进程中均有效,但是指向struct的不同副本( malloc()仅分配私有内存,从不共享)。 As it is, however, the pointers are only valid in the child, which is the one performing the malloc() . 但是,实际上,指针仅在执行malloc()的子代中有效。

So, instead of an array of pointers, allocate an array of structs: 因此,分配一个结构数组,而不是一个指针数组:

val_t *val;

/* ... */

size = sizeof(val_t) * LEN;

/* ... */

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

If you do it this way, moreover, there is no need to malloc() (or free() ) individual struct s. 而且,如果您这样做,就不需要malloc() (或free() )单个struct

In, 在,

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

val points to an array of type val_t* in shared memory. val指向共享内存中类型为val_t*的数组。 This can be accessed in another process that attaches to the same shared memory segment. 可以在附加到同一共享内存段的另一个进程中访问它。

But in, 但在,

val[i] = (val_t *) malloc(sizeof(val_t));

val[i] points to memory allocated by malloc() which is private to a process. val[i]指向由malloc()分配的malloc() ,该内存是进程专用的。 This pointer cannot be accessed in a different process. 不能在其他进程中访问此指针。 Hence the Segmentation fault when you do this in the child process. 因此,当您在子进程中执行此操作时,就会出现Segmentation fault

val[0]->val = 3;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM