Your Browser is not longer supported

Please use Google Chrome, Mozilla Firefox or Microsoft Edge to view the page correctly
Loading...

{{viewport.spaceProperty.prod}}

Interaction of file descriptors and streams

&pagelevel(4)&pagelevel

An open file description may be accessed through a file descriptor that is created by open() or pipe() or through a stream created by the fopen() or popen() functions. A file descriptor or a stream is called a handle on (or a link to) the open file description to which it refers; an open file description may have several handles.

Handles can be created or destroyed by explicit user action, without affecting the underlying open file description. Some of the functions to create them include fcntl(), dup(), fdopen(), fileno() and fork(). The handles can be destroyed by at least fclose(), close() and the exec functions.

A file descriptor that is never used in an operation that could affect the file offset (for example, read(), write() or lseek()) is not considered a handle, but could become one (as a consequence of fdopen(), dup() or fork() for example). This exception does not include the file descriptor underlying a stream, whether created with fopen() or fdopen(), so long as it is not used directly by the application to affect the file offset. The read() and write() functions implicitly affect the file offset; lseek() affects it explicitly.

The result of function calls involving only one handle (the active handle) are described in the reference section. If two or more handles are used, however, and one of them is a stream, their actions must be coordinated as described in the section “Actions” on "Interaction of file descriptors and streams".

A handle which is a stream is considered to be closed when either an fclose() or freopen() is executed on it (the result of freopen() is a new stream, which cannot be a handle on the same open file description as its previous value), or when the process owning that stream terminates with exit() or abort(). A file descriptor is closed by close(), _exit() or one of the exec functions when FD_CLOEXEC is set on that file descriptor.

For a handle to become the active handle, the actions below must be performed between the last use of the handle (the current active handle) and the first use of the second handle (the future active handle). The second handle then becomes the active handle. All activity by the application affecting the file offset on the first handle must be suspended until it again becomes the active file handle. If a stream function calls an underlying function that affects the file offset, the calling stream function will be considered to affect the file offset. The underlying functions involved are described below.

The handles need not be in the same process for these rules to apply.

Actions

If a handle is still open after the actions required below are taken, the application can close it.

  • No action is required for the first handle if one of the following conditions apply:

    • The handle is a file descriptor or an unbuffered stream.

    • The only further action to be performed on any handle is to close it.

    • The handle is a stream which is line buffered, and the last action has the same effect on the associated file as fputs().

    • The handle is a stream open for reading and feof() is TRUE.

  • If none of the conditions listed above apply, either an fflush() must occur or the stream must be closed in the following cases:

    • If it is a stream which is open for writing or appending, but not also open for reading.

    • If the stream is open with a mode that allows reading, and the underlying open file description refers to a device that is capable of seeking.

  • In all other cases, the result is undefined.

The following applies to the second handle:

If any previous active handle has been used by a function that explicitly changed the file offset, except as required above for the first handle, the application must perform an lseek() or fseek() (as appropriate to the type of handle) to an appropriate location.

If the active handle ceases to be accessible before the requirements on the first handle have been met, the state of the open file description becomes undefined. This could occur during the execution of functions such as a fork() or _exit().

The exec functions ensure that all streams which are open at the time they are called are made inaccessible, independent of which streams or file descriptors are available to the new process image.

If the above rules are followed, regardless of the sequence of handles used, the C runtime library will ensure that an application, even one consisting of several processes, will always yield correct results, i.e. that no data will be lost or duplicated when writing, that all data will written in order (except when the order is changed as requested by seeks), and that all data will be found when reading sequentially. It does not matter which order the handles are used. If the rules above are not followed, the result is undefined.

See also the manual "POSIX Basics" [1 (Related publications)].