Shared
memory allows two
unrelated processes to access the same logical memory. Shared memory
is a very efficient way of transferring data between two running
processes. Although the X/Open standard doesn’t require it, it’s
probable that most implementations of shared memory arrange for the
memory being shared between different processes to be the same
physical memory.
Shared
memory provides an efficient way of sharing and passing data between
multiple processes. Since it provides no synchronization facilities,
we usually need to use some other mechanism to synchronize access to
the shared memory. Typically, we might use shared memory to provide
efficient access to large areas of memory and pass small messages to
synchronize access to that memory.
Shared
memory is a special range of addresses that is created by IPC for one
process and appears in the address space of that process. Other
processes can then “attach” the same shared memory segment into
their own address space. All processes can access the memory
locations just as if the memory had been allocated by malloc.
If one process writes to the shared memory, the changes immediately
become visible to any other process that has access to the same
shared memory.
The
functions for shared memory resemble those for semaphores:
#include
<sys/shm.h>
void
*shmat(int shm_id, const void *shm_addr, int shmflg);
int
shmctl(int shm_id, int cmd, struct shmid_ds *buf);
int
shmdt(const void *shm_addr);
int
shmget(key_t key, size_t size, int shmflg);
As with
semaphores, the include files
sys/types.h and sys/ipc.h
are normally also required before shm.h
is included.
shmget
We
create shared memory using the shmget function:
int
shmget(key_t key, size_t size, int shmflg);
As with
semaphores, the program provides key,
which effectively names the shared memory segment, and the shmget
function returns a shared memory identifier that
is used in subsequent shared memory functions. There’s a special
key value, IPC_PRIVATE, that
creates shared memory private to the process. You wouldn’t normally
use this value, and, as with semaphores, you may find the private
shared memory is not actually private on many Linux systems. The
second parameter, size,
specifies the amount of memory required in bytes. The third
parameter, shmflg, consists
of nine permission flags that are used in the same way as the mode
flags for creating files. Aspecial bit defined by IPC_CREAT
must be bitwise ORed with the permissions to
create a new shared memory segment. It’s not an error to have the
IPC_CREAT flag set and pass
the key of an existing shared memory segment. The IPC_CREAT
flag is silently ignored if it is not required.
The permission flags are very useful with shared memory because they
allow a process to create shared memory that can be written by
processes owned by the creator of the shared memory but only read by
processes that other users have created. We can use this to provide
efficient read-only access to data by placing it in shared memory
without the risk of its being changed by other users. If the shared
memory is successfully created, shmget returns
a nonnegative integer, the shared memory identifier. On failure, it
returns –1.
shmat
When we
first create a shared memory segment, it’s not accessible by any
process. To enable access to the shared memory, we must attach it to
the address space of a process. We do this with the shmat
function:
void
*shmat(int shm_id, const void *shm_addr, int shmflg);
The
first parameter, shm_id, is
the shared memory identifier returned from shmget.
The second parameter, shm_addr,
is the address at which the shared memory is to be attached to the
current process. This should almost always be a null pointer, which
allows the system to choose the address at which the memory appears.
The third parameter, shmflg,
is a set of bitwise flags. The two possible values are SHM_RND,
which, in conjunction with shm_addr,
controls the address at which the shared memory is attached, and
SHM_RDONLY, which makes the
attached memory read-only. It’s very rare to need to control the
address at which shared memory is attached; you should normally allow
the system to choose an address for you, as doing otherwise will make
the application highly hardware-dependent. If the shmat
call is successful, it returns a pointer to the
first byte of shared memory. On failure –1 is returned.
The
shared memory will have read or write access depending on the owner
(the creator of the shared memory), the permissions, and the owner of
the current process. Permissions on shared memory are similar to the
permissions on files. An exception to this rule arises if shmflg
& SHM_RDONLY is true.
Then the shared memory won’t be writable, even if permissions would
have allowed write access.
shmdt
The
shmdt function detaches the
shared memory from the current process. It takes a pointer to the
address returned by shmat. On
success, it returns 0, on error –1. Note that detaching the shared
memory doesn’t delete it; it just makes that memory unavailable to
the current process.
shmctl
The
control functions for shared memory are (thankfully) somewhat simpler
than the more complex ones for semaphores:
int
shmctl(int shm_id, int command, struct shmid_ds *buf);
The
shmid_ds structure has at
least the following members:
struct
shmid_ds {
uid_t
shm_perm.uid;
uid_t
shm_perm.gid;
mode_t
shm_perm.mode;
}
The
first parameter, shm_id, is
the identifier returned from shmget.
The
first parameter, shm_id, is
the identifier returned from shmget.
The second parameter, command,
is the action to take. It can take three values:
Command
Description
IPC_STAT
Sets the data in the shmid_ds
structure to reflect the values associated with
the shared memory.
IPC_SET
Sets the values associated with the shared memory
to those provided in the shmid_ds data
structure, if the process has permission to do so.
IPC_RMID
Deletes the shared memory segment.
The
third parameter, buf, is a
pointer to structure containing the modes and permissions for the
shared memory.
On
success, it returns 0, on failure, –1. X/Open doesn’t specify
what happens if you attempt to delete a shared memory segment while
it’s attached. Generally, a shared memory segment that is attached
but deleted continues to function until it has been detached from the
last process. However, because this behavior isn’t specified, it’s
best not to rely on it.
No comments:
Post a Comment