PerlでNFS上のファイルロックの仕方

Perlでよく使われるflockはNFS上のファイルをロックする保障がされていません。
そこでfcntlを使ってファイルロックすることにします。


ケータイ・セカンドライフ対応
動画共有サイト「モヴィエ」
大容量ファイル転送サービス
デカメール
エーエイチレフ運営
株式会社シーズ

NFS上のファイルをflockでファイルロックできるのか?検証
Debian Etchを使ってNFS上のファイルをflockでロックするとどうなるか?
ロックはできましたが、ロックが開放されません。プロセスが終了すればロックが解除されますが、同じプログラム内で2回以上ロックするような処理では 画面が固まってしまう現象がありました。
他にもロックすらできない現象もありますが、kernelのバージョンとNFSのバージョンによって挙動はさまざま。保障外ですから。比較的に新しいkernelとNFSのバージョンで おかしな挙動するようです。




fcntlを使ってみよう
perlでファイルロックの仕方はflock以外にもlockfやfcntlがありますが、今回はfcntlを使ったファイルロックの仕方を説明します。
fcntlはこのように使います。

#!/usr/bin/perl

use Fcntl;

my $filepath = '/home/hoge/test.txt';
my $sdata = 'test';

# ロックのオプションを設定
my ($locked) = pack("ssL", Fcntl::F_WRLCK, 'SEEK_SET', 0);   @
# ロック解除のオプションを設定
my ($unlocked) = pack("ssL", Fcntl::F_UNLCK, 'SEEK_SET', 0);   A

# ファイルオープン
open(F, "+< $filepath") or &error($filepath);

# ロック
fcntl(F, F_SETLK, $locked) or &error('ロックできませんでした。'." $$ @_: $!");   B

# ファイル書き込み
truncate(F, 0);
seek(F, 0, 0);
print(F $sdata);


# 解除
fcntl(F, F_SETLK, $unlocked) or &error('ロック解除できませんでした。');   C

close(F);

print
"Content-type: text/html; charset=EUC-JP\n\n";
print "OK!";
exit;


sub error {
   my $data = shift;
   print
"Content-type: text/html; charset=EUC-JP\n\n";
   print $data;
   exit;
}


@ A
fcntlの第3の引数に渡す構造体を作成します。perlの場合、packする必要があります。

B
fcntl関数でロックします。
第1引数:ファイルハンドラ
第2引数:オプションです。今回ロックするために必要なオプションを紹介します。
【F_SETLK】ファイルのロックする場合、既にロックされている場合エラーを返します。
【F_SETLKW】ファイルのロックをする場合、既にロックされている場合は解除されるまで待ちます。
第3引数:@ Aでpackしたスカラー変数


C
ロックしたファイルを解除します。この一行を書かなくても、ファイルをcloseすればロックは解除されます。

NFS上でファイルをロックするためのサーバ設定
NFS上のファイルをロックするためにはNFSサーバ側とマウントする側のどちらにもstatdとlockdが必要になってきます。
DEBIANの場合apt-get install nfs-commonしてnfs-commonを起動するとstatdとlockdが立ち上がります。
これをしないとNFS上のファイルをロックできません。




ご意見、ご質問、間違いの訂正等大歓迎です。info@ahref.org



©2007ahref.org