CGIの基礎知識

このエントリーをはてなブックマークに追加
1monalove
基本に立ちもどって、CGIに関する技術的な解説を試みるスレッドです。
内容はAS-ISで、無保証です。
2monalove:2000/07/08(土) 15:14
「危険領域」について。

CGIとして実行するプログラムは、複数個のプロセスとして同時に起動され、
並行して動作することがあります。そして、プログラムが行う処理のなかには、
必ず単一のプロセスが連続して行わなければならない(複数のプロセスが個々
に並行して行ってはいけない)処理があります。このような処理を行う部分を、
「危険領域」(critical section)と呼びます。

危険領域で行うべき処理とは、複数のプロセスが共有するファイル(資源)を参
照/更新するような処理です。たとえば、カウンタであれば、1)現在のカウン
タ値をファイルから読み込み 2)カウンタ値をインクリメントし 3) カウンタ
値をファイルに書き込む という一連の処理は、危険領域として分離する必要
があります。なぜなら、カウンタ値をファイルから読み込んで、ファイルに書
き戻すまでは、ファイルに存在する値と、メモリ上の変数に格納された値とが
食い違う不安定な状態にあるからです。このような状態を、「競合状態」
(race condition)と呼びます。
3monalove:2000/07/08(土) 15:14
たとえば、プロセスPが1)の処理を開始してカウンタ値"50" を読み込んだ後、
"51" を書き戻す前に、別のプロセスQが1)の処理を開始した場合を考えてみま
す。プロセスQ はファイルからカウンタ値"50"を読み込むことになるので、プ
ロセスPとプロセスQ は、共に同じカウンタ値を表示することになってしまい
ます。プロセスQがファイルから読み込むカウンタ値は、"51"でなければいけ
ません。

逆に、複数のプロセスが共有するファイル(資源)とは関係のない処理、実行し
ているプロセスの中だけで完結してしまう処理は、危険領域として分離する必
要はありません。カウンタの例でいえば、プログラムが起動されてからカウン
タ値を読み込む直前までの初期設定等の処理、また、カウンタ値を書き戻して
からプログラムが終了するまでの、カウンタ値に基いたビットマップ画像の生
成処理などが相当します。

危険領域として分離すべき処理は、正しく分離しなければ誤動作の原因になり
ますが、危険領域に含める必要のない処理を危険領域に含めてしまうのは、
(カウンタのような単純なプログラムの場合は)無害です。
4monalove:2000/07/08(土) 15:15
「ファイルロック」について。

同時にたった一つのプロセスだけが実行できる危険領域を実現するために、
CGI で使用するのが、ファイルロックです。ファイルロックは「相互排除」
(mutual exclusion/略してmutex)の一種です。ファイルロック以外にも、相互
排除を行う方法はありますが、ファイルロックがUNIX 系のOSでは最もポピュ
ラーで、最も効率が良いです。

理解を容易にするために、ファイルを「カラオケボックスの個室」に喩えてみ
ます。ファイルのオープンは、「個室に入ること」であり、ファイルロックは
「マイク」です。危険領域で行う処理に相当するのは、歌を歌うことです。

歌を歌うには、まず個室に入ります(ファイルのオープン)。個室には誰でも、
同時に何人でも入れます。

個室に入った人間は、次にマイクを取ろうとします(ファイルロックの獲得)。
5monalove:2000/07/08(土) 15:16
マイクは各個室の中に一つずつ置かれています。誰も歌っていなければ、マイ
クは簡単に手に入りますが、誰かがマイク片手に歌っているときは、その人が
マイクを手放すのを待つことになります。個室の中に何人も人がいて、皆がマ
イクを欲しがっている場合、マイクの順番が回ってくるのを待つことになりま
す。いずれにせよ、マイクは一つしかないので、同時に歌うことのできる人間
は、必ず一人であることが保証されます。一本のマイクで、二人が歌を歌うこ
とはありません。

