如何在C中将结构存储和检索到共享存储区中

时间:2010-11-24 04:26:23

标签: c unix shared-memory

对于单一赋值,我需要创建一个最多10个文件名的循环列表,然后将它们存储在共享内存区域中,这样2个子进程就可以读/写到列表中(使用信号量来控制访问) )。麻烦的是,我是一个全新的C新手,我感到失落和绝望,因为它完全超出了我的深度。我需要一些帮助来填补我的知识。

现在,我只是一次只关注它一个问题,而目前,我只想把我的循环列表放到共享内存区域。

到目前为止,我有:

typedef struct FILE
{
   struct FILE *f_link;  /* forward link for linked list */
   char name[255];       /* name of the file */

} FILE_entry;

作为我的结构,它将保存对下一个文件的引用(f_link)。通过这种方式,我可以调用 - > f_link来获取列表中的下一个项目,并且第10个元素将使其f_link直接返回到第1个。我这样做的原因是我可以在没有迭代器的情况下简单地遍历列表(并且不必像使用数组那样检查列表的结尾)。

我也知道我需要使用shmget来获取内存区域,我理解它,我传递shmget一个密钥,一个大小和一个标志(我没有得到)和它返回int类型的标识符。

所以我的问题是2折。如何将链接列表存储到共享内存区域 - 如何从共享内存区域访问它?

4 个答案:

答案 0 :(得分:9)

shmget只保留一定数量的共享内存 - 比如在磁盘上创建固定大小的文件。标志是低9位的权限掩码(如mode的{​​{1}}参数)加上一些额外的标志openIPC_CREAT,对应{{1} }和IPC_EXCL O_CREAT。要实际访问该内存,您需要将其映射到进程的地址空间(“附加”它 - 类似于文件的O_EXCL)。这是使用open(返回指针)完成的。然后,您需要从该指针分配mmap结构。整个过程看起来像这样:

shmat

映射后,您可以像常规内存一样使用它 - 因为常规内存。这就是重点!

编辑:一个重要的警告,我忘了提及。将链接列表放入这样的共享内存段只有在所有相关进程将其映射到同一地址时才有效!所以你需要这样做(使用FILE的第二个参数)或者从指针切换到相对于共享内存范围的基地址的偏移量。这意味着将int id; FILE_entry *entries; id = shmget(key, N * sizeof(FILE_entry), IPC_CREAT | 0644); entries = (FILE_entry *) shmat(id, NULL, 0); // you can now access entries as if it was a N-element array. // to turn it into a circular list, link the entries appropriately. 字段从指针转换为shmat,并在加载时添加映射内存范围的基地址(并在存储时将其减去)。

答案 1 :(得分:2)

您调用shmat(identifier, NULL, 0),返回指向共享内存在您的进程中映射到的位置的指针。在该位置创建您的对象,或者memcpy / memmove在该位置创建对象。

您可能会发现Beej's Unix IPC guide很有用,它包含一个专门针对共享内存的部分。

答案 2 :(得分:2)

shmget获取密钥后,您必须使用它来通过shmat获取实际指针。以下是一些示例:

int shmid;
key_t key;
FILE* shm;

shmid = shmget(key, sizeof(FILE) * 10, IPC_CREAT | 0666);
shm = shmat(shmid, NULL, 0);

这样,您就可以使用shm指针访问共享内存。在此链接中,您可以看到shmgetshmat

的联机帮助页

http://linux.die.net/man/2/shmget

http://linux.die.net/man/2/shmat

请参阅http://www.cplusplus.com以获取更多参考。它还包含C引用。

我不知道我是否足够清楚,所以,请提出一些意见,如果有必要,我会尽力为你启发。

编辑:在此网站中,您可以找到一个非常简单的示例:http://simplestcodings.blogspot.com/2010/08/ipc-shared-memory-implementation-in-c.html

答案 3 :(得分:1)

对于标志,如果要分配新的共享内存段,则需要至少指定IPC_CREATE,否则,如果找不到,则需要运行现有的segemnt并失败。

其次,由于共享内存段是一个连续的内存块,您需要能够将所有10个FILE_entry结构存储在一起(或者分配10个共享内存段 - 哎呀!)。

所以你真的需要为至少10个FILE结构的数组留出足够的内存。

最后,FILE和FILE_entry真的是坏名字!使用不太通用的东西,如MY_FILE_REF和MyFileRefEntry。