任何人都可以帮我在C中制作共享内存段

时间:2012-11-21 01:53:45

标签: c struct shared-memory

我需要创建一个共享内存段,以便我可以让多个读者和编写者访问它。我想我知道我在做什么,就信号量,读者和作家来说......

但我对如何创建共享内存段毫无头绪。我希望段包含20个结构的数组。每个结构都将包含一个名字,一个int和另一个int。

任何人都可以帮助我至少开始这个吗?我很绝望,我在网上看到的一切让我更加困惑。

编辑:好的,所以我做了这样的事情来开始

int memID = shmget(IPC_PRIVATE, sizeof(startData[0])*20, IPC_CREAT);

使用startData作为保存我的数据初始化的结构数组,我得到一个错误说 “分段错误(核心转储)”

1 个答案:

答案 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部分(最好查阅手册页,因为它们记录了这些函数的系统特定行为)。