【问题标题】:Can anyone help me make a Shared Memory Segment in C谁能帮我在 C 中创建一个共享内存段
【发布时间】:2012-11-21 01:53:44
【问题描述】:

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

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

谁能帮助我至少开始这个?我很绝望,我在网上阅读的所有内容都让我更加困惑。

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

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

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

【问题讨论】:

  • man shmgetshmat
  • 在致电shmget 或之后?您是否检查了对 shmget 的调用是否返回了错误(如果返回,则 memID 将为 -1,您可以使用 perror 打印错误)。
  • 我建议您首先复制现有示例并根据需要进行更改。 support.sas.com/documentation/onlinedoc/sasc/doc750/html/lr2/…
  • @Nick 当我运行该代码时,它甚至不会为我编译。我得到“test.c: In function main': test.c:51: error: S_IRUSR' undeclared (first use in this function) test.c:51: error: (每个未声明的标识符只报告一次 test.c:51: error: 对于每个函数出现在。)test.c:51:错误:S_IWUSR' undeclared (first use in this function) test.c:51: error: S_IRGRP'未声明(在此函数中首次使用)test.c:51:错误:S_IWGRP' undeclared (first use in this function) test.c:51: error: S_IROTH'未声明(在此函数中首次使用)test.c: 51:错误:`S_IWOTH' ...

标签: c struct shared-memory


【解决方案1】:

获取共享内存的现代方法是使用由单一 UNIX 规范提供的 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 上的glibc 中的malloc() 使用匿名内存映射来进行更大的分配)。然后该进程将数据写入数组并等待直到按下 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 的 memory management 部分(最好查阅手册页,因为它们记录了这些函数的系统特定行为)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-06-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多