readcond()

Updated: April 19, 2023

Read data from a terminal device

Synopsis:

#include <unistd.h>

int readcond( int fd,
              void * buf,
              int n,
              int min,
              int time,
              int timeout );

Arguments:

fd
The file descriptor associated with the terminal device that you want to read from.
buf
A pointer to a buffer into which readcond() can put the data.
n
The maximum number of bytes to read.
min, time, timeout
When used in RAW mode, these arguments override the behavior of the MIN and TIME members of the terminal's termios structure. For more information, see below.

Library:

libc

Use the -l c option to qcc to link against this library. This library is usually included automatically.

Description:

The readcond() function reads up to n bytes of data from the terminal device indicated by fd into the buffer pointed to by buf.

This function is an alternative to the read() function for terminal devices, providing additional arguments for timed read operations. These additional arguments can be used to minimize overhead when dealing with terminal devices.

The three arguments (min, time, and timeout), when used on terminal devices in RAW mode, override the behavior of the MIN and TIME elements of the currently defined termios structure (for the duration of this call only). The termios structure also defines a forwarding character (in c_cc[VFWD]) that can be used to bypass min, time, and timeout.

The normal case of a simple read by an application would block until at least one character was available.

Figure 1. Conditions that satisfy an input request.

In the case where multiple conditions are specified, the read will be satisfied when any one of them is satisfied.

MIN

The qualifier MIN is useful when an application has knowledge of the number of characters it expects to receive.

Any protocol that knows the character count for a frame of data can use MIN to wait for the entire frame to arrive. This significantly reduces IPC and process scheduling. MIN is often used in conjunction with TIME or TIMEOUT. MIN is part of the POSIX standard.

TIME

The qualifier TIME is useful when an application is receiving streaming data and wishes to be notified when the data stops or pauses. The pause time is specified in tenths of a second. TIME is part of the POSIX standard.

TIMEOUT

The qualifier TIMEOUT is useful when an application has knowledge of how long it should wait for data before timing out. The timeout is specified in tenths of a second.

Any protocol that knows the character count for a frame of data it expects to receive can use TIMEOUT. This in combination with the baud rate allows a reasonable guess to be made when data should be available. It acts as a deadman timer to detect dropped characters. It can also be used in interactive programs with user input to time out a read if no response is available within a given time.

TIMEOUT is a QNX Neutrino extension and isn't part of the POSIX standard.

FORWARD

The qualifier FORWARD is useful when a protocol is delimited by a special framing character. For example, the PPP protocol used for TCP/IP over a serial link start and end its packets with a framing character. When used in conjunction with TIMEOUT, the FORWARD character can greatly improve the efficiency of a protocol implementation. The protocol process will receive complete frames, rather than character by character. In the case of a dropped framing character, TIMEOUT or TIME can be used to quickly recover.

This greatly minimizes the amount of IPC work for the OS and results in a much lower processor utilization for a given TCP/IP data rate. It is interesting to note that PPP doesn't contain a character count for its frames. Without the data-forwarding character, an implementation would be forced to read the data one character at a time.

FORWARD is a QNX Neutrino extension and isn't part of the POSIX standard.

To enable the FORWARD character, you must set the VFWD character in the c_cc member of the termios structure:

/* PPP forwarding character */
const char fwd_char = 0x7e;

#include <termios.h>

…

int fd;
struct termios termio;

…

tcgetattr( fd, &termio );
termio.c_cc[VFWD] = fwd_char;
tcsetattr( fd, TCSANOW, &termio );

The following table summarizes the interaction of min, time, and timeout:

min time timeout Description
0 0 0 Returns immediately with as many bytes as are currently available (up to n bytes).
M 0 0 Return with up to n bytes only when at least M bytes are available.
0 T 0 Return with up to n bytes when at least one byte is available, or T * .1 sec has expired.
M T 0 Return with up to n bytes when either M bytes are available, or at least one byte has been received and the inter-byte time between any subsequently received characters exceeds T * .1 sec.
0 0 t RESERVED.
M 0 t Return with up to n bytes when t * .1 sec has expired, or M bytes are available.
0 T t RESERVED.
M T t Return with up to n bytes when M bytes are available, or t * .1 sec has expired and no characters are received, or at least one byte has been received and the inter-byte time between any subsequently received characters exceeds T * .1 sec.

Note that when timeout is zero, the behavior of min and time is exactly the same as the behavior of the MIN and TIME parameters of the termios controlling structure. Thus, readcond() can be used as a higher speed alternative to consecutive calls of tcgetattr(), tcsetattr(), and read() when dealing with RAW terminal I/O.

The (M, 0, t) case is useful for communications protocols that cannot afford to block forever waiting for data that may never arrive.

The (M, T, t) case is provided to permit readcond() to return when a burst of data ends (as in the (M, T, 0) case), but also to return if no burst at all is detected within a reasonable amount of time.

Returns:

The number of bytes read, or -1 if an error occurs (errno is set).

Errors:

EAGAIN
The O_NONBLOCK flag is set on this fd, and the process would have been blocked in trying to perform this operation.
EBADF
The argument fd is invalid or file isn't opened for reading.
EINTR
The readcond() call was interrupted by the process being signalled.
EIO
This process isn't currently able to read data from this fd.
ENOSYS
This function isn't supported for this fd.

Classification:

QNX Neutrino

Safety:  
Cancellation point Yes
Interrupt handler No
Signal handler Yes
Thread Yes