Asynchronous Input/Output (AIO) is the ability to perform input and output operations concurrently with ordinary internal processing. AIO enables you to decouple I/O operations from the activities of a particular task when these are logically independent.
The benefit of AIO is greater processing efficiency: it permits I/O operations to take place whenever resources are available, rather than making them await arbitrary events such as the completion of independent operations. AIO eliminates some of the unnecessary blocking of tasks that is caused by ordinary synchronous I/O; this decreases contention for resources between input/output and internal processing, and expedites throughput.
The VxWorks AIO implementation meets the specification in the POSIX 1003.1b standard. To include AIO in your VxWorks configuration, select INCLUDE_POSIX_AIO and INCLUDE_POSIX_AIO_SYSDRV in the project facility VxWorks view; see Tornado User's Guide: Projects for information on configuring VxWorks. The second configuration constant enables the auxiliary AIO system driver, required for asynchronous I/O on all current VxWorks devices.
The VxWorks library aioPxLib provides the POSIX AIO routines. To access a file asynchronously, open it with the open( ) routine, like any other file. Thereafter, use the file descriptor returned by open( ) in calls to the AIO routines. The POSIX AIO routines (and two associated non-POSIX routines) are listed in Table 3-4.
The default VxWorks initialization code calls aioPxLibInit( ) automatically when INCLUDE_POSIX_AIO is selected for inclusion in the project facility VxWorks view. This routine takes one parameter, the maximum number of lio_listio( )calls that can be outstanding at one time. By default this parameter is MAX_LIO_CALLS (which can be seen on the Params tab of the properties window to be 0 by default). When the parameter is 0, the value is taken from AIO_CLUST_MAX (defined in installDir/target/h/private/aioPxLibP.h).
The AIO system driver, aioSysDrv, is initialized by default with the routine aioSysInit( ) when both INCLUDE_POSIX_AIO and INCLUDE_POSIX_AIO_SYSDRV are included. The purpose of aioSysDrv is to provide request queues independent of any particular device driver, so that you can use any VxWorks device driver with AIO.
The routine aioSysInit( ) takes three parameters: the number of AIO system tasks to spawn, and the priority and stack size for these system tasks. The number of AIO system tasks spawned equals the number of AIO requests that can be handled in parallel. The default initialization call( )uses three constants, all defined in configAll.h:
aioSysInit( MAX_AIO_SYS_TASKS, AIO_TASK_PRIORITY, AIO_TASK_STACK_SIZE )
When any of the parameters passed to aioSysInit( )is 0, the corresponding value is taken from AIO_IO_TASKS_DFLT, AIO_IO_PRIO_DFLT, and AIO_IO_STACK_DFLT (all defined in installDir/target/h/aioSysDrv.h).
Table 3-5 lists the names of the constants called from usrConfig.c and their default values (which can be seen on the Params tab of the properties window). It also shows the constants used within initialization routines when the parameters are left at their default values of 0, and where these constants are defined.
|
|||||||||||||||||||
|
|||||||||||||||||||
|
|||||||||||||||||||
Each of the AIO calls takes an AIO control block (aiocb) as an argument to describe the AIO operation. The calling routine must allocate space for the control block, which is associated with a single AIO operation. No two concurrent AIO operations can use the same control block; an attempt to do so yields undefined results.
The aiocb and the data buffers it references are used by the system while performing the associated request. Therefore, after you request an AIO operation, you must not modify the corresponding aiocb before calling aio_return( ); this function frees the aiocb for modification or reuse.
|
CAUTION: If a routine allocates stack space for the aiocb, that routine must call aio_return( ) to free the aiocb before returning.
|
||||||||||||||||||
The routines aio_read( ), aio_write( ), or lio_listio( ) initiate AIO operations. The last of these, lio_listio( ), allows you to submit a number of asynchronous requests (read and/or write) at one time. In general, the actual I/O (reads and writes) initiated by these routines does not happen immediately after the AIO request. For that reason, their return values do not reflect the outcome of the actual I/O operation, but only whether a request is successful--that is, whether the AIO routine is able to put the operation on a queue for eventual execution.
After the I/O operations themselves execute, they also generate return values that reflect the success or failure of the I/O. There are two routines that you can use to get information about the success or failure of the I/O operation: aio_error( ) and aio_return( ). You can use aio_error( )to get the status of an AIO operation (success, failure, or in progress), and aio_return( ) to obtain the return values from the individual I/O operations. Until an AIO operation completes, its error status is EINPROGRESS. To cancel an AIO operation, call aio_cancel( ).
The following code uses a pipe for the asynchronous I/O operations. The example creates the pipe, submits an AIO read request, verifies that the read request is still in progress, and submits an AIO write request. Under normal circumstances, a synchronous read to an empty pipe blocks and the task does not execute the write, but in the case of AIO, we initiate the read request and continue. After the write request is submitted, the example task loops, checking the status of the AIO requests periodically until both the read and write complete. Because the AIO control blocks are on the stack, we must call aio_return( ) before returning from aioExample( ).
/* aioEx.c - example code for using asynchronous I/O */
The following example is similar to the preceding aioExample( ), except that it uses signals to be notified when the write is complete. If you test this from the shell, spawn the routine to run at a lower priority than the AIO system tasks to assure that the test routine does not block completion of the AIO request. (For details on the shell, see the Tornado User's Guide: Shell.)
/* aioExSig.c - example code for using signals with asynchronous I/O */