BY:-SATINDER.EMBDEVELOPER
Shared Memory:
Shared Memory is an efficeint means of passing data between programs. One program will create a memory portion which other processes (if permitted) can access.
In the Solaris 2.x operating system, the most efficient way to implement shared memory applications is to rely on the mmap() function and on the system’s native virtual memory facility. Solaris 2.x also supports System V shared memory, which is another way to let multiple processes attach a segment of physical memory to their virtual address spaces. 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()|. The original owner of a shared memory segment can assign ownership to another user with shmctl(). It can also revoke this assignment. Other processes with proper permission can perform various control functions on the shared memory segment using shmctl(). Once created, a shared segment can be attached to a process address space using shmat(). It can be detached using shmdt() (see shmop()). The attaching process must have the appropriate permissions for shmat(). 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 structures and prototypews can be found in <sys/shm.h>.
Accessing a Shared Memory Segment
shmget() is used to obtain access to a shared memory segment. It is prottyped by:
int shmget(key_t key, size_t size, int shmflg);
The key argument is a access value associated with the semaphore ID. The size argument is the size in bytes of the requested shared memory. The shmflg argument specifies the initial access permissions and creation control flags.
When the call succeeds, it returns the shared memory segment ID. This call is also used to get the ID of an existing shared segment (from a process requesting sharing of some existing memory portion).
The following code illustrates shmget():
#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() */ int 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); } ...
Controlling a Shared Memory Segment
shmctl() is used to alter the permissions and other characteristics of a shared memory segment. It is prototyped as follows:
int shmctl(int shmid, int cmd, struct shmid_ds *buf);
The process must have an effective shmid of owner, creator or superuser to perform this command. The cmd argument is one of following control commands:
- SHM_LOCK
- – Lock the specified shared memory segment in memory. The process must have the effective ID of superuser to perform this command.
- SHM_UNLOCK
- – Unlock the shared memory segment. The process must have the effective ID of superuser to perform this command.
- IPC_STAT
- – 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.
- IPC_SET
- – 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.
- IPC_RMID
- – Remove the shared memory segment.
The buf is a sructure of type struct shmid_ds which is defined in <sys/shm.h>
The following code illustrates shmctl():
#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); } ...
Attaching and Detaching a Shared Memory Segment
shmat() and shmdt() are used to attach and detach shared memory segments. They are prototypes as follows:
void *shmat(int shmid, const void *shmaddr, int shmflg); int shmdt(const void *shmaddr);
shmat() returns a pointer, shmaddr, to the head of the shared segment associated with a valid shmid. shmdt() detaches the shared memory segment located at the address indicated by shmaddr
. The following code illustrates calls to shmat() and shmdt():
#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("shmop: shmat failed"); nap--; } else (void) fprintf(stderr, "shmop: shmat returned %#8.8x\n", p->shmaddr); ... i = shmdt(addr); if(i == -1) { perror("shmop: 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]; } ...