システムプログラミング 第9回 、10回 ハードリンク、シンボリックリンク プロセスの生成

Slides:



Advertisements
Similar presentations
システムプログラミング 第11回 シグナル 情報工学科 篠埜 功. 今回の内容 前回の補足( exit システムコールについ て) プロセス間通信 – シグナルの送信 --- 今回の内容 – パイプによる通信 – ソケットによる通信.
Advertisements

システムプログラミング 情報工学科 篠埜 功 情報工学科 3 年生対象 専門科目 第5回 シェルスクリプトの続 き レポート課題 main 関数の引数 usage メッセージ.
ネットワーク・プログラミ ング カーネルの役割とプロセス生成. 1.1 OS の役割 仮想マシン OS はハードウェアの多様性 をカプセル化し、利用者を 複雑な処理から開放する。 プロセス管理 時間多重化により各プロセ スに CPU を割当てる。 メモリ管理 メモリ空間の多重化により、 各プロセスにメモリを割当.
プロセスの生成とコマンドの実行 プロセスの生成とコマンドの実行 プロセス生成のシステムコール プロセス生成のシステムコール プロセス生成のプログラム例 プロセス生成のプログラム例 プログラム実行のシステムコール プログラム実行のシステムコール 子プロセスの終了を待つシステムコール 子プロセスの終了を待つシステムコール.
オブジェクト指向言語・ オブジェクト指向言語演習 中間試験回答例. Jan. 12, 2005 情報処理技術基礎演習 II 2 オブジェクト指向言語 中間試験解説 1  (1) 円柱の体積(円柱の体積 = 底面の円の面積 x 高さ) を求めるプログラムを作成しなさい。ただし、出力結果は、入 力した底面の円の半径.
システムプログラミング 第10回 情報工学科 篠埜 功. 今回の内容 プロセス(続き) – execve システムコール 現在のプロセスを、引数に与えられたファイル(実行 形式ファイルあるいはシェルスクリプト等の実行可能 なファイル)を受け取り、現在のプログラムをそれで 置き換える(変身)。 fork.
システムプログラミング 第7回、8回 ファイルシステム関連の システムコール
プログラミング入門2 第4回 配列 for文 変数宣言 初期化
情報基礎演習B 後半第5回 担当 岩村 TA 谷本君.
システムプログラミング 第6回、7回 main関数の引数 usageメッセージ システムコールのエラーメッセージ ファイル
数理情報工学演習第一C プログラミング演習 (第3回 ) 2014/04/21
プログラミング入門2 第10回 動的な領域確保 情報工学科 篠埜 功.
プログラミング入門2 第10回 構造体 情報工学科 篠埜 功.
プログラミング入門2 第10回 構造体 情報工学科 篠埜 功.
システムプログラミング 第5回 情報工学科 篠埜 功 ヒアドキュメント レポート課題 main関数の引数 usageメッセージ
システムプログラミング 第11回 シグナル 情報工学科  篠埜 功.
OSとコマンド OS:コンピュータを使うための基本プログラム コマンド:OS上で使用できる命令 OS本体であるカーネルの内部コマンド
記憶クラス 変数をどのような記憶領域に割り当てるかを指定するのが記憶クラス 記憶クラスには、自動変数、静的変数、外部変数などがある。
担当:青木義満 情報工学科 3年生対象 専門科目 システムプログラミング システムプログラミング プロセス間通信(パイプ) 担当:青木義満
構造体.
アルゴリズムとデータ構造 補足資料6-3 「サンプルプログラムcat3.c」
担当:青木義満、篠埜 功 情報工学科 3年生対象 専門科目 システムプログラミング 第8回、第9回 シグナル処理 担当:青木義満、篠埜 功
システムプログラミング 第11回 シグナル 情報工学科  篠埜 功.
精密工学科プログラミング基礎 第9回資料 (12/11 実施)
オペレーティングシステム2004 プロセス (1) 2004年10月8日 海谷 治彦.
情報工学科 3年生対象 専門科目 システムプログラミング 第5回、第6回 ヒアドキュメント レポート課題 情報工学科 篠埜 功.
ちょっとした練習問題① 配列iroを['R', 'W', 'R', 'R', 'W' , 'W' , 'W']を宣言して、「W」のときの配列の番号をprintfで表示するようなプログラムを記述しなさい。
プログラミング2 関数
システムプログラミング 第6回、7回、8回 情報工学科 篠埜 功.
システムプログラミング 第12回 プロセス間通信 情報工学科 篠埜 功.
マルチスレッド処理 マルチプロセス処理について
プログラミング入門2 第8回 ポインタ 情報工学科 篠埜 功.
システムプログラミング 第3回、第4回、第5回、第6回 情報工学科 篠埜 功 makeコマンド 動的リンクライブラリ シェルスクリプト
プログラミング入門2 第11回 情報工学科 篠埜 功.
演習1の解答例の解説 2004年10月21日 海谷 治彦.
プログラミング入門2 第11回 情報工学科 篠埜 功.
第7回 プログラミングⅡ 第7回
復習 前回の関数のまとめ(1) 関数はmain()関数または他の関数から呼び出されて実行される.
第11回 プログラミングⅡ 第11回
演習1の解答例の解説 2006年11月8日 海谷 治彦.
担当:青木義満 情報工学科 3年生対象 専門科目 システムプログラミング 第6回 システムプログラミング概要 プロセスの生成 担当:青木義満
システムプログラミング 第7回、8回 ファイルシステム関連の システムコール
精密工学科プログラミング基礎Ⅱ 第4回資料 今回の授業で習得してほしいこと: 文字列の扱い ファイル入出力の方法 コマンドライン引数の使い方
岩村雅一 知能情報工学演習I 第12回(C言語第6回) 岩村雅一
配列変数とポインタ 静的確保と動的確保 ポインタ配列 2次元配列 時間計測 第1回レポートの課題
情報工学科 3年生対象 専門科目 システムプログラミング 第4回 シェルスクリプト 情報工学科 篠埜 功.
システムプログラミング 第7回、8回 ファイルシステム関連の システムコール
プログラミング入門2 第9回 ポインタ 情報工学科 篠埜 功.
システムプログラミング 第12回 プロセス間通信 情報工学科 篠埜 功.
プログラミング入門2 第6回 関数 情報工学科 篠埜 功.
プログラミング入門2 第13回、14回 総合演習 情報工学科 篠埜 功.
システムプログラミング 第6回 システムコールのエラーメッセージ ファイルシステム 情報工学科 篠埜 功.
システムプログラミング 第12回 プロセス間通信 情報工学科 篠埜 功.
ネットワーク・プログラミング デバイスドライバと環境変数.
プログラミング入門2 第5回 配列 for文 変数宣言 初期化
システムプログラミング 第9回 、10回 ハードリンク、シンボリックリンク プロセスの生成
情報工学科 3年生対象 専門科目 システムプログラミング 第3回 makeコマンド 動的リンクライブラリ 情報工学科 篠埜 功.
岩村雅一 知能情報工学演習I 第12回(後半第6回) 岩村雅一
情報工学科 3年生対象 専門科目 システムプログラミング 第3回 makeコマンド 動的リンクライブラリ 情報工学科 篠埜 功.
ネットワーク・プログラミング 1対多のプロセス間通信.
プログラミング入門2 第6回 関数 情報工学科 篠埜 功.
プログラミング演習I 2003年6月11日(第9回) 木村巌.
システムプログラミング 第11回 シグナル 情報工学科  篠埜 功.
ネットワーク・プログラミング マルチタスク.
情報処理Ⅱ 2005年11月25日(金).
ネットワーク・プログラミング プロセスとファイルシステム管理.
プログラミング入門2 第5回 配列 変数宣言、初期化について
情報処理Ⅱ 小テスト 2005年2月1日(火).
プログラミング入門2 第3回 条件分岐(2) 繰り返し文 篠埜 功.
岩村雅一 知能情報工学演習I 第7回(後半第1回) 岩村雅一
Presentation transcript:

