アプリ版:「スタンプのみでお礼する」機能のリリースについて

cgiで簡易chatを作っているのですが、
open(FILE, "<", $DATAFILE);
flock(FILE, 2);
・・・・・・
open(FILE, ">", $DATAFILE);
・・・・・・
close(FILE);
最初にファイルをロックをかけたまま最後に閉じるまで
ロックはかかったままになるでしょうか。

質問者からの補足コメント

  • どう思う?

    質問があいまいでした。
    1.openで開いたファイルをcloseで閉じないで、同じファイルハンドルで別モードで開きなおすことはできますか?
    2.1が可能なら最初にopenした時にロックをかけていた場合、開きなおしたときにロックは継続されていますか?
    よろしくお願いします。

    No.1の回答に寄せられた補足コメントです。 補足日時:2023/05/02 15:13
  • へこむわー

    理解できたと思って、プログラムを修正したのですが、チャットを打つとデータが消えてしまいます。
    修正した内容は次の通りです。
    open($fh1, "<", $DATAFILE);
    flock($fh1, 2);
    ・・・データを読み込みそれに変更を加える・・・
    open($fh2, ">", $DATAFILE);
    ・・・データの書き込み・・・
    close($fh2);
    close($fh1);

    No.3の回答に寄せられた補足コメントです。 補足日時:2023/05/03 21:05
  • どう思う?

    次のように修正したらデータが消えることはなくなりましたが、
    同時に書き込まれた時のロックが正しく機能してるかどうかは検証してません。
    (検証の仕方がわからない)

    if (! -f $DATAFILE) {
    open(FH, ">", $DATAFILE);
    close(FH);
    }
    open(FH, "+<", $DATAFILE); # データファイルを読み書きモードで開く
    flock(FH, 2); # ロックをかける
    ・・・データを読み込み修正する・・・
    seek(FH, 0, 0);
    ・・・データを書き込む・・・
    truncate(FH, tell(FH));
    close(FH); # closeと共にロック解除

    これで問題ないでしょうか

      補足日時:2023/05/04 12:44

A 回答 (3件)

>ロックはファイルハンドルが指すファイルにかかっているのですか?


https://linuxjm.osdn.jp/html/LDP_man-pages/man2/ …
――によると「flock() によって作られるロックは、 オープンファイル記述 と関連付けられる」とあるので、厳密にいえばロックとファイルは別物かと。

ロックの存在にかかわらず、ファイルに対するopen()は何度でも実行可能です。
それとは別の話で、ロックによりflock()の実行で処理がブロック(=排他制御)されます。
この回答への補足あり
    • good
    • 0
この回答へのお礼

回答ありがとうございます。
なるほど、ロックされているファイルでも後から自由にオープンできて(ロックとは無関係でこのオープンの時に排他制御は働かない)、後からオープンしたあとそのファイルにロックを試みた時に初めてロックされていたら排他制御されるということですね。
CGIのchatプログラムをいろんな場所から同時に動かしたとして、
最初の人が
open($fh1, "<", $datafile);
flock($fh1, 2);
を実行して、次の人が
open($fh2, "<", $datafile); #--->1
flock($fh2, 2); #--->2
を実行した場合
1の所では$datafileに最初の人がロックをかけててもオープンは自由にできて
2の所で$fh2ファイルハンドルが指す$datafileファイルに対してロックをかけようと試みるが、$datafileに対してロックをかけているファイルハンドルが存在するので2の処理は排他制御により最初の人のロックが解除されるまで待つことになるということですね。

お礼日時:2023/05/03 19:29

>同じファイルハンドルで別モードで開きなおすことはできますか?



open(FILE, "<", $DATAFILE);
flock(FILE, 2);
open(FILE, ">", $DATAFILE);
――と書いたとき、3行目のopen()は成功しますが、1行目のファイルハンドルFILEはいったんクローズされます。2行目のロックはクローズされたとき解除されます。

open(FILE, "<", $DATAFILE);
flock(FILE, 2);
open(ANOTHER_FH, ">", $DATAFILE);
――なら別です。異なるファイルハンドル指定であれば、1行目のFILEはクローズされてませんので、2行目のロックはかかってます。
また、問題なくopen()は成功します。何度でも。回答No.1はこの意味です。
3行目で$DATAFILEは空になります。

下記はサンプル。コメントアウトを外すと挙動が変わります。
system( 'echo OK >a.txt;cat a.txt' );
my $f1, $f2, $f3;
open( FH, '<a.txt' ) or die; $f1 = fileno( FH );
flock( FH, 1 ) or die;
#if ( fork() == 0 ){ sleep 5; exit( 0 ); }
#open( F2, '<a.txt' ) or die; $f2 = fileno( F2 );
#flock( F2, 1 ) or die;
#print "F2:",scalar( <F2> );
open( FH, '>a.txt' ) or die; $f3 = fileno( FH );
flock( FH, 2 ) or die;
print "FH:",scalar( <FH> ),"\n";
printf "fileno: FH=%d,F2=%d,FH(re)=%d\n", $f1, $f2, $f3;
system( 'cat a.txt' );
    • good
    • 0
この回答へのお礼

回答ありがとうございます。
すいません私にはちょっと難しくてサンプルを理解できませんでした。
ロックはファイルハンドルが指すファイルにかかっているのですか?
そうだとすると別ファイルハンドルで同じファイルを開こうとするとロックがかかっていて開けないと思うのですがどうでしょうか。
もしかして同じプロセス内からだとロックをかけたファイルでも別ファイルハンドルで開くことができるということでしょうか?

お礼日時:2023/05/03 09:51

答えとしてはYesです。


ロックしてるしてないに拘わらずopenできますし、書き込みや削除もできます。
※OSによっては削除できない場合もあります。
この回答への補足あり
    • good
    • 0
この回答へのお礼

回答ありがとうございます。
2回目openしたときにロック解除にはならないで、そのままロックが継続されるのですか?

お礼日時:2023/05/02 15:07

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!