我在我的驱动程序中添加了对 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)...