Specifications
This is the Title of the Book, eMatter Edition
Copyright © 2005 O’Reilly & Associates, Inc. All rights reserved.
438
|
Chapter 15: Memory Mapping and DMA
For the rare driver author who needs to implement asynchronous I/O, we present a
quick overview of how it works. We cover asynchronous I/O in this chapter, because
its implementation almost always involves direct I/O operations as well (if you are
buffering data in the kernel, you can usually implement asynchronous behavior with-
out imposing the added complexity on user space).
Drivers supporting asynchronous I/O should include <linux/aio.h>. There are three
file_operations methods for the implementation of asynchronous I/O:
ssize_t (*aio_read) (struct kiocb *iocb, char *buffer,
size_t count, loff_t offset);
ssize_t (*aio_write) (struct kiocb *iocb, const char *buffer,
size_t count, loff_t offset);
int (*aio_fsync) (struct kiocb *iocb, int datasync);
The aio_fsync operation is only of interest to filesystem code, so we do not discuss it
further here. The other two, aio_read and aio_write, look very much like the regular
read and write methods but with a couple of exceptions. One is that the
offset
parameter is passed by value; asynchronous operations never change the file posi-
tion, so there is no reason to pass a pointer to it. These methods also take the
iocb
(“I/O control block”) parameter, which we get to in a moment.
The purpose of the aio_read and aio_write methods is to initiate a read or write oper-
ation that may or may not be complete by the time they return. If it is possible to
complete the operation immediately, the method should do so and return the usual
status: the number of bytes transferred or a negative error code. Thus, if your driver
has a read method called my_read, the following aio_read method is entirely correct
(though rather pointless):
static ssize_t my_aio_read(struct kiocb *iocb, char *buffer,
ssize_t count, loff_t offset)
{
return my_read(iocb->ki_filp, buffer, count, &offset);
}
Note that the struct file pointer is found in the ki_filp field of the kiocb structure.
If you support asynchronous I/O, you must be aware of the fact that the kernel can,
on occasion, create “synchronous IOCBs.” These are, essentially, asynchronous
operations that must actually be executed synchronously. One may well wonder why
things are done this way, but it’s best to just do what the kernel asks. Synchronous
operations are marked in the IOCB; your driver should query that status with:
int is_sync_kiocb(struct kiocb *iocb);
If this function returns a nonzero value, your driver must execute the operation
synchronously.
In the end, however, the point of all this structure is to enable asynchronous opera-
tions. If your driver is able to initiate the operation (or, simply, to queue it until some
future time when it can be executed), it must do two things: remember everything it
,ch15.13676 Page 438 Friday, January 21, 2005 11:04 AM