2016-09-20 9 views
0

原則として、私が望むものは非常に簡単です。ポーリングなしのLinux同期

2つの実行ファイル./read./writeはそれぞれリソース(ファイルと言う)からの読み書きです。 flock(2)を使用すると、任意の呼び出しでの任意の呼び出しの間の競合状態を任意の時刻に簡単に防ぐことができます(./read./write)。

要件は、./readの各呼び出しは、前の呼び出しからのリソースのスナップショットが含まれており、現在のリソースがスナップショットと一致した場合./writeの呼び出しがリソースを変更するまで、./readは、(スリープ)待たなければならないことです。

私が集まるものとは、各プログラムのプログラムの流れのようなものでなければなりません:

//read.c 
obtain mutex0 
    read resource 
    is resource same as our snapshot? 
    release mutex0 [1] 
    sleep until ./write says to wake up [2] 
    obtain mutex0 
    read resource 
    do something with resource 
release mutex0 

//write.c 
obtain mutex0 
    change resource in some way 
    tell any sleeping ./read's to wake up 
release mutex0 

このアプローチの主な問題は、[1][2]ラベルされた線の間の具体的な遅延があるということです。これは./readは、[1]mutex0を解放することができます./writeの全体の呼び出しが完了することができ、その後、[2]実行されますが、./writeはすでに./readの前に任意の睡眠を目覚めしようとしたので、無限にストールすることを意味します。

別に本格的なサーバープロセス全体を使用する以外に、私がしたいことを簡単に行う方法はありませんか?また、好奇心をそそる人たちのために、私はCGIのアプリケーションでこれをやりたいのです。

+1

ミューテックスの代わりにセマフォを使用できます。 – Riley

+0

プロセス間通信が必要です。あなたのアドホックなスキームではなく、Linuxの名前付きパイプや[ZeroMQ](http://czmq.zeromq.org/)を読むことをお勧めします。 – orlp

+0

私が指摘した競争条件については、どちらのコメントも対応していません。私はセマフォについて知っている、私はIPCについて知っている。 –

答えて

1

いいえ、リーダーのプログラムフローが正しくありません。 1つ以上の読み取りが進行中のときに書き込みを防止するためのロック機構と、書き込みが完了するたびに読み取り機に通知するための何らかの種類の起動機構が必要です。

ライター(S)のためのあなたのプログラムの流れは大丈夫です:

# Initial read of file contents 
    Obtain lock 
     Read file 
    Release lock 

    # Whenever wishes to modify file: 
    Obtain lock 
     Modify file 
     Signal readers 
    Release lock 

リーダー(S)のためのプログラムの流れは次のようになります。

# Initial read of file contents 
    Obtain lock 
     Read file 
    Release lock 

    # Wait and respond to changes in file 
    On signal: 
     Obtain lock 
      Read file 
     Release lock  
     Do something with modified file contents 

一つだけがある場合共有メモリ(すべてのライターとリーダーにアクセス可能)のミューテックス(pthread_mutex_t)で十分です。それ以外の場合は、代わりにrwlock(pthread_rwlock_t)を使用することをお勧めします。待機中の読者を目覚めさせるために、条件変数(pthread_cond_t)でブロードキャストします。もちろん、難しいことは、その共有メモリを設定することです。


アドバイザリファイルロックとfanotifyインターフェイスでも十分です。読者はfanotify FAN_MODIFYマークをインストールし、対応するイベントを待つだけです。ライターは、アドバイザリーロック(ファイルが変更されている間に読者の読書を止めるためにのみ存在する)の使用を除いて、協力する必要はありません。

現在のところ、インターフェイスにはCAP_SYS_ADMINの機能が必要です。この機能は、ランダムCGIプログラムには望ましくありません。


アドバイザリファイルロッキングおよびinotifyインターフェースが十分であり、そして両方のリーダとライタオープンとは、操作のセットごとにファイルを閉じるとき、私は、このための最も適切と考えています。リーダー(S)のために、この場合のプログラムの流れは次のとおりです。

Initialize inotify interface 
Add inotify watch for IN_CREATE and IN_CLOSE_WRITE for "file" 

Open "file" read-only 
    Obtain shared/read-lock 
     Read contents 
    Release lock 
Close "file" 

Loop: 
    Read events from inotify descriptor. 
    If IN_CREATE or IN_CLOSE_WRITE for "file": 
     Open "file" read-only 
      Obtain shared/read-lock 
       Read contents 
      Release lock 
     Close "file" 
     Do something with file contents 

ライターライターがロックを取得していない場合であっても、読者は時に通知されますまだちょうど

# Initial read of file contents 
    Open "file" for read-only 
     Obtain shared/read-lock on "file" 
      Read contents 
     Release lock 
    Close "file" 

    # Whenever wishes to modify file: 
    Open "file" for read-write 
     Obtain exclusive/write-lock 
      Modify file 
     Release lock 
    Close "file" 

ですライターはファイルを閉じます。唯一のリスクは、読者がファイルを読み込んでいる間に別の変更セットが(別のロック・スパーリング・モディファイアによって)書き込まれることです。

修飾子でファイルを新しいものに置き換えた場合でも、新しいものが用意できたら、読者は正しく通知されます(古いファイルの上に改名/リンクされるか、新しいファイル作成者がファイルを閉じます)。読者がファイルを開いたままにしておくと、ファイル記述子が新しいファイルに魔法のようにジャンプすることはなく、古い(おそらく削除された)内容のみが表示されることに注意することが重要です。


それは読者や作家が読者がまだinotifyを使用することができ、ファイルを閉じていないが、ファイルが切り捨てられるかに書き込まれるたびIN_MODIFYマークではなく、通知することが重要何らかの理由である場合。この場合、ファイルが置き換えられる(名前が変更された、または削除されて再作成される)と、読者とライターは新しいファイルを見ることはできませんが、古い、現在は見えない-filesystemファイルの内容。

リーダーのためのプログラムの流れ:

Initialize inotify interface 
Add inotify watch for IN_MODIFY for "file" 

Open "file" read-only 
    Obtain shared/read-lock 
     Read contents 
    Release lock 

    Loop: 
     Read events from inotify descriptor. 
     If IN_CREATE or IN_CLOSE_WRITE for "file": 
      Obtain shared/read-lock on "file" 
       Read contents 
      Release lock 
      Do something with file contents 

作家のためのプログラムの流れは依然としてほぼ同じである:

# Initial read of file contents 
    Open "file" for read-only 
     Obtain shared/read-lock on "file" 
      Read contents 
     Release lock 
    Close "file" 

    Open "file" for read-write 

    # Whenever writer wishes to modify the file: 
    Obtain exclusive/write-lock 
     Modify file 
    Release lock 

はそれが重要であるかもしれないが注意することはinotifyイベント事実の後に起こる。通常、マシンの負荷に依存する可能性のある小さな待機時間があります。したがって、システムが正常に動作するためにファイルの変更に対する迅速な対応が重要な場合は、代わりにmutexまたはrwlockと共有メモリの条件変数を使用する必要があります。

私の経験では、これらの待ち時間は典型的な人間の反応間隔よりも短くなる傾向があります。したがって、私は、あなたがそうすることをお勧めします - 人間のタイムスケールで十分に高速かつ信頼できるinotifyインターフェイス。ミリ秒単位とミリセカンド単位のマシンタイムスケールではそうではありません。

関連する問題