危険領域は、ファイルロックを使って、このようにして実現されます。

マイクを持たなくても地声で歌うことができるように、ファイルロックを獲得
しないまま危険領域の処理を実行することは、残念ながらできてしまいます。
エラー等は発生しません。操作に先立ってファイルロックの獲得を試みるのは、
「仲間同士でそういうお約束になっている」のに過ぎません。約束を無視する
と、危険領域が危険領域でなくなり、処理に異常をきたすので、そのような誤
りが混入しないよう、プログラミングする側が注意する必要があります。
6monalove:2000/07/08(土) 15:17
では、別スレ http://tako.2ch.net/test/read.cgi?bbs=perl&key=962797645
の110より提起された、「perlのflock()関数の呼び出しは、実際にはOSの提供
するシステムコールflock()等を呼び出している。このため、実際にロックさ
れるまでには、わずかな隙があるのではないか」という疑問について検討して
みます。

perl scriptで書かれた処理のロジックを、以下のように模式化したとします。

: <routine-A> <flock(LOCK_EX)> <routine-B> <flock(LOCK_UN)> <routine-C>

routine-Aが前処理、routine-Bが危険領域、routine-Cが後処理です。
routine-Bはファイルロックの獲得と解放によって囲まれることで、危険領域
を実現しています。同時に動く他のプロセスがあっても、ファイルロックを獲
得してroutine-Bを実行できるのは、同時にたかだか一つのプロセスです。
これを、routine-Bは他のプロセスを排他して実行される、といいます。

routine-Bが subroutine B1とB2で構成されているとき、(プロセスの実行が中
断しない限り)B1とB2は、必ず同じプロセスによって、連続して実行されます。
プロセスPがB1やB2を実行している最中に、別のプロセスQがB1の実行を始める
ことはありません。110の言うところの「アトミックであることの保証」とは、
このことです。危険領域の中の一連の処理は、アトミックであることが保証さ
れます。逆に、危険領域でないroutine-Aやroutine-Cは、アトミックであるこ
とが保証されません。たとえば、プロセスPがroutine-Aを実行中に、別のプロ
セスQがroutine-A やB, Cを実行することがあり得ます。
7monalove:2000/07/08(土) 15:18
さて次に、perl programのflock()関数がどのように実装されているかを見て
みます。perl 5.0のソースでは、pp_sys.cのpp_flock()関数が該当しますが、
これは以下のようなロジックに模式化することができます。

: <routine-A'> <flock(fd, arg)> <routine-B'>

routine-A'が、引数取得などの前処理、flock()がflock(2)システムコール呼
び出し、routine-B'が戻り値のpushなどの後処理です。実際には、インタプリ
タなど諸々の内部処理がその前後に加わります。いずれにしても、routine-A'
とB'は、プロセスの内部で処理が完結しており、複数のプロセスが共有するファ
イルや資源にアクセスすることがありません。つまり、routine-A'とB'は複数
のプロセスが同時に実行してもよく、危険領域として分離する必要はない処理
です。

flock()システムコールの呼び出し以降は、他のプロセスが排他されているこ
とを保証します。つまり、flock()システムコールの呼び出しを境に、前は危
険領域ではなく、後ろは危険領域になります。
8monalove:2000/07/08(土) 15:19
模式化されたロジックを、前述のロジックの前半部分に埋め込んでみます。

: <routine-A> <routine-A'> <flock(fd, arg)> <routine-B'> <routine-B>

routine-Aはperl scriptで記述された前処理、routine-A'はperl programとし
て記述された、flock()システムコールの呼び出しに先立って実行する処理で
す。いずれもflock()システムコールの呼び出しよりも前なので、危険領域で
はなく、つまり他のプロセスを排他していません。が、前述のように、これら
の処理は排他する必要がありません。つまり、routine-Aとroutine-A'が危険
領域でないことによる問題はありません。

