[Operating Systems] Synchronization
Key C functions:
int shmid = shmget(key_t key, size_t size, int shmflg); // Create an identifier for the shared mem segment by key
void *shmat(int shmid, const void *shmaddr, int shmflg); // attach
int shmdt(const void *shmaddr); // detach; only the address to the mem is needed here
int shmctl(int shmid, int cmd, struct shmid_ds *buf); // perform some operation on the mem segment
Code snippet:
#include <sys/ipc.h>
#include <sys/shm.h>
# define SHM_SHARED_KEY 8999
key_t key = SHM_SHARED_KEY;
//int shmget(key_t key, size_t size, int shmflg);
int shmid = shmget(key, sizeof( int ), IPC_CREAT | /*IPC_EXCL |*/ 0660 );
/* IPC_CREAT Creat a new segment; if not set, shmget() check the segment associated with key and check if the user has permission to access it.
IPC_EXCL used with IPC_CREAT to ensure this call creates the segment. If the segment already exists, the call fails.
...
When a new shared memory segment is created, its contents are
initialized to zero values, ...
Return a memory identifier on success; -1 on error
*/
/* Attach to the shared memory segment */
// void *shmat(int shmid, const void *shmaddr, int shmflg);
int * data = shmat( shmid, NULL, 0 );
/* Notice that 'void *' means returning a pointer which can be used to point to any type of data */
/* shmat() attaches the System V shared memory segment identi‐
fied by shmid to the address space of the calling process.
The attaching address is specified by shmaddr with one of the
following criteria:
* If shmaddr is NULL, the system chooses a suitable (unused)
page-aligned address to attach the segment.
* If shmaddr isn't NULL and SHM_RND is specified in shmflg,
the attach occurs at the address equal to shmaddr rounded
down to the nearest multiple of SHMLBA.
* Otherwise, shmaddr must be a page-aligned address at which
the attach occurs.
shmat() returns the address of the attached
shared memory segment; on error, (void *) -1 is returned
*/
/* Detach from the shared memory segment*/
//int shmdt(const void *shmaddr);
int rc = shmdt( data );
/* Detach from the shared mem segment specified by address shmaddr
On success, shmdt() returns 0; on error -1 is returned, */
/* Perform some operation specified by cmd on the shared memoey segment identified by shimid */
/* int shmctl(int shmid, int cmd, struct shmid_ds *buf);*/
int rc = shmctl( shmid, IPC_RMID, 0 );
/* In this case, destroy the mem segment identified by shmid;
If not destroy it, this mem segment will still be accessible from other processes. (i.e. when re-run this programme, the old data still exists)
IPC_RMID Mark the segment to be destroyed. The segment will
actually be destroyed only after the last process
detaches it. The caller must be the owner or creator of the segment,
or be privileged. The buf argument is ignored.
*/
Notes:
-
If a shared memory segment is not destroyed (i.e. using
shmctl( shmid, IPC_RMID, 0 )
), it will still be accessible from other processes if given the same key. (Q: Thus within the period key -> shmid is some motonous function?); when it is destroyed, using shmget(key, **argv) will map to a different identifier shmid. -
When a parent process attachs to a shared mem segment (before fork), its child processes will also attach to that mem segment.
-
When calling destroy to a shared mem segment, it will only be destroyed after the last process attached to it detached from it.
-
A destroy call can only be made from the owner or creator of the mem segment.