In the SunOS 5.11 operating system, the most efficient way to implement shared memory applications is to rely on mmap(2) and on the system's native virtual memory facility. See Chapter 1, Memory and CPU Management for more information.
The SunOS 5.11 platform also supports System V shared memory, which is a less efficient way to enable the attachment of a segment of physical memory to the virtual address spaces of multiple processes. When write access is allowed for more than one process, an outside protocol or mechanism, such as a semaphore, can be used to prevent inconsistencies and collisions.
A process creates a shared memory segment using shmget(2). This call is also used to get the ID of an existing shared segment. The creating process sets the permissions and the size in bytes for the segment.
The original owner of a shared memory segment can assign ownership to another user with shmctl(2). The owner can also revoke this assignment. Other processes with proper permission can perform various control functions on the shared memory segment using shmctl(2).
Once created, you can attach a shared segment to a process address space using shmat(2). You can detach it using shmdt(2). The attaching process must have the appropriate permissions for shmat(2). Once attached, the process can read or write to the segment, as allowed by the permission requested in the attach operation. A shared segment can be attached multiple times by the same process.
A shared memory segment is described by a control structure with a unique ID that points to an area of physical memory. The identifier of the segment is called the shmid. The structure definition for the shared memory segment control structure can be found in sys/shm.h.
shmget(2) is used to obtain access to a shared memory segment. When the call succeeds, it returns the shared memory segment ID (shmid). The following code illustrates shmget(2).
#include <sys/types.h> #include <sys/ipc.h> #include <sys/shm.h> ... key_t key; /* key to be passed to shmget() */ int shmflg; /* shmflg to be passed to shmget() */ int shmid; /* return value from shmget() */ size_t size; /* size to be passed to shmget() */ ... key = ... size = ... shmflg) = ... if ((shmid = shmget (key, size, shmflg)) == –1) { perror("shmget: shmget failed"); exit(1); } else { (void) fprintf(stderr, "shmget: shmget returned %d\n", shmid); exit(0); } ...
shmctl(2) is used to alter the permissions and other characteristics of a shared memory segment. The cmd argument is one of following control commands.
Lock the specified shared memory segment in memory. The process must have the effective ID of superuser to perform this command.
Unlock the shared memory segment. The process must have the effective ID of superuser to perform this command.
Return the status information contained in the control structure and place it in the buffer pointed to by buf. The process must have read permission on the segment to perform this command.
Set the effective user and group identification and access permissions. The process must have an effective ID of owner, creator or superuser to perform this command.
Remove the shared memory segment. The process must have an effective ID of owner, creator, or superuser to perform this command.
The following code illustrates shmctl(2).
#include <sys/types.h> #include <sys/ipc.h> #include <sys/shm.h> ... int cmd; /* command code for shmctl() */ int shmid; /* segment ID */ struct shmid_ds shmid_ds; /* shared memory data structure to hold results */ ... shmid = ... cmd = ... if ((rtrn = shmctl(shmid, cmd, shmid_ds)) == –1) { perror("shmctl: shmctl failed"); exit(1); ...
shmat() and shmdt() are used to attach and detach shared memory segments (see the shmop(2) man page). shmat(2) returns a pointer to the head of the shared segment. shmdt(2) detaches the shared memory segment located at the address indicated by shmaddr. The following code illustrates calls to shmat(2) and shmdt(2)
#include <sys/types.h> #include <sys/ipc.h> #include <sys/shm.h> static struct state { /* Internal record of attached segments. */ int shmid; /* shmid of attached segment */ char *shmaddr; /* attach point */ int shmflg; /* flags used on attach */ } ap[MAXnap]; /* State of current attached segments. */ int nap; /* Number of currently attached segments. */ ... char *addr; /* address work variable */ register int i; /* work area */ register struct state *p; /* ptr to current state entry */ ... p = &ap[nap++]; p–>shmid = ... p–>shmaddr = ... p–>shmflg = ... p–>shmaddr = shmat(p->shmid, p->shmaddr, p->shmflg); if(p–>shmaddr == (char *)-1) { perror("shmat failed"); nap–-; } else (void) fprintf(stderr, "shmop: shmat returned %p\n", p–>shmaddr); ... i = shmdt(addr); if(i == –1) { perror("shmdt failed"); } else { (void) fprintf(stderr, "shmop: shmdt returned %d\n", i); for (p = ap, i = nap; i–-; p++) { if (p–>shmaddr == addr) *p = ap[–-nap]; } } ...