routine-B'はperl programとして記述された、flock()システムコールの後処
理であり、routine-Bはperl scriptで記述された危険領域の処理です。これら
はいずれもflock()システムコールの呼び出しよりも後なので、危険領域に含
まれます。routine-B'は他のプロセスを排他する必要がない処理ですが、その
ような処理が危険領域に含まれるのは問題がありません。

つまり、perl scriptが呼び出したflock()関数を、perl programが解釈してOS
のflock()システムコールを呼び出すとき、システムコールの呼び出しの前後
に、隙は *一切* ありません。
9monalove:2000/07/08(土) 15:19
留意すべきは、ファイルロックの獲得が、単一のflock()システムコールの呼
び出しによって実現されていることです。もしも仮に、複数のシステムコール
によって実現されていた場合、

: <routine-A'> <flock-x()> <flock-y()> <routine-B'>

flock-x()とflock-y()システムコールの呼び出しの間に、隙が生じます。この
ようなことがないように、OSのシステムコールは設計されています。
10monalove:2000/07/08(土) 15:19
では、もっとシステムの奥深くに辿ってみます。perl programからのflock()
システムコール呼び出しはどのように実行されるのでしょうか。FreeBSDを例
にとりますが、システムコールの呼び出しはライブラリlibc内の関数
/usr/src/lib/libc/i386/sys/syscall.S に記述されており、そのロジックを
模式化すると以下のようになります。

: <routine-A''> <int 0x80h> <routine-B''>

int 0x80hは、0x80h番のソフトウェア割り込みの呼び出しです。OSを呼び出す
特殊なサブルーチンコール命令と考えてください。routine-A''はシステムコー
ル番号等設定等の前処理、routine-B''は後処理です。routine-A''とB''はい
ずれも、プロセスの内部で処理が完結しており、複数のプロセスが共有するファ
イルや資源にアクセスすることがありません。つまり、排他する必要がありま
せん。

ここまで書くと説明しなくてもわかるかと思いますが、int 0x80hの呼び出し
を境に、後ろの部分は危険領域となります。routine A''とroutine-B''はとも
に他のプロセスを排他する必要のない処理なので、ソフトウェア割り込みの呼
び出しの前後に、隙は *一切* ありません。
11monalove:2000/07/08(土) 15:21
さらにシステムを深く辿ると、OSのカーネルによるflock()システムコールの
実装部分に辿りつきます。ここで例にあげているFreeBSDは、非プリエンプティ
ブなモノリシックカーネル構成を採用しています。これは、あるプロセスの、
flockのような単純な(メモリ上だけで処理が済む)システムコールを処理して
いる最中に、他のプロセスのシステムコールを処理することがない、というこ
とを示しています。つまり、カーネルの内部、システムコールの処理に着目し
ても、ファイルロックを獲得する前後に隙は *一切* ありません。

他のシステム・OSであっても、同じです。SMP構成のFreeBSDシステムの場合、
複数のCPUが並行しげプロセスを実行しますが、カーネルのシステムコールを
処理することのできるCPUは、同時にはたかだか一つに制限されています。ファ
イルロックを獲得する前後に隙は *一切* ありません。

カーネルがマルチスレッド構成を持つSolarisの場合、複数のCPUが、同時に複
数のプロセスのシステムコールを処理できます。しかしこの場合でも、カーネ
ル内部の相互排除機構を使用して、ファイルロックを実際に獲得する処理が競
合状態にならないよう、注意深く設計されています。カーネル内部の相互排除
機構は、CPUがハードウェアで提供する機能を利用しています。隙は *一切*
ありません。

以上の理由により、perlのflock()関数の呼び出しが、OSの提供するシステム
コールを呼び出しに変換されるために、実際には微細な隙が生じる、というこ
とはない、ということが、おわかりいただけるのではないかと思います。

