Inter-Process Communication

Modern POSIX-compliant operating systems provide several means of inter-process communication (IPC), among others:

Signals

On POSIX-compliant operating systems, signals are used to interrupt, terminate, or control running processes. A process can react to specific signals by implementing signal handlers. For example, an application may catch SIGINT to terminate when the user presses CTRL + C. Some signal numbers for FreeBSD are shown in table 1. See the FreeBSD man pages for a list of all signals.

Number Name Default Action Description
1 SIGHUP terminate process terminal line hang-up
2 SIGINT terminate process interrupt program
3 SIGQUIT create core image quit program
9 SIGKILL terminate process kill program
Table 1: Selection of signals on FreeBSD (source)

A signal handler is registered by calling the signal() routine. The signal number and the handler function must be passed as arguments:

! signal.f90
program main
    external :: sigint_handler

    call signal(2, sigint_handler)
    call sleep(30)
end program main

subroutine sigint_handler()
    print '(a)', 'Process interrupted (SIGINT), exiting ...'
end subroutine sigint_handler

Press CTRL + C to send SIGINT to the Fortran program.

Anonymous Pipes

Unix pipes allow processes to communicate with other processes without having been designed explicitly for this task. The input and output streams of processes can be chained together, providing a one-way flow of data.

Anonymous or unnamed pipes are a way of inter-process communication that let the output of one program to become the input of another. The output can be redirected by using the pipe symbol | on the command-line.

The following example program reads given degrees Fahrenheit from stdin and writes the converted degrees Celsius to stdout:

! f2c.f90
program f2c
    implicit none
    integer :: rc
    real    :: f

    do
        read (*, *, iostat=rc) f                    ! Read degrees Fahrenheit from stdin.
        if (rc /= 0) exit                           ! Exit on input error.
        print '(f0.2, " °C")', (f - 32) * 5 / 9     ! Write degrees Celsius to stdout.
    end do
end program f2c

After compilation, just pipe the value in degrees Fahrenheit to the Fortran program:

$ gfortran8 -Wl,-rpath=/usr/local/lib/gcc8/ -o f2c f2c.f90
$ echo "60.45" | ./f2c
15.81 °C

The < symbol allows to redirect the input to come from a file, while > writes the output to a file:

$ cat fahrenheit.txt
24.6
74.3
79.8
30.0
$ ./f2c < fahrenheit.txt
-4.11 °C
23.50 °C
26.56 °C
-1.11 °C
$ ./f2c < fahrenheit.txt > celsius.txt
$ cat celsius.txt
-4.11 °C
23.50 °C
26.56 °C
-1.11 °C

The output of a Fortran program can be piped to other applications as well, for instance, the current time:

! time.f90
program time
    implicit none
    integer :: values(8)

    call date_and_time(values=values)
    print '(i0, a, i0, a, i0, a, i0)', values(5), ":", &
                                       values(6), ":", &
                                       values(7), ":", &
                                       values(8)
end program time

Pipe the output of time to figlet:

$ gfortran8 -Wl,-rpath=/usr/local/lib/gcc8/ -o time time.f90
$ ./time | figlet -f mini
        _  _  _  _     _ __
/||_|_o|_ / \o_)|_ o/||_  /
 |  | o _)\_/o_) _)o ||_)/

Named Pipes

Another kind are named pipes, also knows as FIFO (“first in, first out”). The name of a named pipe is just a file name within the file system. They can be created with mkfifo, and removed with rm or unlink.

$ mkfifo ./pipe
$ echo "Hello, World!" > ./pipe

Another process can then read from the named pipe:

$ tail -f ./pipe
Hello, World!