今回(初回)はshellについて。普通はbootloaderから見て行くのかもしれないけど身近なものから。
恐らく、shellについて理解する最短で最良の方法が,こいつhttps://github.com/mit-pdos/xv6-public/blob/master/sh.cをじっくり読むこと。
ざっとみて、新しく気付いた点を簡単に列挙してみる。
- cd(change directory)は唯一の別processとして切り出されてないcommand (逆にcdをexec経由で実行するってできない?->execされたプロセスからshellのプロセスのcwdを変更しなきゃダメ)
- shellのcommandは、5つ(list(;,&&)/pipe(|)/redirection(<,>)/back(&)/exec)に分類される
- parse後に,command毎に各種識別可能なtypeを持たせた構造体を二分木的に結合させ,topDownで処理
- systemcall側から分類すると、pipeはfork2回(close/dup/close/closeが続く),backはfork1回,listはfork1個にwaitを追加,redirはopen,execはexecのみという流れ。
因みにpipeのsystemcallに関しては、左右1と0のfileのtypeを"pipe"に設定しているだけで、そのあとにfileをread/writeした時にkernel内でtypeがfileだったら、kernel内にあるpipe専用の構造体に値をセットしましょっていう流れ。
redirectionのopenに関しては、> だと左のprocessの1に右のfile descriptor0番設定してね(逆はその逆)というだけでopen一つで行けてシンプルだ。
forkしてあげた先のedge nodeのexecで実行されたprocessはdefaultで親のfile descriptor(0/1/2)を引き継ぐので、入出力が上手く回るのね。
気になる点として
- shellのprocessがfd0/1/2以外をopenする可能性ってあるの?
- shell自体のprocessが持ってるpathはshellのproc構造体が知ってるけど、環境変数から与えられるexecで実行可能なpathをどう設計するのがベスト?
- shellのprocessが毎回のcommand実行時にcommand分の構造体の大きさを確保するsbrk()呼んでるけど、こいつ木のrootで一回呼べばよくね?
とりあえず以上。暇があったら拡張したい。