…ていうか、おわかりいただいてくれ。これ以上わかりやすく書けといわれたら死亡。
12名無しさん:2000/07/08(土) 19:00

             / ̄ ̄⌒V⌒ ̄ ̄ヽ― 、
           / / ̄ ̄\V/ ̄ ̄ヽ-、 \
          /  / ̄ ̄\    ̄ ̄\ \ ヽ
          / /  ,― ' ̄⌒V⌒ ̄ヽ― 、_   ヽ
         |  /               \  |
         |  /                  | |
         | / /// /ノノ∧ヽヽヽヽ\ \ ゝ| |
         ∠/// /Vノノ  ヽヽヽヽヽ\ \ ) /
         _VVノ ノノ ノ   V V V  V  /
        /〆ヽ --―-- \≡≡/--―--  /⌒)
        ヽ6 ヽ   __  | | ____   / 8)    ________
        ∠(ヽヽ\/ ○ l\ /l ○ \/ |/)   /
         (/)ヽ~\___/  | |  \___/~  /(/) <  おいぃーーーッス。
         (\ )ヽ \   /_ヽ   / / (ヾ )  \
         (/)  ヽ  | / ____ \ |  /  (/)   \_______
         (\ )   \| /  \ | /   (\)
         (/)     ヽ ̄ ̄ ̄/     (/)
         (\)   /(|   ̄   |)\    (\)
          ――' ̄   ヽ      /   ̄ ̄ヽ―― 、
                 ヽ    /

13名無しさん:2000/07/09(日) 00:21
複数ファイルを同期(?)させながら更新したい場合、flockは
使えるのですか?

いわゆる lockfile を作らないと無理な気がするんだけど、
何せ厨房なものでようわからんのです…。
14>12:2000/07/09(日) 00:30
惚れた
15名無しさん:2000/07/09(日) 00:52
議論はやがて収束する・・・
16monalove:2000/07/09(日) 00:56
>13
使えます。

flock()によるファイルロックは、危険領域を実現するために使用します。操
作の対象となるファイルが単一であるか複数であるかには全く関係なく、「適
当な」一つのファイルをロックすればよいのです。

実は、ロックする対象は、読み書きを行うファイルそのものである必要はあり
ません。処理とは無関係なダミーのファイルをロックファイルとしても、相互
排除に関してはなんら不都合は生じません。通常そのようにしないのは、ロッ
クのためだけにダミーのファイルを用意しオープンするのが無駄だからです。

処理対象のファイルが複数ある場合は、そのうちのいずれか一つをロックの対
象と決め、全てのプログラムが危険領域の直前でそのファイルをロックするよ
うにすれば、相互排除が実現できます。異なるファイルをロックするプログラ
ムがあると、「マイクが2本(以上)ある状態」になってしまい、相互排除が不
完全になってしまうので注意してください。

処理対象のファイルが複数あっても、相互排除の原則は変わりません。プログ
ラムの中で、ファイル上とメモリ上とで(少しでも)状態が異なる可能性がある
個所は、全て危険領域に含まれるように、ロックとアンロックの位置を決定し
てください。
17monalove:2000/07/09(日) 01:02
嘘あるいは電波書いてたらツッコミ入れてください…。
勉強し直します。
1813:2000/07/09(日) 01:10
ありがとうございます。つまり、

if( flock( どれかのファイル ) ){
 複数ファイルを操作…
}
else{ エラー }

ってことですか?
19名無しさん:2000/07/09(日) 01:15
evalによる呼び出しだとどうでしょう?
flockサポートしていないOSの場合のために、
eval{flock();};とかよくしますが。
20japu:2000/07/09(日) 01:39
ロックできてないのにロック出来てるふりして動くより、死んでくれたほうが有難いと思うが...
21名無しさん:2000/07/09(日) 01:41
flockでロックしたいファイルがNFS上にあると
flockが成功しても排他制御が上手くいかないという話を
よく耳にしますが、
そういう場合はどうしようもないんでしょうか?
22japu:2000/07/09(日) 01:59
そういうときはflockがうまくいく保証が無いので、symlinkとかmkdirを使ってロックかけるしかないのでは?
2321:2000/07/09(日) 08:28
やっぱそれしかないですよねえ。
http://tako.2ch.net/test/read.cgi?bbs=perl&key=961217263
↑の22の言ってることが気になるところです。
24monalove:2000/07/09(日) 08:52
おはようございます。今朝の私のドジを晒します。自戒の意味を込めて書きま
すが、エラーのハンドリングは常に行うよう心掛けましょう。

