なぜ非同期I/OのAPIが存在するのか

Linuxでは、ユーザー空間で使用できる非同期I/Oを使う手段としては、2種類あります。

  1. aio_readなどを使うPOSIX準拠の非同期I/O
  2. io_setupなどを使うシステムコールによる非同期I/O

しかし、LinuxのI/Oは同期?非同期?で、LinuxのI/Oがたいていの場合、非同期であると説明しましたのに、何故、非同期I/OのAPIというのがあるのでしょうか?

ここで注意しなければいけないのは、前のエントリでいっていた非同期と非同期I/OのAPIの非同期とはの意味が若干変わるということです。前のエントリでの非同期では、ディスクへのアクセスがユーザー空間からの要求と同時に行われるかどうかでしたが、非同期I/O APIによる非同期という意味は、要求をだしてから、read系ならその要求をだした関数から返ってきたら、すぐにそのメモリにデータが使える状態になるようなことを同期、要求を出し関数から返ってくるのとI/O操作(ここでのI/O操作はページキャッシュに対する操作を含む)の完了が一致しないことを非同期と呼びます。

では、I/O要求とI/O操作が非同期であると何がうれしいのでしょうか。

それは、I/O操作を行っている間に、他の仕事をさせることができるということです。

まず、ディスクに対するアクセスが行われるとき、ディスクとメモリのデータの転送には、CPUは使われず、DMAによる転送になります。DMA転送を行っている間、CPUは遊んでしまいます。

ページキャッシュに対する操作も、ディスクに対する操作がたいていの場合、非同期に行われるとはいえ、ページキャッシュの検索や、writeの場合であれば、dartyフラグをたてなければいけないと、いろいろ操作を行わなければなりません。

非同期I/O APIによるI/O要求をだすと、ページキャッシュやディスクに対する操作要求をだすだけで、プロセスがCPUを使うことができます。ページキャッシュやディスクにアクセスする操作は、I/O要求を出したプロセスとは別のコンテキストで行われることになります。そうすることで、要求をだしたプロセスはI/O操作の完了するまで、他の操作を行うことができるわけです。

ページキャッシュにのっていないようなファイルや、I/Oの直接転送を行うときなどI/O操作に時間がかかるようなときに、非同期I/Oを用いることでCPUを有効に使えます。特に、マルチプロセスなどの環境では、特に有効になってきます(そのプロセス自身の実行とそのプロセスが要求した非同期I/Oの操作が同時に複数のプロセスで行われる可能性があるため)。

ということで、これかのエントリでは、上で紹介した2つの非同期I/Oについて書いていきます。