2001/5/1
また最初にもどる。我々は計算機をつかって作業を実行する。 計算機はプログラムを実行する。プログラムって?
プログラムとは
したがってプログラムは「容れ物」として使えると同時に、 何かを操作する「機械」として使える。だからこれをつかって作業する。
問: プログラムを「容れ物」として使っているのはどういうアプリケーションか?
UNIX では複数のプログラム (プロセス) を同時に走らせることができる。
問: 次の違いを説明せよ。
UNIX の特徴として、ファイルシステムが目に見えない (視覚化されていない) というのがあった。 UNIX のもうひとつの特徴は、アプリケーションも「見えない」 ということである (ただし見えるものもある)。 Windows では、各々のプロセスは各ウインドウに 対応づけられていた (図1)。
図1・Windows のプロセス
UNIX プロセスには、目に見えるプロセスと見えないプロセスがある。
一瞬だけ起動してすぐに死ぬプロセスもある (ls などはそうだ)。
UNIX 設計思想の中核:
Windows や Mac を使い慣れている人は注意。 UNIX でふつう「コマンド」や「プログラム」というと、その意図する意味は Windows や Mac でいうところの「アプリケーション」とはだいぶ違う。 UNIX の「コマンド」や「プログラム」は Windows や Mac のアプリケーション よりもずっと単純な機能しかもたない (Netscape や Acroread は 数少ない例外)。 UNIX では、Windows や Mac よりもずっと安易な理由で プロセスを起動したり終了したりする。たとえば Windows や Mac などでは、 わざわざファイル名の一覧を見るためだけに毎回アプリケーションを起動して すぐ終了する、などといったことはひどく非効率に聞こえるだろう。 しかしこれはまさに UNIX の ls コマンドが実際にやっていることであり、 きみたちはプロセスを一瞬だけ走らせてはすぐに終了させる、 ということを 1時間のうちに何百回とやっていることになる。 つまり、UNIX というのは プロセスを贅沢に使う OS なわけだ。
UNIX がこうなっている理由のひとつとして、まず UNIX では、 プロセスの起動 / 終了が、Windows や Mac のそれよりもケタ違いに 効率的だ、ということがある。そのためプロセスをたくさん起動 / 終了しても そんなに遅くない。しかし、実はもっと大きな理由がある。それは 複雑なプログラムを可能なかぎり単純な部品に分解する ためである。これは UNIX 設計思想の中核ともいえるもので、 複雑な仕事はすべて、単純なプログラムを「組み合わせる」ことによって 実現するのが UNIX の流儀である。
たとえば Windows の圧縮/展開ソフトといえばふつう WinZip か LHA だが、 これには複数のファイルを一気に圧縮/展開する機能がある。しかしこれは UNIX の流儀ではない。UNIX では、これらは普通それぞれ 2つのプログラム tar (複数のファイルをひとつのファイルにまとめる) と gzip (単一のファイルを圧縮する) によって実現される。
なぜ、プログラムを分解するのか? ある問題を部分問題に分割することによって解答が容易になるといったことは、 よくあることだからだ。一般に大きくて複雑なプログラムは作りにくく、 バグも多い。しかもたいていのプログラムには似たような部分がいくつもあり、 それらをすべて毎回設計するよりは、他のプログラムの一部を再利用したほうが 簡単に答えが手に入る。ならばプロセスを最小単位として各プロセスには 極力簡単な機能のみを持たせ、各プロセスどうしを協力させて仕事を 行わせよう、というのが UNIX の根本的な設計思想である。 これはとくにテキスト処理のときに力を発揮する。詳しくは シェルの使い方 (2) を参照。
問: いま snow で走っているプロセスを見てみよう。 誰が何をしているか? 新しいプロセスを起動するとどうなるか?
さて、あるマシンで動くプロセスは、そのマシンでの操作しかできない。 しかし UNIX 環境の特長は、ネットワーク上の別のマシンでも プロセスを実行できることにある。これが rlogin, rsh である。
問: あなたがよくプロセスを動かしているマシンは?
問: ネットワーク上の別のマシンでプロセスを動かして、様子を見る。
プロセスにも所有者がある。 ある所有者 X のプロセス P は、以下のようなことができる:
おさらい問題: ファイル操作で、その所有者にしかできない特権とは?
ユーザが UNIX にログインした瞬間、UNIX のなかに 「自分の」プロセスがひとつ生まれる。これはふつう 「シェル (shell)」と呼ばれるもので、ユーザはここから すべてのプロセスを起動していく。これは UNIX を使うとき 中心的な役割を果たす。 (シェルは実はプロセスを起動するだけでなく、ほかにもたくさんんの機能が ある、けどこれについては次回)
シェルは基本的に、入力された文字列(コマンド)を プログラムの名前だと解釈し、新しく子プロセスを生成する。
% kterm (終わるまで待つ) % cat /etc/motd (終わるまで待つ) % kterm & (実際にはシェルも一緒に起動する、ktermはかならずペアで起動) [1] 19343 (プロセスID が出る) % ls & % LOCAL/ Mail/ ar/ bin/ pub@ tmp/ work/
シェルはふつう、子プロセスが終了するまで待つ。 しかし & をつけると、待たずに次のコマンドを受けつける。
一般に、あるプロセスが起動するすべてのプロセスには 「親子関係」がある。シェルが起動するプロセスは、 すべてシェルの子プロセス (child process) である。
なぜそんな「関係」が必要なのか? それはプロセスの「属性」を 受けつぐためである。
ひとつプロセスは、いくつかの属性をもっている。
したがって、UNIX のプロセスもまた木構造をなしている (図2)。 (でもこの木構造はファイルシステムの木構造とはまったく違って、 ファイルとフォルダのような入れ子関係ではない。)
図2・UNIX のプロセス
子は親の属性をうけつぐ。そのため、ある所有者 X が 作成したプロセスは必ずその所有者のものになる。
UNIX には、すべての親プロセスとして init がある。 これはシステム起動時に最初に生成され、電源が切られるときまで ずっと走りつづける。ユーザの各プロセスもここから生まれる。 あるユーザがログインすると、そのプロセスの部分木はすべて 同じユーザでまとまることになる (図3)。
図3・同じユーザのプロセス
init などの、「システムプロセス」の所有者は UNIX では root に決められている。これがその計算機に関するすべての権限をもつ。
問: 親プロセスを殺された子プロセスはどうなるか?
さて、ではプロセスの場合、その所有者がプロセスに対してできる 「所有者だけの特権」とは何か? それが「シグナルを送ること」である。
シグナルとは、プロセスに送る特別な指令である。 Windows ではこれはたとえば「×」や「アイコン化」ボタンを クリックすることに相当する。シグナルには何種類もあり、 いくつかは意味もだいたい決まっている。けれども プロセスによっては別の動きをするものもある。
シグナルの種類:
シグナルを送るには kill コマンドを使う。 プロセスはプロセス ID によって指定する (省略時は TERM)。べつに名前が kill だからといって KILL シグナルしか送れないわけではない。
% kill -シグナル名 プロセスID
ふつう、端末から起動されたプログラムは、その端末を 一時的に「借りる」。現在、端末を借りているプロセスを 「フォアグラウンド (foreground)」にあるという (そうでないものは 「バックグラウンド (background)」にあるという)。 フォアグラウンドにあるプロセスは、端末の特別な機能を 使ってキーボードから直接シグナルを送ることができる。
しかし、INT も TERM も拒否するプロセスも存在する。
% forever ^C^C^Z
このような奴には、強制終了の KILL シグナルを送るしかない。これは 絶対に拒否できないが、こうするとデータその他は まったく保存されずに不完全な状態でいきなり殺されてしまうので、 あとで起動したときにおかしくなるかもしれない。なのでこれは最終手段 (けれども Netscape はよく暴走する)。
バックグラウンドのプロセスや、ネットワーク上の 別マシンで動いているプロセスには kill を使うしかない。
さて、各プロセスの属性は独立していて、他のプロセスから 属性を変えることはできない。
問: シェルから kterm を起動させた。kterm のカレントディレクトリを 親プロセスから変えることはできるか? 逆は?
問: すると、cd はどうやってカレントディレクトリを変えているのか?
じつは、シェルには「外部のプロセスを起動しないコマンド (内部コマンド)」 というものがある。これらは一見、ふつうのコマンドとまったく同じに 見える。
まとめ: ユーザは自分の道具であるプロセスを使って、 ファイルその他を操作する。プロセスはシェルから生成できる。 プロセスはシグナルによって制御できる。シェルには内部コマンドも存在する。
プロセスには「優先度」とよばれる属性もついている。 これは現在その計算機でのプロセスの速さ(?) をあらわすもので、 他のプロセスが途中で変えられる。実験で重いプロセスを動かすときは なるべくこの優先度を下げて使おう。
(参考) 空いている計算機時間の有効利用:
締め切りは 5/8。
提出先:
du dir/を実行すると容量は 5MBytes であった。 しかし
cp -r dir/ ~を実行すると 100MBytes 以上のファイルがコピーされ、 ホームディレクトリが溢れてしまった。 これはなぜか。
(mslr は田中・徳永研で開発されているパーザで重くなるプロセスの代表、 sleep については man を参照)
ついしん:
ちなみに、田中・徳永研では一般ユーザであれば誰でも勝手に
「ユーザ名-なんとか」のようなメールアドレスをつくることができます。
メーリングリストなどの立ち上げにどうぞ。詳しくは
.qmail の書きかた 参照。