flock()の挙動を確認しようとして書いた以下のスクリプトは、エラーを出さ
ずに終了しますが、実際にはファイルをロックしません。

#!/usr/bin/perl
use Fcntl;
open(F, ">foo");
flock(F, LOCK_EX);

use行で':flock'タグが欠けているために、LOCK_EXが定義されず、flock(F,
0); として評価され、flock()がエラーになるからです。しかしこのスクリプ
トではエラーメッセージを出力しないので、その誤りに気付くのは難しい。

誤りに迅速に気付くために、以下のように記述する方がよいです。

#!/usr/bin/perl -w
use Fcntl ':flock';
open(F, ">foo") || die $!;
flock(F, LOCK_EX) || die $!;

perlの-wオプションは、未定義のシンボルの使用に関してwarningを出します。
これにより、つまらないタイプミスに起因するバグはチェックできるようにな
ります。

失敗する可能性のある関数の呼び出しは、戻り値をチェックします。"die $!"
は、失敗の原因に関する有用なメッセージ("Bad file descriptor"等)ととも
に終了します。エラーメッセージの意味については、UNIXならばman errno と
して、オンラインマニュアルを参照してください。
25monalove:2000/07/09(日) 08:54
>18
同じことですが、もう少し別の書き方をすると

1. オープン(FILE1)
2. ファイルのロック(FILE1, LOCK_EX)
3. 一連の処理 # 危険領域
2. ファイルのアンロック(FILE1)
4. ファイルクローズ(FILE1)

です。(エラーのハンドリングは個々に行ってください)

ファイルのアンロックは省略できます。ファイルをクローズする際に、そのファ
イルのロックが獲得されたままであれば、OSによって自動的にアンロックされ
るからです。

逆に言うと、危険領域の一連の処理の最中に、ロック対象のファイルの読み書
きが終わったからといって、ファイルをクローズしてはいけません。ファイル
がアンロックされ、相互排除がそこで終わってしまうからです。ファイルをク
ローズは、危険領域の処理が終了するまで遅延してください。

ロック対象のファイルをオープンしたままプロセスが終了した場合(異常終了
も含む)も、OSによって自動的にアンロックされます。flock()によるファイル
ロックは、(プロセスが無限ループ等で生きのこったままにならない限り)ロッ
クされたまま、ということがありません。
26monalove:2000/07/09(日) 08:56
>19
どうでしょう? と聞かれても何が「どう」なのかよくわかりませんが…

flock()は、プラットフォームによっては実装されていません。man perlport
を見ると、Mac OS, VMS, RISC OS, VOS, Windows95で実装されていない、と
あります。

実装されていないプラットフォーム上でflock()を実行すると、致命的なエラー
になりプログラムが異常終了します。eval{} で囲むのは、致命的エラーが発
生した場合でも、スクリプトを異常終了させないための便法です。

flock()が実装されていない場合は、単にエラーを無視するのではなく、
flock()以外の手段で相互排除を行うべきです。そうしなければ、プログラム
は正しく動作しません。正しく動作しないプログラムは、有用ではありません。

