Named pipes or UNIX FIFO special files are created with the mknod(2) system call; these special files allow any two processes to exchange information. The system call creates an inode for the named pipe and establishes it as a read/write named pipe. It can then be used by standard Fortran I/O or C I/O. Piped I/O is faster than normal I/O; it requires less memory than memory-resident files.
After a named pipe is created, Fortran programs can access that pipe almost as if it were a typical file; the differences between process communication using named pipes and process communication using normal files is discussed in the following list. The examples show how a Fortran program can use standard Fortran I/O on pipes.
/etc/mknod fort.13 p
A named pipe can be created from within a Fortran program by using ISHELL(3f) or by using the C language library interface to the mknod(2) system call; either of the following examples creates a named pipe:
CALL ISHELL('/etc/mknod fort.13 p')
I = MKNOD ('fort.13',010600B,0)
Fortran programs can communicate using two named pipes: one to read and one to write. A Fortran program must either read from or write to any named pipe, but it cannot do both at the same time. This is a Fortran restriction on pipes, not a system restriction. It occurs because Fortran does not allow read and write access at the same time.
I/O transfers through named pipes use memory for buffering. A separate buffer is created for each named pipe that is created. The PIPE_BUF parameter defines the kernel buffer size in the /sys/param.h parameter file. The default value of PIPE_BUF is 8 blocks (8 * 512 words), but the full size may not be needed or used. I/O to named pipes does not transfer to or from a disk. However, if I/O transfers fill the buffer, the writing process waits for the receiving process to read the data before refilling the buffer. If the size of the PIPE_BUF parameter is increased, I/O performance may decrease; there may be more I/O buffer contention. If memory has already been allocated for buffers, more space will not be allocated.
Binary data transferred between two processes through a named pipe must use the correct file structure. The undefined file structure (specified by assign -s u) should be specified for a pipe by the sending process. The unblocked structure (specified by assign -s unblocked) should be specified for a pipe by the receiving process.
The file structure for the pipe of the sending (write) process should be set to undefined (assign -s u), which issues a system call for each write. You can also select a file specification of system (assign -F system) for the sending process.
The file structure of the receiving or read process can be set to either the undefined or the unblocked file structure. However, if the sending process writes a request that is larger than MAXPIPE, it is essential for the receiving process to read the data from a pipe set to the unblocked file structure. A read of a transfer larger than MAXPIPE on an undefined file structure yields only MAXPIPE amount of data. The receiving process would not wait to see whether the sending process is refilling the buffer. The pipe may be less than MAXPIPE.
For example, the following assign commands specify that the file structure of the named pipe (unit 13, file name pipe) for the sending process should be undefined (-s u). The named pipe (unit 15, file name pipe) is type unblocked (-s unblocked) for the read process.
assign -s u -a pipe u:13 assign -s unblocked -a pipe u:15
A read from a pipe that is closed by the sender causes a detection of end-of-file (EOF).
In this example, two Fortran programs communicate without end-of-file (EOF) detection. In the example, program writerd generates an array that contains the elements 1 to 3 and writes the array to named pipe pipe1. Program readwt reads the three elements from named pipe pipe1, prints out the values, adds 1 to each value, and writes the new elements to named pipe pipe2. Program writerd reads the new values from named pipe pipe2 and prints them. The -a option of the assign(1) command allows the two processes to access the same file with different assign characteristics.
program writerd parameter(n=3) dimension ia(n) do 10 i=1,n ia(i)=i 10 continue write (10) ia read (11) ia do 20 i=1,n print*,'ia(',i,') is ',ia(i),' in writerd' 20 continue end
program readwt parameter(n=3) dimension ia(n) read (15) ia do 10 i=1,n print*,'ia(',i,') is ',ia(i),' in readwt' ia(i)=ia(i)+110 continue write (16) ia end
The following commands execute the programs:
f90 -o readwt readwt.f f90 -o writerd writerd.f /etc/mknod pipe1 p /etc/mknod pipe2 p assign -s u -a pipe1 u:10 assign -s unblocked -a pipe2 u:11 assign -s unblocked -a pipe1 u:15 assign -s u -a pipe2 u:16 readwt & writerd
The following is the output of the two programs:
ia(1) is 1 in readwt ia(2) is 2 in readwt ia(3) is 3 in readwt ia(1) is 2 in writerd ia(2) is 3 in writerd ia(3) is 4 in writerd
The following conditions must be met to detect end-of-file on a read from a named pipe within a Fortran program: the program that sends data must open the pipe in a specific way, and the program that receives the data must open the pipe as read-only.
The program that sends or writes the data must open the named pipe as read and write or write-only. This is the default because the /etc/mknod command creates a named pipe with read and write permission.
The program that receives or reads the data must open the pipe as read-only. A read from a named pipe that is opened as read and write waits indefinitely for the data. Use the ACTION=READ specifier on the OPEN statement to open a file as read-only.
This example uses named pipes for communication between two Fortran programs with end-of-file detection. The programs in this example are similar to the programs used in the preceding section. This example shows that program readwt can detect the EOF.
Program writerd generates array ia and writes the data to the named pipe pipe1. Program readwt reads the data from the named pipe pipe1, prints the values, adds one to each value, and writes the new elements to named pipe pipe2. Program writerd reads the new values from pipe2 and prints them. Finally, program writerd closes pipe1 and causes program readwt to detect the EOF.
The following commands execute these programs:
f90 -o readwt readwt.f f90 -o writerd writerd.f assign -s u -a pipe1 u:10 assign -s unblocked -a pipe2 u:11 assign -s unblocked -a pipe1 u:15 assign -s u -a pipe2 u:16 /etc/mknod pipe1 p /etc/mknod pipe2 p readwt & writerd
program writerd parameter(n=3) dimension ia(n) do 10 i=1,n ia(i)=i 10 continue write (10) ia read (11) ia do 20 i=1,n print*,'ia(',i,') is',ia(i),' in writerd' 20 continue close (10) end
program readwt parameter(n=3) dimension ia(n) C open the pipe as read-only open(15,form='unformatted', action='read') read (15,end = 101) ia do 10 i=1,n print*,'ia(',i,') is ',ia(i),' in readwt' ia(i)=ia(i)+1 10 continue write (16) ia read (15,end = 101) ia goto 102 101 print *,'End of file detected' 102 continue end
The output of the two programs is as follows:
ia(1) is 1 in readwt ia(2) is 2 in readwt ia(3) is 3 in readwt ia(1) is 2 in writerd ia(2) is 3 in writerd ia(3) is 4 in writerd End of file detected