Linuxロックファイル飢餓

Linuxロックファイル飢餓

並行して実行されるbashスクリプトでロックファイル機能を使用したいと思います。問題は、以下のスクリプトの関数から最初のロックされた関数をすぐに再呼び出しすると、飢餓現象が発生する可能性があることです。lockfileポーリングタイムアウトが異なるプロセスがロックを取得できるほど十分に大きいようです。

本当に?では、どうすれば対処すべきでしょうか?

lockfile test.lock
echo "TESTING $$"
sleep 10
rm test.lock

たとえば、

2つのシェル:
SH1とSH2が一緒にスクリプトを実行し、
SH1がロックを獲得し、SH2がブロックされます。
問題:
SH1がロックを完了して削除しても、SH2はまだブロックされ(約1秒間...)、SH1がスクリプトを繰り返すと、SH2は永久にブロックされます。

答え1

ロックファイルを刺してもスリープ状態にならないため、ロックファイルをtmpfsに入れる必要があります。

これには2つの解決策があります。

一部のプロセスでは静的睡眠で十分です。

WAIT=5  # max seconds between two procs; larger is nicer for the system
lockfile -${WAIT} -r-1 "${LOCKFILE}"

## payload

rm -f "${LOCKFILE}"
# sleep outside the lock for at least $WAIT seconds
#  to give another proc a chance to lock it
sleep ${WAIT}s

ランダムな睡眠は多くのプロセスを処理しますが、非常に良いではありません。

MAX=5
MIN=3
WAIT=$((MIN+RANDOM/(1+MAX-MIN))) # random sleep between min and max
lockfile -${WAIT} -r-1 "${LOCKFILE}"

## payload

rm -f "${LOCKFILE}"
# sleep outside the lock for at least $WAIT seconds
#  to give another proc a chance to lock it
sleep ${WAIT}s

ウェイターは、持続時間が長くなるほど多くのプロセスに適しています。

MAX=600
MIN=1
WAIT=${MAX}  # max seconds between two procs; larger is nicer
while ! lockfile -r0 "${LOCKFILE}"
do
    sleep ${WAIT}s
    WAIT=$(( WAIT / 2 )) # backoff formula
    if [ ${WAIT} -lt ${MIN} ]; then
        WAIT=${MIN}
    fi
done

## payload

rm -f "${LOCKFILE}"
# reduced WAIT means likely to run again; alternatively use MAX
sleep ${WAIT}s

答え2

問題があるかどうかわかりません。

これfs/locks.cのカーネルコード以下の説明が含まれています。

 519 /* Insert waiter into blocker's block list.
 520  * We use a circular list so that processes can be easily woken up in
 521  * the order they blocked. The documentation doesn't require this but
 522  * it seems like the reasonable thing to do.
 523  */

まだこれを信じられない場合、唯一の合理的な選択はセマフォを使用することです。semop(2), semget(2)

関連情報