具有指针的共享内存数据结构

Shared memory data structure having pointer

您好,我正在尝试使用共享内存 IPC 在进程之间进行通信。但是,当我尝试使用 shmat 将指针分配给数据结构时,shmat 返回共享内存地址的起始位置。我的代码如下

#define SHM_SIZE 10240
struct myds {
 int ind;
 char *data[1];
};
int main()
{

    key_t key = ftok("shmfile",65);
    struct myds *nums;

    int shmid = shmget(key,SHM_SIZE,0666|IPC_CREAT);

    char *shm_addr = (char*) shmat(shmid,(void*)0,0);
    int *count = (int *) shm_addr;
    *count = 5;
    nums = (struct myds *)((void *)shm_addr + sizeof(int));
    for(int i = 0; i < *count; i++) {
         nums[i].ind = i;
    }
    
    char *t = (char*) shmat(shmid,(void*)0,0);
    printf("%d\n", *count);
    sprintf(t, "check- 112[=10=]");
    nums[0].data[0] = t;
    printf("Data written in memory:");

    getc(stdin);
    printf("%d\n", *count);

    shmdt(shm_addr);
    shmctl(shmid,IPC_RMID,NULL);

    return 0;
}

*count 的最后一次打印应该打印 5,但打印出不同的值并且非常大。这似乎是 sprintf(t, "check- 112[=15=]") 的效果。我是不是做错了什么?

countt指向同一个内存地址。当 sprintf() 通过 t 将新数据写入该地址时,它会覆盖通过 *count 读取的值。这就是为什么你在 sprintf().

之后从 *count 得到垃圾

看起来您正在尝试将 sprintf() 数据写入 nums[0].data[0] 指向的内存,但实际上您并未将 data[0] 设置为指向任何有意义的地方。 shmat() 返回的起始地址是存储在 data[0] 中的错误地址。

由于您正在分配一个非常大的内存块,远远超过实际需要的 5 个 myds 结构的数组,您可以将 data[0] 指向最后分配的 [=24= 之后的内存] 数组中的结构。

试试像这样的东西:

#define SHM_COUNT 5

struct myds {
    int ind;
    char* data[1];
};

int main()
{
    key_t key = ftok("shmfile",65);
    struct myds *nums;

    int shmid = shmget(key, sizeof(int) + (sizeof(struct myds) * SHM_COUNT) + 11, 0666|IPC_CREAT);

    char *shm_addr = (char*) shmat(shmid, NULL, 0);
    int *count = (int *) shm_addr;
    *count = SHM_COUNT;

    nums = (struct myds *)(shm_addr + sizeof(int));
    for(int i = 0; i < SHM_COUNT; i++) {
        nums[i].ind = i;
    }

    char *t = (char*) (nums + SHM_COUNT);
    printf("%d\n", *count);
    sprintf(t, "check- 112[=10=]");

    for(int i = 0; i < SHM_COUNT; i++) {
        nums[i].data[0] = t;
    }

    printf("Data written in memory:");

    getc(stdin);
    printf("%d\n", *count);

    shmdt(shm_addr);
    shmctl(shmid, IPC_RMID, NULL);

    return 0;
}

然后另一个进程可以简单地使用存储在 nums[i].data[0] 中的 char* 指针来访问每个 nums[] 元素的字符串。

如果您想为每个 nums[] 元素添加不同的字符串,只需分配足够的共享内存来容纳所有字符串,然后在该内存中相应地指向 nums[i].data[0]


更新:如果存储 char* 指针对你不起作用,那么存储偏移量,例如:

#define SHM_COUNT 5

struct myds {
    int ind;
    size_t data_offset[1];
};

int main()
{
    key_t key = ftok("shmfile",65);
    struct myds *nums;

    int shmid = shmget(key, sizeof(int) + (sizeof(struct myds) * SHM_COUNT) + 11, 0666|IPC_CREAT);

    char *shm_addr = (char*) shmat(shmid, NULL, 0);
    int *count = (int *) shm_addr;
    *count = SHM_COUNT;

    nums = (struct myds *)(shm_addr + sizeof(int));
    for(int i = 0; i < SHM_COUNT; i++) {
        nums[i].ind = i;
    }

    char *t = (char*) (nums + SHM_COUNT);
    printf("%d\n", *count);
    sprintf(t, "check- 112[=11=]");

    for(int i = 0; i < SHM_COUNT; i++) {
        nums[0].data_offset[0] = (t - shm_addr);
    }

    printf("Data written in memory:");

    getc(stdin);
    printf("%d\n", *count);

    shmdt(shm_addr);
    shmctl(shmid, IPC_RMID, NULL);

    return 0;
}

然后其他进程可以简单地将 nums[i].data_offset[0] 添加到它们的本地 shm_addr 地址以访问每个 nums[] 元素的字符串。