システムプログラミング 第9回 、10回 ハードリンク、シンボリックリンク プロセスの生成 情報工学科 篠埜 功

今回の内容 ハードリンク、シンボリックリンク プロセスの生成

ハードリンク $ ls –l で表示される、permission情報の隣の数字は、リンク数(ハードリンク)である。複数のファイル名を同じファイル(inode番号)に対応させてよい。 ディレクトリファイルにおいてファイル名とinode番号が対応付けられている。この対応付けをハードリンクと呼ぶ。 各ファイル(inode)は、それにつけられているファイル名の数を保持している。すべてのファイル名(ハードリンク)が削除されたとき、それに対応するinodeとファイルの中身が削除される。

ハードリンクの作成 $ ln test.c foo とすると、test.cが指すファイルを、fooという名前で指すようになる。 ディレクトリに対するハードリンクは作成できない。(ただし、ディレクトリ作成時に、., ..というハードリンクが自動的に作成される。)

シンボリックリンク リンクには2種類あり、ハードリンクとシンボリックリンクがある。 $ ln –s test.c foo によって、fooはtest.cを指すようになる。 これにより、fooという新しいファイル(test.cというファイル名(一般にはパス名)を中身に持っているファイル)が作成される。 ls –l で表示されるリンクカウントは、ハードリンクの数である。

