takaha.siの技術メモ

勉強したことをお伝えします。ちょっとでも誰かの役に立てればいいな…

O_DIRECTでopenするときはmemalign使わないとだめだよ

O_DIRECTopenしてwriteしたいときがたまにあると思います。

通常のopenしてwriteだとカーネル内部でページキャッシュが使われて、カーネル内部でのメモリコピーが何回か行われちゃいます。が、O_DIRECTだとページキャッシュをバイパスできて、その結果カーネル内部でのメモリコピー回数が減ります。

通常O_DIRECTは使わないんですけども、自前でバッファリングとかしてるアプリケーションとかだと(データベースとか)、カーネルのページキャッシュ層と競合してわけわかんないことになったりするのでOFFにしたりします。

あとは、ベンチマークプログラムでファイルシステムの生の性能を知りたいときなどもコレを使います。

んで、僕知らなかったんですがO_DIRECTでopenしたfdにread/writeするときってalignされたメモリ空間じゃないと受け付けないんですね。つまり、通常のmallocだとだめなんです。これで30分ぐらいハマりました。

普通のmallocで確保したバッファをwrite(2)に渡そうとすると、perror()Invalid argumentエラーが出ちゃいます。

write
: Invalid argument

なんでmallocじゃなくてposix_memalignとか使いましょうって話です。こんな感じ。

  if (posix_memalign((void **)&buf, 512, bs)) {
    perror("posix_memalign");
    exit(EXIT_FAILURE);
  }

ページ空間をまるごと直接アロケーションしちゃってるんですかね?

まあ、manにはちゃんと書いてあります。ちゃんと読めって話ですね。

   O_DIRECT
       The O_DIRECT flag may impose alignment restrictions on the length
       and address of user-space buffers and the file offset of I/Os.

man7.org

すべてのコードは以下の通り:

gist.github.com

O_DIRECT tipsでした。