このような便法が有用な場合もあります。たとえば、ローカルのWindows9xマ
シンでスクリプトをテストする場合など、flock()は実装されていないが、相
互排除も不要だとわかっている(同時に一つのプロセスしか実行されることが
ない)状況で、スクリプトを実行する場合です。しかし、"eval{flock()}" の
ように記述すると、実際のサーバでの運用時にflock()で発生したエラー(多く
は、プログラミング時の誤り)を捉えることができませんので、バグの温床に
なります。常にeval{}でエラーを無視するのではなく、何らかの方法でテスト
用環境であることを識別し、テスト用環境で実行する場合のみflock()をスキッ
プする、というふうに記述した方が、よいと思います。
27monalove:2000/07/09(日) 08:57
>21
NFS上のファイルに対してflock()を行ったときの挙動は、NFSクライアントお
よびサーバとなるプラットフォームによって異なるはずですが、私はその詳細
を知りません。japuさんは御存知ないですか?

NFSクライアントとしてのFreeBSD 4.0-RELEASEについて言えば、NFS上のファ
イルに対するファイルロックはサポートされていません。
/usr/src/sys/nfs/nfs_vnops.c のnfs_advlock()関数のコメント部分には、
"Currently unsupported."とはっきり書かれています。ただし興味深いことに、
NFS上のファイルに対して行っても、flock()システムコールそのものはエラー
になりません。ローカルファイルをロックした場合と、同じ挙動になります。
つまり、NFSマウントするマシンが複数あれば、個々のマシンごとのロックに
なる、ということです。ファイルがNFS上にあっても、CGIの動作するWWWサー
バが1台であれば、flock()は期待通りに機能する、ということになります。実
際に確かめてはいません。

CGIの動作するWWWサーバが1台であれば、ローカルファイルシステム上にロッ
ク対象となるダミーファイルを用意する、という方法もとれるでしょう。しか
し、公共のサーバでは、ホームディレクトリ以外の使用は困難かもしれません。

たとえプラットフォームとしてNFS上のファイルロックがサポートされていて
も、ロック機能を提供するシステムプログラム(lockd)のバグによって、特定
の状況でうまくロックできないことも有り得ます。Solarisの最近のバージョ
ンであれば問題ないのではないか、という予感がしますが、調べていないので
なんとも言えません。
28japu:2000/07/09(日) 12:42
NFS は状態が無い (stateless) プロトコルなのでロックという概念が無く rpc.lockd を使用してロックを行うはずですが、多くの実装 (商用OS含む) でこの動作はあまり信頼性が無いものと聞いています。
勉強不足の為詳しくは分かりません。

man rpc.lockd ではこうなっています (4.0 RELEASE):
BUGS
The current implementation provides only the server side of the protocol
(ie. clients running other OS types can establish locks on a FreeBSD
fileserver, but there is currently no means for a FreeBSD client to es-
tablish locks).

すくなくともクライアントが FreeBSD の場合はうまく動作しないようです。(あと、FreeBSD の場合は、常に "ロック成功" を返すという話も聞いています。数年前の話で今は直っているのかもしれませんが。)

ただ、NFS越しのファイルに関してflockが常に成功するわけではないというのは昔から良く言われていますのであのように書きました。

----
私も24のようなドジをよくやってしまいます。一度痛い目にあったことがあるので、テストプログラムでも常に -w を付けるようにしています。(もちろん、open MOE, "sakura" or die; のようにチェックも行う。)

# 2ch にしてはまともなスレッドになっているなぁ。
29japu:2000/07/09(日) 12:43
というわけでちょっとテストしてみました。

#! /usr/local/bin/perl -w

use Fcntl ":flock";

open F, "+< test.dat" or die;
flock F, LOCK_EX or die;
$SIG{TERM} = $SIG{KILL} = $SIG{HUP} = $SIG{USR1} = "IGNORE";
$count = <F>;
$count++;
seek F, 0, 0;
truncate F, 0;
print F $count;
sleep 1;
close F;
$SIG{TERM} = $SIG{KILL} = $SIG{HUP} = $SIG{USR1} = "DEFAULT";

__END__

test.dat は他のクライアントからのアクセスがないようにして perl flocktest.pl & ... & perl flocktest.pl & として一気に40個起動して実験してみたところ、

