2010年11月21日日曜日

第1回 V7から始めるUNIX講座 まとめと疑問

先週から始まった、 V7から始めるUNIX講座、UST中継しますが保存しないので記憶および視聴者の方のつぶやきを元にまとめながら、疑問に思ったことを書いていきます。

メモ書きなので系統だった書き方になっていませんがご容赦を

はじめに
カーネルソースは/usr/sysの下
総ステップ数は25KSくらい

1、SWAPとPagingの違い
UNIXでいうところのSWAPとPagingの違いについて

●SWAPはメモリからプログラム全体をハードディスクに追い出す。
そのため、完全にプログラムを実行できる(メモリ上)、できない(HD上)のいずれかになる。
(補足)
Lions本によれば、proc構造体のp_addrにより以下のように判断できるようです。
メインメモリ内:ブロック番号
HD内:ディスクレコード番号

●Pagingは、プログラムをPageと呼ばれる単位(4KB)に分割して、使っていない(今後も使わないだろう)部分をあるアルゴリズムを使って決定しHDに追い出して(ページアウト)、現在実行中のものだけをメモリ上に保持する。

プログラムがページアウトされたメモリにアクセスしたら、ストップしてハードディスクから読み出し(ページイン)して実行する。
そのため16MBのメモリしかなくても、それ以上のプログラムを実行することが出来る。

Pagingという説明でしたが、つまり仮想記憶をサポートするということになると思います。
仮想記憶を実現するためにハードウエアレベル(MMU)でも対応が必要。
そのため初期のUNIXではSWAPしかなかった。

SWAPとPagingの違い:イメージ
画像


仮想記憶のイメージ:不連続な実メモリをプログラムからは連続したメモリ領域のように見せる。
仮想記憶の実態は、使っているところだけメモリに保持していて、使ってないところはHDに内に追い出しているので実メモリ以上のプログラムを(見かけ上)同時に動かすことができる。
画像


実行していない部分を追い出すのは、リストみたいなものを持っていて古いものを判別している?
画像


疑問
Page単位でプロラムを分割するということですが、
1、最初から4KBに分かれている?あるいは、だれかが4KB単位に分割する?
2、4KBに分かれるときは、問答無用?あるいは関数単位とかでなるべく固める?
3、最後のページで4KBに満たないときは、何か値を詰めたりする?

2、スタックとヒープ
環境変数はスタックの奥底に格納されていて、execしても書き換わらない。

ちょっとここの説明分かりませんでした。
一般的に
スタック:ローカル変数、関数呼び出しの際の引数や関数呼び出し元(関数の実行が終了した後の戻り先)の格納場所として使われます。 置かれた変数は関数の実行が終了した時点で消滅します

ヒープ:ヒープ領域に確保された値はスタック領域におかれた変数と違い、関数の実行が終了しても存在し続けます

3、procとuser
proc構造体はスワップアウトされない(必ずメモリに存在する)スケジューラが使用するため。
user構造体はスワップアウトされる場合がある。

user構造体に参照しているフォルダ、ファイル等が保持している。
フォルダを削除できないのはこれを見ているから

4、TSS(Time Sharing System)
スケジューリングして瞬間で動いているのは1つのプロセス。
停止した状態をproc構造体に保持しておいて、順番に実行している

5、fork
forkすると全てのものを親から受け継ぐ(コピーする)。違うのPIDのみ。
ただし、親プロセスが消費した時間は子プロセスに引き継がないで0リセットする。→458~464行
わざわざforkしてからexecしてるのは、パイプとリダイレクト読むと分かってくる。乞うご期待

fork()
http://www.tamacom.com/tour/kernel/unix/S/98.html#L422
431行:mallocとあるがCのメモリ確保ではなくてメモリ上に領域が取れるかのチェック
438~445行:プロセス数の最大までループしながら、proc構造体の空いてるところを探している。
457行:newproc()で実際のプロセスの生成を行っている。
458~464行:生成した子プロセスにプロセスIDをセット、時間は0でリセット

newproc()
http://www.tamacom.com/tour/kernel/unix/S/96.html#L426
442行:プロセス数の上限は、30000
461~471行:ほとんどのものを親からコピーする

476~487行:ファイルはディレクトリのアクセスカウントをインクリメントする。コピーして親が参照しているファイルについても継承するため。

fork関数は2度リターンする。
503~506行:1をリターンしている。子ププロセス側のリターン:forkの457行目で分岐して、子プロセスの初期化実施。ただしリターン先は子プロセスのfork関数
529行:0をリターンしている。親プロセス側のリターン:forkの457行目で分岐して、親プロセスの処理実施

(疑問)
今まで何度もforkとexecの話は聞きましたが、どうしても分からなかったのは、「Forkが2回リターンする」ってのを知らないせいだというのが先週の説明でやっと分かりました。すっきりー(^^)

ですが、普通にリターンしてしまうと、後続の処理が実行できないので、どうやってるんだろう?
この辺のコードでうまくやっててくれるとは思うのですが?


503 if (save(u.u_ssav)) {
504 sureg();
505 return(1);
506 }

       

fork(newporc)が2回リターンするイメージ
画像


6、FD(file descriptor)の実態
ファイルをオープンした時には、0~19の小さな整数が返る。

実装は以下の通り。
http://www.tamacom.com/tour/kernel/unix/S/85.html#L218

user構造体の*u_ofile[NOFILE]に保持しているので、配列の上限NOFILE(20)以上のファイルは開けない。





Linuxシステムコールプログラミング (エッセンシャルソフトウェアガイドブック)
技術評論社
山森 丈範

ユーザレビュー:

amazon.co.jpで買う
Amazonアソシエイト by Linuxシステムコールプログラミング (エッセンシャルソフトウェアガイドブック) の詳しい情報を見る / ウェブリブログ商品ポータル

0 件のコメント:

コメントを投稿