Interprocess Communication
This chapter is for programmers who develop multiprocess applications.
SunOS 5.9 and compatible operating environments have a large variety of mechanisms for concurrent processes to exchange data and synchronize execution. All of these mechanisms, except mapped memory, are introduced in this chapter.
Pipes (anonymous data queues) are described in "Pipes Between Processes".
Named pipes (data queues with file names.) "Named Pipes" covers named pipes.
System V message queues, semaphores, and shared memory are described in "System V IPC".
POSIX message queues, semaphores, and shared memory are described in "POSIX Interprocess Communication".
"Sockets" describes interprocess communication using sockets.
Mapped memory and files are described in "Memory Management Interfaces".
Pipes Between Processes
A pipe between two processes is a pair of files that is created in a parent process. The pipe connects the resulting processes when the parent process forks. A pipe has no existence in any file name space, so it is said to be anonymous. A pipe usually connects only two processes, although any number of child processes can be connected to each other and their related parent by a single pipe.
A pipe is created in the process that becomes the parent by a call to pipe(2). The call returns two file descriptors in the array passed to it. After forking, both processes read from p[0] and write to p[1]. The processes actually read from and write to a circular buffer that is managed for them.
Because calling fork(2) duplicates the per-process open file table, each process has two readers and two writers. Closing the extra readers and writers enables the proper functioning of the pipe. For example, no end-of-file indication would ever be returned if the other end of a reader is left open for writing by the same process. The following code shows pipe creation, a fork, and clearing the duplicate pipe ends.
#include <stdio.h> #include <unistd.h> ... int p[2]; ... if (pipe(p) == -1) exit(1); switch( fork() ) { case 0: /* in child */ close( p[0] ); dup2( p[1], 1); close P[1] ); exec( ... ); exit(1); default: /* in parent */ close( p[1] ); dup2( P[0], 0 ); close( p[0] ); break; } ... |
The following table shows the results of reads from a pipe and writes to a pipe, under certain conditions.
Table 5-1 Read/Write Results in a Pipe
Attempt | Conditions | Result |
---|---|---|
read | Empty pipe, writer attached | Read blocked |
write | Full pipe, reader attached | Write blocked |
read | Empty pipe, no writer attached | EOF returned |
write | No reader | SIGPIPE |
Blocking can be prevented by calling fcntl(2) on the descriptor to set FNDELAY. This causes an error return (-1) from the I/O call with errno set to EWOULDBLOCK.
Named Pipes
Named pipes function much like pipes, but are created as named entities in a file system. This enables the pipe to be opened by all processes with no requirement that they be related by forking. A named pipe is created by a call to mknod(2). Any process with appropriate permission can then read or write to a named pipe.
In the open(2) call, the process opening the pipe blocks until another process also opens the pipe.
To open a named pipe without blocking, the open(2) call joins the O_NDELAY mask (found in sys/fcntl.h) with the selected file mode mask using the Boolean or operation on the call to open(2). If no other process is connected to the pipe when open(2) is called, -1 is returned with errno set to EWOULDBLOCK.
Sockets
Sockets provide point-to-point, two-way communication between two processes. Sockets are a basic component of interprocess and intersystem communication. A socket is an endpoint of communication to which a name can be bound. It has a type and one or more associated processes.
Sockets exist in communication domains. A socket domain is an abstraction that provides an addressing structure and a set of protocols. Sockets connect only with sockets in the same domain. Twenty three socket domains are identified (see sys/socket.h), of which only the UNIX and Internet domains are normally used in Solaris 9 and compatible operating environments.
You can use sockets to communicate between processes on a single system, like other forms of IPC. The UNIX domain (AF_UNIX) provides a socket address space on a single system. UNIX domain sockets are named with UNIX paths. UNIX domain sockets are further described in "UNIX Domain Sockets" in Network Interface Guide. Sockets can also be used to communicate between processes on different systems. The socket address space between connected systems is called the Internet domain (AF_INET). Internet domain communication uses the TCP/IP internet protocol suite. Internet domain sockets are described in "Socket Interfaces" in Network Interface Guide.
POSIX Interprocess Communication
POSIX interprocess communication (IPC) is a variation of System V interprocess communication. It was introduced in the Solaris 7 release. Like System V objects, POSIX IPC objects have read and write, but not execute, permissions for the owner, the owner's group, and for others. There is no way for the owner of a POSIX IPC object to assign a different owner. POSIX IPC includes the following features:
Messages allow processes to send formatted data streams to arbitrary processes.
Semaphores allow processes to synchronize execution.
Shared memory allows processes to share parts of their virtual address space.
Unlike the System V IPC interfaces, the POSIX IPC interfaces are all multithread safe.
POSIX Messages
The POSIX message queue interfaces are listed in the following table.
Table 5-2 POSIX Message Queue Interfaces
Interface Name | Purpose |
---|---|
mq_open(3RT) | Connects to, and optionally creates, a named message queue |
mq_close(3RT) | Ends the connection to an open message queue |
mq_unlink(3RT) | Ends the connection to an open message queue and causes the queue to be removed when the last process closes it |
mq_send(3RT) | Places a message in the queue |
mq_receive(3RT) | Receives (removes) the oldest, highest priority message from the queue |
mq_notify(3RT) | Notifies a process or thread that a message is available in the queue |
mq_setattr(3RT), mq_getattr(3RT) | Set or get message queue attributes |
POSIX Semaphores
POSIX semaphores are much lighter weight than are System V semaphores. A POSIX semaphore structure defines a single semaphore, not an array of up to 25 semaphores.
The POSIX semaphore interfaces are shown below.
Table 5-3 POSIX Semaphore Interfaces
sem_open(3RT) | Connects to, and optionally creates, a named semaphore |
sem_init(3RT) | Initializes a semaphore structure (internal to the calling program, so not a named semaphore) |
sem_close(3RT) | Ends the connection to an open semaphore |
sem_unlink(3RT) | Ends the connection to an open semaphore and causes the semaphore to be removed when the last process closes it |
sem_destroy(3RT) | Initializes a semaphore structure (internal to the calling program, so not a named semaphore) |
sem_getvalue(3RT) | Copies the value of the semaphore into the specified integer |
sem_wait(3RT), sem_trywait(3RT) | Blocks while the semaphore is held by other processes or returns an error if the semaphore is held by another process |
sem_post(3RT) | Increments the count of the semaphore |