flockについての質問

このQ&Aのポイント
  • ファイルを読み書きする場合に使用するflockですが、closeする前に別ファイルのflockは使用できるのでしょうか?
  • openとflockの使用例として、ファイルの読み書きと同時にflockを行う方法を試しましたが、確証が持てません。
  • flockを使用する中で、別のファイルのflockを使用することはできるのでしょうか?
回答を見る
  • ベストアンサー

flockについて

ファイルを読み書きする場合に使用するflockですが、closeする前に別ファイルのflockは使用できるのでしょうか? テストしてみたところ、うまくいってるような気もするのですが、確証が持てないので質問させていただきました。 例) $file1="file1.txt"; $file2="file2.txt"; open(OUT,"+<$file") flock(OUT,2); $count1=<OUT>; open(DAT,"<$file2") flock(DAT,1); $count2=<DAT>; close DAT; $count=$count1+$count2; truncate(OUT,0); seek(OUT,0,0); print OUT "$count "; close OUT; ちょっとあえて複雑な書き方としてみましたが、上記のようにflockを使ってる最中に別ファイルのflockを使用することは出来ますでしょうか? 参考URLでも結構ですので、どなたかよろしくお願いいたします。

  • hana43
  • お礼率49% (105/212)
  • Perl
  • 回答数2
  • ありがとう数3

質問者が選んだベストアンサー

  • ベストアンサー
回答No.2

> ファイルを読み書きする場合に使用するflockですが、closeする前に別ファイルのflockは使用できるのでしょうか? はい。できます。 ただ、デッドロックをしないように気をつけてください。 flockによるロックはファイルごとに設定されるので、一つのプログラムから複数のファイルを開き、それぞれにflockを発行することができます。 ちなみに、後述するドキュメントによると、OSがflockをサポートしている環境では、perlのflockはOSのファイルをロックする仕組みを呼び出し、そのファイルを独占します。一応、知っているとは思いますが、共有ロックでのflock中に別のプログラムが排他ロックをかけると、共有ロックがはずされるまでそのプログラムは待たされます。排他ロック中に他のプログラムが排他ロックをかけると、そのプログラムは排他ロックがはずされるまで待たされます。なお、ファイルのロックはファイルをcloseした時か、プログラムの実行が修了した時に自動的にアンロックされるので明示的にアンロックをする必要はありません。 参考URLとなると、これでしょうか。 Perlのflock関数についての説明です。 http://perldoc.perl.org/functions/flock.html (和訳) http://perldoc.jp/func/flock このflock(2)というのは例えばこれですね。 http://www.freebsd.org/cgi/man.cgi?query=flock&sektion=2 OSにファイルをロックする仕組みが予め備わっています。 デッドロックについては、これでも読んでください。 http://ja.wikipedia.org/wiki/%E3%83%87%E3%83%83%E3%83%89%E3%83%AD%E3%83%83%E3%82%AF 典型的な起こし方はこんな感じでしょう。 あなたが2つのプログラムを使っていて、プログラムAではfile1、file2の順でロックをとり、プログラムBではfile2、file1の順でロックを取ると、運が悪い時にデッドロックが置きます。 この状況では、プログラムAがfile1をロックした時にプログラムBが動き出し、file2をロックすることがありえますが、そうなるとプログラムAはfile2がアンロックされるのを待ち、プログラムBはfile1がアンロックされるのを待つので、どちらもアンロック待ちで止まってしまいます。 典型的な防ぎ方はロックの順序をすべてのプログラムで一定にすることです。 つまり、必ずfile1、file2の順で取るようにするなどします。そうすると、あとから来たのはfile1のロックを取れずに待っている間に先のプログラムは処理を完了させることができます。 まあ、一つのプログラムから複数のファイルを開いてロックを取れます。ただ、複数のロックを取る場合、デッドロックに気をつけてください。

hana43
質問者

お礼

ありがとうございます。 参考URLも拝見させていただき、説明も丁寧にいただきまして、とても分かりやすく理解することが出来ました。 デッドロックについては初めて聞きましたので、この機会に勉強したいと思います。 丁寧に説明いただき、ありがとうございました。

その他の回答 (1)

回答No.1

「flockを使ってる最中に別ファイルのflockを使用」できないなんて、ガセネタとしてすら一度も聞いたことがありませんね。なぜそのような発想に至ったのか謎です。 何らかのファイルを開いている間に別なファイルを 「開ける」=「アクセスできる」=「ロックできる」 と考えてみれば、当たり前だと思いませんか?

