## 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

- A FIFO is created with the mknod() system call.

           int mknod(char *pathname,int mode,int dev)

  - pathname is a Unix pathname
  - mode specifies the access mode (permissions)
  - dev is ignored (mknod is used for other things)
- A FIFO can also be created with mkfifo() system call (POSIX).

## 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

- By default, an open() call to a FIFO will block.
- The order of open() calls is important !!!
- Can avoid some problems with O_NONBLOCK option to open():

            fd = open(path, O_NONBLOCK | O_RDONLY);