Server / Client
FreeBSD 3.1-RELEASE / FreeBSD 3.1-RELEASE i386 - OK
SGI CHALLENGE L / FreeBSD 4.0-RELEASE i386 - OK
SGI CHALLENGE L / OSF1 V4.0 alpha - OK
SGI CHALLENGE L / IRIX 6.5 IP32 - OK

ちょっとサンプル数が少ないので何とも言えませんが。
30monalove:2000/07/09(日) 14:20
このスクリプトで、signal無視するのって意味はあるんですか?
31japu:2000/07/09(日) 17:59
この場合は無いでしょうね...
32名無しさん:2000/07/10(月) 00:29
monaloveはカリスマカーネル設計者ですね。
33monalove:2000/07/28(金) 19:11
排他ロックは、同時に一つのプロセスしか獲得できないロックです。通常、ファ
イルロックと呼ばれるのは、排他ロックです。これに対して共有ロックは、複
数のプロセスが同時に獲得できるロックです。共有ロックは、排他ロックと共
に使用します。

二つのロックの組み合わせには、次のような性質があります。あるプロセスが
排他ロックを獲得すると、他のプロセスは排他ロックも共有ロックも共有ロッ
クも獲得できなくなります。これに対し、あるプロセスが共有ロックを獲得す
ると、他のプロセスは、共有ロックは獲得できますが、排他ロックは獲得でき
なくなります。

ロックをカラオケボックスのマイクに喩えれば、共有ロックは合唱用のマイク、
排他ロックはソロ用のマイクに相当します。合唱用のマイクは複数人で同時に
使用できますが、合唱中はソロ用のマイクを使用することができません。ソロ
用のマイクは、誰もマイクを使用していないときのみ使用でき、ソロが終わる
までは、他の人間は合唱もソロもできません。
34monalove:2000/07/28(金) 19:16
共有ロックは読込ロック、排他ロックは書込ロックと呼ばれることがあります。
これは次のような、一般的な使い方を示しています。

ファイル上にある情報があります。プロセスがファイルの情報を更新するとき、
他のプロセスは情報を更新したり、読み取ったりしてはいけません。(不完全な情報が読み取られたり、書き込まれたりという問題が発生するからです)
これを保証するために、情報の読み込みあるいは書き込みを行うときに、排他
ロック(だけ)を使用して他のプロセスを排他する、というのが簡単な方法です。
このようにすれば、読み込みあるいは書き込みを行うプロセスは、同時に一つ
しか存在しないことが保証できるからです。

しかしよく考えてみると、書き込みを行うプロセスが同時に複数存在するのは
問題ですが、読み込みを行うプロセスは、同時に複数存在しても問題ないはず
です。読み込みを行うプロセスは、書き込みを行うプロセスだけを排他すれば
よく、他の読み込みを行うプロセスを排他する必要はありません。つまり、排
他ロックだけを使用して相互排除を行う場合、排他する必要のないプロセスま
で排他してしまうことになります。

書き込みを行うプロセスは排他ロックを獲得するが、読み込みを行うプロセス
は共有ロックを獲得するようにすると、この問題を改善できます。あるプロセ
スが読み込みを行っている最中は、他のプロセスが書き込みを行うのは防ぎま
すが、他のプロセスが読み込みを行うのは邪魔しません。あるプロセスが書き
込みを行っている最中は、他の読み書きを行うプロセスの実行は全て防がれま
す。

このように、ロックの一部を共有ロックに変更することで、読み込みを行うプ
ロセスが複数同時に実行できるようになり、システム全体のパフォーマンスが
向上する可能性があります。
35monalove:2000/07/28(金) 19:17
見出し入れ忘れました…。
33,34は「共有ロックと排他ロックについて」
36名無しさん:2000/09/17(日) 23:12
勉強になるなぁ、age。
37locker room:2000/09/18(月) 03:33
>monalove

