演習1の解答例の解説 2004年10月21日 海谷 治彦.

Slides:



Advertisements
Similar presentations
システムプログラミング 情報工学科 篠埜 功 情報工学科 3 年生対象 専門科目 第5回 シェルスクリプトの続 き レポート課題 main 関数の引数 usage メッセージ.
Advertisements

ネットワーク・プログラミ ング カーネルの役割とプロセス生成. 1.1 OS の役割 仮想マシン OS はハードウェアの多様性 をカプセル化し、利用者を 複雑な処理から開放する。 プロセス管理 時間多重化により各プロセ スに CPU を割当てる。 メモリ管理 メモリ空間の多重化により、 各プロセスにメモリを割当.
プロセスの生成とコマンドの実行 プロセスの生成とコマンドの実行 プロセス生成のシステムコール プロセス生成のシステムコール プロセス生成のプログラム例 プロセス生成のプログラム例 プログラム実行のシステムコール プログラム実行のシステムコール 子プロセスの終了を待つシステムコール 子プロセスの終了を待つシステムコール.
システムプログラミング 第10回 情報工学科 篠埜 功. 今回の内容 プロセス(続き) – execve システムコール 現在のプロセスを、引数に与えられたファイル(実行 形式ファイルあるいはシェルスクリプト等の実行可能 なファイル)を受け取り、現在のプログラムをそれで 置き換える(変身)。 fork.
システムプログラミング 第7回、8回 ファイルシステム関連の システムコール
情報処理演習C2 ファイル操作について (2).
情報基礎演習B 後半第5回 担当 岩村 TA 谷本君.
システムプログラミング 第6回、7回 main関数の引数 usageメッセージ システムコールのエラーメッセージ ファイル
数理情報工学演習第一C プログラミング演習 (第3回 ) 2014/04/21
データ構造とアルゴリズム 第10回 mallocとfree
リダイレクト パイプ 標準入出力プログラム コマンド行引数 関数 system()
システムプログラミング 第5回 情報工学科 篠埜 功 ヒアドキュメント レポート課題 main関数の引数 usageメッセージ
プログラミング演習Ⅱ 第12回 文字列とポインタ(1)
岩村雅一 知能情報工学演習I 第9回(C言語第3回) 岩村雅一
システムプログラミング 第11回 シグナル 情報工学科  篠埜 功.
OSとコマンド OS:コンピュータを使うための基本プログラム コマンド:OS上で使用できる命令 OS本体であるカーネルの内部コマンド
12: コマンドライン引数 C プログラミング入門 総機1 (月1) Linux にログインし、以下の講義ページ を開いておくこと
記憶クラス 変数をどのような記憶領域に割り当てるかを指定するのが記憶クラス 記憶クラスには、自動変数、静的変数、外部変数などがある。
12: コマンドライン引数 C プログラミング入門 基幹7 (水5) Linux にログインし、以下の講義ページ を開いておくこと
第8回 プログラミングⅡ 第8回
アルゴリズムとデータ構造 補足資料6-3 「サンプルプログラムcat3.c」
システムプログラミング 第11回 シグナル 情報工学科  篠埜 功.
精密工学科プログラミング基礎 第9回資料 (12/11 実施)
オペレーティングシステム2004 プロセス (1) 2004年10月8日 海谷 治彦.
情報工学科 3年生対象 専門科目 システムプログラミング 第5回、第6回 ヒアドキュメント レポート課題 情報工学科 篠埜 功.
オペレーティングシステム2004 プロセス (2) および カーネルモード・システムコール
システムプログラミング 第9回 、10回 ハードリンク、シンボリックリンク プロセスの生成
マルチスレッド処理 マルチプロセス処理について
iioLoadFile()とiioMallocImageBuffer()の補足
iioLoadFile()とiioMallocImageBuffer()の補足
精密工学科プログラミング基礎 第10回資料 (12/18実施)
プログラミング 4 記憶の割り付け.
リダイレクト パイプ 標準入出力プログラム コマンド行引数 関数 system()
2005年度 データ構造とアルゴリズム 第3回 「C言語の復習:再帰的データ構造」
岩村雅一 知能情報工学演習I 第9回(後半第3回) 岩村雅一
プログラミング入門2 第11回 情報工学科 篠埜 功.
第7回 プログラミングⅡ 第7回
演習1の解答例の解説 2006年11月8日 海谷 治彦.
P n ポインタの基礎 5 q m 5 7 int* p; int 型の変数を指すポインタ int* q; int 型の変数を指すポインタ int n=5, m=7; int 型の変数 int array[3]; int* pArray[3]; p = &n; ポインタにアドレスを代入しているのでOK.
プログラミング基礎B 文字列の扱い.
システムプログラミング 第7回、8回 ファイルシステム関連の システムコール
岩村雅一 知能情報工学演習I 第9回(後半第3回) 岩村雅一
精密工学科プログラミング基礎Ⅱ 第4回資料 今回の授業で習得してほしいこと: 文字列の扱い ファイル入出力の方法 コマンドライン引数の使い方
岩村雅一 知能情報工学演習I 第9回(C言語第3回) 岩村雅一
配列変数とポインタ 静的確保と動的確保 ポインタ配列 2次元配列 時間計測 第1回レポートの課題
システムプログラミング 第7回、8回 ファイルシステム関連の システムコール
精密工学科プログラミング基礎Ⅱ 第5回資料 今回の授業で習得してほしいこと: 構造体 (教科書 91 ページ)
岩村雅一 知能情報工学演習I 第9回(後半第3回) 岩村雅一
プログラミング基礎a 第6回 C言語によるプログラミング入門 配列と文字列(その2)
15.1 文字列処理の基本 15.2 文字列処理用ライブラリ関数
文字列へのポインタの配列 static char *lines[MAXLINES]; lines[0] NULL
情報基礎演習B 後半第2回 担当 岩村 TA 谷本君.
ファイルの読み込み, ファイルからのデータの取り出し, ファイルの書き出し
12: コマンドライン引数 C プログラミング入門 基幹7 (水5) Linux にログインし、以下の講義ページを開いておく こと
ネットワーク・プログラミング デバイスドライバと環境変数.
高度プログラミング演習 (11).
情報処理Ⅱ 2006年12月22日(金).
情報処理Ⅱ 2006年11月24日(金).
システムプログラミング 第9回 、10回 ハードリンク、シンボリックリンク プロセスの生成
モジュール分割.
プログラミング演習I 2003年6月11日(第9回) 木村巌.
システムプログラミング 第11回 シグナル 情報工学科  篠埜 功.
情報処理Ⅱ 2005年11月25日(金).
プログラミング演習II 2004年11月 16日(第5回) 理学部数学科・木村巌.
15.1 文字列処理の基本 15.2 文字列処理用ライブラリ関数
情報処理Ⅱ 小テスト 2005年2月1日(火).
モバイルプログラミング第3回 Cプログラミングの基礎( 2 )
岩村雅一 知能情報工学演習I 第7回(後半第1回) 岩村雅一
12: コマンドライン引数 C プログラミング入門 基幹2 (月4) Linux にログインし、以下の講義ページ を開いておくこと
岩村雅一 知能情報工学演習I 第9回(C言語第3回) 岩村雅一
Presentation transcript:

