【问题标题】:How does one keep an int and an array in shared memory in C?如何在 C 中的共享内存中保留一个 int 和一个数组?
【发布时间】:2010-12-12 21:10:21
【问题描述】:

我正在尝试编写一个程序,其中子进程在 Linux 上相互通信。

这些进程都是从同一个程序创建的,因此它们共享代码。

我需要他们访问两个整数变量以及一个整数数组。

我不知道共享内存是如何工作的,而且我搜索过的每一个资源都没有做任何事情,只会让我感到困惑。

任何帮助将不胜感激!

编辑:这是我迄今为止编写的一些代码示例,只是为了共享一个 int,但它可能是错误的。

int segmentId;  
int sharedInt;  
const int shareSize = sizeof(int);  
/* Allocate shared memory segment */  
segmentId = shmget(IPC_PRIVATE, shareSize, S_IRUSR | S_IWUSR);  

/* attach the shared memory segment */    
sharedInt = (int) shmat(segmentId, NULL, 0);  

/* Rest of code will go here */  

/* detach shared memory segment */  
shmdt(sharedInt);  
/* remove shared memory segment */  
shmctl(segmentId, IPC_RMID, NULL);

【问题讨论】:

  • 请注意昨天的这个问题:stackoverflow.com/questions/1664519/…(相同的主题,尽管您选择了 Sys V IPC)。
  • 在 IPC_PRIVATE 之外,如果你使用不同的密钥,它做什么或不做什么?

标签: c shared-memory


【解决方案1】:

您将需要增加共享内存的大小。你需要多大的阵列?无论它是什么值,您都需要在创建共享内存段之前选择它 - 动态内存在这里不会很好地工作。

当你附加到共享内存时,你会得到一个指向起始地址的指针。它将充分对齐以用于任何目的。因此,您可以沿着这些行创建指向您的两个变量和数组的指针(从您的代码示例中抄袭一些骨架) - 请注意使用指针来访问共享内存:

enum { ARRAY_SIZE = 1024 * 1024 };
int segmentId;  
int *sharedInt1;
int *sharedInt2;
int *sharedArry;

const int shareSize = sizeof(int) * (2 + ARRAY_SIZE);  
/* Allocate shared memory segment */  
segmentId = shmget(IPC_PRIVATE, shareSize, S_IRUSR | S_IWUSR);  

/* attach the shared memory segment */    
sharedInt1 = (int *) shmat(segmentId, NULL, 0);
sharedInt2 = sharedInt1 + 1;
sharedArry = sharedInt1 + 2;

/* Rest of code will go here */
...fork your child processes...
...the children can use the three pointers to shared memory...
...worry about synchronization...
...you may need to use semaphores too - but they *are* complex...
...Note that pthreads and mutexes are no help with independent processes...  

/* detach shared memory segment */  
shmdt(sharedInt1);  
/* remove shared memory segment */  
shmctl(segmentId, IPC_RMID, NULL);

【讨论】:

  • 这看起来很棒。非常感谢!
【解决方案2】:

从您的评论看来,您使用的是IPC_PRIVATE,这看起来肯定是错误的(“私人”类型暗示它不适合分享,不是吗?-)。尝试类似:

#include <sys/ipc.h>
#include <sys/shm.h>

...

int segid = shmget((key_t)0x0BADDOOD, shareSize, IPC_CREAT);
if (segid < 0) { /* insert error processing here! */ }
int *p = (int*) shmat(segid, 0, 0);
if (!p) { /* insert error processing here! */ }

【讨论】:

  • 这看起来很有趣。在 C 方面我不是最棒的,所以在这种情况下 p 会是 int 数组吗?我也很好奇你在 shmget 中的十六进制值。
  • IPC_PRIVATE 如果父级创建共享内存然后分叉要共享它的子级。
  • @Josh:您需要一个 32 位值作为共享内存的键。您可以使用 ftok() 创建一个,或者选择一个固定的名称。 No Bad Dood 对于一块共享内存和其他任何名称一样好。 0xDEADBEEF 是另一个众所周知的值。但是 IPC_PRIVATE 也很好——只要父进程在分叉之前创建并附加共享内存。
  • 哦!我什至没有得到那个参考。好甜哈哈
  • @Jonathan,是的——如果你正在分叉(而不是执行:每 linux.die.net/man/2/shmget,exec 分离所有 shm 段)IPC_PRIVATE 很好。但是根据我的经验,fork-w/o-exec 是一个非常罕见的案例。
【解决方案3】:

本指南看起来很有用:http://www.cs.cf.ac.uk/Dave/C/node27.html。它包括一些示例程序。

还有Linux man pages online

【讨论】:

  • 谢谢,但不幸的是,这是让我彻底困惑的页面之一。
  • 您是否尝试过将示例代码复制并粘贴到那里并进行编译?如果你可以编译它,你可能已经理解它的一半了。
  • 我对那个例子的问题是它似乎是不同的程序以客户端-服务器的方式交谈。我当时没有在最初的问题中阐明我需要什么,但在我的代码中,我将从同一个程序创建多个进程并需要它们进行通信。
  • 我认为您需要将问题分解为多个步骤,然后尝试一次解决一个问题。
【解决方案4】:

共享内存只是一个进程分配的一段内存,具有唯一的id,另一个进程也会进行分配,具有相同的id,内存的大小就是你所在的结构的大小使用,因此您将拥有一个包含 2 个整数和一个整数数组的结构。

现在它们都有一个指向同一内存的指针,因此其中一个的写入将覆盖那里的任何其他内容,而另一个可以立即访问它。

【讨论】:

  • @Josh 不,评论格式很烂——但是你应该编辑你的问题来澄清它,而不是评论,所以你可以在编辑你的答案时漂亮地格式化你的代码,并删除这些 cmets!
  • 我建议您对原始问题进行澄清。
  • @Josh - 你可能想看看这个教程:ecst.csuchico.edu/~beej/guide/ipc/shmem.html,因为他还展示了如何使用 ftok 为呼叫创建密钥。
猜你喜欢
  • 2015-08-18
  • 1970-01-01
  • 2010-12-28
  • 2021-12-10
  • 2011-04-05
  • 2011-05-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多