[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:

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

  2. When a parent process attachs to a shared mem segment (before fork), its child processes will also attach to that mem segment.

  3. When calling destroy to a shared mem segment, it will only be destroyed after the last process attached to it detached from it.

  4. A destroy call can only be made from the owner or creator of the mem segment.

posted @ 2019-02-28 14:00  gooey  阅读(178)  评论(0编辑  收藏  举报