要创建新和空共享内存段,我可以执行以下操作:
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*)-1
或int* 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()
解决此问题,我很高兴听到它。)