90 likes | 304 Views
セマフォのシステムコールと応用プログラム. semget(): セマフォを生成し、識別子を得る semctl(): セマフォの制御 semop(): セマフォの操作 ipcs - IPC リソース情報の表示 ipcrm – IPC の各資源(メッセージキュー・セマフォ・共有メモリ)を削除する 事例: セマフォの応用プログラム writer & cleaner 事例: fork() したプロセス間の排他制御. key: セマフォの鍵 nsems: セマフォの総数 semflg: IPC_CREAT|0666.
E N D
セマフォのシステムコールと応用プログラム • semget(): セマフォを生成し、識別子を得る • semctl(): セマフォの制御 • semop(): セマフォの操作 • ipcs - IPC リソース情報の表示 • ipcrm – IPCの各資源(メッセージキュー・セマフォ・共有メモリ)を削除する • 事例: セマフォの応用プログラム writer & cleaner • 事例: fork()したプロセス間の排他制御
key: セマフォの鍵 nsems: セマフォの総数 semflg: IPC_CREAT|0666 semget(): セマフォを生成し、識別子を得る 使用例) int semid; key_t semkey; semkey=ftok("seminit", 'a'); semid=semget(semkey, 1, IPC_CREAT|0666); • インクルードファイル • #include <sys/types.h> • #include <sys/ipc.h> • #include <sys/sem.h> • 書式 • int semget(key_t key, int nsems, int semflg); • 戻値 • 成功時 セマフォ識別子、 • 失敗時 -1
semid: セマフォ識別子 semnum: セマフォ番号 cmdの種類 GETVAL:セマフォ値を得る SETVAL: セマフォ値をセット IPC_RMID:セマフォを削除 IPC_STAT:セマフォ状態を得る IPC_SET:semid_ds構造体の値をセット semctl(): セマフォの制御 使用例) int semid; semctl(semid, 0, SETVAL, 1); • インクルードファイル • #include <sys/types.h> • #include <sys/ipc.h> • #include <sys/sem.h> • 書式 • int semctl(int semid, int semnum, int cmd, …); • 戻値 • 成功時 0 、 • 失敗時 -1
semid: セマフォ識別子 struct sembuf { unsigned short int sem_num short int sem_op; short int sem_flg; } nsops: 操作するセマフォの総数 semop(): セマフォの操作 アンロック操作 ロック操作 • インクルードファイル • #include <sys/types.h> • #include <sys/ipc.h> • #include <sys/sem.h> • 書式 • int semop(int semid, struct sembuf *sops, unsigned int nsops); • 戻値 • 成功時 0 、 • 失敗時 -1 使用例) int semid; struct sembuf buf[1]; buf[0].sem_num=0; buf[0].sem_flg=0; buf[0].sem_op=-1; semop(semid,buf,1); 使用例) int semid; struct sembuf buf[1]; buf[0].sem_num=0; buf[0].sem_flg=0; buf[0].sem_op=1; semop(semid,buf,1); セマフォ番号 セマフォ値を 増す(減す)値
ipcs は、IPC リソース機能に関する情報を出力する。 -i を指定すると、後続の idで指定されたリソースの情報だけが出力される。 リソースの指定は次のようになる: -m シェアードメモリセグメントを指定する。 -q メッセージキューを指定する。 -s セマフォを指定する。 -a すべてのリソースの情報が出力される(ディフォルト)。 出力フォーマットの指定は、次のようになる: -t リソースが最後に変更された時間を出力する。 -p リソースの所有、作成、最終変更を示すプロセスIDを出力する。 -c リソースの作成ユーザーおよびグループの情報を出力する。 -l 各リソースの上限値を出力する。 -u 各リソースの使用状況を示すサマリが出力される. ipcs - IPC リソース情報の表示
ipcrm は System V プロセス間通信 (interprocess communication, IPC) オブジェクトと、それに関連するデータ構造をシステムから削除する。 これらのオブジェクトを削除するためには、スーパーユーザーであるか、オブジェクトの作成者または所有者でなければならない。 メッセージキューオブジェクトとセマフォオブジェクトの削除は、 (他のプロセスがそのオブジェクトの IPC 識別子を持っていたとしても) 即座に行われる。 共有メモリオブジェクトが削除されるのは、現在付加 (attach) されている全てのプロセスが (shmdt(2) で) 仮想アドレス空間からオブジェクトを分離 (detach) してからである。 -M shmkey最後の分離が行われた後、 shmkeyで作成された共有メモリセグメントを削除する。 -m shmid最後の分離が行われた後、 shmidで識別される共有メモリセグメントを削除する。 -Q msgkeymsgkeyで作成されたメッセージキューを削除する。 -q msgidmsgidで識別されるメッセージキューを削除する。 -S semkeysemkeyで作成されたセマフォを削除する。 -s semidsemidで識別されるセマフォを削除する。 ipcrm – IPCの各資源(メッセージキュー・セマフォ集合・共有メモリ ID)を削除する
事例: セマフォの応用プログラムwriter & cleaner (1) 各プロセスは、同じ鍵を持っている writer writer.c(画面に数字を書く) • セマフォ識別子を獲得 • 以下を繰返す • セマフォをロックする • 画面に数字(0~4)を書く • セマフォをアンロックする cleaner.c(画面の数字を消す) • セマフォ識別子を獲得 • 以下を繰返す • セマフォをロックする • カーソルを後退し数字を消す • セマフォをアンロックする 使い終わったら1増やす(アンロック) writer 使う時 1減らす (ロック) writer使用中 Critical Section +1 -1 セマフォ 1 セマフォ 0 セマフォ 0 セマフォ 1 セマフォ 0 seminit.c int main() { int semid; key_t semkey; semkey=ftok("seminit", 'a'); semid=semget(semkey, 1, IPC_CREAT|0666); semctl(semid, 0, SETVAL, 1); return EXIT_SUCCESS; } -1 cleaner使用中 Critical Section cleaner 初期値=1 待ち解除 使う時1減らす (ロック)
事例: セマフォの応用プログラムwriter & cleaner (2) cleaner.c(画面の数字を消す) writer.c(画面に数字を書く) int main() { int semid; key_t semkey; struct sembuf buf[1]; semkey=ftok("seminit", 'a'); semid=semget(semkey, 1, IPC_CREAT|0666); buf[0].sem_num=0; buf[0].sem_flg=0; while (1) { int i; buf[0].sem_op=-1; semop(semid,buf,1); for (i=0; i<5; i++) { printf("%d",i); fflush(stdout); sleep(1); } buf[0].sem_op=1; semop(semid,buf,1); sleep(1); } return EXIT_FAILURE; } int main() { int semid; key_t semkey; struct sembuf buf[1]; srand(time(NULL)); semkey=ftok("seminit", 'a'); semid=semget(semkey, 1, IPC_CREAT|0666); buf[0].sem_num=0; buf[0].sem_flg=0; while (1) { int i, loop; buf[0].sem_op=-1; semop(semid,buf,1); loop=rand()%5+1; for (i=0; i<loop; i++) { printf("\b \b"); fflush(stdout); sleep(1); } buf[0].sem_op=1; semop(semid,buf,1); sleep(1); } return EXIT_FAILURE; } キーを作る キーを作る セマフォ識別子を得る ロック操作 ロック操作 乱数を5で割った余+1 資源 (ディスプレイ) を独占的に使う リソース (ディスプレイ) を独占的に使う 後退し、空白を書き、後退する アンロック操作 アンロック操作
事例: fork()したプロセス間の排他制御 independent_sem_init.cにより作成されたセマフォを使って排他処理を行うプロセス(キーが同じならば複数起動させても排他処理が行われます) • セマフォの初期化プロセスを作成する。 • 初期化プロセスで作成したセマフォと同一の鍵を利用して、独立した複数のプロセス間で、排他処理を行う。 • 各プロセスは、自身のpidを出力する。 • 各プロセスは、ディスプレイの利用をクリティカルセクションとして保護し、排他制御する。 independent_sem_ope.c kishima@DdeDynabook-4 $ gcc independent_sem_ope.c -o independent_sem_ope kishima@DdeDynabook-4 $ ./independent_sem_ope & [1] 3892 kishima@DdeDynabook-4 $ ./independent_sem_ope & [2] 2384 kishima@DdeDynabook-4 $ ./independent_sem_ope & [3] 3076 kishima@DdeDynabook-4 $ pid=3892, pid=3892, pid=3892, pid=3892, pid=3892, pid=3892, pid=3892, pid=3892, pid=3892, pid=3892, pid=2384, pid=2384, pid=2384, pid=2384, pid=2384, pid=2384, pid=2384, pid=2384, pid=2384, pid=2384, pid=3076, pid=3076, pid=3076, pid=3076, pid=3076, pid=3076, pid=3076, pid=3076, pid=3076, pid=3076, [1] Done ./independent_sem_ope [2]- Done ./independent_sem_ope [3]+ Done ./independent_sem_ope kishima@DdeDynabook-4 $ セマフォの生成・初期化・削除を管理するプログラム independent_sem_init.c kishima@DdeDynabook-4 $ gcc independent_sem_init.c -o independent_sem_init kishima@DdeDynabook-4 $ ./independent_sem_init $ Enterが押されたらセマフォを削除します kishima@DdeDynabook-4 $