読み込みにロックかけるメリットは?
読み込みが、その他の条件に対して全く事後の影響を
与えない(つまり、記録更新のための読み出しではない)
場合には、必要無いんじゃないかな?
38locker room:2000/09/18(月) 03:36
あ、わかった、上の質問失敗ね。読み出した情報を
何か他に利用する場合ありってことね。人間が
見るとか以外に。
上の質問無視してくれ。
39:2000/09/19(火) 04:20
>>25
close前のアンロックは、バッファをフラッシュ(ファイルの書き出し)
せずにアンロックしてしまうと言うのを読んだことあるのですが…
40名無しさん@9月病:2000/09/19(火) 13:50
>>39
Perlメモかなにかに書いてあったね。close で自動的に解除してくれるらしい。
flock 使う時はアンロックしてないけどそもそも symlink のしか使わなくなった。
41名無しさん:2000/09/19(火) 16:02
symlink とかで独自実装すると 異常終了時に困りませんか?
SIGKILLじゃなくても 通常のSIGNALであっても。
42名無しさん@9月病:2000/09/19(火) 16:19
数回ロックにトライして駄目なら異常とみなしてロックファイル消して終わらせてます。
少なくともflockでロックかけた上にファイル2重化していたときよりはよっぽどマシです。
今は希にタイムアウトになることはあってもシングルファイルでもファイル飛んでませんし。
43名無しさん:2000/09/19(火) 18:23
ふむふむ
長時間ロックすることが無いならそれでOKですね。
長時間ロックする場合は設計が悪いってことで大丈夫だな。
アイデアいただき。ありがとです。
44monalove:2000/10/19(木) 02:01
>>39
ごめんなさい。バッファリングのことを忘れていました。
ちゃんとフラッシュしてからアンロックしてください。
(最近のバージョンのperlでは、アンロック時に暗黙にフラッシュして
くれるようですが)
45なんか:2000/10/29(日) 06:40
役に立ちそうなのであげ
46名無しさん:2000/11/28(火) 18:25
役に立ちそうなのであげ


47マイケル市井:2001/04/28(土) 20:08
選挙に勝てそうなのであげ
48名無しさん:2001/07/19(木) 19:19
よし!
49名無しさん:2001/07/19(木) 22:57
白痴氏ねや、ヴォケ
50名無しさん:2001/07/23(月) 19:35
>>49
どうしてそういうこと言うの?悲しいよ・・・
51名無しさん:2001/07/23(月) 19:41
>>50

分かった、「氏ね」じゃなく死ね!いや寧ろ消えろ!!

この世から塵一つ残さず、お前が居た痕跡、記憶さえも残さず
完全に消え去れ!!!
52名無しさん:2001/07/23(月) 22:51
おもむろに糞スレageてんじゃねーよ、ヴォケ。1000回氏ね
53名無しさん:2001/07/24(火) 12:11
私はどうすればいいの?
死ぬのは嫌だ。消えるも嫌・・・
54名無しさん:2001/07/24(火) 13:06
>>53
おまえに決定権は無いんだからさっさと死ね。
55名無しさん:2001/07/24(火) 22:47
見苦しいからやめれ。

--------------終了--------------
56名無しさん:2001/07/24(火) 22:55
>>55
おまえのレスも相当見苦しい。

=== 昇天 ===
57名無しさん@お腹いっぱい。:2001/07/26(木) 14:12
age
58名無しさん@お腹いっぱい。:2001/07/26(木) 15:25
>>57 鯖も変わって板名もレンタルサーバになったんだから
いい加減板違いスレageるの止めれ、ボケ。

過去スレtakoに置いてけぼりで良かった気がする。

#「置いて『け』ぼり」?「置いて『き』ぼり」?
#googleの検索結果じゃどっこいどっこいだ。
59名無しさん@お腹いっぱい。:2001/07/26(木) 23:02
>>58=真性白痴
60名無しさん@お腹いっぱい。:2001/07/27(金) 06:48
>>59=あほ。
>>61=バカ
書けませんよ( ̄ー ̄)ニヤリッ