pikesaku’s blog

個人的な勉強メモです。記載内容について一切の責任は持ちません。

ミューテックスとセマフォ

ミューテックスセマフォはどちらもOS排他制御を実現する機能

セマフォ

https://e-words.jp/w/%E3%82%BB%E3%83%9E%E3%83%95%E3%82%A9.html#:~:text=%E3%82%BB%E3%83%9E%E3%83%95%E3%82%A9%20%E3%80%90semaphore%E3%80%91,%E3%82%92%E8%A1%A8%E3%81%99%E5%80%A4%E3%81%AE%E3%81%93%E3%81%A8%E3%80%82

※以下に記載した"プロセス"は、"スレッド"に読み替え可能。

・共有資源にアクセスできるプロセス数を管理するカウンタ(カウンティングセマフォ
・P操作で1減算、V操作で1加算
・値を10に設定すれば、10個のプロセスが同時にアクセス可能。
・値をゼロに設定すれば、他プロセスは1以上になるまでプロックされる為、ミューテックスと同様にロックとしても利用可能。(バイナリセマフォ
・この動作を複数のプロセスの同期処理(待ち合わせ)にも利用できる。
→待ち合わせ=同時実行される複数プロセス間での処理タイミングの調整

★重要★
 "共有資源"は複数プロセス間でメモリ上で共有される変数等。ファイルではない。
 ・スレッドの場合、スレッド間の共有変数
 ・プロセスの場合、名前付きセマフォ(仮想ファイルシステム上に生成)

セマフォ利用方法

Linuxシステムコール、セマフォの使い方
セマフォにはキーがある。
・複数のプロセス間でキーによって、生成済みのセマフォを特定できる。
セマフォはリスト(集合)で、1つのセマフォの中に複数のセマフォカウンタを定義できる。

上記参考URLのサンプルコードの処理内容
seminit.c
・ftok()関数で任意のファイルから、ftok()関数でセマフォキーを生成
・生成したキーでセマフォを定義。(要素数は1個だけのセマフォ)
semproc.c
・seminit.cで生成したセマフォでロックをかける。成功したら、ユーザー入力を受けてロックを解除。

seminit.cを実行して、1個目のターミナルでsemproc.cを実行するとセマフォでロックがかかる。2個目のターミナルでsemproc.cを実行するとロック取得待ちになる。

★プロセスはOSのセマフォ機能を使うことで、プロセス間でのロックによる同期処理ができる★

コマンドでの動作確認

カウンタ1個のセマフォを生成(ipcmk) & 生成確認(ipcs) & 削除(ipcrm)
$ ipcs -s

------ Semaphore Arrays --------
key        semid      owner      perms      nsems

$ ipcmk -S 1
Semaphore id: 0
$ ipcs -s

------ Semaphore Arrays --------
key        semid      owner      perms      nsems
0x7890f5a3 0          ec2-user   644        1

$ ipcrm -s 0
$ ipcs -s

------ Semaphore Arrays --------
key        semid      owner      perms      nsems

$
カウンタ10個のセマフォを生成(ipcmk) & 生成確認(ipcs) & 削除(ipcrm)
$ ipcs -s

------ Semaphore Arrays --------
key        semid      owner      perms      nsems

$ ipcs -s

------ Semaphore Arrays --------
key        semid      owner      perms      nsems

$ ipcmk -S 10
Semaphore id: 1
$ ipcs -s

------ Semaphore Arrays --------
key        semid      owner      perms      nsems
0xdec22ed2 1          ec2-user   644        10

$ ipcrm -s 1
$ ipcs -s

------ Semaphore Arrays --------
key        semid      owner      perms      nsems
$

セマフォメモ

OSが動作するために必須の機能ではないよう。

Amazon Linux起動直後にセマフォ利用状況をipcsコマンドで確認しても、一切使われてない。

kernelパラメタでセマフォ制限の設定あり。
# sysctl kernel.sem
kernel.sem = 32000      1024000000      500     32000
#

パラメタの意味は以下URL参照
2.1.1 システムパラメーターのチューニング【Linux】
※上記URLより引用

kernelパラメタのセマフォ制限の確認

システム全体のセマフォ識別子の上限(引数4個目)超え時の動作

# sysctl kernel.sem
kernel.sem = 32000      1024000000      500     32000
# sysctl -w kernel.sem="32000 1024000000 500 2"
kernel.sem = 32000 1024000000 500 2
# ipcmk -S 1
Semaphore id: 1
# ipcmk -S 1
Semaphore id: 2
# ipcmk -S 1
ipcmk: create semaphore failed: No space left on device
# ipcs -s

------ Semaphore Arrays --------
key        semid      owner      perms      nsems
0x737eced2 1          root       644        1
0x496e3ae4 2          root       644        1
#

セマフォのリスト要素数上限(引数1個目)超え時の動作

# sysctl kernel.sem
kernel.sem = 32000      1024000000      500     32000
# ipcmk -S 32000
Semaphore id: 3
# ipcmk -S 32001
ipcmk: create semaphore failed: Invalid argument
# ipcs -s

------ Semaphore Arrays --------
key        semid      owner      perms      nsems
0xb01d3240 3          root       644        32000

#

システム全体のセマフォカウンタ数の上限(引数2個目)超え時の動作

# sysctl -w kernel.sem="32000 32000 500 32000"
kernel.sem = 32000 32000 500 32000
# ipcs -s

------ Semaphore Arrays --------
key        semid      owner      perms      nsems

# ipcmk -S 32000
Semaphore id: 4
# ipcmk -S 1
ipcmk: create semaphore failed: No space left on device
#

上記制限はシステム全体の制限。
なので、特定ユーザーが大量消費し制限到達したら、他ユーザーは使えなくなる。
ただし、rootユーザーはセマフォを削除できる。
他ユーザーは別ユーザーのセマフォは削除はできなさそう。

$ id
uid=1001(hoge) gid=1001(hoge) groups=1001(hoge)
$ ipcs -s

------ Semaphore Arrays --------
key        semid      owner      perms      nsems
0x44564196 5          root       777        1
0x1833097e 6          ec2-user   644        1
0x96432e7c 7          ec2-user   777        1

$ ipcrm -s 5
ipcrm: permission denied for id (5)
$ ipcrm -s 7
ipcrm: permission denied for id (7)
$

参考

同期処理
セマフォによる同期処理

Man page of SEM_OVERVIEW
→名前付きセマフォの説明あり。「2 つのプロセス間で同じ名前のセマフォ に対し操作を行うことができる。」

multiprocessing --- プロセスベースの並列処理 — Python 3.10.6 ドキュメント
threading --- スレッドベースの並列処理 — Python 3.10.6 ドキュメント
→multiprocessingとthreadingどちらにもセマフォ操作のメソッドあり。セマフォはマルチスレッドだけでなく、マルチプロセス間でも利用可能。

プロセスの同期
ミューテックスもプロセス間で利用可能

マルチスレッド・プログラミングの道具箱
ミューテックスセマフォの違い。ロック所有権の概念の有無。※以下引用