truncate (2)

自作中のビーコンモニタは Linux 上で動いていて、複数のプロセスを協調させて動作しています。最近になって、その中のビーコン自動録音用のプロセスで一日のうちのある時刻において、ALSA サウンドデータ取り込みがオーバーランを起こすことに気付きました。いつも同じ時刻なのです。おまけに、プロセススケジューリングを SCHED_FIFO で動かしているのにですよ!
最初、SoftRock 受信機の周波数切り替えでこけるのでないか*1と考えたり、ファイルの open(), close() で予想以上の時間を要しているのではないか*2と考えていたのですが、朝の通勤電車の中で思いつきました。

そうだ。一日一回、1週間以上前の古い録音データを消す cron が原因だ!*3

実は、一日分の音声データは 15GB に及ぶのですが、これを unlink() するときにカーネルに負荷がかかって、せっかく SCHED_FIFO のプロセスをブロックしてしまっているようです。まだ、想像ですけど。
考えられる解決策は 2つ。

  • Linux カーネルのスケジューリングをもう少し勉強して、unlink() が SCHED_FIFO プロセスをブロックしないようにする。(できそうだけど、調べるのメンドーだなあ)
  • デカいファイルをいきなり unlink() しないで、少しずつ truncate() してから消す。

後者は Linux に依存しないので、ちょっと美しいような気がしています。惜しむらくは、truncate (2) で実装したユーザーコマンドが標準では存在しないことです。truncate (2) は 4.2BSD で実装されたシステムコールのようで、それだけを呼び出すユーザーコマンドというのは、作られなかったのでしょうか。誰か御存知の方は、教えてくださいまし。

*1:試作版では、外部コマンドを system() で呼び出していた。

*2:毎朝 9:00 に、書き出しファイルを入れ替えている。

*3:自分でやったんですけど、気付かなかった。