ドライバーに 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 にアップグレードする前に少しだけ使用しただけで、今では正気に戻り、何十回も試してみました)。( 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 の) バグが含まれています。