0

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

但我对如何创建共享内存段一无所知。我希望该段包含 20 个结构的数组。每个结构将包含一个名字、一个 int 和另一个 int。

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

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

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

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

4

1 回答 1

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)。一旦映射完成,它就可以作为常规的动态分配内存进行访问(事实上,malloc()glibcLinux 上使用匿名内存映射来进行更大的分配)。然后该进程将数据写入数组并等待直到按下 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 的内存管理部分(最好查阅手册页,因为它们记录了这些函数的系统特定行为)。

于 2012-11-21T21:52:52.350 回答