【发布时间】: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