Interprocess Communication
- Networking involves communication between processes.
- Not all interprocess communication involves networking.
- Typically, IPC services are provided by the Operating System.
IPC - Single System
IPC - Different Systems
Single System IPC
- Pipe: one-way data stream
- FIFO: special kind of pipe
- Message Queue: message passing (not a data stream)
- Semaphores: Synchronization primitive
- Shared Memory: data does not go through the kernel (Operating System).
File Locking
- Allows cooperating processes to share a resource safely (mutual
exclusion).
- Example:
- integer count kept in a file
- the count is updated by a program every time some event occurs
- without file locking the value can be corrupted.
Advisory vs. Mandatory Locking
- Advisory - operating system keeps track of file locks but does not
enforce access restrictions. Requires cooperating processes.
- Mandatory - operating system checks every read and write, withholding services when appropriate.
Record Locking
- Lock part of a file, in Unix this typically means a range of character positions within the file.
- Multiple processes can use the same file at the same time as long as they are working on different parts of the file.
lockf() sytem call (Sys V)
- Single system call for all file locking services:
- lock a region of a file
- unlock a region of a file
- test and lock a region (non-blocking)
- test to see if a region is locked
Blocking vs. Non-Blocking System Calls
- A blocking system call does not return until the requested operation is possible (or an error occurs). The calling process is put to sleep until the operation is possible.
- A non-Blocking - system call returns if the operation is not possible immediately. There must be some way for the calling process to determine what happened !
Back to lockf()
int lockf( int fd, int function, long size)
fd is a file descriptor (small integer)
function can be:
- F_ULOCK unlock a region
- F_LOCK lock a region (blocking)
- F_TLOCK lock a region (non-blocking)
- F_TEST test a region
lockf() example
/* lock a file */
if ( lockf(file, F_LOCK, 0) ==1 )
/* error can't lock the file */
/* unlock a file */
if ( lockf(file, F_ULOCK, 0) ==1 )
/* error can't unlock the file */
POSIX file locking
- POSIX supports advisory file locking.
- All file locking services provided via the fcntl() system call.
- Additional services (beyond lockf):
- shared locks (read locks)
- can find out what process has a lock (pid)
Pipes
- One-way stream of data
- Kernel buffers the data
pipe() system call
int pipe( int filedes[2])
- filedes is a 2 element array of file descriptors - pipe fills in the
values.
- return value is less than 0 if an error occurred.
pipe()
pipe() followed by fork()
Cleanup with close()
2-way communication
- Need 2 pipes to support 2-way communication between parent process and child process.
- Both pipes must be created before the fork()
Creating 2-way communication
int fd_a[2], fd_b[2];
if ( (pipe(fd_a) < 0) || (pipe(fd_b) < 0) )
/* error opening pipes */
if (fork()==0){
/* child process */
close(fd_a[0]); close(fd_b[1]);
/* write to parent via fd_a[1], read from fd_b[0] */
} else {
/* parent process */
close(fd_a[1]); close(fd_b[0]);
/* write to child via fd_b[1], read from fd_a[0] */
}
2-way communication
IPC using pipes
- Processes must be closely related (must have a common ancestor).
- Unix shells use pipes extensively to pass the output of one process as input to another process.
- ls | sort | more
FIFOs - First In, First Out
- Also known as Named Pipe
- Data stream buffered by the kernel
- A FIFO has a name associated with it - this makes IPC between independent processes possible.
- The name is a Unix pathname.
mknod() system call
opening a FIFO
- the open() system call is used to open a FIFO for reading or writing.
- opening a FIFO for reading will block until a process opens the FIFO for writing.
- opening a FIFO for writing will block until a process opens the FIFO for reading.
- Use the O_NDELAY flag when opening a FIFO to avoid the problem (O_NONBLOCK for POSIX).
Rules for reading FIFOs & Pipes
- any read() requesting more data than exists in the FIFO (pipe)
returns less than the requested amount of data.
- read from empty FIFO (pipe) returns:
- . 0 if no process has the FIFO (pipe) open for writing End-of-File condition.
- . If non-blocking mode is set read() returns a 0 whenever there is no data available.
Rules for writing FIFOs & Pipes
- writes of less than the capacity of the FIFO (pipe) are atomic.
- a write to a FIFO or pipe wich is not open for reading by any process generate a SIGPIPE and write() returns an error.
- a write to a full FIFO or pipe will block (unless non-blocking mode).
Streams vs. Messages
- Stream I/O
- no record boundaries
- reading process cannot tell how bytes were written (how many bytes at a time).
- O.S. does buffering
- Any structure to the data must be supported by the application
Streams vs. Messages
- Message based I/O:
- structured data
- each read corresponds to a write
- depending on the message service, the order of messages may not be preserved.
System V IPC
- The book describes Sys V message queues, semaphores and
shared memory.
- We won't cover this material
- Could be a case study:
- Review Sys V IPC programming interface
- describe how it could be done with a network.
FIFO Example
- Client - Server architecture
- Need 2 FIFOs for 2-way communication
- Server accessible via well known address (FIFO pathname).
- Client creates FIFO and sends server the name.
FIFO Example
Server
opens well known FIFO (fifo_wk) for reading.
reads name of temporary FIFO (fifo_tmp) from fifo_wk.
opens fifo_tmp for writing.
receives request from fifo_wk and sends response to fifo_tmp.
close fifo_tmp and go back to step 1.
Client
create temporary FIFO fifo_tmp.
open well known FIFO fifo_wk for writing.
write name of temporary FIFO to fifo_wk.
open fifo_tmp for reading.
write request to fifo_wk
read response from fifo_tmp.
close FIFOs and delete fifo_tmp.
Deadlock
Homework #1
- Develop a FIFO based talk program.
- Once the client and server have established communication via
FIFOs, anything typed in to the client process is sent to the
server and vice-versa.
- It is required that you need to be able to run at least 2
sessions on the same computer at the same time (you must avoid FIFO
name collisions).
Homework #1 Suggestions
- Server uses a well known FIFO that is specified on the
server command line.
- Client generates a unique FIFO name based on the PID of the
client and sends this name to the server via the well known
FIFO.
- Use the code in the book as a starting point
Homework #1 Multiplexed I/O
- You will need to figure out how to look for input from 2 sources
at the same time:
- from the user keyboard (STDIN)
- from a FIFO
- The Wrong Way:
- use nonblocking I/O to check each source until some input
is found. This results in "busy waiting".
- The Right Way:
- use a system call that handles the multiplexing for you.
-
select()
is described in the book.
-
poll()
is available on many versions of Unix.