AIO是2.6内核增加的一个主要的“企业级”特征。AIO让用户进程可以发起多个IO操作,无需等待任何一个操作完成;操作状态可以随后获取。块设备驱动和网络驱动已经是完全异步的了,无需为支持这种新的异步操作而做特别的事情。然而,具有同步API的字符设备却需要额外的工作才能支持AIO。对于大多数字符设备驱动,支持AIO并不能获得太多好处。然而,在极少数情况下,让用户可以使用AIO可能是有利的。
1 AIO文件操作
为支持AIO而要做的第一步(除了包含外)是实现file_operations结构体中新增加的三个方法:
对于大多数驱动程序,真正的工作在aio_read()和aio_write()的实现中完成。这两个函数与标准的read()和write()方法类似,但是有两处不同:file参数被替换成了IO控制块(iocb),并且函数(通常)不需要立即完成请求的操作。通常可以把iocb看作AIO子系统使用的不透明数据结构。然而,如果需要文件描述符的struct file指针,可以通过iocb->ki_flip获取。
aio操作也可以是同步的。一个明显的例子是,操作可以不阻塞地完成时。如果操作在aio_read()或者aio_write()返回前完成,则返回值应该是通常的状态码或者错误码。所以,下面的aio_read()方法虽然没有意义,却是完全正确的:
某些情况可能确实要求同步行为。所谓的“同步iocb”使得需要时可以同步地使用AIO子系统。如果必须同步处理请求,则宏
将返回true。
然而,大多数情况下aio_read()和aio_write()是不能立即满足IO请求的。此时,这些函数应该启动操作,返回-EIOCBQUEUED。注意:必须在返回前完成任何必须在用户进程上下文中完成的工作,因为随后是不能访问用户进程上下文的。为访问用户缓冲区,可能需要在返回前建立DMA映射,或者将buffer指针转换成一系列struct page指针。还应该牢记的是,任何时刻可能有多个活动的异步IO请求。实现AIO的驱动程序必须包含正确的锁操作(以及可能的排队),让这些请求不会相互干扰。
IO操作完成时,必须调用aio_complete()通知AIO子系统:
当然,这里的iocb就是发起请求时的IOCB。res是IO操作的通常结果:传输的字节数,或者负值的错误码。res2是返回给用户的第二个状态值,当前(2.6.0-test9)内核中aio_complete()的调用者总是设置它为0。可以在中断处理器中安全地调用aio_complete()。一旦调用aio_complete(),驱动程序就不再拥有IOCB或者用户缓冲区了,不应该再触碰它们。
aio_fsync()的目的与fsync()相同:确保所有未决的数据都写入到磁盘了。一般来说,设备驱动程序不需要实现aio_fsync()。