Chapter 5. System and C I/O

This chapter describes systems calls used by the I/O library to perform asynchronous or synchronous I/O. This chapter also describes Fortran callable entry points to several C library routines and describes C I/O on UNICOS/mk systems.

System I/O

The I/O library and programs use the system calls described in this chapter to perform synchronous and asynchronous I/O, to queue a list of distinct I/O requests, and to perform unbuffered I/O without system buffering. For more information about the system calls described in this chapter, see the Cray document, UNICOS System Calls Reference Manual or the individual man pages.

Synchronous I/O

With synchronous I/O, an executing program relinquishes control during the I/O operation until the operation is complete. An operation is not complete until all data is moved.

The read(2) and write(2) system calls perform synchronous reads and writes. The READ(3f) and WRITE(3f) functions provide a Fortran interface to the read and write system calls. The read system call reads a specified number of bytes from a file into a specified buffer. The write system call writes from a buffer to a file.

Asynchronous I/O

Asynchronous I/O lets the program use the time that an I/O operation is in progress to perform some other operations that do not involve the data in the I/O operation. In asynchronous I/O operations, control is returned to the calling program after the I/O is initiated. The program may perform calculations unrelated to the previous I/O request or it may issue another unrelated I/O request while waiting for the first I/O request to complete.

The asynchronous I/O routines provide functions that let a program wait for a particular I/O request to complete. The asynchronous form of BUFFER IN and BUFFER OUT statements used with UNIT(blank) and LENGTH(blank) routines provide this type of I/O.

On UNICOS and UNICOS/mk systems, the READA(3f) and WRITEA(3f) functions provide a Fortran interface to the reada(2) and writea(2) system calls. The reada system call reads a specified number of bytes from a file into a specified buffer. The system call returns immediately, even if the data cannot be delivered until later. The writea system call writes from a buffer to a file as specified.

listio I/O (Not Available on IRIX systems)

Use the listio(2) system call to initiate a list of distinct I/O requests and, optionally, wait for all of them to complete. No subroutine or function interface to listio exists in Fortran. The AQIO package provides an indirect Fortran interface to listio.

Unbuffered I/O

The open(2) system call opens a file for reading or writing. If the I/O request is well-formed and the O_RAW flag is set, the read(3f) or write(3f) system call reads or writes whole blocks of data directly into user space, bypassing system cache. On UNICOS and UNICOS/mk systems, doing asynchronous system buffered I/O (for example, not using O_RAW) can cause performance problems because system caching can cause performance problems.

C I/O

This section describes C library I/O from Fortran, and describes C library I/O on CRAY T3E systems.

C I/O from Fortran

The C library provides a set of routines that constitute a user-level I/O buffering scheme to be used by C programmers. UNICOS and UNICOS/mk systems also provide Fortran callable entry points to many of these routines. For more information about the C library functions, see the Cray document, UNICOS System Libraries Reference Manual.

The getc(3c) and putc(3c) inline macros process characters. The getchar and putchar macros, and the higher-level routines fgetc, fgets, fprintf, fputc, fputs, fread, fscanf, fwrite, gets, getw, printf, puts, putw, and scanf all use or act as if they use getc and putc. They can be intermixed.

A file with this associated buffering is called a streams and is associated with a pointer to a defined type FILE. The fopen(3c) routine creates descriptive data for a stream and returns a pointer to designate the stream in all further transactions. Three open streams with constant pointers are usually declared in the <stdio.h> header file and are associated with stdin, stdout, and stderr.

Three types of buffering are available with functions that use the FILE type: unbuffered, fully buffered, and line buffered, as described in the following list:

  • If the stream is unbuffered, no library buffer is used.

  • For a fully buffered stream, data is written from the library buffer when it is filled, and read into the library buffer when it is empty.

  • If the stream is line buffered, the buffer is flushed when a new line character is written, the buffer is full, or when input is requested.

The setbuf(blank) and setvbuf(blank) functions let you change the type and size of the buffers. By default, output to a terminal is line buffered, output to stderr is unbuffered, and all other I/O is fully buffered. See the setbuf(3c) man page for details.

On UNICOS and UNICOS/mk systems, Fortran interfaces exist for the following C routines that use the FILE type:

FCLOSE(blank)FREAD(blank)
FDOPEN(blank)FREOPEN(blank)
FGETS(blank)FSEEK(blank)
FILENO(blank)FWRITE(blank)
FOPEN(blank)
FPUTS(blank) 

Mixing the use of C I/O functions with Fortran I/O on the same file may have unexpected results. If you want to do this, ensure that the Fortran file structure chosen does not introduce unexpected control words and that library buffers are flushed properly before switching between types of I/O.

The following example illustrates the use of some C routines. The assign environment does not affect these routines.

Example 5-1. C I/O from Fortran

       PROGRAM STDIOEX
       INTEGER FOPEN, FCLOSE, FWRITE, FSEEK
       INTEGER FREAD, STRM
       CHARACTER*25 BUFWR, BUFRD
       PARAMETER(NCHAR=25)
C      Open the file /tmp/mydir/myfile for update
       STRM = FOPEN('/tmp/mydir/myfile','r+')
       IF (STRM.EQ.0) THEN
          STOP 'ERROR OPENING THE FILE'
       ENDIF
C      Write
       I = FWRITE(BUFWR, 1, NCHAR, STRM)
       IF (I.NE.NCHAR*1)THEN
          STOP 'ERROR WRITING FILE'
       ENDIF
C      Rewind and read the data
       I = FSEEK(STRM, 0, 0)
       IF (I.NE.0)THEN
          STOP 'ERROR REWINDING FILE'
       ENDIF
       I = FREAD(BUFRD, 1, NCHAR, STRM)
       IF (I.NE.NCHAR*1)THEN
          STOP 'ERROR READING FILE'
       ENDIF
C      Close the file
       I = FCLOSE(STRM)
       IF (I.NE.0) THEN
          STOP 'ERROR CLOSING THE FILE'
       ENDIF
       END


C I/O on CRAY T3E Systems

When using system calls on CRAY T3E systems, if more than one processing element (PE) opens the same file with an open(2) system call, distinct file descriptors are returned. If each PE uses its file descriptor to perform a read operation on the file, each PE reads the entire file.

If each PE uses its file descriptor to perform a write operation to the file, the results are unpredictable.

When a program opens a stream with fopen(), a pointer to the stdio.h file structure associated with the stream is returned. This stream pointer points to a structure contained in local memory on a PE; therefore, the stream pointer may not be used from another PE. If a stream is buffered, its buffer is contained in local memory to the PE that opened it, and it is unknown to other PEs.

At program startup, each PE has an open stdio stream pointer for stdin, stdout, and stderr; stderr is usually not fully buffered and stdin and stdout are fully buffered only if they do not refer to an interactive device. Buffers associated with stdin, stdout, and stderr are local to a PE.

Results are unpredictable if stdin is buffered and more than one PE attempts to read from it and if stdout is buffered and more than one PE attempts to write to it. The file descriptor for any of these streams is shared across all PEs; therefore, applying an fclose () operation to stdin, stdout, or stderr on any PE closes that stream on all PEs.

When a program opens a file for flexible file input/output (FFIO) with ffopen(3c) or ffopens(3c), the library associates a structure local to the PE that contains descriptive data with the value returned to the user. Therefore, the value returned by ffopen may not be used from another PE. The FFIO processing layers may also contain buffering that is local to the PE. Attempting to perform an ffopen operation and do I/O to the same file from more than one PE may produce unpredictable results.