5. シェルからプログラムを起動したとき何が起こるか?

シェルとは、ユーザが打ち込んだコマンドを解釈する Unix のインタープリタ です。これがシェルと呼ばれるのは、オペレーティングシステムのカーネルを 包み込んで、これをユーザから隠す働きをしているからです(訳注:木の実の 比喩であり、シェル (shell) とは殻を意味し、中核となる実(ここではカーネル) を包み込んでいることから、その名前があります)。シェルとカーネル とが別々のプログラムとなっていて、両者が一連のシステムコール経由で 通信するという仕組みは、Unix の重要な特徴となっています。このように 両者を分離することで、様々なシェルプログラムの実装が可能となり、 ユーザの好みに合わせていろいろなインターフェイスを選べるようになっています。

通常のシェルでは、ユーザがログインすると、(特にカスタマイズをしていない 限り) '$' というプロンプトが表示されます。ここではシェルの構文や、画面を 見ていればだいたい分かるような事柄には触れません。むしろ、こうした表示の 背景で何が起こっているのかを、コンピュータの視点から解説しようと思います。

ブートが終了した後でまだ何らプログラムを実行していない時点における コンピュータというのは、一連のプロセス全体がやるべき仕事を待っている状態である と考えることができます。あらゆるプロセスがイベント (event) を待っているわけです。ここでイベントとは、ユーザがキーを 押すとかマウスを動かすとかいったことです。あるいは、マシンがネットワーク に接続されているなら、そのネットワーク越しに送られてくるデータパケット の着信などもイベントにあたります。

カーネルもそうしたプロセスのひとつです。ただし、カーネルは特殊なプロセス でもあります。カーネルプロセス以外のユーザプロセス (user process) をいつ実行すべきか制御を行うのがカーネルプロセスであり、マシンの ハードウェアに直接アクセスできるのも通常はカーネルプロセスだけだからです。 実際、ユーザプロセスが、キーボードの入力を読み込んだり、スクリーンに何かを 表示したり、ディスクに対して読み書きしたり等、メモリとのやりとり以外の すべての処理をする際には、カーネルに対してリクエストを送らなければなりま せん。こうしたリクエストは、システムコール (system call) と呼ばれています。

通常、I/O ポートへのアクセスはすべてカーネルを通じて行われるので、 カーネルはそうした処理をスケジューリングしたり、相互の干渉を防止したり する機能を持っています。ただ、少数の特別なユーザプロセスは、カーネルを 通さずに処理する権限を与えられています。たいていの場合、それは I/O ポート へ直接アクセスできるという権限です。X サーバ (これは、大部分の Unix マシン 上で、スクリーンへの画像表示に関する他のプログラムからのリクエストを 受け取って、処理しているプログラムのことです) が、その典型的な例です。しかし、 今のところ、まだ X サーバが立ち上がるところまで話が進んでいません。 まだ、文字端末上で、シェルプロンプトを見ている状態です。

シェルは、単なるユーザプロセスであり、何ら特別な権限を与えられているわけ ではありません。シェルはキーストロークを待っており、(カーネル経由で) キーボードの I/O ポートを監視しています。カーネルはキーストロークを 認識すると、それをそのままスクリーン上に表示します。カーネルは 'Enter" キーが押されたことを認識すると、そのキーが押されるまでに入力された テキスト行をシェルに渡します。シェルは、それらのキーストロークを コマンドとして解釈しようとします。

たとえば、Unix のディレクトリ表示コマンドを起動するために、'ls' という 文字をタイプして、Enter を押したとします。シェルは、あらかじめ組み込まれて いるルールに従ってそれを解釈し、ユーザが '/bin/ls' ファイルにある実行コマンドを起動したがっているのだと理解します。 シェルはシステムコールを発して、カーネルに /bin/ls を新規の子プロセス (child process) として 起動するとともに、その子プロセスに対してカーネル経由でスクリーンと キーボードへのアクセス権限を与えるよう要求します。そして、シェルは スリープ状態に入り、ls コマンドが終了するのを待ちます。

/bin/ls コマンドが終了する際、コマンドは、 exit システムコールを発行して、処理が終了した ことをカーネルに伝えます。すると、カーネルが、スリープしていたシェルを 目覚めさせて、シェルが実行を再開できるようになったことを伝えます。 シェルは、再度プロンプトを発し、次の入力がなされるのを待ちます。

とはいえ、上記の 'ls' が実行されている最中に、他のプロセスを進行させる ことも可能です(非常に長いディレクトリのリストを表示しようと しているとしましょう)。たとえば、'ls' の実行中に、別の仮想コンソールに 切り替えて、ログインし、ゲームの Quake で遊び始めることができます。 あるいは、インターネットに接続している状態だとすれば、 ls の実行中に、読者のマシンがメールの送受信を することも可能です。