1

我在我的驱动程序中添加了对 AIO 的支持(内核态中的 .aio_read 、 .aio_write 调用,用户态中的 libaio )并查看了各种来源(假设在调用 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)...

4

1 回答 1

0

来自aio_read 的手册页

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

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

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

于 2014-03-06T15:14:45.913 回答