Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
シェルスクリプトで学ぶ排他制御
Search
Satoru Takeuchi
PRO
September 19, 2020
Technology
0
640
シェルスクリプトで学ぶ排他制御
以下動画のテキストです。
https://youtu.be/RPKt1p2SkxY
Satoru Takeuchi
PRO
September 19, 2020
Tweet
Share
More Decks by Satoru Takeuchi
See All by Satoru Takeuchi
様々なファイルシステム
sat
PRO
0
250
ソースを読む時の思考プロセスの例-MkDocs
sat
PRO
1
210
ソースを読むプロセスの例
sat
PRO
18
12k
メモリマップトファイル
sat
PRO
1
130
「Linux」という言葉が指すもの
sat
PRO
4
210
APIとABIの違い
sat
PRO
5
190
ファイルシステムへのアクセス方法
sat
PRO
0
77
ファイルシステム
sat
PRO
1
75
低レイヤソフトウェア技術者が YouTuberとして食っていこうとした話
sat
PRO
7
6.2k
Other Decks in Technology
See All in Technology
OpenTelemetry が拡げる Gemini CLI の可観測性
phaya72
2
2.3k
ゼロコード計装導入後のカスタム計装でさらに可観測性を高めよう
sansantech
PRO
1
450
NLPコロキウム20251022_超効率化への挑戦: LLM 1bit量子化のロードマップ
yumaichikawa
3
490
AIとともに歩んでいくデザイナーの役割の変化
lycorptech_jp
PRO
0
880
Observability — Extending Into Incident Response
nari_ex
1
440
IoTLT@ストラタシスジャパン_20251021
norioikedo
0
140
「最速」で Gemini CLI を使いこなそう! 〜Cloud Shell/Cloud Run の活用〜 / The Fastest Way to Master the Gemini CLI — with Cloud Shell and Cloud Run
aoto
PRO
1
180
パフォーマンスチューニングのために普段からできること/Performance Tuning: Daily Practices
fujiwara3
2
130
GraphRAG グラフDBを使ったLLM生成(自作漫画DBを用いた具体例を用いて)
seaturt1e
1
150
SQLAlchemy の select(User).where(User.id =="123") を理解してみる/sqlalchemy deep dive
3l4l5
3
440
可観測性は開発環境から、開発環境にもオブザーバビリティ導入のススメ
layerx
PRO
1
460
生成AI時代のPythonセキュリティとガバナンス
abenben
0
140
Featured
See All Featured
"I'm Feeling Lucky" - Building Great Search Experiences for Today's Users (#IAC19)
danielanewman
230
22k
Sharpening the Axe: The Primacy of Toolmaking
bcantrill
46
2.5k
Dealing with People You Can't Stand - Big Design 2015
cassininazir
367
27k
Building Better People: How to give real-time feedback that sticks.
wjessup
369
20k
Building Flexible Design Systems
yeseniaperezcruz
329
39k
Fantastic passwords and where to find them - at NoRuKo
philnash
52
3.5k
Learning to Love Humans: Emotional Interface Design
aarron
274
41k
Chrome DevTools: State of the Union 2024 - Debugging React & Beyond
addyosmani
9
930
How to Create Impact in a Changing Tech Landscape [PerfNow 2023]
tammyeverts
55
3k
Java REST API Framework Comparison - PWX 2021
mraible
34
8.9k
Why Our Code Smells
bkeepers
PRO
340
57k
The Cult of Friendly URLs
andyhume
79
6.6k
Transcript
シェルスクリプトで学ぶ排他制御 Sep 19th, 2020 Satoru Takeuchi Twitter: satoru_takeuchi, EnSatoru 1
排他制御 • 以下のことを一つの処理からしか操作できないようにする ◦ コード上のある箇所 (クリティカルセクション )の実行 ◦ あるリソースを操作する •
抽象的で意味わからん! ◦ これ聞くだけで「なるほど!」ってなる人はあんまりいない • 実例を使って説明 ◦ 多くの人から見て身近なシェルスクリプトを使う 2
身近な排他制御の使用例 • apt系コマンドが以下のようなメッセージと共に異常終了 • この問題の発生ロジック ◦ apt系コマンドは同時に複数実行できないようになっている ◦ /var/lib/apt/lists/lockが存在しなければ実行、存在すれば異常終了する ▪
上記のようなファイルをロックファイルと呼ぶ ◦ 実際に発生するのはほとんど次のような場合 1. apt系コマンド実行中にC-cで異常終了させたりするとファイルが残る 2. 次に実行すると必ず失敗 3. ユーザがファイルを消せば再実行可能になる 3 E: Could not get lock /var/lib/apt/lists/lock – open (11: Resource temporarily unavailable)
身近な排他制御の使用例 • apt系コマンドが以下のようなメッセージと共に異常終了 • この問題の発生ロジック ◦ apt系コマンドは同時に複数実行できないようになっている ◦ /var/lib/apt/lists/lockが存在しなければ実行、存在すれば異常終了する ▪
上記のようなファイルをロックファイルと呼ぶ ◦ 実際に発生するのはほとんど次のような場合 1. apt系コマンド実行中にC-cで異常終了させたりするとファイルが残る 2. 次に実行すると必ず失敗 3. ユーザがファイルを消せば再実行可能になる 4 E: Could not get lock /var/lib/apt/lists/lock – open (11: Resource temporarily unavailable) 今回のテーマ
最初に思いつく実装: シェルスクリプトで表現 5 if [ -e /var/lib/apt/lists/lock ] ; then
echo <さっきのメッセージ> >&2 exit 1 fi touch /var/lib/apt/lists/lock aptの実処理 rm -f /var/lib/apt/lists/lock ここがクリティカルセクション ①最初にファイルの存在確認 ②なければファイルを作って 他の処理が割り込めないように してから先に進む ③最後にファイルを消して、他のプロセスが実処理を実行できるようにする
これはうまく動かない • 例: apt Aとapt Bを同時に実行 6 if [ -e
/var/lib/apt/lists/lock ] ; then echo <さっきのメッセージ> >&2 exit 1 fi touch /var/lib/apt/lists/lock aptの実処理 rm -f /var/lib/apt/lists/lock if [ -e /var/lib/apt/lists/lock ] ; then echo <さっきのメッセージ> >&2 exit 1 fi touch /var/lib/apt/lists/lock aptの実処理 rm -f /var/lib/apt/lists/lock apt A apt B
これはうまく動かない • 2つのif文が同時に実行。両方ファイルが存在しないと判定する 7 if [ -e /var/lib/apt/lists/lock ] ;
then echo <さっきのメッセージ> >&2 exit 1 fi touch /var/lib/apt/lists/lock aptの実処理 rm -f /var/lib/apt/lists/lock if [ -e /var/lib/apt/lists/lock ] ; then echo <さっきのメッセージ> >&2 exit 1 fi touch /var/lib/apt/lists/lock aptの実処理 rm -f /var/lib/apt/lists/lock apt A apt B ファイルは無いな… ファイルは無いな…
これはうまく動かない • 2つとも先に進んでaptの実処理を実行 ◦ aptの処理が正しく動作しない &データベースがブッ壊れる 8 if [ -e
/var/lib/apt/lists/lock ] ; then echo <さっきのメッセージ> >&2 exit 1 fi touch /var/lib/apt/lists/lock aptの実処理 rm -f /var/lib/apt/lists/lock if [ -e /var/lib/apt/lists/lock ] ; then echo <さっきのメッセージ> >&2 exit 1 fi touch /var/lib/apt/lists/lock aptの実処理 rm -f /var/lib/apt/lists/lock apt A apt B 先に進もう 先に進もう
もうちょっとわかりやすい例 • いわゆるカウンタプログラムを使う ◦ countファイルの初期値は 0 ◦ 一回実行するごとにファイルの中身の数値を 1つ足す ◦
すでに同じプログラムが実行中ならすぐリトライ (スピンロック) • 最初に思いつく実装: inc-counter.sh 9 while : ; do if [ ! -e lock ] ; then break fi done touch lock TMP=$(cat count) echo $((TMP + 1)) >count rm -f lock ここがクリティカルセクション
inc-counterプログラムの並列実行 • カウントを1000増加させるスクリプト(inc-counter-1000.sh)を同時に2つ実行 • 結果 ◦ 期待: 最終的にcountの値が2000になる ◦ 実際:
2000より小さな値になる(ことがある) ▪ 同じCPU上で実行すると起きやすい 10 for ((i=0;i<1000;i++)) ; do ./inc-counter.sh done for ((i=0;i<1000;i++)) ; do ./inc-counter.sh done
うまくいかない理由 • 2つのプログラムが両方クリティカルセクションに入ることがある 11 while : ; do if [
! -e lock ] ; then break fi done touch lock TMP=$(cat count) echo $((TMP + 1)) >count rm -f lock 2つのプログラムが同時にここを実行するとアウト 2つともクリティカルセクションに入り、 countの計算が狂う 例: カウンタA,Bを同時に動かす&countの初期値は0 1. countから0を読み出す 2. countに1を書き込む カウンタA 1. countから0を読み出す 2. countに1を書き込む カウンタB 終了時のcountは2であるべきだが1になる
解決方法 • 以下2つの処理を他の処理に割り込まれないよう実行(アトミック操作) 1. ロックファイルが存在するかどうかをチェック 2. 存在していれば成功、そうでなければ失敗 • シェルスクリプトからはflockコマンドが使える ◦
カウンタプログラムは以下のように実装できる inner-inc-counter.sh ▪ 12 TMP=$(cat count) echo $((TMP + 1)) >count while ((i=0;i<1000;i++)) ; do flock lock ./inner-counter.sh done “lock”ファイルを使って上記アトミック操作を実現 inner-inc-counter.sh correct-inc-counter-1000.sh
flockの内部 • flock()システムコールを使う ◦ あるファイルに対して flock(O_EX)を呼び出すと以下2つの処理をアトミックに実行 1. ファイルに対してロックがかかっているかどうかを確認 2. アンロック状態ならロックしてから正常終了、ロック済なら異常終了
◦ flock(O_UN)でアンロック ◦ 詳細は”man 2 flock”を参照 • Linuxならopen(O_CREAT|O_EXCL)を使うという手もある ◦ “その14 マウント中のファイルシステムの破壊を防ぐ小技 ”で紹介しました ▪ https://youtu.be/Hbgtt1dj9tM 13
まとめ • 排他制御: 以下のことを一つの処理からしか操作できないようにする ◦ コード上のある箇所 (クリティカルセクション )の実行 ◦ あるリソースを操作する
• 身近なところではapt系コマンドの同時実行を防ぐために使われている • シェルスクリプトならflockコマンドで排他制御ができる 14