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