プロセスとは? Unix系OSでは、複数のプログラムを同時に並行して実行させることができる(各時点では1つのプログラムが実行されている)。OSは各プログラムを切り替えて実行する。一つ一つのプログラムについて、プログラム中のどこをどういう状態(メモリ、レジスタ)で実行しているか、(今実行していない場合は)復帰できるように覚えておく必要がある。このそれぞれのプログラムの実行の状態(を管理するテーブルのエントリ)をプロセスという。 各プロセスは、生成状態、実行状態、休眠状態、実行可能状態、ゾンビ状態のいずれかの状態にある。

プロセスの状態 5つの状態を遷移 実行状態:現在CPUで実行中の状態 実行可能状態:スケジューラによるCPUの割り当てを待っている状態 休眠状態:入出力の終了待ちなどで実行を継続できない状態 生成状態:fork()システムコールにより生成された状態 ゾンビ状態:exit()システムコールにより終了した状態

プロセスの状態遷移図 入力待ちにより実行状態から休眠状態へ 他のプロセスへ実行権を譲る CPU占有時間経過による実行状態から実行可能状態への遷移 Time Sharing Systemの実現

プロセスの優先度 実行可能状態にあるプロセスに対して優先度を定義 スケジューラにより,優先度の高い順に選択されて実行 カーネル プロセス優先度を自律的制御で刻々と変化させ、プロセス実行の機会均等を実現 プロセスの優先度を変更するためのシステムコールniceがある。nice(3)などで呼び出すと、呼び出したプロセスの優先度に3が足される(優先度が下がる)。(マイナスの数を指定できるのはroot権限で実行されているプロセスのみ。一般ユーザのプロセスは優先度を下げることのみ可能。)

プロセスID pid_tはint型。 headerファイル内でtypedefで定義されている。 プロセスID プロセスを一意に識別するための番号。この番号ですべてのプロセスを管理する。 現在実行中のプロセスIDは、getpid()システムコールにより取得できる。 現在実行中のプロセスの親プロセスのプロセスIDは、getppid()システムコールにより取得できる。 SYNOPSIS #include <sys/types.h> #include <unistd.h> pid_t getpid(void); pid_t getppid(void); pid_tはint型。 headerファイル内でtypedefで定義されている。

例(打ち込んで確認) #include <sys/types.h> #include <unistd.h> #include <stdio.h> int main (void) { printf ("ID of the current process is %d.\n", getpid()); printf ("ID of the parent process is %d.\n", getppid()); return 0; } このプログラムをプロンプト上で $ ./a.out のように実行した場合は、親プロセスは、シェル(私の場合はtcsh)である。 $ ps –ef | grep sasano のようにして確認。

プロセスの木構造 プロセスinit --- プロセスID 1番のプロセス。 initは、すべてのプロセスの先祖である。 $ ps –ef | less で、一番上に表示される。 PIDの欄を確認。

実際のプロセスの木構造の例(p.145)

forkシステムコール SYNOPSIS #include <sys/types.h> プロセスはforkシステムコールにより生成する。生成されたプロセスを、forkシステムコールを呼び出したプロセスの子プロセスという。 子プロセスにとっては、forkシステムコールを呼び出したプロセスを親プロセスという。 親は一つなので、プロセスは木構造を成す。 すべてのプロセスはforkシステムコールで生成される(プロセス0番以外は) 。 SYNOPSIS #include <sys/types.h> #include <unistd.h> pid_t fork(void);

