我需要创建一个共享内存段,以便我可以让多个读者和编写者访问它。我想我知道我在做什么,就信号量,读者和作家来说......
但我对如何创建共享内存段毫无头绪。我希望段包含20个结构的数组。每个结构都将包含一个名字,一个int和另一个int。
任何人都可以帮助我至少开始这个吗?我很绝望,我在网上看到的一切让我更加困惑。
编辑:好的,所以我做了这样的事情来开始int memID = shmget(IPC_PRIVATE, sizeof(startData[0])*20, IPC_CREAT);
使用startData作为保存我的数据初始化的结构数组,我得到一个错误说 “分段错误(核心转储)”
答案 0 :(得分:1)
获取共享内存的现代方法是使用Single UNIX Specification提供的API。这是一个包含两个进程的示例 - 一个创建共享内存对象并将一些数据放入其中,另一个读取它。
第一个过程:
#include <stdio.h>
#include <unistd.h>
#include <sys/mman.h>
#include <fcntl.h>
#define SHM_NAME "/test"
typedef struct
{
int item;
} DataItem;
int main (void)
{
int smfd, i;
DataItem *smarr;
size_t size = 20*sizeof(DataItem);
// Create a shared memory object
smfd = shm_open(SHM_NAME, O_RDWR | O_CREAT, 0600);
// Resize to fit
ftruncate(smfd, size);
// Map the object
smarr = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, smfd, 0);
// Put in some data
for (i = 0; i < 20; i++)
smarr[i].item = i;
printf("Press Enter to remove the shared memory object\n");
getc(stdin);
// Unmap the object
munmap(smarr, size);
// Close the shared memory object handle
close(smfd);
// Remove the shared memory object
shm_unlink(SHM_NAME);
return 0;
}
该过程使用shm_open()
创建共享内存对象。创建的对象初始大小为零,因此使用ftruncate()
进行放大。然后使用mmap()
将对象内存映射到进程的虚拟地址空间。这里重要的是映射是读/写(PROT_READ | PROT_WRITE
)并且它是共享的(MAP_SHARED
)。映射完成后,可以将其作为常规动态分配的内存进行访问(事实上,Linux上的malloc()
中的glibc
使用匿名内存映射进行更大的分配)。然后,该过程将数据写入数组并等待直到按下Enter。然后使用munmap()
取消映射对象,关闭其文件句柄并将对象与shm_unlink()
取消链接。
第二个过程:
#include <stdio.h>
#include <sys/mman.h>
#include <fcntl.h>
#define SHM_NAME "/test"
typedef struct
{
int item;
} DataItem;
int main (void)
{
int smfd, i;
DataItem *smarr;
size_t size = 20*sizeof(DataItem);
// Open the shared memory object
smfd = shm_open(SHM_NAME, O_RDONLY, 0600);
// Map the object
smarr = mmap(NULL, size, PROT_READ, MAP_SHARED, smfd, 0);
// Read the data
for (i = 0; i < 20; i++)
printf("Item %d is %d\n", i, smarr[i].item);
// Unmap the object
munmap(smarr, size);
// Close the shared memory object handle
close(smfd);
return 0;
}
这个只打开共享内存对象以进行读访问,并且内存映射它仅用于读访问。任何写入smarr
数组元素的尝试都会导致传递分段错误。
编译并运行第一个进程。然后在单独的控制台中运行第二个进程并观察输出。第二个进程完成后,返回第一个进程并按Enter清除共享内存块。
有关更多信息,请参阅每个函数的手册页或SUS的memory management部分(最好查阅手册页,因为它们记录了这些函数的系统特定行为)。