home ホーム search 検索 -  login ログイン  | reload edit datainfo version cmd icon diff delete  | help ヘルプ

Perl/codepiece/flock01

Perl/codepiece/flock01

Perl / codepiece / flock01
id: 133 所有者: msakamoto-sf    作成日: 2007-03-14 22:57:58
カテゴリ: Perl 

Perlでのファイルのロック方法メモ

  • 基本は flock 。但し、ここで使用するLOCK_SH, LOCK_EX, LOCK_UN, LOCK_NBは、
use Fcntl(:flock);
or
use Fcntl(:DEAFULT :flock);

しておく必要がある。FcntlはシステムのCライブラリのfcntl.hをh2xsで取り込んで利用できるようにしてくれたモジュール。基本的に#defineされたものが取り込まれている。

  • :DEFAULT を指定すると、F_*, O_* 系列をデフォルトでEXPORTしてくれる。他に :flock, :seek, :mode なども指定できる。
  • flockはファイルハンドルのみを扱える。ネットワークソケットなど、Cの世界で言うところのファイルディスクリプタを生で取り扱うシーンでは、Cと同様に fcntl を使用する。
  • NFSを除くファイルシステムでのファイルのロックでは、flockで充当する。NFSにおいてはfcntlを行う必要があるらしい。これはLinuxのCレイヤーの現象らしい。

以下、参考。

Perlのflockは"advisory"ロックである点に要注意

flockのperldocにもしっかり太字で記載されていますが、Perlのflockは"advisory"ロックです。つまり、flockを使用しているもの同士であればロックは機能しますが、flockを使用せずに読み書きを行うプロセスに対しては機能しません。

実際、下のコードピースを使うと明らかです。コードピース同士でのロックは、同じflockを使用しているので、排他ロックは「その通りに」動作します。(戻り値がそのように見えます。)

しかしechoやviなどの読み書きプロセスと同時に動かして実験してみると、Perl側でLOCK_EXをかけているのに、echoシェルリダイレクトでファイルに書き込めますし、viの編集も何の問題もなく上書き保存可能です。

Perl同士でしか読み書きしないCGIのロックファイルについては有効ですが、別のプログラミング言語やプログラムなどで同時に読み書きするときは、Perlのflockが機能しない場合も有る点に注意が必要です。

コードピース(LOCK_{SH|EX|UN|NB}の実験)

標準入力からLOCK_*を受付け、コマンドラインで指定されたファイルに対してflock操作を行う。
異なる端末から二つ以上立ち上げていろいろ遊んでみる事を想定。
ここではローカルファイルシステム上のファイルをロック・アンロックする実験を行いたい為、flockで問題ない。

ファイルロックの他に、標準入力からのreadlineやswitch構文、他参考リンク。

#!/usr/bin/perl
use strict;
use warnings;
use Data::Dumper;
use Switch;
use Fcntl qw(:flock);

if(@ARGV < 1) {
	die "usage: $0 <lock_file>\n";
}

my $file = $ARGV[0];
my $lock_nb = 0;

if(! -e $file ) {
	die "$file is not exist!\n";
}
print "Lock target file is '$file'.\n";

## 通常のファイルハンドルを使用した書き方
# open my $fh, "<$file" or die "Open failure '$file'.($!)\n";

## IO::Fileを用いた書き方
my $fh = IO::File->new("+<$file");
# エラーハンドリングは$fhがdefinedか否かで判別する。
# エラーコードはシステムのerrnoなので $! を参照する。
die "Open file failure '$file' ($!).\n" unless defined($fh);

sub help {
	my ($msg) = @_;
	print "unrecognized statement: $msg\n";
	print "statement are: LOCK_SH, LOCK_EX, LOCK_UN, LOCK_NB.\n";
	print "(LOCK_NB switches LOCK_NB mode.)\n";
}

my $line = undef;
for(;;) {
	undef $!;
	unless (defined($line = <STDIN>)) {
		# if reached EOF, break loop.
		die $! if $!;
		last;
	}

	if($line !~ /^([A-Z_]+)/ ) {
		&help($line);
		next;
	}

	switch($1) {
		my $ret = 0;
		case "LOCK_SH" {
			$ret = flock($fh, LOCK_SH | $lock_nb);
			print "LOCK_SH results $ret.\n";
		}
		case "LOCK_EX" {
			$ret = flock($fh, LOCK_EX | $lock_nb);
			print "LOCK_EX results $ret.\n";
		}
		case "LOCK_UN" {
			$ret = flock($fh, LOCK_UN);
			print "LOCK_UN results $ret.\n";
		}
		case "LOCK_NB" {
			$lock_nb = ($lock_nb) ? 0 : LOCK_NB;
			print "LOCK_NB is ". (($lock_nb) ? "ON" : "OFF") . ".\n";
		}
		else {
			&help($1);
		}
	}
}
# open my $fh の場合
#close $fh;
# IO::File の場合
$fh->close;


プレーンテキスト形式でダウンロード
現在のバージョン : 2
更新者: msakamoto-sf
更新日: 2008-12-28 23:01:35
md5:1753c5ab9a39ad3a159aca4377763c0c
sha1:2b14ab5fc2c0d59949cdf1220836163354a4f9f7
コメント
コメントを投稿するにはログインして下さい。