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

时间:2022-01-28 13:13:53

For a uni assignment I need to create a circular list of up to 10 file names, and then store these in a shared memory area, so that 2 child processes can read/write to the list (using a semaphore to control access). Trouble is, that I am a total C novice and I feel loss and despair because its totally out of my depth. I need some help in "filling in the holes" of my knowledge.

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

Right now, I am simply focussing on it one problem at a time, and presently, I am only trying to get my circular list into the shared memory area.

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

So far I have:

到目前为止我有:

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

} FILE_entry;

As my struct which will hold the reference to the file that comes next (f_link). this way I can just call ->f_link to get the next item in the list, and where the 10th element will simply have its f_link directed back to the 1st. My reason for doing this is so that I can simply traverse the list without an iterator (and never have to check for the end of the list as I would with an array).

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

I also know that I need to use shmget to get the memory area, and I understand it, I pass shmget a key, a size and a flag (which i dont get) and it returns an identifier in the type of an int.

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

So my question is 2 fold. How do I store my linked list INTO the shared memory area - and how do I access it FROM the shared memory area?

所以我的问题是2折。如何将链表存储在共享存储区中 - 如何从共享存储区访问它?

4 个解决方案

#1


8  

shmget just reserves some amount of shared memory - like creating a fixed-size file on disk. The flags are a permission mask (like the mode parameter for open) in the low 9 bits plus some extra flags, IPC_CREAT and IPC_EXCL, corresponding to O_CREAT and O_EXCL for open. To actually access that memory, you need to map it into the address space of your process ("attach" it - analogous to mmap for files). This is done using shmat (which returns a pointer). You then need to allocate your FILE structures from that pointer. The whole process looks something like this:

shmget只保留一定数量的共享内存 - 比如在磁盘上创建固定大小的文件。标志是低9位的权限掩码(类似于open模式参数)加上一些额外标志IPC_CREAT和IPC_EXCL,对应于O_CREAT和O_EXCL用于打开。要实际访问该内存,您需要将其映射到进程的地址空间(“附加”它 - 类似于文件的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.

After mapping, you can work with it like regular memory - since it is regular memory. That's the whole point!

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

EDIT: One important caveat I forgot to mention. Putting a linked list into a shared memory segment like this will only work if all involved processes map it to the same address! So you either need to do that (using the second argument of shmat) or switch from pointers to offsets relative to the base address of the shared memory range. That means turning your next field from a pointer to a ptrdiff_t and adding the base address of the mapped memory range whenever you load it (and subtracting it whenever you store it).

编辑:我忘了提一个重要的警告。将链接列表放入这样的共享内存段只有在所有相关进程将其映射到同一地址时才有效!所以你需要这样做(使用shmat的第二个参数)或者从指针切换到相对于共享内存范围的基地址的偏移量。这意味着将下一个字段从指针转换为ptrdiff_t,并在加载时添加映射内存范围的基地址(并在存储时减去它)。

#2


2  

You call shmat(identifier, NULL, 0), getting back a pointer to the location the shared memory has been mapped to in your process. Either create your object(s) at that location, or memcpy/memmove them to that location.

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

You'll probably find Beej's Unix IPC guide useful, it contains a section specifically on shared memory.

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

#3


2  

After you get the key from shmget, you have to use it to get the actual pointer via shmat. Here is some sample:

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

int shmid;
key_t key;
FILE* shm;

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

This way, you will be able to access the shared memory using the shm pointer. In this links you can see the manpage for shmget and shmat:

这样,您就可以使用shm指针访问共享内存。在此链接中,您可以看到shmget和shmat的联机帮助页:

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

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

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

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

And see http://www.cplusplus.com for additional reference. It contains C reference also.

有关其他参考,请参阅http://www.cplusplus.com。它还包含C引用。

I don't know if I was clear enough, so, give some comments and I'll try to enlighten it for you, if necessary.

我不知道我是否足够清楚,所以,给一些评论,如果有必要,我会尽力为你启发。

EDIT: In this site you can find a really simple example: http://simplestcodings.blogspot.com/2010/08/ipc-shared-memory-implementation-in-c.html

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

#4


1  

For the flag you need to specify at least IPC_CREATE if you want to allocate a new shared memory segment, otherwise, it will look of ran existing segemnt and fail if it does not find one.

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

Secondly as the shared memory segment is a contiguous block of memory you need to be able to store all 10 of your FILE_entry structures together (or allocate 10 shared memory segments -- yuck!).

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

So you really need to shmeget enough memory for an array of at least 10 FILE structures.

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

Lastly FILE and FILE_entry are really bad names! Use something less generic like MY_FILE_REF and MyFileRefEntry.

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

#1


8  

shmget just reserves some amount of shared memory - like creating a fixed-size file on disk. The flags are a permission mask (like the mode parameter for open) in the low 9 bits plus some extra flags, IPC_CREAT and IPC_EXCL, corresponding to O_CREAT and O_EXCL for open. To actually access that memory, you need to map it into the address space of your process ("attach" it - analogous to mmap for files). This is done using shmat (which returns a pointer). You then need to allocate your FILE structures from that pointer. The whole process looks something like this:

shmget只保留一定数量的共享内存 - 比如在磁盘上创建固定大小的文件。标志是低9位的权限掩码(类似于open模式参数)加上一些额外标志IPC_CREAT和IPC_EXCL,对应于O_CREAT和O_EXCL用于打开。要实际访问该内存,您需要将其映射到进程的地址空间(“附加”它 - 类似于文件的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.

After mapping, you can work with it like regular memory - since it is regular memory. That's the whole point!

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

EDIT: One important caveat I forgot to mention. Putting a linked list into a shared memory segment like this will only work if all involved processes map it to the same address! So you either need to do that (using the second argument of shmat) or switch from pointers to offsets relative to the base address of the shared memory range. That means turning your next field from a pointer to a ptrdiff_t and adding the base address of the mapped memory range whenever you load it (and subtracting it whenever you store it).

编辑:我忘了提一个重要的警告。将链接列表放入这样的共享内存段只有在所有相关进程将其映射到同一地址时才有效!所以你需要这样做(使用shmat的第二个参数)或者从指针切换到相对于共享内存范围的基地址的偏移量。这意味着将下一个字段从指针转换为ptrdiff_t,并在加载时添加映射内存范围的基地址(并在存储时减去它)。

#2


2  

You call shmat(identifier, NULL, 0), getting back a pointer to the location the shared memory has been mapped to in your process. Either create your object(s) at that location, or memcpy/memmove them to that location.

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

You'll probably find Beej's Unix IPC guide useful, it contains a section specifically on shared memory.

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

#3


2  

After you get the key from shmget, you have to use it to get the actual pointer via shmat. Here is some sample:

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

int shmid;
key_t key;
FILE* shm;

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

This way, you will be able to access the shared memory using the shm pointer. In this links you can see the manpage for shmget and shmat:

这样,您就可以使用shm指针访问共享内存。在此链接中,您可以看到shmget和shmat的联机帮助页:

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

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

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

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

And see http://www.cplusplus.com for additional reference. It contains C reference also.

有关其他参考,请参阅http://www.cplusplus.com。它还包含C引用。

I don't know if I was clear enough, so, give some comments and I'll try to enlighten it for you, if necessary.

我不知道我是否足够清楚,所以,给一些评论,如果有必要,我会尽力为你启发。

EDIT: In this site you can find a really simple example: http://simplestcodings.blogspot.com/2010/08/ipc-shared-memory-implementation-in-c.html

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

#4


1  

For the flag you need to specify at least IPC_CREATE if you want to allocate a new shared memory segment, otherwise, it will look of ran existing segemnt and fail if it does not find one.

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

Secondly as the shared memory segment is a contiguous block of memory you need to be able to store all 10 of your FILE_entry structures together (or allocate 10 shared memory segments -- yuck!).

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

So you really need to shmeget enough memory for an array of at least 10 FILE structures.

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

Lastly FILE and FILE_entry are really bad names! Use something less generic like MY_FILE_REF and MyFileRefEntry.

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