関連するQ&A

  • flockが使えない場合のスクリプトを教えて下さい

    こんにちわ。私はwindows meなのですがflockが使えないようなのでその場合はどのようなスクリプトで表現したらよいのか方法があったら教えて下さい。このflockの部分に代わるものを教えて下さい、又他の方法があればアドバイス下さい。宜しくお願いします。 open(COUNT,"+<countdata.txt") || die "File'countdata.txt'Open Error\n"; #flock(COUNT,2); $counter=<COUNT>; $counter_new=$counter+1; print"$counter_new\n"; seek(COUNT,0,0); print COUNT"$counter_new\n"; close(COUNT); #flock(COUNT,8);

    • ベストアンサー
    • Perl
  • flockについて

    http://www.freespace.jp/phpstudy.php4 のサイト様を拝見したり、フリーで配布されているスクリプトを見ると、書き込むファイルに対して、 $fp = fopen('bbs.log', 'r+'); flock($fp, LOCK_EX); … とやっていると思うのですが、perl記述のcgiで掲示板を作成したときは、書き込むファイルとは別にロック用のファイルを用意し、(perl記述です) open(LOCK,"+<$lockfile"); flock(LOCK,2); open(IN,"$logfile"); .... close(IN,"$logfile"); open(OUT,"$logfile"); .... close(OUT,">$logfile"); としていました。(書き込むファイルが2つあったのでこのような方法をとってました) そこでphpでも同じ方法は使えるのでしょうか? $fp = fopen('bbs.log', 'r+'); flock($fp, LOCK_EX); … の方法を使おうと思っていたのですが、最初にログファイルを読み込むとき、 file("bbs.log"); という風にしているので、flockに記述すべきファイルハンドルが見当たりません。仮に取得できたとしても、file();の仕様からして内部にcloseが入ってそうなので、flockできたとしてもcloseで無効になってしまわないかが心配です。なのでこの場合はやはり別にログファイルを用意しないとできないということでしょうか。

    • ベストアンサー
    • PHP
  • 同じようなソースなのですが片方だけエラーが出てしまいます。

    open(test1,"+<test1.txt"); flock(test1,2); print test1 ""; truncate(test1,tell(test1)); close(test1); open(test2,"+<test2.txt"); flock(test2,2); print test2 ""; truncate(test2,tell(test2)); close(test2); open(test3,"+<test3.txt"); flock(test3,2); print test3 ""; truncate(test3,tell(test3); close(test3); foreach(test1,test2,test3){ open($_,"+<$_.txt"); flock($_,2); print $_ ""; truncate($_,tell($_)); close($_); 上の二つのプログラムなのですが前者は問題なく出来るのですが 後者はtruncateの後にor die("$!"); とおくと"No such file or directory"と表示されてしまいます。 3つともループせずにやるかforeachでやっているかだけで ソース的には同じだと思うのですが何が違うのでしょうか・・・?

    • ベストアンサー
    • Perl
  • Perlのtruncateについて

    + test.txt 0 1 2 3 + main.cgi open(FH, "+<test.txt"); my @Log = <FH>; truncate(FH, 0); seek($FileHandle, 0, 0); print(FH "4"); close(FH); これで、main.cgiを実行すると、test.txtの中身は 4 1 2 3 となってしまいます。truncateがきいてないようなのですが、なぜでしょうか。 truncate(FH, 0) or die "error"; とすると、errorと表示されてしまいます。 なぜこうなるのでしょうか。 致命的エラーがでるわけでもないので、環境が悪いわけではないような気がするのですが。 flockをしたいのですが、他にファイルの中身を空にする方法とかありませんか。

    • ベストアンサー
    • Perl
  • ログの一部を消す Perl

    ログの一部を消すPerlを考えています。 ここではソースを短くするために、ログの一部を消し去って ログファイルに上書きするデータは $deta だけだとすると open F, '+<a.log'; flock F,2; $deta = <F>;//実際はここでもっと処理 truncate F,0; seek F,0,0; print F $deta; close F; と、 open IN, 'a.log'; flock IN,2; open OUT, '>a.log'; flock OUT,2; $deta = <IN>;//実際はここでもっと処理 print OUT $deta; close OUT; close IN; の2つを考えました。 上のように 読み込み と 書き込み を同時にやった方がいいのか 下のように分けてやった方がいいのか教えてください。 ロックは flock を使って、普通レベルのロックが できるぐらいでいいと思っているんだけど、 この flock の書き方でおかしいところがあれば 教えてください。

    • ベストアンサー
    • CGI
  • openでのファイルの書き込みについて

    現在、メールを受信した際に、そのメールを別のアドレスに転送し、さらにサーバーに保存する、といったプログラムを作成しています。 メールを転送する処理が無事完成し、いざ書き込みを、と思っていたのですが ファイルの書き込みがうまくできません。 メール受信時に、以下のようにメールフィルターの振り分けにて動作させています。 | /usr/bin/perl /home/hoge/public_html/piyo.cgi 書き込み処理はこのようにしています。 open(OUT, "+>foo.txt") or die "Can't open : $!"; flock(OUT, 2) or die "Can't flock : $!"; seek(OUT, 0, 0) or die "Can't seek : $!"; print OUT "piyo\n"; truncate(OUT, tell(OUT)) or die "Can't truncate: $!"; close(OUT); とくにdieで処理が終了しているわけではなく、この後の処理も正常に行われているのですが foo.txtへの書き込みが行われません。 また、メール受信時ではなく、通常アクセスでの場合はこの処理でファイルが正常に書き込まれることを確認しました。 エラーがでてとまるわけではなく、状況がわからず困っております。 皆様の知恵をお貸しください。よろしくお願いいたします。

    • 締切済み
    • CGI
  • flockのタイミング

    掲示板のスクリプトを作っています。 ログは1行ごとに1記事分のデータが格納されているので、書き込み処理の場合は、 $lines = file("./log.dat"); としていったん配列にログを読み込み、 array_unshift($lines, $new_data); 等して、新しい記事のデータを配列の先頭に追加し、 $fp = fopen("./log.dat", "wb"); foreach ($lines as $line) { fputs($fp, $_); } fclose($fp); として、最終的にログに書き込みます。 Perlを扱っているときは(複数更新すべきログファイルがあったので)、別途ロックファイルを作ってそれに対してflockをかけるという方法を行っていましたが、今回はログファイルが1つであるのでそのログファイル自体にflockをかけようと思っています。 しかし、fileで最初にopenしているため、ファイルポインタが取得できず、flockをかけるタイミングは、本当の書き込み作業の部分(fopen)からかけるしかなさそうなのですが、これは危険ではないでしょうか? それと、マニュアルに、 注意: flock()は、ファイルポインタを必要とするため、 (fopen()へ引数"w"または"w+"を指定して)書き込 みモードでオープンすることにより丸めるファイルにアクセス保護する 特別なロックファイルを使用する必要があるかもしれません。 とかいてありますが、この意味がいまいちわからず、困惑しています。

    • ベストアンサー
    • PHP
  • 入出力共用が出来ないんです

    カウンターを作ろうとしてるんですけど、入出力共用が出来ないんです。 その部分は open INOUT, "+>$txt";       #$txtはテキストファイルへのアドレス $count = <INOUT>; $count++; print INOUT $count; close INOUT; ってやっています。ここだけコマンドプロンプトで試しているんですが、上手く動きません。"+>$txt"を"+<$txt"としたり、">+$txt"にしたり、最後には、">+<$txt"といろいろ試したんですがダメでした。 ちなみに open IN, "<$txt"; $count = <IN>; close IN; $count++; open OUT, ">$txt"; print OUT $txt; close OUT; ってやると動きます。別にこれでもいいんですが、本には共用出来ると書いてあるのに出来ない、なんかすっきりしません。 入出力共用って出来ないんでしょうか?

    • ベストアンサー
    • CGI
  • TXTファイルに文字を入れ込む事が出来ない

    下記のような方法でファイルを書き込みたいと思っていますが、書き込まれずにいつまで立っても白紙のままです。 どうかご指摘頂けないでしょうか? お願いします。 $in_file = "oyamanew.txt"; if ( !open( IN_FILE, "+<$in_file") ){ print "INファイルのオープンに失敗しました。"; exit; } @record = <IN_FILE>; $record[0] = "$ROWKDATA[3]\n"; seek( IN_FILR, 0, 0 ); print IN_FILR @record; truncate( IN_FILE, tell( IN_FILE ) ); close( IN_FILE );

  • カウンタのcgiについて教えてください。

    カウンタのcgiについて教えてください。 open(File,"+<count.dat")or die("エラー"); eval{flock(File,2);}; $count=<File>; seek(File,0,0); print File++$count; close(File); print<<END; Content-type:text/html <html> <head> <title>タイトル</title></head> <body>$count人目の訪問者です </body> </html> みたいな感じでカウンタのcgiを作りました。 (Perl・Apache) (携帯からなので、見にくい感じはご容赦ください) これを別htmlファイルにiframeで組み込みました。 今は、単純にファイルが開かれたら+1なので、F5などで更新してもカウントされます。 これを同一IPもしくはコンピュータ名からの連続更新はカウントしないようにするのはどのように書き加えればいいのでしょうか? また、総カウント数だけでなく、昨日のカウント数、今日のカウント数、今月、先月などで集計するためにはどのようにすればよいのでしょうか? わかりにくいかと思いますが、お願いいたします。 m(__)m

    • ベストアンサー
    • CGI

専門家に質問してみよう