forkとexecをなぜ分ける設計にしたかの説明が出てきます。
Code: File descriptors
・プロセスは、ファイル、ディレクトリ、デバイスをオープンするか、パイプを生成するか、既存のdescriptorを複製することによりdescriptorを得る。
・プロセス毎に0から始まる複数のdescriptorを持つ。
・標準入力が0、標準出力が1、標準エラーが2番。
・read(fd, buf, n)はfdから最大でnバイト読み出してbufにコピーする。読み出したバイト数を返す。
・descriptor毎にoffsetを持ち、readした分ずれていく。
・read(fd, buf, n)が0を返すときend of fileの意味。
・write(fd, buf, n)はfdにbufからfdに書き込んだバイト数を返す。返値がnより小さければエラーである。
・descriptor毎にoffsetを持ち、writeした分ずれていく。
・close(fd)によりdescriptorを開放する。
・新たに割り当てられるdescriptorは現プロセスで使用していない最小番号のdescriptorである。
・descriptorとforkによってI/Oリダイレクションがうまく実装できる。
・forkによって子プロセスは親プロセスと全く同じファイルがオープンされた状態で始まる。
・execによってメモリは置き換えられるがfileテーブルはそのまま保たれる。
・cat < input.txt は、シェルによってclose(0);open("input.txt", O_RDONLY);することにより0番としてinput.txtがオープンされる。0番を開放した直後なので最小番号の0番が割り当てられるから。
・このように、forkとexecが分かれていることにより、シェルは子プロセスが目的のプログラムを走らせる前に子プロセスに設定変更することができる。←うまい設計!
・親プロセスと子プロセスでoffsetは共有される。
・dupによって複製されたdescriptorは同じI/Oオブジェクトを参照しているのでoffsetも共有される。
・File descriptorにより実際に操作している対象が何であるかを隠蔽するという強力な抽象化がなされる。
Code: File descriptors
・プロセスは、ファイル、ディレクトリ、デバイスをオープンするか、パイプを生成するか、既存のdescriptorを複製することによりdescriptorを得る。
・プロセス毎に0から始まる複数のdescriptorを持つ。
・標準入力が0、標準出力が1、標準エラーが2番。
・read(fd, buf, n)はfdから最大でnバイト読み出してbufにコピーする。読み出したバイト数を返す。
・descriptor毎にoffsetを持ち、readした分ずれていく。
・read(fd, buf, n)が0を返すときend of fileの意味。
・write(fd, buf, n)はfdにbufからfdに書き込んだバイト数を返す。返値がnより小さければエラーである。
・descriptor毎にoffsetを持ち、writeした分ずれていく。
・close(fd)によりdescriptorを開放する。
・新たに割り当てられるdescriptorは現プロセスで使用していない最小番号のdescriptorである。
・descriptorとforkによってI/Oリダイレクションがうまく実装できる。
・forkによって子プロセスは親プロセスと全く同じファイルがオープンされた状態で始まる。
・execによってメモリは置き換えられるがfileテーブルはそのまま保たれる。
・cat < input.txt は、シェルによってclose(0);open("input.txt", O_RDONLY);することにより0番としてinput.txtがオープンされる。0番を開放した直後なので最小番号の0番が割り当てられるから。
・このように、forkとexecが分かれていることにより、シェルは子プロセスが目的のプログラムを走らせる前に子プロセスに設定変更することができる。←うまい設計!
・親プロセスと子プロセスでoffsetは共有される。
・dupによって複製されたdescriptorは同じI/Oオブジェクトを参照しているのでoffsetも共有される。
・File descriptorにより実際に操作している対象が何であるかを隠蔽するという強力な抽象化がなされる。