Chapter 2. Interprocess Communication

The term interprocess communication (IPC) describes any method of coordinating the actions of multiple processes, or sending data from one process to another. IPC is commonly used to allow processes to coordinate the use of shared data objects; for instance, to let two programs update the same data in memory without interfering with each other, or to make data acquired by one process available to others.

This chapter provides an overview of the IPC implementations available, including:

The following chapters in this Part provide details, as follows:

Types of Interprocess Communication Available

IRIX is compatible with a broad variety of IPC mechanisms. IRIX conforms to the POSIX standards for real-time extensions (IEEE standard 1003.1b) and threads (IEEE 1003.1c). Other IPC features are compatible with the two major schools of UNIX programming: BSD UNIX and AT&T System V Release 4 (SVR4) UNIX.

Table 2-1 summarizes the types of IPC that IRIX supports, and lists the systems with which IRIX is compatible.

Table 2-1. Types of IPC and Compatibility

Type of IPC

Purpose

Compatibility

Signals

A means of receiving notice of a software or hardware event, asynchronously.

POSIX, SVR4, BSD

Shared memory

A way to create a segment of memory that is mapped into the address space of two or more processes, each of which can access and alter the memory contents.

POSIX, IRIX, SVR4

Semaphores

Software objects used to coordinate access to countable resources.

POSIX, IRIX, SVR4

Locks, Mutexes, and Condition Variables

Software objects used to ensure exclusive use of single resources or code sequences.

POSIX, IRIX

Barriers

Software objects used to ensure that all processes in a group are ready before any of them proceed.

IRIX

Message Queues

Software objects used to exchange an ordered sequence of messages.

POSIX, SVR4

File Locks

A means of gaining exclusive use of all or part of a file.

SVR4, BSD

Sockets

Virtual data connections between processes that may be in different systems.

BSD

The different implementations of these IPC features can be summarized as follows:

  • POSIX compliant library calls are provided for signal handling, shared memory, semaphores, mutexes, condition variables, and message queues. The implementation is highly tuned and has low system overhead. POSIX facilities are usable from POSIX threads (see Chapter 13, “Thread-Level Parallelism”).

  • IRIX unique library calls are provided for shared memory, semaphores, locks, and barriers. The implementation has slightly more overhead than POSIX operations, but sometimes takes advantage of concurrent hardware in multiprocessors, and has a number of special features, such as the ability to apply poll() to semaphores.

  • System function calls compatible with AT&T System V Release 4 are provided for signal handling, shared memory, semaphores, message queues, and file locking. The implementation is provided for ease of porting software, but is not particularly efficient.

  • Library functions compatible with BSD UNIX are provided for signal handling, file locking, and socket support.

Select your IPC mechanisms based on these guidelines:

  • Never mix the implementations of a given mechanism in a single program. For example, unpredictable results can follow when a single program mixes POSIX and System V signal-handling functions, or mixes both BSD and System V file locking calls.

  • The POSIX libraries are the newest implementations, and in many cases they are the most efficient.

  • A program based on POSIX threads should use POSIX synchronization mechanisms because they are optimized for pthreads use.

  • Use System V IPC functions for code that must comply with the MIPS ABI, or code that you are porting from another System V operating system.

Using POSIX IPC

In order to use the POSIX IPC functions described in this part of the book, you must include the correct header files and libraries when compiling.

The header files required for each function are listed in the reference pages for the functions (you will find clickable links to reference pages in the following chapters).

POSIX IPC functions are defined in the standard libc library. That library is included automatically in any link by the cc command.

POSIX IPC Name Space

POSIX shared memory segments, named semaphores, and message queues are persistent objects that survive the termination of the program that creates them (unless the program explicitly removes them). The POSIX standard specifies that these persistent names can be implemented in the filesystem, and the current IRIX implementation does use filenames in the filesystem to represent IPC objects. In order to access a named semaphore or message queue, a program opens the object using a pathname, similar to the way a program opens a disk file.

Because these persistent objects are currently implemented as files, you can display and access them using IRIX commands for files such as ls, rm, chmod and chown. However, you should keep in mind that this is an implementation choice, not a standardized behavior. Other implementations of POSIX IPC may not use the filesystem as a name space for IPC objects, and the IRIX implementation is free to change its implementation in the future. For best portability, do not assume that IPC objects are always files.

If you plan to share an object between processes that could be started from different working directories, you should always open the object using the full pathname starting with a slash (“/”). That ensures that unrelated processes always refer to the same object, regardless of their current working directory.

When a shared object is temporary, you can use the tempnam() library function to generate a temporary pathname (see the tempnam(3) reference page).

Other POSIX IPC objects—nameless semaphores, mutexes, and condition variables—are not persistent, but exist only in memory and are identified only by their addresses. They disappear when the programs that use them terminate.

Using IRIX IPC

The IRIX IPC facilities are designed to meet the demands of parallel programming in multiprocessor systems. They offer advantages for this use, but they are IRIX specific, so programs using them are not portable to other systems.

In order to use any IRIX IPC functions, you need to include the correct header files and link libraries when compiling. The header files required for each function are listed in the reference pages for the functions (you will find clickable links to reference pages in the following chapters).

IRIX IPC functions are defined in the standard libc library (it is included automatically in any link by the cc command) and in the libmpc library, which you include with -lmpc.

