情報学類主専攻実験/システムプログラム (2002年)

最終更新: 2002/09/04 11:47:34

このページは、筑波大学 情報学類 3年生を対象とした 情報学類主専攻実験の、 テーマ K-3 (システム・プログラム) のためのページ(新城担当部分)です。この実験には、 課題が2つあり、シェルとftpのプログラムを作成します。 このページでは、シェルの作成に関連した追加情報を掲載します。

科目番号:

情報科学実験I,II
L41 2403, L41 2503
計算機システム実験I,II
L51 1903, L51 2003
知能情報メディア実験I,II
L61 1903, L51 2003
ソフトウェア工学実験I,II
L11 1613, L11 1623
情報処理工学実験
L21 1213, L21 1223

実験時間:水3・4、金4・5

実験テキスト:

■連絡事項

2学期は、最初の時間、9月4日水曜日に、説明をやります。3C113計 算機室に集まって下さい。

実験を取っている人のメーリング・リストを作りました。最初のメールは送り ました。届いていない人は、新城まで連絡してください。

■中間報告

この課題では、何回か中間報告を出してもらいます。

2002年2学期では、次の日時までに課題を仕上げて指定された方法で提出 してください。

9月11日水曜日 23:59:59
シェルの課題1−1を行い、電子メールで新城まで提出する。 ただし、図については、付けなくてもよい。テキスト部分だけでよい。 (最終的なレポートには必ず図を付けること。)
10月2日水曜日
残り課題1−2、1−3を行い、課題1−1も含めて全て紙に印刷して レポート提出箱(C棟1階の予定)に提出する。

■注意

この実験を取る人は、関連した講義を取るように してください。1学期の講義の中でも、実験に関連した話をします。

■実験テキスト

■シェル用構文解析器

利用者が打ち込んだ行を、シェルの構文に従って解析し、解析木を出力するよ うなプログラムを用意しました。この実験では、シェルの構文解析の部分につ いては、このプログラムを利用してください。

プログラムは、次の場所にあります。

~yas/slab-syspro-2002/myshparse3/

cp -rp などでコピーして使ってください。必要な部分は、次のファイルです。

command.c
command構造体操作
command.h
command構造体データ構造
lexer.c
字句解析器
lexer.h
字句解析器データ構造
parser.c
構文解析器
parser.h
構文解析器データ構造
ここもっとも重要な関数が、parse() です。これは、引数で与 えられた1行を解析し、commandという構造体からなる木構造を返します。

次の2組のサンプルがあります

  1. サンプル1
    mysh.c
    mainプログラム。1行読み込み。
    executer.c
    実行部分
    executer.h
    実行部分データ構造
  2. サンプル2
    mysh.c
    mainプログラム。1行読み込み。
    executer2.c
    実行部分
    executer.h
    実行部分データ構造
このサンプルは、command構造体からなる木構造の内容を画面に表示するよう になっています。

次のような手順で、execute_command() を書き換えていくとよいでしょう。

  1. 1行として簡単なもの(パイプも入出力の切り替えもなし)を与えたと きに、どのような木構造になるか調べる。id がどうなるか、argc, argv がど うなるか、sinfile, soutfile,out_mode, comm1, comm2 がどうなるかを 調べる。
  2. do_simple() でコマンドを実行する。この時、内部コマンドなら自分自 身で実行する。外部コマンドなら、fork()システムコールと execve() システ ムコール(またはexecv() や execvp() )を使って実行する。 リターンバリューとして、PID を返す。
  3. fork() した場合、親プロセス側は、親は、wait(0), wait3() などで子 供が終了することを待たなければならない。どこで wait すべきかをよく考え る。必ずしも fork() をした関数で wait しなければならいことはない。
  4. 標準入力の切り替え(<)を与えた時に command 構造体が どうなるかを調べる。
  5. 標準入力を切り替えを実現する。open() システム・コールとdup() (ま たは、dup2())システム・コール、close() システム・コールを用いる。
  6. 標準出力の切り替え(>)、標準エラーの切り替え (>&)について、標準入力の切り替えと同様のことを行う。 out_mode にも注意する。
  7. パイプ(|)が打ち込まれた時に command 構造体がどうなるかを調べる。
  8. パイプ(|)を実現する。まず、pipe() システム・コールでパイプを作成 し、fork() してから親子で左右の枝を分担して再起する。fork() した後、パ イプの不要な口を閉じることを忘れないようにする。
  9. パイプラインでは、一番最後のコマンドだけを一番外側で wait すれば よい。
do_シリーズの関数には、引数を追加する必要がでてくるでしょう。 ファイル記述子を付け加えたり、fork すべきかどうかのフラグを 付け加えたりする必要がでてくるでしょう。

fork() のタイミングには注意してください。内部コマンドの場合、fork() を してはいけません。ただし、標準出力がパイプの場合、まずパイプを作成して からfork() する必要があります。fork() すべきかどうかを、木を先読みして 調べる方法もあります。

木構造の探索については、2年生の教科書を読み返して復習して下さい。木構 造を手繰る時に、fork() しながら同時に左右2つの枝を降りていくようにし ます。戻ってくる必要がないので、ある意味では、逐次のアルゴリズムよりは 自然です。

■パイプラインの作り方

課題1−1では、プロセスの親子関係を中心に調べなさい。これを調べるには、 自分が作成するシェルの参考にするためです。同じ方法を使ってもよいし、独 自の方法を使ってもかまいません。

親子関係を調べるには、ps コマンドを使います。この時、意味はありません が、ps コマンドには、X ウインドウ関係のプログラム(すぐには終了しない) を使うとよいようです。

% csh [←]
% emacs | ps -l [←]
% emacs | kterm | ps -l [←]
% sh [←]
$ emacs | ps -l[←]
$ emacs | kterm | ps -l[←]
$ []
本格的に調べるには、strace コマンドを使います。
% strace -f -o sh.log sh [←]
$ ls[←]
$ ls | head[←]
$ exit[←]
% less sh.log [←]
% egrep 'fork|dup|exec|close|wait' sh.log | less [←]
% []
プロセスが実行していく過程でどのようにシステムコールを発行していったか の「足跡」をプロセスのトレース(trace)といいます。 strace (Linux) は、プロセスのトレースを表示するコマンドです。-f で、 fork() を越えて子プロセスまで追跡します。-o file で、画面(標準エラー) の代りに、ファイルに結果を落とすことができます。

詳しくは、man strace を見てください。

■関連ページ


Last updated: 2002/09/04 11:47:34
Yasushi Shinjo / <yas@is.tsukuba.ac.jp>