Interprocess Communication

   - A process is an instance of a program that is being executed by the OS.
   - In UNIX, the *only* way to create a process is with the fork()
     system call.
          -  The operating system creates the "init" process (that's
             PID 1).  The init process reads /etc/inittab to figure
             out what process to run next.
          -  Two important processes are "ttymon" that monitors terminals
             and "inetd" that starts networking programs.
   - Every process has a process ID (a PID) and a parent process ID
There are several ways that two prcessses can communicate:
    If the processes are on the same machine:
    1. A process can send a "signal" to another process (the OS can
       send a signal as well).
       - A signal is a notification to a process that an event has
       - Signals are "asynchronous".  That means a process does not know
         when they will occur.
       - Every signal has a signal number.
         Some examples:
             SIGINT   --  OS sends to a process when interrupt key is
                          hit (for example, control-C).
             SIGUSR1  --  User defined signal.
       - Every signal has a "default action".  For example, the kernel will
         send you a SIGSEGV if you access a bad memory location.  The default
         action for that is to dump core and exit.
       - You can change the default action.
       - For example:
            To send a signal:
            int kill(int pid, int signal_number)
            i.e.,  kill(1234, SIGUSR1);
            To handle a signal:
            void (*sigset (int sig, void (*disp)(int)))(int);
               void doit(int);
               sigset(SIGUSR1, doit);
       - More on this later.........
     2.  Process can use file and record locking
         - advisory and mandatory
         - applications use lockf() and fcntl().
     3.  Process can use "semaphore" files
         -  process A does an action, then creates file_1 when done.
         -  process B checks if file_1 exists
     4. Process can use pipes.
        - Example:
                int filedes[2];
                if (pipe(filedes) < 0) {
                   printf("can't create pipe\n");
         pipe() creates an I/O mechanism called a pipe and  returns
         two  file  descriptors,  fildes[0] and fildes[1].  The files
         associated with fildes[0] and fildes[1] are both  opened  for
         reading  and  writing.
         A read from fildes[0] accesses the data written to fildes[1]
         on  a  first-in-first-out  (FIFO)  basis  and  a  read  from
         fildes[1] accesses the data written to fildes[0] also  on  a
         FIFO basis.
         - General actions:
               - process creates a pipe;
               - fork;
               - parent closes filedes[0];
               - child closes filedes[1];
               - parent writes to filedes[1];
               - child reads from filedes[0];
     5. Process can use "Named Pipes"
        - A named pipes exists in the file system
                $ mknod /tmp/FIFO p
        - Process A can open and write;
        - Process B can open and read;
     6. Processes can use message queues, semaphores, and shared memory.
        - A message queue is memory in the kernel that lets
          process read and write to queues.
           - a process creates a message queue with the msgget() routine.
           - other processes can place data on the queue and extrace data from
             the queue by using msgsnd() and msgrcv().
        - A shared memory segment is common space in the kernel that
          several processes can read and write to.
           - use shmget() get create a shared memory segment, access
             it by mapping the memory to local variables with the
             shmat() routine.
           - semaphores allow synchronization.
    If the processes are on the different machines: