【问题标题】:Linux kernel asynchronous AIO: do I need to copy over the struct iovec for later processing?Linux 内核异步 AIO:我是否需要复制 struct iovec 以供以后处理?
【发布时间】:2014-03-06 15:08:02
【问题描述】:

我在我的驱动程序中添加了对 AIO 的支持(内核态中的 .aio_read 、 .aio_write 调用,用户态中的 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 个异步命令。

为了让事情变得更有趣: 我在 3.13 内核上大约 80% 的时间都有损坏。

但我以前从未在 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)...

【问题讨论】:

    标签: c asynchronous linux-kernel aio


    【解决方案1】:

    来自man page for aio_read

    注意事项 在使用前将控制块归零是个好主意。读取操作正在进行时,不得更改控制块。 在操作过程中不能访问正在读入的缓冲区,否则可能会出现未定义的结果。所涉及的内存区域必须 保持有效。

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

    这表明驱动程序可以在操作过程中依赖用户的数据结构。如果在操作过程中检测到这些结构已更改,则放弃操作并返回异步错误是谨慎的做法。

    【讨论】:

    • 确实,对于他们提到的控制块。但是“const struct iovec *iovec 参数”不是控制块的一部分,因为它不在“struct kiocb *iocb”内。在我的情况下,我在用户空间中遵循这些规则(并且为了使用户空间中的事情尽可能简单,我在这个简单的测试用例中只有一个控制块,用户线程等待它完成。这是对顺便说一句,单个地址,所以我在 iovect 中只得到 1 个段)。但我也会在 iocb 块上添加一些检查,以查看该块是否也发生了变化......
    • 小更新:iocb 区域在 3.13 上保持未损坏,即使 iovector 已损坏。示例地址以防万一:'pIOCB at addr:0xbfb91200 Contents: bf01bd80 bfba2000 0000 <...>'
    猜你喜欢
    • 1970-01-01
    • 2011-10-18
    • 1970-01-01
    • 1970-01-01
    • 2016-04-29
    • 1970-01-01
    • 1970-01-01
    • 2013-03-18
    • 2012-07-23
    相关资源
    最近更新 更多