我在我的驱动程序中添加了对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)...
答案 0 :(得分:0)
备注强> 在使用之前将控制块清零是个好主意。在读取操作正在进行时,不得更改控制块。 在操作期间不得访问正在读入的缓冲区,否则可能会出现未定义的结果。涉及的内存区域必须 仍然有效。
指定相同aiocb结构的同时I / O操作产生 未定义的结果。
这表明驱动程序可以在操作期间依赖于用户的数据结构。如果在操作期间检测到这些结构发生了变化,那么放弃操作并返回异步错误是明智的。