10. process and signal
DESCRIPTION
Linuxプログラミング―例題で学ぶUNIXプログラミング環境のすべて [単行本] ニール マシュー (著), リチャード ストーンズ (著), Neil Matthew (原著), Richard Stones (原著), 葛西 重夫 (翻訳) 単行本: 715ページ 出版社: ソフトバンククリエイティブ; 改訂第2版 (2004/08) ISBN-10: 4797327014 ISBN-13: 978-4797327014 発売日: 2004/08 --- 読み合わせ資料 発表担当の章 10章:プロセスとシグナルTRANSCRIPT
第第第第10101010章章章章::::プロセスとシグナルプロセスとシグナルプロセスとシグナルプロセスとシグナル阿部1研 松川怜右(0312004136)
はじめに
端末上で行う操作には、緑色緑色緑色緑色。
プログラム内に書かれる記法については、茶色茶色茶色茶色
で記述しております。
プロセス(Process)とは①
� OSの行う処理の基本単位。
� OSから領域を割り当てられる。
� スレッド⊂プロセス
� スレッドに関しては、11章
プロセス(Process)とは②
� 1つのプロセスに1つのPIDが割り当てられる。� PIDはProcess IDのこと。
� OSはPIDでプロセスを管理している。
� プロセスを実際表示するにはpsコマンドを使う。
� psコマンドについては補足資料を参考下さい。
$ ps -a <enter>
このオプションにはいろいろ種類があるので、端末上で、
$ man ps と打ち込んでみると分かります。
プロセス(Process)とは③
� プロセス間で共有するもの
� プログラムコード (“mule”とか)
� システムライブラリ
� 共有しないもの
� 変数
� プログラムカウンタ
プロセス(Process)とは④
� UNIXではプロセスを同時実行できる。
� マルチタスク
� タイムスライス以上の処理は、停止再開。
� 優先度の高いプログラムは、NI値が小さい。
� 常に動き続けるのではなく、入力を待って、入力されたら動き出すのがよい。
$ nice プログラム名プログラム名プログラム名プログラム名 <enter>$ renice 10 PID値値値値 <enter>
プロセスの起動①
� SYSTEM関数を使って、プログラムからプロセスを起動することができる。
� SYSTEM関数はシェルを使う。
� だから非効率。
system(“ps -l”);
system(“ps -l &”);
※後者の命令は、SYSTEM関数が終了と同時に次の命令に移るため、注意が必要。
=$ ps -l <enter>
$ ps -l & <enter>
プロセスの起動②
� 非効率なSYSTEM関数を使わないならば、exec関数を使う。
� exec関数にはいろいろ種類がある。
� 実行中のプロセスを置き換える。
� ゆえに、プログラムは、exec族関数を呼び出した時点で終わる。
� 動作環境に制限があるので注意が必要。
プロセスの起動③
� exec族は、いわば、ハイジャックのようなもの。
� ハイジャックされたプログラムはその時点で、本来の目的を失う。
� 新しいプロセスを複製するのがfork関数。
fork();
※※※※返り値によって、子プロセス返り値によって、子プロセス返り値によって、子プロセス返り値によって、子プロセスorororor親プロセスを判別する。親プロセスを判別する。親プロセスを判別する。親プロセスを判別する。
0000 →→→→ 子プロセス子プロセス子プロセス子プロセス新しい新しい新しい新しいPIDPIDPIDPID →→→→ 親プロセス親プロセス親プロセス親プロセス
プロセスの待機
� fork関数では、親と子のプロセスが独立して動くため、483ページのように出力が乱れる場合がある。
� 子プロセスが終了したか親プロセスが知る必要がある。
� wait関数を使えば、OK。
� また、WEXITSTATUEなどのマクロを使用することで、子プロセスのステータスを親プロセスが取得できる。
ゾンビ(zombie)プロセス①
� すでに終了した子プロセスが、死んでいるのか生きているのか分からない常態。
� 子プロセスは、早死にして、ゾンビになる。
� 親プロセスが死ねば、子プロセスも死ぬ。
� ゾンビプロセスは、リソースを消費する。
ゾンビ(zombie)プロセス②
� 補足資料1.8.1(P485等)のプログラムにおいて、子プロセスが、親プロセスが早く終わった場合、子プロセスは、ゾンビプロセスになる。
� ゾンビの子プロセスは、親プロセスの処理が終わるまで待つ。
� psコマンドを途中で入れれば、P487のようにわかる。
シグナル(Signal)とは①
� エラーが発生したときや、強制終了したときに、プロセスに渡される一種の値(など)
� よく使うのはCtrl Ctrl Ctrl Ctrl ----CCCCでのプログラム終了操作
� これを実行すると、SIGINTというシグナルが生成されて、プログラムは終了する。
signalライブラリ関数
� signalライブラリ関数は、受け取ったシグナルに対する処理を決める。
� SIG_IGN 受け取ったシグナルを無視
� SIG_DFL 次回シグナルを受け取ったときには
通常処理を行う。
(void) signal(シグナル名シグナル名シグナル名シグナル名, SIG_DFL);
(void) signal(シグナル名シグナル名シグナル名シグナル名, SIG_IGN);
kill関数
� kill関数では、プロセスから別プロセスにシグナルを送信することができる。
� 自分自身を含んだ、同じユーザIDのプロセスだけ。
� PIDを指定してシグナルを送る。
� P496-497では、alarm関数をkill関数で実現している。
� alarm関数とは指定された秒数後にSIGALRMというシグナルをプロセスに渡します。
unsigned int alarm (unsigned int second);
pause関数
� P494の様に、signal関数はシグナルを取得するのを待たずに、処理を続行する。
� このため、シグナルを受け取るまで待つ処理を行うのが、pause関数
� pause関数はwait関数に似ているが、wait関数は、子プロセスが死んだかどうかの区別に使用するのに対して、pause関数では色んなシグナルの判別に使用できる。
sigaction①
� これまでのシグナルを扱うための操作方法は、少し古い。
� シグナルを扱うにはより信頼性が求められる。
� sigaction構造体の使用が推薦されている。
sigaction構造体とは、シグナルを受け取ったときの動構造体とは、シグナルを受け取ったときの動構造体とは、シグナルを受け取ったときの動構造体とは、シグナルを受け取ったときの動作を設定するために使用される。作を設定するために使用される。作を設定するために使用される。作を設定するために使用される。
sigaction構造体の要素
� void (*) (int) sa_handler
� 関数か、SIG_DFLか、SIG_IGNを入れる。
� sigset_t sa_mask
� sa_handlerを実行中にブロックするシグナルを指定する。ここで指定したシグナルは、プロセスに渡されない。
� これによって、実行終了前にシグナルを受け取った時の問題を回避することができる。
� sa_flag
� シグナルの動作を通常状態に戻す際に使用。
シグナルの集合①
� シグナルの集合とは、シグナルの集合とは、シグナルの集合とは、シグナルの集合とは、sigactionで使用したよで使用したよで使用したよで使用したようなシグナルの集まり。うなシグナルの集まり。うなシグナルの集まり。うなシグナルの集まり。
� sigaddset((((sigset_t *set, int signo))));
� シグナルの集合に対して指定したシグナルを追加。
� sigdelset((((sigset_t *set, int signo))));
� シグナルの集合に対して指定したシグナルを削除。
シグナルの集合②
� sigemptyset(sigset_t *set);
� シグナルの集合を空に初期化する。
� sigfillset(sigset_t *set);
� 定義済みのすべてのシグナルを含むように初期化。
シグナルの集合③
� 前ページで紹介した4つの関数はそれぞれ、成功すると、0を、失敗すると-1を返す。
� エラーは、指定したシグナルが無効の場合のみ。
シグナルが集合に入ってるかを調べる
� 指定したシグナルが、指定したシグナルの集合に入っているかどうかを調べる時は、sigismember関数を使う。
� シグナルが集合のメンバの場合は、1を、メンバではない場合、0を返し、エラーの場合は、-1を返す。
int sigismember(sigset_t *set, int signo);
シグナルマスクを調べる
� シグナルマスクは、現在ブロックされているシグナルの集合。これらのシグナルをプロセスは受け取らない。
� これらのシグナルマスクを調べるには、sigprocmask関数を使う。
int sigprocmask(int how, const sigset_t *sig,
sigset_t *oset);
ブロックされたシグナルを調べる
� ブロックされたシグナルは、保留中の状態となる。この保留中のシグナルを調べるために使うのが、sigpending関数。
� 成功すると、0。それ以外の場合には、-1を返す。
int sigpending(sigset_t *set);
pauseより汎用的な関数
� sigsuspend関数は、指定したシグナルの集合をシグナルマスクに置き換えて、その中のどれかが実行されない限りプロセスの実行を中断する。
int sigsuspend(const sigset_t *sigmask);
その他のシグナルに関すること。
� P503-504に載っている通り、シグナルに関する関数関数関数関数は、たくさんある。
� 重要なシグナルに関しては、P504の表10.4に載っていますし、その他のよく使われるシグナルは、P505に載っています。
� P504-505はシグナルのリファレンスなので、シグナルを調べたいときに参照するといいと思います。
☆ご静聴ありがとうございました☆
� 遠慮なく質問をしてください。