ネットワークプログラミング講座

セマフォによる排他制御
セマフォによる排他制御











排他制御の目的
セマフォ(Semaphore) - 排他制御のアナロジー
排他制御のシステム概要
排他制御のプロセスシーケンス
セマフォの操作
排他制御の実施例
セマフォの基本操作プログラミング: セマフォオブジェクト(集合)の生成
セマフォの基本操作プログラミング: セマフォオブジェクトの初期化
セマフォの基本操作プログラミング: セマフォのロック
セマフォの基本操作プログラミング: セマフォのアンロック
事例: forkした子プロセス間の排他制御
セマフォによる排他制御
排他制御の目的



Critical Sectionの保護
Critical Section
 コンピュータ資源を、複数のプロセスが同時に利用するこ
とを回避(=排他制御)しなければならないプログラムの
部分
コンピュータ資源(排他制御の対象となりうるあらゆる資源)
 オブジェクト
 CPU
 ファイル
 メモリ
 ネットワーク
 周辺装置(ディスプレイ等)
 外部環境(制御対象システム等)
セマフォによる排他制御
セマフォ(Semaphore) - 排他制御のアナロジー
Semaphore
腕木信号
Critical Section
セマフォによる排他制御
排他制御のシステム概要
プロセスA,B,Cは、同じ鍵を持っている
★セマフォの動作原理
•セマフォから値を引いた結果
が、0以下になると、プロセス
がスリープする。また、結果
が0または0以上になると自動
的にスリープから脱する。
•セマフォのロックは値から-1
する。
•セマフォのロック解除は値に
+1する。
ロック操作
プロセスA
プロセスB
ロック操作
semget();
semop();
{
//critical section
}
semget();
アンロック操作
semop();
アンロック操作
{
//critical section
}
semop();
semop();
初期値
プロセスC
(初期設定)
セマフォ
semget();
1
semctl();
カーネル
1: 使用中
0: 未使用
セマフォによる排他制御
排他制御のプロセスシーケンス
プロセスA,B,Cは、同じ鍵を持っている
プロセスA
★動作原理
•セマフォから値を引いた結果
が、0以下になると、プロセス
がスリープする。また、結果
が0または0以上になると自動
的にスリープから脱する。
•セマフォのロックは値から-1
する。
•セマフォのロック解除は値に
+1する。
使い終わったら1増やす
(アンロック)
プロセスA
使う時
1減らす
(ロック)
-1
A使用中
Critical
Section
+1
セマフォ
セマフォ
セマフォ
セマフォ
セマフォ
1
0
0
1
0
-1
プロセスC
(初期設定)
プロセスB
初期値=1
待ち解除
semget();
semctl();
使う時1減らす
(ロック)
B使用中
Critical
Section
セマフォによる排他制御
セマフォの操作
プロセスA,B,Cは、同じ鍵を持っている
プロセスA
★操作
•セマフォオブジェクトの生成
•鍵、セマフォ数
•初期化
•セマフォ値を設定する
•アンロック
•セマフォ値を増やす
•ロック
•セマフォ値を減らす
使い終わったら1増やす
(アンロック)
プロセスA
使う時
1減らす
(ロック)
-1
A使用中
Critical
Section
+1
セマフォ
セマフォ
セマフォ
セマフォ
セマフォ
1
0
0
1
0
-1
プロセスC
(初期設定)
プロセスB
初期値=1
待ち解除
semget();
semctl();
使う時1減らす
(ロック)
B使用中
Critical
Section
セマフォによる排他制御
排他制御の実施例
プロセスA,B,Cは、同じ鍵を持っている
プロセスA
★実施例
•セマフォ値=1の時
•プロセスはセマフォ値を
0にし、資源を使用する
(即ち、クリティカルセク
ションを実行する。)
•セマフォ値=0の時
•プロセスはセマフォ値を
変更せず、セマフォ値が
0になるまで待つ
使い終わったら1増やす
(アンロック)
プロセスA
使う時
1減らす
(ロック)
-1
A使用中
Critical
Section
+1
セマフォ
セマフォ
セマフォ
セマフォ
セマフォ
1
0
0
1
0
-1
プロセスC
(初期設定)
プロセスB
初期値=1
待ち解除
semget();
semctl();
使う時1減らす
(ロック)
B使用中
Critical
Section
セマフォによる排他制御
セマフォの基本操作プログラミング:
セマフォオブジェクト(集合)の生成
プロセスA,B,Cは、同じ鍵を持っている
//セマフォオブジェクトの生成
int semid;
key_t semkey;
semkey = ftok("seminit", 'a');
semid = semget(semkey, 1,
IPC_CREAT|0666);
if(semid==EOF)
{ printf("%s\n","ERR"); exit(0); }
プロセスA
使い終わったら1増やす
(アンロック)
プロセスA
使う時
1減らす
(ロック)
-1
A使用中
Critical
Section
+1
セマフォ
セマフォ
セマフォ
セマフォ
セマフォ
1
0
0
1
0
-1
プロセスC
(初期設定)
プロセスB
初期値=1
待ち解除
semget();
semctl();
使う時1減らす
(ロック)
B使用中
Critical
Section
セマフォによる排他制御
セマフォの基本操作プログラミング:
セマフォオブジェクトの初期化
プロセスA,B,Cは、同じ鍵を持っている
プロセスA
//セマフォに初期値1を書き込
む
if((semctl(semid,0,SETVAL,1))
== EOF)
{ printf("%s\n","ERR"); exit(0); }
使い終わったら1増やす
(アンロック)
プロセスA
使う時
1減らす
(ロック)
-1
A使用中
Critical
Section
+1
セマフォ
セマフォ
セマフォ
セマフォ
セマフォ
1
0
0
1
0
-1
プロセスC
(初期設定)
プロセスB
初期値=1
待ち解除
semget();
semctl();
使う時1減らす
(ロック)
B使用中
Critical
Section
セマフォによる排他制御
セマフォの基本操作プログラミング:
セマフォのロック
プロセスA,B,Cは、同じ鍵を持っている
//排他処理の開始するためのロック
//自分よりも先にロックされていた場合に
//はロック解除されるまでスリープする プロセスA
void lock(int semid)
使う時
{
1減らす
struct sembuf sb[1];
(ロック)
sb[0].sem_num=0;
sb[0].sem_op=-1;
sb[0].sem_flg=0;
セマフォ
if(EOF==semop(semid,sb,1))
1
{ printf("%s\n","lock ERR"); exit(1); }
}
プロセスC
(初期設定)
プロセスA
使い終わったら1増やす
(アンロック)
-1
A使用中
Critical
Section
セマフォ
セマフォ
セマフォ
セマフォ
0
0
1
0
-1
プロセスB
初期値=1
待ち解除
semget();
semctl();
+1
使う時1減らす
(ロック)
B使用中
Critical
Section
セマフォによる排他制御
セマフォの基本操作プログラミング:
セマフォのアンロック
プロセスA,B,Cは、同じ鍵を持っている
//排他処理の終了のためのロック解除
void unlock(int semid)
プロセスA
{
使う時
struct sembuf sb[1];
1減らす
sb[0].sem_num=0;
(ロック)
sb[0].sem_op=1;
sb[0].sem_flg=0;
if(EOF==semop(semid,sb,1))
{ printf("%s\n","unlock ERR"); exit(1); }
セマフォ
}
1
プロセスA
使い終わったら1増やす
(アンロック)
-1
A使用中
Critical
Section
+1
セマフォ
セマフォ
セマフォ
セマフォ
0
0
1
0
-1
プロセスC
(初期設定)
プロセスB
初期値=1
待ち解除
semget();
semctl();
使う時1減らす
(ロック)
B使用中
Critical
Section
セマフォによる排他制御
事例: forkした子プロセス間の排他制御
•
•
•
3つの子プロセスを作成して排他処理を行う。
子プロセス1では文字Aを、子プロセス2では文字B
を、子プロセス3では文字Cを、出力する。
各子プロセスは、ディスプレイの利用をクリティカル
セクションとして保護し、排他制御する。
kishima@DdeDynabook-4
$ gcc sem_fork.c -o sem_fork
sem_fork.c
kishima@DdeDynabook-4
$ ./sem_fork
AAAAAAAAAABBBBBBBBBBCCCCCCCCCC
kishima@DdeDynabook-4
$