forkシステムコール int 親プロセスの分身が子プロセスとして生成される。 fork()システムコールの戻り値により親と子をプログラム内で識別する。(具体的にはif文で分岐すればよい。)

親プロセスと子プロセスの切り分け forkシステムコールを呼び出す典型的書き方 forkシステムコールの返り値 0: 0を受け取ったら、そのプロセスは子プロセスである。 1以上:これを受けったら、そのプロセスは親プロセスである。値は生成された子プロセスのプロセスIDである。 -1: これを受け取ったら、forkシステムコールがエラーで終了している。この場合は子プロセスは生成されていない。 forkシステムコールを呼び出す典型的書き方

例(打ち込んで確認) #include <sys/types.h> #include <unistd.h> #include <stdio.h> #include <stdlib.h> int main (void) { int pid; if ((pid = fork()) == 0) { printf ("Child process. ID=%d\n", getpid()); } else if (pid >= 1) { printf ("Parent process. ID=%d, pid=%d\n", getpid(), pid); } else { perror ("fork"); exit(1); } exit (0);

execシステムコール 現在のプロセスを、引数に与えられたファイル(実行形式ファイルあるいはシェルスクリプト等の実行可能なファイル)を受け取り、現在のプログラムをそれで置き換える(変身)。 forkシステムコールによって子プロセスの生成後、子プロセスがexecveシステムコールによって新しいプログラムを読み込むというのが典型的な使い方(fork-exec)。 execveシステムコールを使って定義されたいくつかのライブラリ関数があり、自分の使い方あった、便利がよい関数を用いればよい。以下ではこれらをまとめてexecシステムコールと呼ぶこととする。

実行形式ファイルに格納されているプログラムを別プロセスで実行したい場合は、forkで子プロセスを作り、子プロセスでexecシステムコールを用いる。これをfork-execという。

例(打ち込んで確認) 子プロセスでpsコマンドを実行する例 #include <sys/types.h> #include <unistd.h> #include <sys/wait.h> #include <stdlib.h> #include <stdio.h> int main (void) { int pid, status; char * argv [2] = {"/bin/ps", NULL}; if ((pid = fork()) == 0) { execv("/bin/ps", argv); } else if (pid >= 1) { wait (&status); } else { perror ("fork"); exit(1); } exit (0); 子プロセスでpsコマンドを実行する例

waitシステムコール 子プロセス生成後,親プロセスはwait()を呼んで子プロセスの終了を待つ。 子プロセスが終了すると、waitシステムコールにより、子プロセス用のプロセステーブルのエントリ、プロセスIDが消され、それらが再利用可能な状態になる。 子プロセスが終了した後、親プロセスがwaitシステムコールを呼ばなかった場合は、子プロセスはゾンビ状態となる。親プロセスが終了したらinitプロセスが親になり、initプロセスがwaitシステムコールを呼び出す(のでゾンビ状態ではなくなり、プロセスが終了する)。 子プロセスの終了ステータス情報を得るため,引数にint型へのポインタを渡す。

ゾンビプロセス(打ち込んで確認) #include <unistd.h> #include <sys/wait.h> #include <stdio.h> #include <stdlib.h> int main (void) { int pid; int status; if ((pid = fork()) == 0) { } else if (pid >= 1) { sleep (5); wait (&status); } else { perror ("fork"); exit(1); } exit (0); このプログラムを実行し、5秒以内にCtrl-zでsuspendする。そのときにpsコマンドを実行すると、以下のように、<defunct>と書かれたプロセスがあるはずである。これがゾンビプロセスである。 19570 pts/0 00:00:00 a.out 19571 pts/0 00:00:00 a.out <defunct>

例:コマンドの引数に与えられたプログラムを実行(打ち込んで確認) #include <unistd.h> #include <stdio.h> #include <stdlib.h> int main (int argc, char * argv []) { if (argc < 2) { fprintf (stderr, "Usage: %s command [option]\n", argv[0]); exit(1); } if (execv (argv[1], &argv[1]) == -1) { perror ("execv"); return 0; /* ここには来ない */ $ ./a.out /bin/ps –ef のようにして実行する。 この場合、 $ /bin/ps –ef と打ったのと同じ結果が表示される。

