Linux内核异步AIO:我需要复制struct iovec以便以后处理吗?

时间:2014-03-06 15:08:02

标签: c asynchronous linux-kernel aio

我在我的驱动程序中添加了对AIO的支持(在kernelland中的.aio_read,.aio_write调用,在userland中的libaio)并查看了我在aio_read,.aio_write调用中找不到的各种源代码我只能存储指针iovector参数(假设这个内存在调用例如aio_complete之前保持不变),或者我需要深层复制iovector数据结构。

static ssize_t aio_read( struct kiocb *iocb, const struct iovec *iovec, unsigned long nr_segs, loff_t pos );
static ssize_t aio_write( struct kiocb *iocb, const struct iovec *iovec, unsigned long nr_segs, loff_t pos );

以\ drivers \ usb \ gadget \ inode.c的实现为例,看起来他们只是复制ep_aio_rwtail函数中的指针,该函数具有:

priv->iv = iv;

但是当我尝试做类似的事情时,经常会发生iovector中的数据在处理时被“损坏”。

例如在aio_read / write调用中我记录

iovector located at addr:0xbf1ebf04
segment 0: base: 0x76dbb468        len:512

但是当我在内核线程中执行实际工作时(在附加到用户空间mm之后),我记录了以下内容:

iovector located at addr:0xbf1ebf04
segment 0: base: 0x804e00c8        len:-1088503900

这是一个非常简单的测试用例,我只在我的用户应用程序中提交1个异步命令。

让事情变得更有趣: 我有大约80%的时间在3.13内核上的腐败。

但是我之前从未在3.9内核上看过它(但是我在升级到3.13之前只用了一会儿,现在又恢复了作为一个理智的cnheck并尝试了十几次)。 (使用3.9内核运行的示例有两次

iovector located at addr:0xbf9ee054
segment 0: base: 0x76e28468        len:512)

这会响铃吗?

(另一种可能性是我自己当然正在破坏这些地址/长度,但奇怪的是我从来没有使用3.9)

编辑: 为了回答我自己的问题,在回顾了linux aio的3.13代码(已经发生了很大变化,而且工作的3.9),在fs \ aio.c中你有:

static ssize_t aio_run_iocb(struct kiocb *req, unsigned opcode, char __user *buf, bool compat) { ... struct iovec inline_vec, *iovec = &inline_vec; ... ret = rw_op(req, iovec, nr_segs, req->ki_pos); ... }

所以这个iovec结构只是在堆栈上,一旦aio_read / write函数退出就会丢失。

小工具框架包含\ drivers \ usb \ gadget \ inode.c中的错误(至少3.13)...

1 个答案:

答案 0 :(得分:0)

来自man page for aio_read;

  

备注          在使用之前将控制块清零是个好主意。在读取操作正在进行时,不得更改控制块。          在操作期间不得访问正在读入的缓冲区,否则可能会出现未定义的结果。涉及的内存区域必须          仍然有效。

     

指定相同aiocb结构的同时I / O操作产生          未定义的结果。

这表明驱动程序可以在操作期间依赖于用户的数据结构。如果在操作期间检测到这些结构发生了变化,那么放弃操作并返回异步错误是明智的。