1314 lines
40 KiB
Plaintext
1314 lines
40 KiB
Plaintext
\input texinfo @c -*-texinfo-*-
|
|
@comment %**start of header (This is for running Texinfo on a region.)
|
|
@setfilename ipc.info
|
|
@settitle Inter Process Communication.
|
|
@setchapternewpage odd
|
|
@comment %**end of header (This is for running Texinfo on a region.)
|
|
|
|
@ifinfo
|
|
This file documents the System V style inter process communication
|
|
primitives available under linux.
|
|
|
|
Copyright @copyright{} 1992 krishna balasubramanian
|
|
|
|
Permission is granted to use this material and the accompanying
|
|
programs within the terms of the GNU GPL.
|
|
@end ifinfo
|
|
|
|
@titlepage
|
|
@sp 10
|
|
@center @titlefont{System V Inter Process Communication}
|
|
@sp 2
|
|
@center krishna balasubramanian,
|
|
|
|
@comment The following two commands start the copyright page.
|
|
@page
|
|
@vskip 0pt plus 1filll
|
|
Copyright @copyright{} 1992 krishna balasubramanian
|
|
|
|
Permission is granted to use this material and the accompanying
|
|
programs within the terms of the GNU GPL.
|
|
@end titlepage
|
|
|
|
@dircategory Miscellaneous
|
|
@direntry
|
|
* ipc: (ipc). System V style inter process communication
|
|
@end direntry
|
|
|
|
@node Top, Overview, Notes, (dir)
|
|
@chapter System V IPC.
|
|
|
|
These facilities are provided to maintain compatibility with
|
|
programs developed on system V unix systems and others
|
|
that rely on these system V mechanisms to accomplish inter
|
|
process communication (IPC).@refill
|
|
|
|
The specifics described here are applicable to the Linux implementation.
|
|
Other implementations may do things slightly differently.
|
|
|
|
@menu
|
|
* Overview:: What is system V ipc? Overall mechanisms.
|
|
* Messages:: System calls for message passing.
|
|
* Semaphores:: System calls for semaphores.
|
|
* Shared Memory:: System calls for shared memory access.
|
|
* Notes:: Miscellaneous notes.
|
|
@end menu
|
|
|
|
@node Overview, example, Top, Top
|
|
@section Overview
|
|
|
|
@noindent System V IPC consists of three mechanisms:
|
|
|
|
@itemize @bullet
|
|
@item
|
|
Messages : exchange messages with any process or server.
|
|
@item
|
|
Semaphores : allow unrelated processes to synchronize execution.
|
|
@item
|
|
Shared memory : allow unrelated processes to share memory.
|
|
@end itemize
|
|
|
|
@menu
|
|
* example:: Using shared memory.
|
|
* perms:: Description of access permissions.
|
|
* syscalls:: Overview of ipc system calls.
|
|
@end menu
|
|
|
|
Access to all resources is permitted on the basis of permissions
|
|
set up when the resource was created.@refill
|
|
|
|
A resource here consists of message queue, a semaphore set (array)
|
|
or a shared memory segment.@refill
|
|
|
|
A resource must first be allocated by a creator before it is used.
|
|
The creator can assign a different owner. After use the resource
|
|
must be explicitly destroyed by the creator or owner.@refill
|
|
|
|
A resource is identified by a numeric @var{id}. Typically a creator
|
|
defines a @var{key} that may be used to access the resource. The user
|
|
process may then use this @var{key} in the @dfn{get} system call to obtain
|
|
the @var{id} for the corresponding resource. This @var{id} is then used for
|
|
all further access. A library call @dfn{ftok} is provided to translate
|
|
pathnames or strings to numeric keys.@refill
|
|
|
|
There are system and implementation defined limits on the number and
|
|
sizes of resources of any given type. Some of these are imposed by the
|
|
implementation and others by the system administrator
|
|
when configuring the kernel (@xref{msglimits}, @xref{semlimits},
|
|
@xref{shmlimits}).@refill
|
|
|
|
There is an @code{msqid_ds}, @code{semid_ds} or @code{shmid_ds} struct
|
|
associated with each message queue, semaphore array or shared segment.
|
|
Each ipc resource has an associated @code{ipc_perm} struct which defines
|
|
the creator, owner, access perms ..etc.., for the resource.
|
|
These structures are detailed in the following sections.@refill
|
|
|
|
|
|
|
|
@node example, perms, Overview, Overview
|
|
@section example
|
|
|
|
Here is a code fragment with pointers on how to use shared memory. The
|
|
same methods are applicable to other resources.@refill
|
|
|
|
In a typical access sequence the creator allocates a new instance
|
|
of the resource with the @code{get} system call using the IPC_CREAT
|
|
flag.@refill
|
|
|
|
@noindent creator process:@*
|
|
|
|
@example
|
|
#include <sys/shm.h>
|
|
int id;
|
|
key_t key;
|
|
char proc_id = 'C';
|
|
int size = 0x5000; /* 20 K */
|
|
int flags = 0664 | IPC_CREAT; /* read-only for others */
|
|
|
|
key = ftok ("~creator/ipckey", proc_id);
|
|
id = shmget (key, size, flags);
|
|
exit (0); /* quit leaving resource allocated */
|
|
@end example
|
|
|
|
@noindent
|
|
Users then gain access to the resource using the same key.@*
|
|
@noindent
|
|
Client process:
|
|
@example
|
|
#include <sys/shm.h>
|
|
char *shmaddr;
|
|
int id;
|
|
key_t key;
|
|
char proc_id = 'C';
|
|
|
|
key = ftok ("~creator/ipckey", proc_id);
|
|
|
|
id = shmget (key, 0, 004); /* default size */
|
|
if (id == -1)
|
|
perror ("shmget ...");
|
|
|
|
shmaddr = shmat (id, 0, SHM_RDONLY); /* attach segment for reading */
|
|
if (shmaddr == (char *) -1)
|
|
perror ("shmat ...");
|
|
|
|
local_var = *(shmaddr + 3); /* read segment etc. */
|
|
|
|
shmdt (shmaddr); /* detach segment */
|
|
@end example
|
|
|
|
@noindent
|
|
When the resource is no longer needed the creator should remove it.@*
|
|
@noindent
|
|
Creator/owner process 2:
|
|
@example
|
|
key = ftok ("~creator/ipckey", proc_id)
|
|
id = shmget (key, 0, 0);
|
|
shmctl (id, IPC_RMID, NULL);
|
|
@end example
|
|
|
|
|
|
@node perms, syscalls, example, Overview
|
|
@section Permissions
|
|
|
|
Each resource has an associated @code{ipc_perm} struct which defines the
|
|
creator, owner and access perms for the resource.@refill
|
|
|
|
@example
|
|
struct ipc_perm
|
|
key_t key; /* set by creator */
|
|
ushort uid; /* owner euid and egid */
|
|
ushort gid;
|
|
ushort cuid; /* creator euid and egid */
|
|
ushort cgid;
|
|
ushort mode; /* access modes in lower 9 bits */
|
|
ushort seq; /* sequence number */
|
|
@end example
|
|
|
|
The creating process is the default owner. The owner can be reassigned
|
|
by the creator and has creator perms. Only the owner, creator or super-user
|
|
can delete the resource.@refill
|
|
|
|
The lowest nine bits of the flags parameter supplied by the user to the
|
|
system call are compared with the values stored in @code{ipc_perms.mode}
|
|
to determine if the requested access is allowed. In the case
|
|
that the system call creates the resource, these bits are initialized
|
|
from the user supplied value.@refill
|
|
|
|
As for files, access permissions are specified as read, write and exec
|
|
for user, group or other (though the exec perms are unused). For example
|
|
0624 grants read-write to owner, write-only to group and read-only
|
|
access to others.@refill
|
|
|
|
For shared memory, note that read-write access for segments is determined
|
|
by a separate flag which is not stored in the @code{mode} field.
|
|
Shared memory segments attached with write access can be read.@refill
|
|
|
|
The @code{cuid}, @code{cgid}, @code{key} and @code{seq} fields
|
|
cannot be changed by the user.@refill
|
|
|
|
|
|
|
|
@node syscalls, Messages, perms, Overview
|
|
@section IPC system calls
|
|
|
|
This section provides an overview of the IPC system calls. See the
|
|
specific sections on each type of resource for details.@refill
|
|
|
|
Each type of mechanism provides a @dfn{get}, @dfn{ctl} and one or more
|
|
@dfn{op} system calls that allow the user to create or procure the
|
|
resource (get), define its behaviour or destroy it (ctl) and manipulate
|
|
the resources (op).@refill
|
|
|
|
|
|
|
|
@subsection The @dfn{get} system calls
|
|
|
|
The @code{get} call typically takes a @var{key} and returns a numeric
|
|
@var{id} that is used for further access.
|
|
The @var{id} is an index into the resource table. A sequence
|
|
number is maintained and incremented when a resource is
|
|
destroyed so that access using an obsolete @var{id} is likely to fail.@refill
|
|
|
|
The user also specifies the permissions and other behaviour
|
|
charecteristics for the current access. The flags are or-ed with the
|
|
permissions when invoking system calls as in:@refill
|
|
@example
|
|
msgflg = IPC_CREAT | IPC_EXCL | 0666;
|
|
id = msgget (key, msgflg);
|
|
@end example
|
|
@itemize @bullet
|
|
@item
|
|
@code{key} : IPC_PRIVATE => new instance of resource is initialized.
|
|
@item
|
|
@code{flags} :
|
|
@itemize @asis
|
|
@item
|
|
IPC_CREAT : resource created for @var{key} if it does not exist.
|
|
@item
|
|
IPC_CREAT | IPC_EXCL : fail if resource exists for @var{key}.
|
|
@end itemize
|
|
@item
|
|
returns : an identifier used for all further access to the resource.
|
|
@end itemize
|
|
|
|
Note that IPC_PRIVATE is not a flag but a special @code{key}
|
|
that ensures (when the call is successful) that a new resource is
|
|
created.@refill
|
|
|
|
Use of IPC_PRIVATE does not make the resource inaccessible to other
|
|
users. For this you must set the access permissions appropriately.@refill
|
|
|
|
There is currently no way for a process to ensure exclusive access to a
|
|
resource. IPC_CREAT | IPC_EXCL only ensures (on success) that a new
|
|
resource was initialized. It does not imply exclusive access.@refill
|
|
|
|
@noindent
|
|
See Also : @xref{msgget}, @xref{semget}, @xref{shmget}.@refill
|
|
|
|
|
|
|
|
@subsection The @dfn{ctl} system calls
|
|
|
|
Provides or alters the information stored in the structure that describes
|
|
the resource indexed by @var{id}.@refill
|
|
|
|
@example
|
|
#include <sys/msg.h>
|
|
struct msqid_ds buf;
|
|
err = msgctl (id, IPC_STAT, &buf);
|
|
if (err)
|
|
!$#%*
|
|
else
|
|
printf ("creator uid = %d\n", buf.msg_perm.cuid);
|
|
....
|
|
@end example
|
|
|
|
@noindent
|
|
Commands supported by all @code{ctl} calls:@*
|
|
@itemize @bullet
|
|
@item
|
|
IPC_STAT : read info on resource specified by id into user allocated
|
|
buffer. The user must have read access to the resource.@refill
|
|
@item
|
|
IPC_SET : write info from buffer into resource data structure. The
|
|
user must be owner creator or super-user.@refill
|
|
@item
|
|
IPC_RMID : remove resource. The user must be the owner, creator or
|
|
super-user.@refill
|
|
@end itemize
|
|
|
|
The IPC_RMID command results in immediate removal of a message
|
|
queue or semaphore array. Shared memory segments however, are
|
|
only destroyed upon the last detach after IPC_RMID is executed.@refill
|
|
|
|
The @code{semctl} call provides a number of command options that allow
|
|
the user to determine or set the values of the semaphores in an array.@refill
|
|
|
|
@noindent
|
|
See Also: @xref{msgctl}, @xref{semctl}, @xref{shmctl}.@refill
|
|
|
|
|
|
@subsection The @dfn{op} system calls
|
|
|
|
Used to send or receive messages, read or alter semaphore values,
|
|
attach or detach shared memory segments.
|
|
The IPC_NOWAIT flag will cause the operation to fail with error EAGAIN
|
|
if the process has to wait on the call.@refill
|
|
|
|
@noindent
|
|
@code{flags} : IPC_NOWAIT => return with error if a wait is required.
|
|
|
|
@noindent
|
|
See Also: @xref{msgsnd},@xref{msgrcv},@xref{semop},@xref{shmat},
|
|
@xref{shmdt}.@refill
|
|
|
|
|
|
|
|
@node Messages, msgget, syscalls, Top
|
|
@section Messages
|
|
|
|
A message resource is described by a struct @code{msqid_ds} which is
|
|
allocated and initialized when the resource is created. Some fields
|
|
in @code{msqid_ds} can then be altered (if desired) by invoking @code{msgctl}.
|
|
The memory used by the resource is released when it is destroyed by
|
|
a @code{msgctl} call.@refill
|
|
|
|
@example
|
|
struct msqid_ds
|
|
struct ipc_perm msg_perm;
|
|
struct msg *msg_first; /* first message on queue (internal) */
|
|
struct msg *msg_last; /* last message in queue (internal) */
|
|
time_t msg_stime; /* last msgsnd time */
|
|
time_t msg_rtime; /* last msgrcv time */
|
|
time_t msg_ctime; /* last change time */
|
|
struct wait_queue *wwait; /* writers waiting (internal) */
|
|
struct wait_queue *rwait; /* readers waiting (internal) */
|
|
ushort msg_cbytes; /* number of bytes used on queue */
|
|
ushort msg_qnum; /* number of messages in queue */
|
|
ushort msg_qbytes; /* max number of bytes on queue */
|
|
ushort msg_lspid; /* pid of last msgsnd */
|
|
ushort msg_lrpid; /* pid of last msgrcv */
|
|
@end example
|
|
|
|
To send or receive a message the user allocates a structure that looks
|
|
like a @code{msgbuf} but with an array @code{mtext} of the required size.
|
|
Messages have a type (positive integer) associated with them so that
|
|
(for example) a listener can choose to receive only messages of a
|
|
given type.@refill
|
|
|
|
@example
|
|
struct msgbuf
|
|
long mtype; type of message (@xref{msgrcv}).
|
|
char mtext[1]; message text .. why is this not a ptr?
|
|
@end example
|
|
|
|
The user must have write permissions to send and read permissions
|
|
to receive messages on a queue.@refill
|
|
|
|
When @code{msgsnd} is invoked, the user's message is copied into
|
|
an internal struct @code{msg} and added to the queue. A @code{msgrcv}
|
|
will then read this message and free the associated struct @code{msg}.@refill
|
|
|
|
|
|
@menu
|
|
* msgget::
|
|
* msgsnd::
|
|
* msgrcv::
|
|
* msgctl::
|
|
* msglimits:: Implementation defined limits.
|
|
@end menu
|
|
|
|
|
|
@node msgget, msgsnd, Messages, Messages
|
|
@subsection msgget
|
|
|
|
@noindent
|
|
A message queue is allocated by a msgget system call :
|
|
|
|
@example
|
|
msqid = msgget (key_t key, int msgflg);
|
|
@end example
|
|
|
|
@itemize @bullet
|
|
@item
|
|
@code{key}: an integer usually got from @code{ftok()} or IPC_PRIVATE.@refill
|
|
@item
|
|
@code{msgflg}:
|
|
@itemize @asis
|
|
@item
|
|
IPC_CREAT : used to create a new resource if it does not already exist.
|
|
@item
|
|
IPC_EXCL | IPC_CREAT : used to ensure failure of the call if the
|
|
resource already exists.@refill
|
|
@item
|
|
rwxrwxrwx : access permissions.
|
|
@end itemize
|
|
@item
|
|
returns: msqid (an integer used for all further access) on success.
|
|
-1 on failure.@refill
|
|
@end itemize
|
|
|
|
A message queue is allocated if there is no resource corresponding
|
|
to the given key. The access permissions specified are then copied
|
|
into the @code{msg_perm} struct and the fields in @code{msqid_ds}
|
|
initialized. The user must use the IPC_CREAT flag or key = IPC_PRIVATE,
|
|
if a new instance is to be allocated. If a resource corresponding to
|
|
@var{key} already exists, the access permissions are verified.@refill
|
|
|
|
@noindent
|
|
Errors:@*
|
|
@noindent
|
|
EACCES : (procure) Do not have permission for requested access.@*
|
|
@noindent
|
|
EEXIST : (allocate) IPC_CREAT | IPC_EXCL specified and resource exists.@*
|
|
@noindent
|
|
EIDRM : (procure) The resource was removed.@*
|
|
@noindent
|
|
ENOSPC : All id's are taken (max of MSGMNI id's system-wide).@*
|
|
@noindent
|
|
ENOENT : Resource does not exist and IPC_CREAT not specified.@*
|
|
@noindent
|
|
ENOMEM : A new @code{msqid_ds} was to be created but ... nomem.
|
|
|
|
|
|
|
|
|
|
@node msgsnd, msgrcv, msgget, Messages
|
|
@subsection msgsnd
|
|
|
|
@example
|
|
int msgsnd (int msqid, struct msgbuf *msgp, int msgsz, int msgflg);
|
|
@end example
|
|
|
|
@itemize @bullet
|
|
@item
|
|
@code{msqid} : id obtained by a call to msgget.
|
|
@item
|
|
@code{msgsz} : size of msg text (@code{mtext}) in bytes.
|
|
@item
|
|
@code{msgp} : message to be sent. (msgp->mtype must be positive).
|
|
@item
|
|
@code{msgflg} : IPC_NOWAIT.
|
|
@item
|
|
returns : msgsz on success. -1 on error.
|
|
@end itemize
|
|
|
|
The message text and type are stored in the internal @code{msg}
|
|
structure. @code{msg_cbytes}, @code{msg_qnum}, @code{msg_lspid},
|
|
and @code{msg_stime} fields are updated. Readers waiting on the
|
|
queue are awakened.@refill
|
|
|
|
@noindent
|
|
Errors:@*
|
|
@noindent
|
|
EACCES : Do not have write permission on queue.@*
|
|
@noindent
|
|
EAGAIN : IPC_NOWAIT specified and queue is full.@*
|
|
@noindent
|
|
EFAULT : msgp not accessible.@*
|
|
@noindent
|
|
EIDRM : The message queue was removed.@*
|
|
@noindent
|
|
EINTR : Full queue ... would have slept but ... was interrupted.@*
|
|
@noindent
|
|
EINVAL : mtype < 1, msgsz > MSGMAX, msgsz < 0, msqid < 0 or unused.@*
|
|
@noindent
|
|
ENOMEM : Could not allocate space for header and text.@*
|
|
|
|
|
|
|
|
@node msgrcv, msgctl, msgsnd, Messages
|
|
@subsection msgrcv
|
|
|
|
@example
|
|
int msgrcv (int msqid, struct msgbuf *msgp, int msgsz, long msgtyp,
|
|
int msgflg);
|
|
@end example
|
|
|
|
@itemize @bullet
|
|
@item
|
|
msqid : id obtained by a call to msgget.
|
|
@item
|
|
msgsz : maximum size of message to receive.
|
|
@item
|
|
msgp : allocated by user to store the message in.
|
|
@item
|
|
msgtyp :
|
|
@itemize @asis
|
|
@item
|
|
0 => get first message on queue.
|
|
@item
|
|
> 0 => get first message of matching type.
|
|
@item
|
|
< 0 => get message with least type which is <= abs(msgtyp).
|
|
@end itemize
|
|
@item
|
|
msgflg :
|
|
@itemize @asis
|
|
@item
|
|
IPC_NOWAIT : Return immediately if message not found.
|
|
@item
|
|
MSG_NOERROR : The message is truncated if it is larger than msgsz.
|
|
@item
|
|
MSG_EXCEPT : Used with msgtyp > 0 to receive any msg except of specified
|
|
type.@refill
|
|
@end itemize
|
|
@item
|
|
returns : size of message if found. -1 on error.
|
|
@end itemize
|
|
|
|
The first message that meets the @code{msgtyp} specification is
|
|
identified. For msgtyp < 0, the entire queue is searched for the
|
|
message with the smallest type.@refill
|
|
|
|
If its length is smaller than msgsz or if the user specified the
|
|
MSG_NOERROR flag, its text and type are copied to msgp->mtext and
|
|
msgp->mtype, and it is taken off the queue.@refill
|
|
|
|
The @code{msg_cbytes}, @code{msg_qnum}, @code{msg_lrpid},
|
|
and @code{msg_rtime} fields are updated. Writers waiting on the
|
|
queue are awakened.@refill
|
|
|
|
@noindent
|
|
Errors:@*
|
|
@noindent
|
|
E2BIG : msg bigger than msgsz and MSG_NOERROR not specified.@*
|
|
@noindent
|
|
EACCES : Do not have permission for reading the queue.@*
|
|
@noindent
|
|
EFAULT : msgp not accessible.@*
|
|
@noindent
|
|
EIDRM : msg queue was removed.@*
|
|
@noindent
|
|
EINTR : msg not found ... would have slept but ... was interrupted.@*
|
|
@noindent
|
|
EINVAL : msgsz > msgmax or msgsz < 0, msqid < 0 or unused.@*
|
|
@noindent
|
|
ENOMSG : msg of requested type not found and IPC_NOWAIT specified.
|
|
|
|
|
|
|
|
@node msgctl, msglimits, msgrcv, Messages
|
|
@subsection msgctl
|
|
|
|
@example
|
|
int msgctl (int msqid, int cmd, struct msqid_ds *buf);
|
|
@end example
|
|
|
|
@itemize @bullet
|
|
@item
|
|
msqid : id obtained by a call to msgget.
|
|
@item
|
|
buf : allocated by user for reading/writing info.
|
|
@item
|
|
cmd : IPC_STAT, IPC_SET, IPC_RMID (@xref{syscalls}).
|
|
@end itemize
|
|
|
|
IPC_STAT results in the copy of the queue data structure
|
|
into the user supplied buffer.@refill
|
|
|
|
In the case of IPC_SET, the queue size (@code{msg_qbytes})
|
|
and the @code{uid}, @code{gid}, @code{mode} (low 9 bits) fields
|
|
of the @code{msg_perm} struct are set from the user supplied values.
|
|
@code{msg_ctime} is updated.@refill
|
|
|
|
Note that only the super user may increase the limit on the size of a
|
|
message queue beyond MSGMNB.@refill
|
|
|
|
When the queue is destroyed (IPC_RMID), the sequence number is
|
|
incremented and all waiting readers and writers are awakened.
|
|
These processes will then return with @code{errno} set to EIDRM.@refill
|
|
|
|
@noindent
|
|
Errors:
|
|
@noindent
|
|
EPERM : Insufficient privilege to increase the size of the queue (IPC_SET)
|
|
or remove it (IPC_RMID).@*
|
|
@noindent
|
|
EACCES : Do not have permission for reading the queue (IPC_STAT).@*
|
|
@noindent
|
|
EFAULT : buf not accessible (IPC_STAT, IPC_SET).@*
|
|
@noindent
|
|
EIDRM : msg queue was removed.@*
|
|
@noindent
|
|
EINVAL : invalid cmd, msqid < 0 or unused.
|
|
|
|
|
|
@node msglimits, Semaphores, msgctl, Messages
|
|
@subsection Limis on Message Resources
|
|
|
|
@noindent
|
|
Sizeof various structures:
|
|
@itemize @asis
|
|
@item
|
|
msqid_ds 52 /* 1 per message queue .. dynamic */
|
|
@item
|
|
msg 16 /* 1 for each message in system .. dynamic */
|
|
@item
|
|
msgbuf 8 /* allocated by user */
|
|
@end itemize
|
|
|
|
@noindent
|
|
Limits
|
|
@itemize @bullet
|
|
@item
|
|
MSGMNI : number of message queue identifiers ... policy.
|
|
@item
|
|
MSGMAX : max size of message.
|
|
Header and message space allocated on one page.
|
|
MSGMAX = (PAGE_SIZE - sizeof(struct msg)).
|
|
Implementation maximum MSGMAX = 4080.@refill
|
|
@item
|
|
MSGMNB : default max size of a message queue ... policy.
|
|
The super-user can increase the size of a
|
|
queue beyond MSGMNB by a @code{msgctl} call.@refill
|
|
@end itemize
|
|
|
|
@noindent
|
|
Unused or unimplemented:@*
|
|
MSGTQL max number of message headers system-wide.@*
|
|
MSGPOOL total size in bytes of msg pool.
|
|
|
|
|
|
|
|
@node Semaphores, semget, msglimits, Top
|
|
@section Semaphores
|
|
|
|
Each semaphore has a value >= 0. An id provides access to an array
|
|
of @code{nsems} semaphores. Operations such as read, increment or decrement
|
|
semaphores in a set are performed by the @code{semop} call which processes
|
|
@code{nsops} operations at a time. Each operation is specified in a struct
|
|
@code{sembuf} described below. The operations are applied only if all of
|
|
them succeed.@refill
|
|
|
|
If you do not have a need for such arrays, you are probably better off using
|
|
the @code{test_bit}, @code{set_bit} and @code{clear_bit} bit-operations
|
|
defined in <asm/bitops.h>.@refill
|
|
|
|
Semaphore operations may also be qualified by a SEM_UNDO flag which
|
|
results in the operation being undone when the process exits.@refill
|
|
|
|
If a decrement cannot go through, a process will be put to sleep
|
|
on a queue waiting for the @code{semval} to increase unless it specifies
|
|
IPC_NOWAIT. A read operation can similarly result in a sleep on a
|
|
queue waiting for @code{semval} to become 0. (Actually there are
|
|
two queues per semaphore array).@refill
|
|
|
|
@noindent
|
|
A semaphore array is described by:
|
|
@example
|
|
struct semid_ds
|
|
struct ipc_perm sem_perm;
|
|
time_t sem_otime; /* last semop time */
|
|
time_t sem_ctime; /* last change time */
|
|
struct wait_queue *eventn; /* wait for a semval to increase */
|
|
struct wait_queue *eventz; /* wait for a semval to become 0 */
|
|
struct sem_undo *undo; /* undo entries */
|
|
ushort sem_nsems; /* no. of semaphores in array */
|
|
@end example
|
|
|
|
@noindent
|
|
Each semaphore is described internally by :
|
|
@example
|
|
struct sem
|
|
short sempid; /* pid of last semop() */
|
|
ushort semval; /* current value */
|
|
ushort semncnt; /* num procs awaiting increase in semval */
|
|
ushort semzcnt; /* num procs awaiting semval = 0 */
|
|
@end example
|
|
|
|
@menu
|
|
* semget::
|
|
* semop::
|
|
* semctl::
|
|
* semlimits:: Limits imposed by this implementation.
|
|
@end menu
|
|
|
|
@node semget, semop, Semaphores, Semaphores
|
|
@subsection semget
|
|
|
|
@noindent
|
|
A semaphore array is allocated by a semget system call:
|
|
|
|
@example
|
|
semid = semget (key_t key, int nsems, int semflg);
|
|
@end example
|
|
|
|
@itemize @bullet
|
|
@item
|
|
@code{key} : an integer usually got from @code{ftok} or IPC_PRIVATE
|
|
@item
|
|
@code{nsems} :
|
|
@itemize @asis
|
|
@item
|
|
# of semaphores in array (0 <= nsems <= SEMMSL <= SEMMNS)
|
|
@item
|
|
0 => dont care can be used when not creating the resource.
|
|
If successful you always get access to the entire array anyway.@refill
|
|
@end itemize
|
|
@item
|
|
semflg :
|
|
@itemize @asis
|
|
@item
|
|
IPC_CREAT used to create a new resource
|
|
@item
|
|
IPC_EXCL used with IPC_CREAT to ensure failure if the resource exists.
|
|
@item
|
|
rwxrwxrwx access permissions.
|
|
@end itemize
|
|
@item
|
|
returns : semid on success. -1 on failure.
|
|
@end itemize
|
|
|
|
An array of nsems semaphores is allocated if there is no resource
|
|
corresponding to the given key. The access permissions specified are
|
|
then copied into the @code{sem_perm} struct for the array along with the
|
|
user-id etc. The user must use the IPC_CREAT flag or key = IPC_PRIVATE
|
|
if a new resource is to be created.@refill
|
|
|
|
@noindent
|
|
Errors:@*
|
|
@noindent
|
|
EINVAL : nsems not in above range (allocate).@*
|
|
nsems greater than number in array (procure).@*
|
|
@noindent
|
|
EEXIST : (allocate) IPC_CREAT | IPC_EXCL specified and resource exists.@*
|
|
@noindent
|
|
EIDRM : (procure) The resource was removed.@*
|
|
@noindent
|
|
ENOMEM : could not allocate space for semaphore array.@*
|
|
@noindent
|
|
ENOSPC : No arrays available (SEMMNI), too few semaphores available (SEMMNS).@*
|
|
@noindent
|
|
ENOENT : Resource does not exist and IPC_CREAT not specified.@*
|
|
@noindent
|
|
EACCES : (procure) do not have permission for specified access.
|
|
|
|
|
|
@node semop, semctl, semget, Semaphores
|
|
@subsection semop
|
|
|
|
@noindent
|
|
Operations on semaphore arrays are performed by calling semop :
|
|
|
|
@example
|
|
int semop (int semid, struct sembuf *sops, unsigned nsops);
|
|
@end example
|
|
@itemize @bullet
|
|
@item
|
|
semid : id obtained by a call to semget.
|
|
@item
|
|
sops : array of semaphore operations.
|
|
@item
|
|
nsops : number of operations in array (0 < nsops < SEMOPM).
|
|
@item
|
|
returns : semval for last operation. -1 on failure.
|
|
@end itemize
|
|
|
|
@noindent
|
|
Operations are described by a structure sembuf:
|
|
@example
|
|
struct sembuf
|
|
ushort sem_num; /* semaphore index in array */
|
|
short sem_op; /* semaphore operation */
|
|
short sem_flg; /* operation flags */
|
|
@end example
|
|
|
|
The value @code{sem_op} is to be added (signed) to the current value semval
|
|
of the semaphore with index sem_num (0 .. nsems -1) in the set.
|
|
Flags recognized in sem_flg are IPC_NOWAIT and SEM_UNDO.@refill
|
|
|
|
@noindent
|
|
Two kinds of operations can result in wait:
|
|
@enumerate
|
|
@item
|
|
If sem_op is 0 (read operation) and semval is non-zero, the process
|
|
sleeps on a queue waiting for semval to become zero or returns with
|
|
error EAGAIN if (IPC_NOWAIT | sem_flg) is true.@refill
|
|
@item
|
|
If (sem_op < 0) and (semval + sem_op < 0), the process either sleeps
|
|
on a queue waiting for semval to increase or returns with error EAGAIN if
|
|
(sem_flg & IPC_NOWAIT) is true.@refill
|
|
@end enumerate
|
|
|
|
The array sops is first read in and preliminary checks performed on
|
|
the arguments. The operations are parsed to determine if any of
|
|
them needs write permissions or requests an undo operation.@refill
|
|
|
|
The operations are then tried and the process sleeps if any operation
|
|
that does not specify IPC_NOWAIT cannot go through. If a process sleeps
|
|
it repeats these checks on waking up. If any operation that requests
|
|
IPC_NOWAIT, cannot go through at any stage, the call returns with errno
|
|
set to EAGAIN.@refill
|
|
|
|
Finally, operations are committed when all go through without an intervening
|
|
sleep. Processes waiting on the zero_queue or increment_queue are awakened
|
|
if any of the semval's becomes zero or is incremented respectively.@refill
|
|
|
|
@noindent
|
|
Errors:@*
|
|
@noindent
|
|
E2BIG : nsops > SEMOPM.@*
|
|
@noindent
|
|
EACCES : Do not have permission for requested (read/alter) access.@*
|
|
@noindent
|
|
EAGAIN : An operation with IPC_NOWAIT specified could not go through.@*
|
|
@noindent
|
|
EFAULT : The array sops is not accessible.@*
|
|
@noindent
|
|
EFBIG : An operation had semnum >= nsems.@*
|
|
@noindent
|
|
EIDRM : The resource was removed.@*
|
|
@noindent
|
|
EINTR : The process was interrupted on its way to a wait queue.@*
|
|
@noindent
|
|
EINVAL : nsops is 0, semid < 0 or unused.@*
|
|
@noindent
|
|
ENOMEM : SEM_UNDO requested. Could not allocate space for undo structure.@*
|
|
@noindent
|
|
ERANGE : sem_op + semval > SEMVMX for some operation.
|
|
|
|
|
|
@node semctl, semlimits, semop, Semaphores
|
|
@subsection semctl
|
|
|
|
@example
|
|
int semctl (int semid, int semnum, int cmd, union semun arg);
|
|
@end example
|
|
|
|
@itemize @bullet
|
|
@item
|
|
semid : id obtained by a call to semget.
|
|
@item
|
|
cmd :
|
|
@itemize @asis
|
|
@item
|
|
GETPID return pid for the process that executed the last semop.
|
|
@item
|
|
GETVAL return semval of semaphore with index semnum.
|
|
@item
|
|
GETNCNT return number of processes waiting for semval to increase.
|
|
@item
|
|
GETZCNT return number of processes waiting for semval to become 0
|
|
@item
|
|
SETVAL set semval = arg.val.
|
|
@item
|
|
GETALL read all semval's into arg.array.
|
|
@item
|
|
SETALL set all semval's with values given in arg.array.
|
|
@end itemize
|
|
@item
|
|
returns : 0 on success or as given above. -1 on failure.
|
|
@end itemize
|
|
|
|
The first 4 operate on the semaphore with index semnum in the set.
|
|
The last two operate on all semaphores in the set.@refill
|
|
|
|
@code{arg} is a union :
|
|
@example
|
|
union semun
|
|
int val; value for SETVAL.
|
|
struct semid_ds *buf; buffer for IPC_STAT and IPC_SET.
|
|
ushort *array; array for GETALL and SETALL
|
|
@end example
|
|
|
|
@itemize @bullet
|
|
@item
|
|
IPC_SET, SETVAL, SETALL : sem_ctime is updated.
|
|
@item
|
|
SETVAL, SETALL : Undo entries are cleared for altered semaphores in
|
|
all processes. Processes sleeping on the wait queues are
|
|
awakened if a semval becomes 0 or increases.@refill
|
|
@item
|
|
IPC_SET : sem_perm.uid, sem_perm.gid, sem_perm.mode are updated from
|
|
user supplied values.@refill
|
|
@end itemize
|
|
|
|
@noindent
|
|
Errors:
|
|
@noindent
|
|
EACCES : do not have permission for specified access.@*
|
|
@noindent
|
|
EFAULT : arg is not accessible.@*
|
|
@noindent
|
|
EIDRM : The resource was removed.@*
|
|
@noindent
|
|
EINVAL : semid < 0 or semnum < 0 or semnum >= nsems.@*
|
|
@noindent
|
|
EPERM : IPC_RMID, IPC_SET ... not creator, owner or super-user.@*
|
|
@noindent
|
|
ERANGE : arg.array[i].semval > SEMVMX or < 0 for some i.
|
|
|
|
|
|
|
|
|
|
@node semlimits, Shared Memory, semctl, Semaphores
|
|
@subsection Limits on Semaphore Resources
|
|
|
|
@noindent
|
|
Sizeof various structures:
|
|
@example
|
|
semid_ds 44 /* 1 per semaphore array .. dynamic */
|
|
sem 8 /* 1 for each semaphore in system .. dynamic */
|
|
sembuf 6 /* allocated by user */
|
|
sem_undo 20 /* 1 for each undo request .. dynamic */
|
|
@end example
|
|
|
|
@noindent
|
|
Limits :@*
|
|
@itemize @bullet
|
|
@item
|
|
SEMVMX 32767 semaphore maximum value (short).
|
|
@item
|
|
SEMMNI number of semaphore identifiers (or arrays) system wide...policy.
|
|
@item
|
|
SEMMSL maximum number of semaphores per id.
|
|
1 semid_ds per array, 1 struct sem per semaphore
|
|
=> SEMMSL = (PAGE_SIZE - sizeof(semid_ds)) / sizeof(sem).
|
|
Implementation maximum SEMMSL = 500.@refill
|
|
@item
|
|
SEMMNS maximum number of semaphores system wide ... policy.
|
|
Setting SEMMNS >= SEMMSL*SEMMNI makes it irrelevent.@refill
|
|
@item
|
|
SEMOPM Maximum number of operations in one semop call...policy.
|
|
@end itemize
|
|
|
|
@noindent
|
|
Unused or unimplemented:@*
|
|
@noindent
|
|
SEMAEM adjust on exit max value.@*
|
|
@noindent
|
|
SEMMNU number of undo structures system-wide.@*
|
|
@noindent
|
|
SEMUME maximum number of undo entries per process.
|
|
|
|
|
|
|
|
@node Shared Memory, shmget, semlimits, Top
|
|
@section Shared Memory
|
|
|
|
Shared memory is distinct from the sharing of read-only code pages or
|
|
the sharing of unaltered data pages that is available due to the
|
|
copy-on-write mechanism. The essential difference is that the
|
|
shared pages are dirty (in the case of Shared memory) and can be
|
|
made to appear at a convenient location in the process' address space.@refill
|
|
|
|
@noindent
|
|
A shared segment is described by :
|
|
@example
|
|
struct shmid_ds
|
|
struct ipc_perm shm_perm;
|
|
int shm_segsz; /* size of segment (bytes) */
|
|
time_t shm_atime; /* last attach time */
|
|
time_t shm_dtime; /* last detach time */
|
|
time_t shm_ctime; /* last change time */
|
|
ulong *shm_pages; /* internal page table */
|
|
ushort shm_cpid; /* pid, creator */
|
|
ushort shm_lpid; /* pid, last operation */
|
|
short shm_nattch; /* no. of current attaches */
|
|
@end example
|
|
|
|
A shmget allocates a shmid_ds and an internal page table. A shmat
|
|
maps the segment into the process' address space with pointers
|
|
into the internal page table and the actual pages are faulted in
|
|
as needed. The memory associated with the segment must be explicitly
|
|
destroyed by calling shmctl with IPC_RMID.@refill
|
|
|
|
@menu
|
|
* shmget::
|
|
* shmat::
|
|
* shmdt::
|
|
* shmctl::
|
|
* shmlimits:: Limits imposed by this implementation.
|
|
@end menu
|
|
|
|
|
|
@node shmget, shmat, Shared Memory, Shared Memory
|
|
@subsection shmget
|
|
|
|
@noindent
|
|
A shared memory segment is allocated by a shmget system call:
|
|
|
|
@example
|
|
int shmget(key_t key, int size, int shmflg);
|
|
@end example
|
|
|
|
@itemize @bullet
|
|
@item
|
|
key : an integer usually got from @code{ftok} or IPC_PRIVATE
|
|
@item
|
|
size : size of the segment in bytes (SHMMIN <= size <= SHMMAX).
|
|
@item
|
|
shmflg :
|
|
@itemize @asis
|
|
@item
|
|
IPC_CREAT used to create a new resource
|
|
@item
|
|
IPC_EXCL used with IPC_CREAT to ensure failure if the resource exists.
|
|
@item
|
|
rwxrwxrwx access permissions.
|
|
@end itemize
|
|
@item
|
|
returns : shmid on success. -1 on failure.
|
|
@end itemize
|
|
|
|
A descriptor for a shared memory segment is allocated if there isn't one
|
|
corresponding to the given key. The access permissions specified are
|
|
then copied into the @code{shm_perm} struct for the segment along with the
|
|
user-id etc. The user must use the IPC_CREAT flag or key = IPC_PRIVATE
|
|
to allocate a new segment.@refill
|
|
|
|
If the segment already exists, the access permissions are verified,
|
|
and a check is made to see that it is not marked for destruction.@refill
|
|
|
|
@code{size} is effectively rounded up to a multiple of PAGE_SIZE as shared
|
|
memory is allocated in pages.@refill
|
|
|
|
@noindent
|
|
Errors:@*
|
|
@noindent
|
|
EINVAL : (allocate) Size not in range specified above.@*
|
|
(procure) Size greater than size of segment.@*
|
|
@noindent
|
|
EEXIST : (allocate) IPC_CREAT | IPC_EXCL specified and resource exists.@*
|
|
@noindent
|
|
EIDRM : (procure) The resource is marked destroyed or was removed.@*
|
|
@noindent
|
|
ENOSPC : (allocate) All id's are taken (max of SHMMNI id's system-wide).
|
|
Allocating a segment of the requested size would exceed the
|
|
system wide limit on total shared memory (SHMALL).@refill
|
|
@*
|
|
@noindent
|
|
ENOENT : (procure) Resource does not exist and IPC_CREAT not specified.@*
|
|
@noindent
|
|
EACCES : (procure) Do not have permission for specified access.@*
|
|
@noindent
|
|
ENOMEM : (allocate) Could not allocate memory for shmid_ds or pg_table.
|
|
|
|
|
|
|
|
@node shmat, shmdt, shmget, Shared Memory
|
|
@subsection shmat
|
|
|
|
@noindent
|
|
Maps a shared segment into the process' address space.
|
|
|
|
@example
|
|
char *virt_addr;
|
|
virt_addr = shmat (int shmid, char *shmaddr, int shmflg);
|
|
@end example
|
|
|
|
@itemize @bullet
|
|
@item
|
|
shmid : id got from call to shmget.
|
|
@item
|
|
shmaddr : requested attach address.@*
|
|
If shmaddr is 0 the system finds an unmapped region.@*
|
|
If a non-zero value is indicated the value must be page
|
|
aligned or the user must specify the SHM_RND flag.@refill
|
|
@item
|
|
shmflg :@*
|
|
SHM_RDONLY : request read-only attach.@*
|
|
SHM_RND : attach address is rounded DOWN to a multiple of SHMLBA.
|
|
@item
|
|
returns: virtual address of attached segment. -1 on failure.
|
|
@end itemize
|
|
|
|
When shmaddr is 0, the attach address is determined by finding an
|
|
unmapped region in the address range 1G to 1.5G, starting at 1.5G
|
|
and coming down from there. The algorithm is very simple so you
|
|
are encouraged to avoid non-specific attaches.
|
|
|
|
@noindent
|
|
Algorithm:
|
|
@display
|
|
Determine attach address as described above.
|
|
Check region (shmaddr, shmaddr + size) is not mapped and allocate
|
|
page tables (undocumented SHM_REMAP flag!).
|
|
Map the region by setting up pointers into the internal page table.
|
|
Add a descriptor for the attach to the task struct for the process.
|
|
@code{shm_nattch}, @code{shm_lpid}, @code{shm_atime} are updated.
|
|
@end display
|
|
|
|
@noindent
|
|
Notes:@*
|
|
The @code{brk} value is not altered.
|
|
The segment is automatically detached when the process exits.
|
|
The same segment may be attached as read-only or read-write and
|
|
more than once in the process' address space.
|
|
A shmat can succeed on a segment marked for destruction.
|
|
The request for a particular type of attach is made using the SHM_RDONLY flag.
|
|
There is no notion of a write-only attach. The requested attach
|
|
permissions must fall within those allowed by @code{shm_perm.mode}.
|
|
|
|
@noindent
|
|
Errors:@*
|
|
@noindent
|
|
EACCES : Do not have permission for requested access.@*
|
|
@noindent
|
|
EINVAL : shmid < 0 or unused, shmaddr not aligned, attach at brk failed.@*
|
|
@noindent
|
|
EIDRM : resource was removed.@*
|
|
@noindent
|
|
ENOMEM : Could not allocate memory for descriptor or page tables.
|
|
|
|
|
|
@node shmdt, shmctl, shmat, Shared Memory
|
|
@subsection shmdt
|
|
|
|
@example
|
|
int shmdt (char *shmaddr);
|
|
@end example
|
|
|
|
@itemize @bullet
|
|
@item
|
|
shmaddr : attach address of segment (returned by shmat).
|
|
@item
|
|
returns : 0 on success. -1 on failure.
|
|
@end itemize
|
|
|
|
An attached segment is detached and @code{shm_nattch} decremented. The
|
|
occupied region in user space is unmapped. The segment is destroyed
|
|
if it is marked for destruction and @code{shm_nattch} is 0.
|
|
@code{shm_lpid} and @code{shm_dtime} are updated.@refill
|
|
|
|
@noindent
|
|
Errors:@*
|
|
@noindent
|
|
EINVAL : No shared memory segment attached at shmaddr.
|
|
|
|
|
|
@node shmctl, shmlimits, shmdt, Shared Memory
|
|
@subsection shmctl
|
|
|
|
@noindent
|
|
Destroys allocated segments. Reads/Writes the control structures.
|
|
|
|
@example
|
|
int shmctl (int shmid, int cmd, struct shmid_ds *buf);
|
|
@end example
|
|
|
|
@itemize @bullet
|
|
@item
|
|
shmid : id got from call to shmget.
|
|
@item
|
|
cmd : IPC_STAT, IPC_SET, IPC_RMID (@xref{syscalls}).
|
|
@itemize @asis
|
|
@item
|
|
IPC_SET : Used to set the owner uid, gid, and shm_perms.mode field.
|
|
@item
|
|
IPC_RMID : The segment is marked destroyed. It is only destroyed
|
|
on the last detach.@refill
|
|
@item
|
|
IPC_STAT : The shmid_ds structure is copied into the user allocated buffer.
|
|
@end itemize
|
|
@item
|
|
buf : used to read (IPC_STAT) or write (IPC_SET) information.
|
|
@item
|
|
returns : 0 on success, -1 on failure.
|
|
@end itemize
|
|
|
|
The user must execute an IPC_RMID shmctl call to free the memory
|
|
allocated by the shared segment. Otherwise all the pages faulted in
|
|
will continue to live in memory or swap.@refill
|
|
|
|
@noindent
|
|
Errors:@*
|
|
@noindent
|
|
EACCES : Do not have permission for requested access.@*
|
|
@noindent
|
|
EFAULT : buf is not accessible.@*
|
|
@noindent
|
|
EINVAL : shmid < 0 or unused.@*
|
|
@noindent
|
|
EIDRM : identifier destroyed.@*
|
|
@noindent
|
|
EPERM : not creator, owner or super-user (IPC_SET, IPC_RMID).
|
|
|
|
|
|
@node shmlimits, Notes, shmctl, Shared Memory
|
|
@subsection Limits on Shared Memory Resources
|
|
|
|
@noindent
|
|
Limits:
|
|
@itemize @bullet
|
|
@item
|
|
SHMMNI max num of shared segments system wide ... 4096.
|
|
@item
|
|
SHMMAX max shared memory segment size (bytes) ... 4M
|
|
@item
|
|
SHMMIN min shared memory segment size (bytes).
|
|
1 byte (though PAGE_SIZE is the effective minimum size).@refill
|
|
@item
|
|
SHMALL max shared mem system wide (in pages) ... policy.
|
|
@item
|
|
SHMLBA segment low boundary address multiple.
|
|
Must be page aligned. SHMLBA = PAGE_SIZE.@refill
|
|
@end itemize
|
|
@noindent
|
|
Unused or unimplemented:@*
|
|
SHMSEG : maximum number of shared segments per process.
|
|
|
|
|
|
|
|
@node Notes, Top, shmlimits, Top
|
|
@section Miscellaneous Notes
|
|
|
|
The system calls are mapped into one -- @code{sys_ipc}. This should be
|
|
transparent to the user.@refill
|
|
|
|
@subsection Semaphore @code{undo} requests
|
|
|
|
There is one sem_undo structure associated with a process for
|
|
each semaphore which was altered (with an undo request) by the process.
|
|
@code{sem_undo} structures are freed only when the process exits.
|
|
|
|
One major cause for unhappiness with the undo mechanism is that
|
|
it does not fit in with the notion of having an atomic set of
|
|
operations on an array. The undo requests for an array and each
|
|
semaphore therein may have been accumulated over many @code{semop}
|
|
calls. Thus use the undo mechanism with private semaphores only.@refill
|
|
|
|
Should the process sleep in @code{exit} or should all undo
|
|
operations be applied with the IPC_NOWAIT flag in effect?
|
|
Currently those undo operations which go through immediately are
|
|
applied and those that require a wait are ignored silently.@refill
|
|
|
|
@subsection Shared memory, @code{malloc} and the @code{brk}.
|
|
Note that since this section was written the implementation was
|
|
changed so that non-specific attaches are done in the region
|
|
1G - 1.5G. However much of the following is still worth thinking
|
|
about so I left it in.
|
|
|
|
On many systems, the shared memory is allocated in a special region
|
|
of the address space ... way up somewhere. As mentioned earlier,
|
|
this implementation attaches shared segments at the lowest possible
|
|
address. Thus if you plan to use @code{malloc}, it is wise to malloc a
|
|
large space and then proceed to attach the shared segments. This way
|
|
malloc sets the brk sufficiently above the region it will use.@refill
|
|
|
|
Alternatively you can use @code{sbrk} to adjust the @code{brk} value
|
|
as you make shared memory attaches. The implementation is not very
|
|
smart about selecting attach addresses. Using the system default
|
|
addresses will result in fragmentation if detaches do not occur
|
|
in the reverse sequence as attaches.@refill
|
|
|
|
Taking control of the matter is probably best. The rule applied
|
|
is that attaches are allowed in unmapped regions other than
|
|
in the text space (see <a.out.h>). Also remember that attach addresses
|
|
and segment sizes are multiples of PAGE_SIZE.@refill
|
|
|
|
One more trap (I quote Bruno on this). If you use malloc() to get space
|
|
for your shared memory (ie. to fix the @code{brk}), you must ensure you
|
|
get an unmapped address range. This means you must mallocate more memory
|
|
than you had ever allocated before. Memory returned by malloc(), used,
|
|
then freed by free() and then again returned by malloc is no good.
|
|
Neither is calloced memory.@refill
|
|
|
|
Note that a shared memory region remains a shared memory region until
|
|
you unmap it. Attaching a segment at the @code{brk} and calling malloc
|
|
after that will result in an overlap of what malloc thinks is its
|
|
space with what is really a shared memory region. For example in the case
|
|
of a read-only attach, you will not be able to write to the overlapped
|
|
portion.@refill
|
|
|
|
|
|
@subsection Fork, exec and exit
|
|
|
|
On a fork, the child inherits attached shared memory segments but
|
|
not the semaphore undo information.@refill
|
|
|
|
In the case of an exec, the attached shared segments are detached.
|
|
The sem undo information however remains intact.@refill
|
|
|
|
Upon exit, all attached shared memory segments are detached.
|
|
The adjust values in the undo structures are added to the relevant semvals
|
|
if the operations are permitted. Disallowed operations are ignored.@refill
|
|
|
|
|
|
@subsection Other Features
|
|
|
|
These features of the current implementation are
|
|
likely to be modified in the future.
|
|
|
|
The SHM_LOCK and SHM_UNLOCK flag are available (super-user) for use with the
|
|
@code{shmctl} call to prevent swapping of a shared segment. The user
|
|
must fault in any pages that are required to be present after locking
|
|
is enabled.
|
|
|
|
The IPC_INFO, MSG_STAT, MSG_INFO, SHM_STAT, SHM_INFO, SEM_STAT, SEMINFO
|
|
@code{ctl} calls are used by the @code{ipcs} program to provide information
|
|
on allocated resources. These can be modified as needed or moved to a proc
|
|
file system interface.
|
|
|
|
|
|
@sp 3
|
|
Thanks to Ove Ewerlid, Bruno Haible, Ulrich Pegelow and Linus Torvalds
|
|
for ideas, tutorials, bug reports and fixes, and merriment. And more
|
|
thanks to Bruno.
|
|
|
|
|
|
@contents
|
|
@bye
|
|
|