IPC System Calls: A Synopsis
IPC System Calls A Synopsis
A set of similar system calls are used to create an IPC resource and manipulate IPC information. [3] Due to their flexibility, the syntax for these calls is somewhat arcane (the calls appear, like the camel, to have been designed by a committee). The System V IPC calls are summarized in Table 6.2.
[3] Note Linux also supports a nonstandard, nonportable system call called ipc that can be used to manipulate IPC resources. As this is a Linux-specific call, its use is best left to Linux system developers.
Table 6.2. Summary of the System V IPC Calls.
Functionality |
Message Queue |
System Call Semaphore |
Shared Memory |
---|---|---|---|
Allocate an IPC resource; gain access to an existing IPC resource. |
msgget |
Semget |
Shmget |
Control an IPC resource: obtain/modify status information, remove the resource. |
msgctl |
Semctl |
Shmctl |
IPC operations: send/receive messages,perform semaphore operations, attach/free a shared memory segment. |
msgsnd msgrcv |
Semop |
Shmat shmdt |
The get system calls [4] ( msgget , semget , and shmget ) are used either to allocate a new IPC resource (which generates its associated system IPC structure) or gain access to an existing IPC. Each IPC has an owner and a creator, which under most circumstances are usually one and the same. When a new resource is allocated, the user must specify the access permissions for the IPC. Like the open system call, the get system calls return an integer value called an IPC identifier, which is analogous to a file descriptor. The IPC identifier is used to reference the IPC. From a system standpoint, the IPC identifier is an index into a system table containing IPC permission structure information. The IPC permission structure is defined in that is included by the header file . This structure is defined as
[4] The term get (in italics ) will be used to reference the group of system calls.
struct ipc_perm { __key_t __key; /* Key */ __uid_t uid; /* Owner's user ID. */ __gid_t gid; /* Owner's group ID. */ __uid_t cuid; /* Creator's user ID. */ __gid_t cgid; /* Creator's group ID. */ unsigned short int mode; /* Access permission. */ unsigned short int __pad1; unsigned short int __seq; /* Sequence number. */ unsigned short int __pad2; unsigned long int __unused1; unsigned long int __unused2; };
The type definitions for __uid_t , __gid_t , and so on can be found in the header file . In general, all programs that use the IPC facilities should include the and files. As will be explained in the discussion of ctl system calls, some members of the permission structure can be modified by the user.
There are two arguments common to each of the three get system calls. Each get system call takes an argument of defined type __key_t (of base type integer). This argument, known as the key value, is used by the get system call to generate the IPC identifier. There is a direct, one-to-one relationship between the IPC identifier returned by the get system call and the key value. While the key can be generated in an arbitrary manner, there is a library function called ftok that is commonly used to standardize key production. [5] By calling ftok with the same arguments, unrelated processes can be assured of producing the same key value and thus reference the same IPC resource. The ftok function is summarized in Table 6.3.
[5] In all honesty, the ftok library function is superfluous, but is presented for historical and continuity reasons. As long as processes that wish to access a common IPC resource have a method to communicate the key value for the IPC (such as in a common header file), ftok can be avoided.
Table 6.3. Summary of the ftok Library Function.
Include File(s) |
|
Manual Section |
3 |
||
Summary |
key_t ftok ( char *pathname, char proj ); |
||||
Return |
Success |
Failure |
Sets errno |
||
Returns a key_t value for IPC get system call |
-1 |
As in stat system call |
The ftok function takes two arguments. The first, path , is a reference to an existing accessible file. Often the value "." is used for this argument, since in most situations the self-referential directory entry "." is always present, accessible, and not likely to be subsequently deleted. The second argument for ftok , proj , is a single-character project identifier most commonly represented as a literal. The value returned by a successful call to ftok is of defined type key_t . ftok 's underlying algorithm, which uses data returned by the stat system call for the specified pathname as well as the proj argument value, does not guarantee a unique key value will be returned. If ftok fails, it returns a 1 and sets errno in a manner similar to the stat system call (the stat system call is discussed in Section 2.8, "File Information."
As demonstrated in Program 6.1, the most significant byte of the value returned by ftok is the character proj value, which is passed as the second argument.
Program 6.1 Generating some key values with ftok .
File : p6.1.cxx /* Using ftok to generate key values */ #include + #include #include using namespace std; int main( ){ 10 key_t key; for (char i = 'a'; i <= 'd'; ++i) { key = ftok(".", i); cout << "proj = " << i << " key = [" << hex << key << "] MSB = " << char(key >> 24) << endl; + } return 0; }
Figure 6.3 shows the output of Program 6.1 when run on a local 32-bit system.
Figure 6.3 Output of Program 6.1.
linux$ p6.1 proj = a key = [61153384] MSB = a <-- 1 proj = b key = [62153384] MSB = b proj = c key = [63153384] MSB = c proj = d key = [64153384] MSB = d
(1) The proj argument becomes the most significant byte of the value returned by ftok .
The key value for the get system calls may also be set to the defined constant IPC_PRIVATE. Beneath the covers, IPC_PRIVATE is defined as having a value of 0. Note that regardless of its argument values, the ftok library function will not return a value of 0. Specifying IPC_PRIVATE instructs the get system call to create an IPC resource with a unique IPC identifier. Thus, no other process creating or attempting to gain access to an IPC resource will receive this same IPC identifier.
An IPC resource created with IPC_PRIVATE is normally shared between related processes (such as parent/child or child/child) or in clientserver settings. In the related process settings, the parent process creates the IPC resource. When is performed, an exec , the associated IPC identifier is passed to the child process by way of the environment or as a command-line parameter. In clientserver relationships, the server process usually creates the IPC using IPC_PRIVATE. The IPC identifier is then made available to the client via a file. Note that in either scenario, the child/client process would not specify IPC_PRIVATE when issuing its get system call to gain access to the existing private resource. Finally, using IPC_PRIVATE does not prohibit other processes from gaining access to the resource; it only makes it a bit more difficult for a process to determine the identifier associated with the resource.
The second argument common to all of the IPC get system calls is the message flag. The message flag, an integer value, is used to set the access permissions when the IPC resource is created. The lower nine bits of the message flag argument define the access permissions. Table 6.4 summarizes the subsequent types of permissions required for each of the IPC system calls [6] to perform their functions. The execute bit is not relevant for IPC facilities.
[6] The header files for each of the IPC facilities (i.e., , , and ) contain defined constants for read/write (access) permissions for the facility. As noted previously, using defined constants does increase the portability of code. However, there is no free lunch , as the programmer must often take the time to look up the correct spelling of infrequently used defined constants.
Table 6.4. Required Permissions for IPC System Calls.
Permissions Required |
Message Queues |
Semaphores |
Shared Memory |
---|---|---|---|
write (alter) |
msgsnd place message in the queue |
semop increase or decrease a semaphore value |
shmat to write to the shared memory segment |
msgctl write out modified IPC status information |
semctl set the value of one semaphore or a whole set; write out modified IPC status information |
shmctl write out modified IPC status information |
|
read |
msgrcv obtain message from queue |
semop block until a semaphore becomes 0 |
shmat read from the shared memory segment |
msgctl to retrieve IPC status information |
semctl to retrieve IPC status information |
shmctl to retrieve IPC status information |
In addition to setting access modes, there are two defined constants, found in , that can be OR ed with the access permission value(s) to modify the actions taken when the IPC is created. The constant IPC_CREAT directs the get system call to create an IPC resource if one does not presently exist. When IPC_CREAT is specified, if the resource is already present and it was not created using IPC_PRIVATE, its IPC identifier is returned. In conjunction with IPC_CREAT, the creator may also specify IPC_EXCL. Using these two constants together (i.e., IPC_CREAT IPC_EXCL) causes the get system call to act in a no clobber manner. That is, should there already be an IPC present for the specified key value, the get system call will fail; otherwise , the resource is created. Using this technique, a process can be assured that it is the creator of the IPC resource and is not gaining access to a previously created IPC. In this context, specifying IPC_EXCL by itself has no meaning.
The ctl system calls ( msgctl , semctl , and shmctl ) act upon the information in the system IPC permission structure described previously. All of these system calls require an IPC identifier and an integer command value to stipulate their action. The values the command may take are represented by the following defined constants (found in the header file ):
- IPC_STAT Return the referenced IPC resource status information. When specifying IPC_STAT, the ctl system call must pass a pointer to an allocated structure of the appropriate type to store the returned information.
- IPC_SET Change the owner, group, or mode for the IPC resource. In addition, as with IPC_STAT, a pointer to a structure of the appropriate type (with the changed member information) must be passed.
- IPC_RMID Destroy the contents of the IPC resource and remove it from the system.
A process can specify IPC_SET or IPC_RMID only if it is the owner or creator of the IPC (or if it has superuser privileges). Some of the ctl system calls have additional functionality, which will be presented in later sections.
The remaining IPC system calls are used for IPC operations . The msgsnd and msgrcv calls are used to send and receive a message from a message queue. By default, the system blocks on an msgsnd if a message queue is full, or on an msgrcv if the message queue is empty. The process will remain blocked until the indicated operation is successful, a signal is received, or the IPC resource is removed. A process can specify to not block by OR ing in the IPC_NOWAIT flag with the specified operation flag. The semop system call performs a variety of operations on semaphores (such as setting and testing). Again, the default is to block when attempting to decrement a semaphore that is currently at 0 or if the process is waiting for a semaphore to become 0. The shmat and shmdt system calls are used with shared memory to map/attach and unmap/detach shared memory segments. These calls do not block.
For some reason known only to those who authored the documentation, the msgsnd and msgrcv manual pages (found in Section 2) contain a reference to msgop . However, there is no system call msgop . Likewise, the shmat and shmdt manual pages make reference to shmop , which also is not a system call. The manual page for semop only makes reference to semop (which is indeed a system call). One must only conclude that the initial intent was to group all of these calls under the general heading of IPC operations.
We address each set of IPC system calls in detail as we cover message queues, semaphores, and shared memory.