簡易shell(打ち込んで確認) #include <stdio.h> #include <sys/wait.h> #include <unistd.h> #include <stdlib.h> #define ARG_NUMBER 16 #define PARAM_SIZE 128 int getcomln (char * argvline[]) { int i,j,k; char linebuf [ARG_NUMBER * PARAM_SIZE]; for (i=0; (linebuf [i] = getchar()) != EOF; i++) { if (linebuf[i] == '\n') { linebuf[i] = '\0'; break; } if (linebuf[i] == EOF) return EOF; for (i=j=k=0;;j++, k++) { argvline[i][j] = linebuf[k]; if (argvline[i][j]==' '){ if (j>0) { argvline[i][j] = '\0'; i++; } j=-1; } else if (argvline[i][j]=='\0'){ if (j>0) i++; break; if (i==0 && j==0) return 0; else return i;

簡易shellの続き int main (void) { int argcline, i, pid, status; char * argvline [ARG_NUMBER]; char line [ARG_NUMBER] [PARAM_SIZE]; for (i=0; i<ARG_NUMBER; i++) argvline[i] = line[i]; while (printf ("> "), (argcline = getcomln (argvline)) != EOF) { if (argcline == 0) continue; if ((pid = fork()) == 0) { argvline [argcline] = NULL; if (execvp (argvline[0], argvline) == -1) { perror ("execvp"); exit(1); } else if (pid >= 1) wait (&status); else { perror ("fork"); exit(1); } putchar ('\n'); exit(0);

演習課題 tcsh等のシェルでexitと打つとシェルが終了する。exitはシェルの内部コマンドである。 さきほどの簡易シェルに、exit(シェルの内部コマンド)を追加せよ。配列argvlineの最初の要素がexitという文字列を指しているかどうかで判定すればよい。 文字列の比較にはstrcmpを用いよ。使い方は man strcmp で調べればよい。 tcsh等のシェルのexitコマンドは引数を取ることができ、それによって終了statusを指定できるが、この課題では終了statusは気にしないこととする。 exitによってシェル自体を終了させるので、シェルの内部コマンドとして実装するのが自然である。

cd cdコマンドはshellの内部コマンドである。 cdコマンドによって、shell自体のディレクトリが変更されなければならないので、cdは外部コマンドとしては実装できない。 cdコマンドが入力されたときは、shell本体において、chdirシステムコールを呼び出す。 配列argvlineの最初の要素がcdという文字列を指しているかどうかでcdコマンドかどうかの判定をすればよい。 chdirの使い方は、   $ man –s2 chdir で確認。

レポート課題4 さきほどの簡易shellに、cdコマンドをシェルの内部コマンドとして追加せよ。 引数無しの場合はホームディレクトリに移動。 引数1つの場合は、その引数で指定されたディレクトリへ移動。 それ以外の場合は、cdコマンドの使い方を表示(メッセージは、tcshなどにおけるcdの使い方の表示を参考にして、自分で適当に作成)。 ディレクトリ移動後は、他の通常のコマンドと同様、プロンプト表示に戻る。

レポートの提出方法 □ 下記のファイルを作成し、提出 kadai4.c, kadai4.txt □ 提出方法 システムプログラミング講義用の課題提出用フォルダ内にあるkadai4というフォルダの中に自分の学籍番号を名前とするフォルダを作成し、その中に上記ファイルを置く。kadai4.txt内に学籍番号、氏名、日付、および作成したプログラムの簡単な説明を記載する。 □ 提出期限   12月20日の23:59まで。締め切り後に提出した場合、成績への反映を保証しない。

補足 ホームディレクトリは、getenvライブラリ関数で取得できる。 getenv(“HOME”)の返り値として、 ”/home/sit/sasano”(私の場合) のような文字列(charへのポインタ型)が得られる。 cdコマンドで引数がない場合は、それをchdirの引数に与えれればよい。 (ホームディレクトリの文字列を直書きしないようにする)

補足 cdコマンドの引数に与えられたディレクトリ名について、そのディレクトリが存在するかどうかを確認せずにchdirシステムコールを呼び出してよい。ディレクトリが存在しない場合、chdirシステムコールの返り値が-1になるので、通常通り、perror関数を呼び出せばよい。これにより、ディレクトリが存在しないという内容のエラーメッセージが表示される。