2006年11月22日(Wed) どんより寒い空 [長年日記]
● 冬だなあ、と感じながら半袖半ズボンで仕事に向かう。
● ファイルのロックの続き
LOCK_UNするのはいつ?という疑問に okujiさんが応えてくださった。いつもあ りがとうございます。
確かにシステムコールとstdioを混ぜて使うのは危険ですよね。fで始 まるので気づきませんでした。迂闊すぎ。fopen(3)に対して open(2)、flock(3)に対して、lock(2)…ではなくflock(2)なのですね。
Linux Programmer's Manual (11 December 1998) より、
- 名前
- flock - オープンされたファイルにロックの適用、解除を行なう
- 書式
- #include
int flock(int fd, int operation);- 説明
- オープンされたファイルにアドバイザリ・ロック(advisory lock)の 適用または解除を行う。
で、flockfile(3)ですが、どうも同じプロセス内の他のスレッドに対 するロックのようでした。Linux Programmer's Manual (2001-10-18)よ り、
- 名前
- flockfile, ftrylockfile, funlockfile - 標準入出力 FILE のロックを行う
- 書式
- #include
void flockfile(FILE *filehandle);
int ftrylockfile(FILE *filehandle);
void funlockfile(FILE *filehandle);
- 説明
- …ライブラリの呼び出しが行われる毎に、標準入出力関数は FILE オブジェクトが他のスレッドによってロックされ ていない状態になるま で待ち、FILE オブジェクトをロックし、要求されて入出力を行い、オブ ジェクトのロックを解除する。
(注: このロックは、 flock(2) や lockf(3) といった関数が行うロック とは全く無関係である。)
他のプロセスに対してもロックするのは lockf(3)なのかな?Linux Programmer's Manual (2002-04-22)より、
- 名前
- lockf - 開いているファイルに対して POSIX ロックを適用・テスト・解除する。
- 書式
- #include
int lockf(int fd, int cmd, off_t len);- 説明
- … Linux では、この関数は単に fcntl(2) へのインターフェースである。
さて。advisort lockとPOSIX lockとの関係は…lockf(3)のman ペー
ジに記載されていた、
…flock() and fcntl() locks oblivious to each other. Both can exists, and neither will have any effect on the other.
というわけで、Linux の場合はflock(2)とlockf(3)は互いにもう一方 がロックをかけてるのを知らない、ということになりそうです。
あれ。flock(2)もlockf(3)も、FILE *filehandleではなくint fdを引 数に取る。ということはstdioでプロセスをまたぐロックをするときはシ ステムコール(というか、えーと、stdioより低いレイヤーのストリーム )を混ぜるしかないのかな…。
混沌のまま事情を説明すると、RubyでFile#closeする前に File#flock(LOCK_UN)するのが安全かどうかを調べたかったのです。 どうも実装を見てみないといけないような気がしてきました。いつ〜
● @ITにMomongaのメンバーへのインタビューが載っている。なんとなくこそばゆい感じ。僕は最近はぜんぜんcommitできていないけれど。
● 七面鳥の英語名はトルコの国名に由来するのだそうだ。
● 内職できる機会があったので、ひたすらメールの処理を続けていた。537通あった未処理のメールが179通まで減った。358通以上のメールを読んだ計算になる。すげー…処理漏れがありそうで怖いけど。
● [run] 探検+坂コース 38分06秒
着替えて外を見ると雨が降っていたので一仕事して出直した。暗くなるまで時間がないので急な坂を含んだコースをでっちあげた。まず行ったことがなかった行き止まりの道二本を行き止まりまで往復してみてから坂の下の大学までぐるーっと回って行き、橋から急坂の道を二往復した。
1マイルあたり8.3分かかったとすると4.6マイルの走行。
● RubyのFile#flockはfflush(3)してくれる
manページをめくってみると、Cレベルではstdio.hのストリームをロックするには低位のレベルのロックを使うしかなさそう ということはわかりました。では元に戻ってRubyではどうしているか。 ソースを見てみると、flock(2)を呼ぶまえに、fflush(3)しているようで した。
ruby-1.8.5.tar.gzのfile.cを見てみました。
#ifdef
がいくつかあって(Cの)マクロ定義がどうなって
いるのか調べるのが面倒だったので、
した結果とつきあわせてfile.cから
ruby 1.8.5 (2006-08-25) [i686-linux]
のFile#flockの定
義を抜き出したのが下記です。
実はここに現れるflock()は、flock(2)そのものではなくて直前で rb_thread_flock()として定義されているflock(2)のラッパーなのですが、 今はRubyのスレッドのことは考えていないので、無視していい。よね? よね?
というわけで、RubyのFile#flockは、ストリームが書きこみ可能で開 かれている場合には、flock(2)を呼ぶ前に、fflush(3)を呼んでいるらし い、ということがわかりました。
最近のツッコまれどころ