IRIX IPC functions all require the use of a shared arena, a segment of memory that can be mapped into the address spaces of multiple processes. The first step in preparing to use any IRIX IPC object is to create a shared arena, as documented under “Initializing Arena Attributes”.

A shared arena is identified with a file that acts as the backing store for the arena memory. Communicating processes gain access to the arena by specifying its filename. All processes using the same arena have access to the same set of IPC objects. This makes it relatively easy for unrelated processes to communicate using IRIX IPC; they only have to know the filename of the arena to gain access.

Using System V IPC

IRIX supports SVR4 functions for signals, shared memory, semaphores, message queues, and file locking. To use them you need to include the correct header files when compiling. The header files required for each function are listed in the reference pages for the functions (you will find clickable links to reference pages in the following chapters).

System V functions are primarily kernel functions. No special library linkage is required to access them. There is general discussion of SVR4 IPC operations in the intro(2) reference page.

SVR4 IPC Name Space

All SVR4 IPC objects are named in a special IPC name space. An object such as a shared memory segment or message queue is named by a numeric key, and has the following attributes (which are defined in the header file sys/ipc.h):

  • the UID and GID of the creating process

  • the UID and GID of the owning process (which can be different from the creator)

  • access permissions in the same format as used with files

The commands and functions used to manage the IPC name space are listed in Table 2-2.

Table 2-2. SVR4 IPC Name Space Management

Function Name

Purpose and Operation

ipcs(1)

List existing shared memory segments (and other IPC objects) in the system name space with their status.

ipcrm(1)

Remove a shared memory segment (or other IPC object) from the system name space.

ftok(3)

Create a semi-unique numeric key based on a file pathname.


Configuring the IPC Name Space

SVR4 IPC objects are stored in kernel tables of limited, fixed size. You configure the size of these tables by changing kernel tunable parameters. These parameters are documented in detail in the book IRIX Admin: System Configuration and Operation (007-2859-nnn). See “Appendix A: IRIX Kernel Tunable Parameters.”

Listing and Removing Persistent Objects

Objects in the IPC name space are created by programs and can be removed by programs. However, IPC objects by definition are used by multiple processes, and it is sometimes a problem to determine which process should remove an object, and when it is safe to do so.

For this reason, IPC objects are often created and never removed. In these cases, they persist until the system is rebooted, or until they are removed manually.

You can list all the components of the IPC name space using the ipcs command. You can remove an object with the ipcrm command. If you remove an object that is in use, unpredictable results will follow.

Access Permissions

IPC objects are not part of any filesystem, but access to IPC objects is controlled by rules like the rules that govern file access. For example, if the access permissions of a shared memory segment are set to 640, the segment can be read-write for processes that have the same UID as the segment owner, but the segment is read-only to processes that have only the GID of the owner, and is inaccessible to other processes.

Choosing and Communicating Key Values

The “name” of an IPC object is an integer. Two small problems are: how a program can select a unique key to use when making an IPC object, and how to communicate the key to all the processes that need access to the object. The ftok() library function can be used to create a predictable key based on a file pathname. For example, unrelated but cooperating programs can agree to use ftok() with a designated project file and project code, so that each program will arrive at the same key.

Using ID Numbers

When an IPC object is created, it has the key it is given by the creating process, but it is also assigned a second integer, the ID. The key number is chosen by the application, and is predictable. If the application creates the object each time the application starts up, the key is always the same. The ID number is arbitrary, and a new ID is created each time an object is created.

A process can gain access to an object based on either number, the key or the ID. For example, an SVR4 shared memory segment has a key and an ID. The shmget() function takes a key and returns the corresponding ID. The ID is used to attach the segment. However, if a process knows the ID, it can simply use it, without first calling shmget() to obtain it.

Private Key Values

When creating an IPC object, you can specify a key of KEY_PRIVATE (0). This causes an object to be created and recorded in the IPC name space with a key of 0. The created object cannot be accessed from another process by key, because if another process uses KEY_PRIVATE, it creates its own object. However, another process can access a key-private object using the object's ID number.

You can use the KEY_PRIVATE feature when you want to create an IPC object for use within a single process or share group (a share group is the set of processes that share one address space; see “Process Creation and Share Groups”). The IPC object can be used within the share group based on its address or by ID number. Because it has no key, it cannot be used outside the share group.

Using 4.2 BSD IPC

The 4.2 BSD functions for signals and file locking are available. To use them, you must include the correct header files and link libraries when compiling. The header files required for each function are listed in the reference pages for the functions (you will find clickable links to reference pages in the following chapters).

One header file, signal.h, declares both SVR4 and BSD signal-handling functions. Some of the BSD and SVR4 functions have the same names, but different types of arguments or different results when called. In order to declare the BSD family of signal functions in your program, you must be sure to define the compiler variable _BSD_SIGNALS or _BSD_COMPAT to the compiler. You could do this directly in the source code. More often you will manage compilation with make, and you will include -D_BSD_SIGNALS as one of the compiler options in the Makefile.

The BSD compatible function for file locking, flock(), is defined in the standard libc library. That library is included automatically in any link by the cc command. However, when you are using C++ (not C), the function name “flock” conflicts with a structure name declared in sys/fcntl.h. In order to define the flock() function and not the structure, define the compiler variable _BSD_COMPAT.

A BSD-compatible kernel function for managing the termination of child processes, wait3(), is discussed under “Process “Reaping””.