获取共享内存的现代方法是使用由 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
)。一旦映射完成,它就可以作为常规的动态分配内存进行访问(事实上,malloc()
在glibc
Linux 上使用匿名内存映射来进行更大的分配)。然后该进程将数据写入数组并等待直到按下 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
数组元素的尝试都将导致传递分段错误。
编译并运行第一个进程。然后在单独的控制台中运行第二个进程并观察输出。当第二个进程完成后,回到第一个进程并回车,清理共享内存块。
有关更多信息,请查阅每个函数的手册页或 SUS 的内存管理部分(最好查阅手册页,因为它们记录了这些函数的系统特定行为)。