当前位置:嗨网首页>书籍在线阅读

14-AIO与设备驱动

  
选择背景色: 黄橙 洋红 淡粉 水蓝 草绿 白色 选择字体: 宋体 黑体 微软雅黑 楷体 选择字体大小: 恢复默认

9.4.4 AIO与设备驱动

在内核中,每个I/O请求都对应于一个kiocb结构体,其ki_filp成员指向对应的file指针,通过is_sync_kiocb()可以判断某kiocb是否为同步I/O请求,如果返回非真,表示为异步I/O请求。

块设备和网络设备本身是异步的,只有字符设备必须明确表明应支持AIO。AIO对于大多数字符设备而言都不是必须的,只有极少数设备需要。比如,对于磁带机,由于I/O操作很慢,这时候使用异步I/O将可改善性能。

字符设备驱动程序中,file_operations包含3个与AIO相关的成员函数:

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);

aio_read()和aio_write()与file_operations中的read()和write()中的offset参数不同,它直接传递值,而后者传递的是指针,这是因为AIO从来不需要改变文件的位置。

aio_read()和aio_write()函数本身不一定完成了读和写操作,它只是发起、初始化读和写操作,代码清单9.17给出了驱动程序中aio_read()和aio_write()函数的实现例子。

代码清单9.17 设备驱动中的异步I/O函数

1 struct async_work {

2 struct kiocb iocb; / kiocb结构体指针*/

3 int result; /执行结果 /

4 struct work_struct work; / 工作结构体 /

5 };

6 ...

7 /异步读/

8 static ssize_t xxx_aio_read(struct kiocb iocb, char buf, size_t count, loff_t

9 pos)

10 {

11 return xxx_defer_op(0, iocb, buf, count, pos);

12 }

13

14 /异步写/

15 static ssize_t xxx_aio_write(struct kiocb iocb, const char buf, size_t count,

16 loff_t pos)

17 {

18 return xxx_defer_op(1, iocb, (char*)buf, count, pos);

19 }

20

21 /初始化异步I/O/

22 static int xxx_defer_op(int write, struct kiocb iocb, char buf, size_t count,

23 loff_t pos)

24 {

25 struct async_work *async_wk;

26 int result;

27 / 当我们能访问buffer时进行copy /

28 if (write)

29 result = xxx_write(iocb->ki_filp, buf, count, &pos);

30 else

31 result = xxx_read(iocb->ki_filp, buf, count, &pos);

32 / 如果是同步IOCB,立即返回状态 /

33 if (is_sync_kiocb(iocb))

34 return result;

35

36 / 否则,推后几微秒执行 /

37 async_wk = kmalloc(sizeof(*async_wk), GFP_KERNEL);

38 if (async_wk == NULL)

39 return result;

40 /调度延迟的工作/

41 async_wk->iocb = iocb;

42 async_wk->result = result;

43 INIT_WORK(&async_wk->work, xxx_do_deferred_op, async_wk);

44 schedule_delayed_work(&async_wk->work, Hz / 100);

45 return - EIOCBQUEUED; /控制权返回用户空间/

46 }

47

48 /延迟后执行/

49 static void xxx_do_deferred_op(void *p)

50 {

51 struct async_work async_wk = (struct async_work)p;

52 ... / 执行I/O操作 /

53 aio_complete(async_wk->iocb, async_wk->result, 0);

54 kfree(async_wk);

55 }

上述代码中最核心的是使用work_struct机制通过schedule_delayed_work()函数将I/O操作延后执行,而在具体的I/O操作执行完成后,53行调用aio_complete()通知内核驱动程序已经完成了I/O操作。

通常而言,具体的字符设备驱动一般不需要实现AIO支持,而内核中仅有fs/direct-io.c,drivers/usb/gadget/inode.c、fs/nfs/direct.c等少量地方使用了AIO。