2010年12月5日日曜日

第3回 V7から始めるUNIX講座 復習とまとめ

●復習
以下の内容に対しての復習、補足です。
http://xiangcai.at.webry.info/201011/article_9.html

・LRUに関して
最近使われていないものは今後も使われることがないと仮定する考え方です。
→参照の局所性に基づきます。
最近使われていないPageをページ・アウトして物理メモリを空けます。

当初、2 Way Clock arugorizumuで検索てヒットしませんでしたが
2針クロックアルゴリズムで検索すると資料出てきました。
http://h50146.www5.hp.com/products/software/oe/hpux/developer/document/memmanage/mem8.html
http://docs.sun.com/app/docs/doc/817-0158/6mfvqchsq?l=ja&a=view

時計の針のように2つの針があります。
最初の針は、参照をクリアして参照していない状態にします。
次の針が少し遅れてスキャンしていき(どれくらいの間隔かはパラメータで調整)、ページにプログラムがアクセスするとハードウェアが「ダーティ」ビットを立てるので、ダーティビットが立っていない(参照されていない)ページをページ・アウトの対象とするようです。

・スタックとヒープに関して
基本問題ないが、ヒープを確保するのは、システムコールのbrkとsbrkになる。(mallocの中で使っている)
http://www.ialab.cs.tsukuba.ac.jp/~maeda/class/syspro/syspro3.pdf
この資料の「プロセスのメモリ空間(古典Unix)」が分かりやすいですね。
ヒープ領域を確保するというよりは、ヒープ領域のリミットを変更するというのが正確のようです。

http://yaguchi.txt-nifty.com/blog/2006/07/brk_sbrk_94d5.html

(余談)
mallocとfreeを繰り返すとそのうちフラグメンテーションする。

都市伝説
mallocにはバグがある。
mallocの管理領域を破壊するとfreeした時に障害が発生するので、mallocにバグがあるような挙動になるが、malloc自身のバグではないので注意。

●第3回まとめ(タスクスイッチング)
簡単にいうと、
・メモリ:text, data, bss, ヒープ、スタック
・CPUの状態:GR(汎用レジスタ)、PC(プログラムカウンタ)、SP(スタックポインタ)
が保存されているえば、復元することが出来る。

プロセスAにスイッチ、プロセスAを復元、プロセスAの命令実行、プロセスAの状態を保存
プロセスBにスイッチ、プロセスBを復元、プロセスBの命令実行、プロセスBの状態を保存
プロセスCにスイッチ、プロセスCを復元、プロセスCの命令実行、プロセスCの状態を保存
というのを様々な要素で優先度を決めて、ひたすらカーネル(スケジュール)がやっている。

全体のイメージ
画像


保存する場所
CPUの状態:user構造体(uでアクセス)の「u_ssav」に保存している。
http://www.tamacom.com/tour/kernel/unix/S/80.html

保存は、save関数:保存先は(u.u_ssav)


713 .globl _save
714 _save:
715 mov (sp)+,r1
716 mov (sp),r0
717 mov r2,(r0)+
718 mov r3,(r0)+
719 mov r4,(r0)+
720 mov r5,(r0)+
721 mov sp,(r0)+
722 mov r1,(r0)+
723 clr r0
724 jmp (r1)


●疑問
PDP11では、r0~r7の汎用レジスタがある。
r6がスタックポインタ(SP)でr7がPC(プログラムカウンタ)のはず。Lions本の260ページ
上のコードだとr7退避してないような?

ついでに、復帰するresumeも


.globl _resume
727 _resume:
728 mov 2(sp),r0 / new process
729 mov 4(sp),r1 / new stack
730 bis $HIPRI,PS
731 mov r0,KISA6 / In new process
732 mov (r1)+,r2
733 mov (r1)+,r3
734 mov (r1)+,r4
735 mov (r1)+,r5
736 mov (r1)+,sp
737 mov $1,r0
738 bic $HIPRI,PS
739 jmp *(r1)+


退避した領域から汎用レジスタに値を入れ直しているのが分かります。

resumeをしているのは、sleep, swtch, newproc, expand
このうち、swtchがタスクスイッチを行っているようです。

プロセスのメモリはどこに?
proc構造体にp_addrがあって、これがユーザプロセスへのポインタになっているように思いますが、正しいだろうか?

●プロセス切り替えに関して
画像


カーネルがユーザプロセスにスイッチする時にタイマーを設定して実行する。
無限ループするようなプロセスがいた場合に他のプロセスへのスイッチが出来なくなるため。

以下の場合、ユーザプロセスからカーネルへ切り替わる。
1、タイマーが切れた場合
2、システムコールをコールした場合

3、カーネルに戻って、スケジューラが条件により優先度を決めて次に実行するプロセスを決定する。
4、現在実行中のプロセスの状態(レジスタ)を保存する、保存先はu.u_ssav※。

※user構造体については、現在実行中のものに対して:変数uにてアクセス出来る。

5、次に実行するプロセスの状態をresumeで復元する。
6、次のプロセスを実行する。

疑問
レジスタは退避、復元しているようですが、メモリについてはそのままということなんだろうか?

(余談)
forkした場合に、procのp_addrをコピーしています。


507 a2 = malloc(coremap, n);
508 /*
509 * If there is not enough core for the
510 * new process, swap out the current process to generate the
511 * copy.
512 */
513 if(a2 == NULL) {
514 rip->p_stat = SIDL;
515 rpp->p_addr = a1;
516 xswap(rpp, 0, 0);
517 rip->p_stat = SRUN;
518 } else {
519 /*
520 * There is core, so just copy.
521 */
522 rpp->p_addr = a2;
523 while(n--)
524 copyseg(a1++, a2++);
525 }

0 件のコメント:

コメントを投稿