VxWorks Reference Manual : Libraries
aioPxLib - asynchronous I/O (AIO) library (POSIX)
aioPxLibInit( ) - initialize the asynchronous I/O (AIO) library
aio_read( ) - initiate an asynchronous read (POSIX)
aio_write( ) - initiate an asynchronous write (POSIX)
lio_listio( ) - initiate a list of asynchronous I/O requests (POSIX)
aio_suspend( ) - wait for asynchronous I/O request(s) (POSIX)
aio_fsync( ) - asynchronous file synchronization (POSIX)
aio_error( ) - retrieve error status of asynchronous I/O operation (POSIX)
aio_return( ) - retrieve return status of asynchronous I/O operation (POSIX)
This library implements asynchronous I/O (AIO) according to the definition given by the POSIX standard 1003.1b (formerly 1003.4, Draft 14). AIO provides the ability to overlap application processing and I/O operations initiated by the application. With AIO, a task can perform I/O simultaneously to a single file multiple times or to multiple files.
After an AIO operation has been initiated, the AIO proceeds in logical parallel with the processing done by the application. The effect of issuing an asynchronous I/O request is as if a separate thread of execution were performing the requested I/O.
The AIO library is initialized by calling aioPxLibInit( ), which should be called once (typically at system start-up) after the I/O system has already been initialized.
The file to be accessed asynchronously is opened via the standard open call. Open returns a file descriptor which is used in subsequent AIO calls.
The caller initiates asynchronous I/O via one of the following routines:
- aio_read( )
- initiates an asynchronous read
- aio_write( )
- initiates an asynchronous write
- lio_listio( )
- initiates a list of asynchronous I/O requests
Each of these routines has a return value and error value associated with it; however, these values indicate only whether the AIO request was successfully submitted (queued), not the ultimate success or failure of the AIO operation itself.
There are separate return and error values associated with the success or failure of the AIO operation itself. The error status can be retrieved using aio_error( ); however, until the AIO operation completes, the error status will be EINPROGRESS. After the AIO operation completes, the return status can be retrieved with aio_return( ).
The aio_cancel( ) call cancels a previously submitted AIO request. The aio_suspend( ) call waits for an AIO operation to complete.
Finally, the aioShow( ) call (not a standard POSIX function) displays outstanding AIO requests.
Each of the calls described above takes an AIO control block (aiocb) as an argument. The calling routine must allocate space for the aiocb, and this space must remain available for the duration of the AIO operation. (Thus the aiocb must not be created on the task's stack unless the calling routine will not return until after the AIO operation is complete and aio_return( ) has been called.) Each aiocb describes a single AIO operation. Therefore, simultaneous asynchronous I/O operations using the same aiocb are not valid and produce undefined results.
The aiocb structure and the data buffers referenced by it are used by the system to perform the AIO request. Therefore, once the aiocb has been submitted to the system, the application must not modify the aiocb structure until after a subsequent call to aio_return( ). The aio_return( ) call retrieves the previously submitted AIO data structures from the system. After the aio_return( ) call, the calling application can modify the aiocb, free the memory it occupies, or reuse it for another AIO call.
As a result, if space for the aiocb is allocated off the stack the task should not be deleted (or complete running) until the aiocb has been retrieved from the system via an aio_return( ).
The aiocb is defined in aio.h. It has the following elements:
struct { int aio_fildes; off_t aio_offset; volatile void * aio_buf; size_t aio_nbytes; int aio_reqprio; struct sigevent aio_sigevent; int aio_lio_opcode; AIO_SYS aio_sys; } aiocb
- aio_fildes
- file descriptor for I/O.
- aio_offset
- offset from the beginning of the file where the AIO takes place. Note that performing AIO on the file does not cause the offset location to automatically increase as in read and write; the caller must therefore keep track of the location of reads and writes made to the file (see POSIX COMPLIANCE below).
- aio_buf
- address of the buffer from/to which AIO is requested.
- aio_nbytes
- number of bytes to read or write.
- aio_reqprio
- amount by which to lower the priority of an AIO request. Each AIO request is assigned a priority; this priority, based on the calling task's priority, indicates the desired order of execution relative to other AIO requests for the file. The aio_reqprio member allows the caller to lower (but not raise) the AIO operation priority by the specified value. Valid values for aio_reqprio are in the range of zero through AIO_PRIO_DELTA_MAX. If the value specified by aio_req_prio results in a priority lower than the lowest possible task priority, the lowest valid task priority is used.
- aio_sigevent
- (optional) if nonzero, the signal to return on completion of an operation.
- aio_lio_opcode
- operation to be performed by a lio_listio( ) call; valid entries include LIO_READ, LIO_WRITE, and LIO_NOP.
- aio_sys
- a Wind River Systems addition to the aiocb structure; it is used internally by the system and must not be modified by the user.
A writer could be implemented as follows:
if ((pAioWrite = calloc (1, sizeof (struct aiocb))) == NULL) { printf ("calloc failed\n"); return (ERROR); } pAioWrite->aio_fildes = fd; pAioWrite->aio_buf = buffer; pAioWrite->aio_offset = 0; strcpy (pAioWrite->aio_buf, "test string"); pAioWrite->aio_nbytes = strlen ("test string"); pAioWrite->aio_sigevent.sigev_notify = SIGEV_NONE; aio_write (pAioWrite); /* . . do other work . . */ /* now wait until I/O finishes */ while (aio_error (pAioWrite) == EINPROGRESS) taskDelay (1); aio_return (pAioWrite); free (pAioWrite);A reader could be implemented as follows:
/* initialize signal handler */ action1.sa_sigaction = sigHandler; action1.sa_flags = SA_SIGINFO; sigemptyset(&action1.sa_mask); sigaction (TEST_RT_SIG1, &action1, NULL); if ((pAioRead = calloc (1, sizeof (struct aiocb))) == NULL) { printf ("calloc failed\n"); return (ERROR); } pAioRead->aio_fildes = fd; pAioRead->aio_buf = buffer; pAioRead->aio_nbytes = BUF_SIZE; pAioRead->aio_sigevent.sigev_signo = TEST_RT_SIG1; pAioRead->aio_sigevent.sigev_notify = SIGEV_SIGNAL; pAioRead->aio_sigevent.sigev_value.sival_ptr = (void *)pAioRead; aio_read (pAioRead); /* . . do other work . . */The signal handler might look like the following:
void sigHandler ( int sig, struct siginfo info, void * pContext ) { struct aiocb * pAioDone; pAioDone = (struct aiocb *) info.si_value.sival_ptr; aio_return (pAioDone); free (pAioDone); }
Currently VxWorks does not support the O_APPEND flag in the open call. Therefore, the user must keep track of the offset in the file that the asynchronous writes occur (as in the case of reads). The aio_offset field is used to specify that file position.
In addition, VxWorks does not currently support synchronized I/O.
aio.h
aioPxLib, POSIX 1003.1b document
aioPxLibInit( ) - initialize the asynchronous I/O (AIO) library
STATUS aioPxLibInit ( int lioMax /* max outstanding lio calls */ )
This routine initializes the AIO library. It should be called only once after the I/O system has been initialized. lioMax specifies the maximum number of outstanding lio_listio( ) calls at one time. If lioMax is zero, the default value of AIO_CLUST_MAX is used.
OK if successful, otherwise ERROR.
S_aioPxLib_IOS_NOT_INITIALIZED
aio_read( ) - initiate an asynchronous read (POSIX)
int aio_read ( struct aiocb * pAiocb /* AIO control block */ )
This routine asynchronously reads data based on the following parameters specified by members of the AIO control structure pAiocb. It reads aio_nbytes bytes of data from the file aio_fildes into the buffer aio_buf.
The requested operation takes place at the absolute position in the file as specified by aio_offset.
aio_reqprio can be used to lower the priority of the AIO request; if this parameter is nonzero, the priority of the AIO request is aio_reqprio lower than the calling task priority.
The call returns when the read request has been initiated or queued to the device. aio_error( ) can be used to determine the error status and of the AIO operation. On completion, aio_return( ) can be used to determine the return status.
aio_sigevent defines the signal to be generated on completion of the read request. If this value is zero, no signal is generated.
OK if the read queued successfully, otherwise ERROR.
EBADF, EINVAL
aio.h
aioPxLib, aio_error( ), aio_return( ), read( )
aio_write( ) - initiate an asynchronous write (POSIX)
int aio_write ( struct aiocb * pAiocb /* AIO control block */ )
This routine asynchronously writes data based on the following parameters specified by members of the AIO control structure pAiocb. It writes aio_nbytes of data to the file aio_fildes from the buffer aio_buf.
The requested operation takes place at the absolute position in the file as specified by aio_offset.
aio_reqprio can be used to lower the priority of the AIO request; if this parameter is nonzero, the priority of the AIO request is aio_reqprio lower than the calling task priority.
The call returns when the write request has been initiated or queued to the device. aio_error( ) can be used to determine the error status and of the AIO operation. On completion, aio_return( ) can be used to determine the return status.
aio_sigevent defines the signal to be generated on completion of the write request. If this value is zero, no signal is generated.
OK if write queued successfully, otherwise ERROR.
EBADF, EINVAL
aio.h
aioPxLib, aio_error( ), aio_return( ), write( )
lio_listio( ) - initiate a list of asynchronous I/O requests (POSIX)
int lio_listio ( int mode, /* LIO_WAIT or LIO_NOWAIT */ struct aiocb * list[], /* list of operations */ int nEnt, /* size of list */ struct sigevent * pSig /* signal on completion */ )
This routine submits a number of I/O operations (up to AIO_LISTIO_MAX) to be performed asynchronously. list is a pointer to an array of aiocb structures that specify the AIO operations to be performed. The array is of size nEnt.
The aio_lio_opcode field of the aiocb structure specifies the AIO operation to be performed. Valid entries include LIO_READ, LIO_WRITE, and LIO_NOP. LIO_READ corresponds to a call to aio_read( ), LIO_WRITE corresponds to a call to aio_write( ), and LIO_NOP is ignored.
The mode argument can be either LIO_WAIT or LIO_NOWAIT. If mode is LIO_WAIT, lio_listio( ) does not return until all the AIO operations complete and the pSig argument is ignored. If mode is LIO_NOWAIT, the lio_listio( ) returns as soon as the operations are queued. In this case, if pSig is not NULL and the signal number indicated by pSig->sigev_signo is not zero, the signal pSig->sigev_signo is delivered when all requests have completed.
OK if requests queued successfully, otherwise ERROR.
EINVAL, EAGAIN, EIO
aio.h
aioPxLib, aio_read( ), aio_write( ), aio_error( ), aio_return( ).
aio_suspend( ) - wait for asynchronous I/O request(s) (POSIX)
int aio_suspend ( const struct aiocb * list[], /* AIO requests */ int nEnt, /* number of requests */ const struct timespec * timeout /* wait timeout */ )
This routine suspends the caller until one of the following occurs:
- at least one of the previously submitted asynchronous I/O operations referenced by list has completed,
- a signal interrupts the function, or
- the time interval specified by timeout has passed (if timeout is not NULL).
OK if an AIO request completes, otherwise ERROR.
EAGAIN, EINTR
aio.h
aio_fsync( ) - asynchronous file synchronization (POSIX)
int aio_fsync ( int op, /* operation */ struct aiocb * pAiocb /* AIO control block */ )
This routine asynchronously forces all I/O operations associated with the file, indicated by aio_fildes, queued at the time aio_fsync( ) is called to the synchronized I/O completion state. aio_fsync( ) returns when the synchronization request has be initiated or queued to the file or device.
The value of op is ignored. It currently has no meaning in VxWorks.
If the call fails, the outstanding I/O operations are not guaranteed to have completed. If it succeeds, only the I/O that was queued at the time of the call is guaranteed to the relevant completion state.
The aio_sigevent member of the pAiocb defines an optional signal to be generated on completion of aio_fsync( ).
OK if queued successfully, otherwise ERROR.
EINVAL, EBADF
aio.h
aioPxLib, aio_error( ), aio_return( )
aio_error( ) - retrieve error status of asynchronous I/O operation (POSIX)
int aio_error ( const struct aiocb * pAiocb /* AIO control block */ )
This routine returns the error status associated with the I/O operation specified by pAiocb. If the operation is not yet completed, the error status will be EINPROGRESS.
EINPROGRESS if the AIO operation has not yet completed,
OK if the AIO operation completed successfully,
the error status if the AIO operation failed,
otherwise ERROR.
EINVAL
aio.h
aio_return( ) - retrieve return status of asynchronous I/O operation (POSIX)
size_t aio_return ( struct aiocb * pAiocb /* AIO control block */ )
This routine returns the return status associated with the I/O operation specified by pAiocb. The return status for an AIO operation is the value that would be returned by the corresponding read( ), write( ), or fsync( ) call. aio_return( ) may be called only after the AIO operation has completed (aio_error( ) returns a valid error code--not EINPROGRESS). Furthermore, aio_return( ) may be called only once; subsequent calls will fail.
The return status of the completed AIO request, or ERROR.
EINVAL, EINPROGRESS
aio.h