How Do I Store and Retrieve a Struct into a Shared Memory Area in C

核能气质少年 提交于 2020-01-01 05:23:06

问题


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.

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).

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.

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?


回答1:


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:

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).




回答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.

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




回答3:


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

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:

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

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

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

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




回答4:


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.

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!).

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

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



来源:https://stackoverflow.com/questions/4263444/how-do-i-store-and-retrieve-a-struct-into-a-shared-memory-area-in-c

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!