演習1の解答例の解説 2004年10月21日 海谷 治彦

fork2.c の概要 shellの枠組プログラム 第2回より抜粋 fork2.c の概要 shellの枠組プログラム 1| main(int argc, char* argv[]){ 2| pid_t ch; char buf[100]; 3| 4| while(fgets(buf, 100, stdin)!=NULL){ 5| buf[strlen(buf)-1]='\0'; 6| if((ch=fork())==0){ // child 7| execl(buf, buf, NULL); // execveを呼ぶ 8| }else if(ch>0){ // parent 9| sleep(10); 10| printf("done %d\n", ch); 11| wait(0); 12| } 13| } 14| 15| }

execvの仕様 関数名 execve 返り値 int 成功する場合,返らない.失敗すると –1が返る. 引数 3つ 第3回より抜粋 execvの仕様 関数名 execve 返り値 int 成功する場合,返らない.失敗すると –1が返る. 引数 3つ const char *filename プログラムの完全パス名 char *const argv[] コマンド名も含めた引数のリスト. char *const envp[] 環境変数名と値の対のリスト,mainの引数と同じ. 尚,argv, envpはNULLで終わっている必要がある. 機能: 呼び出したプロセスを引数で指定したプログラムのプロセスに書き換える.

使用例 第3回より抜粋 #include <stdio.h> #include <unistd.h> main(){ char* filename="/bin/ls"; char* argv[4]={ "ls", "-l", "/", NULL }; char* envp[3]={ "PATH=/sbin:/usr/local/bin", "LANG=ja_JP", NULL execve(filename, argv, envp); }

演習1の私の解決方針 execveの簡易版,execvpを使おう. パスは外部変数environを利用しよう. 引数がほとんど同じ. 可変長引数に対応し易い. パスは外部変数environを利用しよう. 問題は単なる文字列をコマンドと引数の文字列配列にバラすことだ.

execvpの仕様 関数名 execvp 返り値 int 成功する場合,返らない.失敗すると –1が返る. 引数 2つ 外部変数 const char *filename プログラムの完全パス名 char *const argv[] コマンド名も含めた引数のリスト. 尚,argvはNULLで終わっている必要がある. 外部変数 char** environ 環境変数のリストが入る 機能: 呼び出したプロセスを引数で指定したプログラムのプロセスに書き換える.

サンプルプログラムと結果 第3回より抜粋 #include <stdio.h> main(int argc, char* argv[], char* envp[]){ char** ptr; for(ptr=envp; *ptr!=NULL; ptr++){ printf("<%s>\n", *ptr); } <USER=kaiya> <LOGNAME=kaiya> <HOME=/home/kaiya> <PATH=/bin:/usr/bin:/usr/local/bin:/usr/X11R6/bin> <SHELL=/bin/tcsh> <HOSTTYPE=i386-linux> <VENDOR=intel> <OSTYPE=linux> <MACHTYPE=i386> <TZ=Japan> <LANG=ja_JP.eucJP>

environの設定,実行方法の決定 extern char** environ; main(int argc, char* argv[]){ environ=argv+1; // argv[0]はコマンド名自体 ・・・・ // 以下略 } ってな感じで, ./a.out PATH=/bin:/usr/bin LANG=dutch TZ=EST とかいう形で実行.

文字列を文字列配列に ls -l /home [エンター] l s - l \t / h o m e \n \0 l s \0 - l \0 このような変換をしなければならない. NULL

ex1a.c の実装 main関数内の行バッファ buf[LINE_MAX] l s - l \t / h o m e \n \0 項目直後のセルに\0を埋める. l s \0 - l \0 \t / h o m e \0 \0 関数 str2args()内の static変数 args[LINE_MAX], 長さは行バッファと同じ. 長さ, LINE_MAX NULL

説明・考察 mallocとか使わないでいいから楽. 関数内static変数を巧みに使っている. 行バッファの中身をそのまま流用. が,しかし,コレが結構アブない. 関数が並行して複数呼び出された場合危険. 行バッファの中身をそのまま流用. コレも実はあぶない. execvp呼び出しまでbuf[]内部を壊さないことを保障する必要がある. 文字列の配列のための行列 args[] は buf[]と同じ長さなので,足りなくなることはありえない. コマンドとオプションは空白文字で区切られるため,buf長より多いオプションが与えられることは論理的にありえない. とはいえ,無駄に長いのも確か.

ex1b.cの実装 この長さをもとに, を動的確保. main関数内の行バッファ buf[LINE_MAX] l s - l \t / h o m e \n \0 項目直後のセルに\0を埋める. l s \0 - l \0 \t / h o m e \0 \0 コピー コピー l s \0 コピー 各文字列も 動的に確保 してコピー. - l \0 / h o m e \0 NULL 関数 str2args内で動的に確保,ポインタ args で捕獲, 長さは入力された文字列の長さと同じにする.

説明・考察 ex1aよりは正統派. それでも入力時の内容 buf[]の一部を改変する. argsで参照する文字列配列もex1aほどは無駄ではない,とはいえ,結構無駄. malloc()を使うので結構長い. execvpを呼ぶともう制御が返ってこないか,もしくはexit()なのでfreeは実は必要ない. しかも,fork()後にstr2buf()を呼ぶので,親側では気にしなくて良い.

パラっと皆さんの解答を見て 割と関数分けしてない人が多い. ま,リハビリになったでしょうか? 解答例にあるように関数わけしたほうが,この程度のプログラムでも見通しが良い. ま,リハビリになったでしょうか? fork(), exec()のからくりがなんとなくわかればOKかと思います. オンラインマニュアルやネットで色々調べましょうね.