"转动"使用SYSV API将内存初始化为共享内存?

时间:2018-02-23 05:29:17

标签: c linux shared-memory

要创建共享内存段,我可以执行以下操作:

int shmid = shmget(IPC_PRIVATE, nbytes, IPC_CREAT | 0777);
int* new_array = (int*)shmat(shmid, NULL, 0);

现在假设int* array拥有一大块预先存在的数据。像

这样的东西
int* array = malloc(2 * sizeof(int));
array[0] = 42;
array[1] = 24;

我希望在Linux上将此内存段转换为使用System V共享内存C API的共享内存段。

  

我该怎么做?

我尝过像

这样的东西
 int shmid = shmget(IPC_PRIVATE, nbytes, IPC_CREAT | 0777);
 void* attach = shmat(shmid, array, SHM_RND);

并且喜欢

int shmid = shmget(IPC_PRIVATE, nbytes, IPC_CREAT | 0777);
array = (int*)shmat(shmid, 0, 0);

但shmat返回(void*)-1int* array将其所有值设置为零。

这是一个显示失败的完整程序:

/*
gcc shm0.c -o shm0 && ./shm0
*/

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#include <sys/stat.h>
#include <sys/ipc.h>
#include <sys/shm.h>

#define NELEMENTS 3

void array_show(int* array, size_t nelements){
    puts("");
  for(int i=0; i < nelements; ++i)
    printf("%d\n", *(array + i));
}

int main(){
  const size_t nbytes = NELEMENTS * sizeof(int);
  int* array;
  posix_memalign((void**)&array, 16*16*16, nbytes);

  int shmid = shmget(IPC_PRIVATE, nbytes, IPC_CREAT | 0777);

  // 1st try...
  void* attach = shmat(shmid, array, SHM_RND);
  if(attach == (void*)-1)
    puts("shmat() failed!");

  // 2nd try...
  memset(array, 1, nbytes);  // Fill array with dummy data!
  array_show(array, NELEMENTS);
  array = (int*)shmat(shmid, 0, 0);
  array_show(array, NELEMENTS);
  if(array[1] == 0)
    puts("array was reset!");

  // 3rd try
  array = (int*)shmat(shmid, array, 0);  // Now accessing, say, array[0] yields a segfault!

  shmdt(array);
}

为什么SYSV共享内存而不是mmap()?因为我使用的是X11 MIT shared memory extension,而且根据文档:

  

...为了能够使用此扩展,您的系统必须提供SYSV共享内存原语。此扩展程序没有基于mmap的版本。要在Sun系统上使用共享内存,必须在启用了SYSV共享内存的情况下构建内核...

(如果有人知道如何解决这个问题,或者如何使用shm_open()解决此问题,我很高兴听到它。)

0 个答案:

没有答案