プロが教える店舗&オフィスのセキュリティ対策術

複数プロセス間で、一つのファイルに対して読み書きしたいです。
その際、ファイルへの書き込み中は、ファイルの読み込みを抑止したいです。
また、読み込みの処理はファイルのロックを参照するだけで、ファイルへのロックは掛けない様にしたいです。

そこで、以下二つプログラムを作成して、簡単な検証を行いました。

■プログラム1
キーボードからの入力があるまで、ファイルをロックする。

#!/usr/local/bin/ruby
file='./hoge.txt'

f=open(file,'r+')
ret=f.flock(File::LOCK_EX|File::LOCK_NB)
STDOUT.write 'Hit any key'
STDIN.gets.chomp

■プログラム2
ファイルがロックされているか状態を取得する。

#!/usr/local/bin/ruby
require "fcntl"
file='./hoge.txt'
f=open(file,'r')
arg=""
f.fcntl(Fcntl::F_GETLK,arg)
l_start,l_len,l_pid,l_type,l_whence = arg.unpack('VVVSS')
puts l_len


※プログラム2は、fcntlの使い方がマニュアルを読んでもよく理解できなかったので、
手探りで記述しました。

実行すると、プログラム1はエラー無く動きましたが、プログラム2は以下の様なエラーが
出てしまいます。

fcntl.rb:6:in `fcntl': Invalid argument - ./hoge.txt (Errno::EINVAL)
from fcntl.rb:6

環境は、unixレンタルサーバ(FreeBSD)です。

上記方法では、上手くいきませんでした。

flockでファイルにロックが掛っているか否かを、そのファイルにロックを掛けることなく
調べるにはどうしたら良いのでしょうか?

ご指導のほど、宜しくお願いいたします。

A 回答 (2件)

これはRubyというより、Unixの問題ですね。


flockのロックはファイル全体のロックで、fcntlのロックはファイルの中のl_startバイト目からl_lenバイトの領域に対するロックですので、全く別のものです。両方同じ方式を使う必要があります。

flockを使うとすると、

#!/usr/local/bin/ruby
file='./hoge.txt'

f=open(file,'r+')
ret=f.flock(File::LOCK_EX|File::LOCK_NB)
if ret
puts "ロック成功"
STDOUT.write 'Hit any key'
STDIN.gets.chomp
else
puts "ロック失敗"
end

#!/usr/local/bin/ruby
file='./hoge.txt'
f=open(file,'r')
ret=f.flock(File::LOCK_SH|File::LOCK_NB)
if ret
f.flock(File::LOCK_UN)
puts "ロックされていなかった"
else
puts "ロックされていた"
end

fcntlでロックするなら、arg="" じゃなくて、man 2 fcntl を見てstruct flockの内容をセットしたものをargとして渡さないといけません。
    • good
    • 0
この回答へのお礼

notnotさん、ご回答ありがとうございます。

File::LOCK_SHは、既にFile::LOCK_SHで掛けられたロックに対しては
ロックを掛けられるが、File::LOCK_EXで掛けられたロックに対してはロックが掛けられないんですね。

これで、読み込み同士は干渉せずに、書き込み中は読み込みを抑止が実現できるのは解ったのですが、

色々試してみると、読み込みで掛けたロック(File::LOCK_SH)中は、書き込みでFile::LOCK_EXのロックが掛かられませんでした。

他プロセスが読み込み中でも、書き込みは出来るのが望ましいのですが、これを実現するのは、ファイルのロックを利用するだけでは無理って事なんですね。

お礼日時:2009/11/21 19:43

排他ロック(LOCK_EX)と共有ロック(LOCK_SH)については理解されたようですね。



読み取りに関係なく書きたいのであれば、読み取り側でロックせずに読めばいいです。質問では「排他ロックがかかっているかどうか知りたい」ということのようですが、何のために知りたいのですか?
    • good
    • 0
この回答へのお礼

notnotsaさん、ご回答ありがとうございます。

>読み取りに関係なく書きたいのであれば、読み取り側でロックせずに読めばいいです。質問では「排他ロックがかかっているかどうか知りたい」ということのようですが、何のために知りたいのですか?

最初に質問した時は、
『他者が書き込み中には書き込みも読み込みはできない』
を実現したいと考えていて、『他者が読み込み中の書き込み』についてはあまり考えていませんでした。

他者が読み込み中でも、他者が読み込んでいる時点のデータを保障しつつ、書き込みが可能って仕様が好ましいのですが、これはファイルのロック機構でなんとかなるものでは無いので、「排他ロックがかかっているかどうか」についは、もうどうでもいいです。

結局、ファイルのロックは使わずに、先ずはテンプファイルに書き込み、
書き込み終了と共にrenameって方法にしました。

お礼日時:2009/11/23 15:07

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