12. user.h(1/5)
冒頭の注釈
(注釈のまんま)
↓左端の数値は行番号 ・user構造体を定義している
・プロセスあたり1つ持つ
1 /* ・1プロセスあたりの全データであ
2 * The user structure. る
3 * One allocated per process. ・プロセスがスワップしている間は、
4 * Contains all per process data 参照しなくてよい
・ユーザのブロック長はUSIZE×64
5 * that doesn't need to be referenced
でこれはスタックポインタ用に使わ
6 * while the process is swapped. れる
7 * The user block is USIZE*64 bytes ・仮想カーネルのデータ長は
8 * long; resides at virtual kernel 140000 (ユーザ毎のシステムス
9 * loc 140000; contains the system タック含む)
10 * stack per user; is cross referenced・同じプロセスの中では、proc構造
と相互参照の関係にある
11 * with the proc structure for the
12 * same process.
13 */ 12
13. 14
15 #define EXCLOSE 01
user.h(2/5)
16
17 struct user
18 {
19 label_t u_rsav; /* save info when exchanging stacks */
20 int u_fper; /* FP error register */
退避時にスタックポインタを格納
21 int u_fpsaved; /* FP regs saved for this proc */
22 struct {
23 int u_fpsr; /* FP status register */
24 double u_fpregs[6]; /* FP registers */ ファイルI/O用の変数
25 } u_fps;
26 char u_segflg; /* IO flag: 0:user D; 1:system; 2:user I */ファイルI/Oの属性等
27 char u_error; /* return error code */ Dはデータ、I、は命令
28 short u_uid; /* effective user id */ systemはカーネルに相当
29 short u_gid; /* effective group id */
userはプロセスユーザと同義
30 short u_ruid; /* real user id */
31 short u_rgid; /* real group id */ proc構造体ポインタ
32 struct proc *u_procp; /* pointer to proc structure */
33 int *u_ap; /* pointer to arglist */ システムコールの引数リスト
34 union { /* syscall return values */
35 struct {
36 int r_val1; システムコールの戻り値
37 int r_val2; 例えばLinuxのコマンド
38 }; ls –laとかで得られる
39 off_t r_off;
一覧のデータを格納
40 time_t r_time; 13
41 } u_r; しておく
14. user.h(3/5)
42 caddr_t u_base; /* base address for IO */
プロセスユーザのI/Oの開始ア
43 unsigned int u_count; /* bytes remaining for IO */
44 off_t u_offset;
ドレス、オフセット、どこのディ
/* offset in file for IO */
45 struct inode *u_cdir; レクトリにあるか、パス名(この
/* pointer to inode of current directory */
46 struct inode *u_rdir; ころは物理アドレス空間を直
/* root directory of current process */
47 char u_dbuf[DIRSIZ]; 接扱っていた?)
/* current pathname component */
48 caddr_t u_dirp; /* pathname pointer */
49 struct direct u_dent; /* current directory entry */
50 struct inode *u_pdir; /* inode of parent directory of dirp */
51 int u_uisa[16]; /* prototype of segmentation addresses */
52 int u_uisd[16]; ファイルI/O
/* prototype of segmentation descriptors */
53 struct file *u_ofile[NOFILE]; /* pointers to file structures of open files *
(ちょっと詳細がわからない)
54 char u_pofile[NOFILE]; /* per-process flags of open files */
55 int u_arg[5]; /* arguments to current system call */
56 unsigned u_tsize; /* text size (clicks) */
57 unsigned u_dsize; /* data size (clicks) */ 現在のシステムコール戻り値
58 unsigned u_ssize; /* stack size (clicks) */
テキスト(プログラム)、データ
59 label_t u_qsav; /* label variable for quits and interrupts */
60 label_t u_ssav; /* label variable for swapping */
(固定値)、スタック(call時のP
61 int u_signal[NSIG]; /* disposition of signals */ C値の格納等)のサイズ、ス
62 time_t u_utime; /* this process user time */ ワップや退避時のラベル値
63 time_t u_stime; /* this process system time */
64 time_t u_cutime; /* sum of childs' utimes */ システムコールの戻り値
65 time_t u_cstime; /* sum of childs' stimes */ プロセスおよび子プロセスの
66 int *u_ar0; /* address of users saved R0 */ CPU使用時間など 14
15. user.h(4/5)
75 struct tty *u_ttyp; /* controlling ttytty(キャラクタ端末)制御用ポイ
pointer */
76 dev_t u_ttyd; /* controlling tty ンタとデバイス制御用情報
dev */
77 struct { /* header of executable file */
78 int ux_mag; /* magic number */
79 unsigned ux_tsize; /* text size */
80 unsigned ux_dsize; /* data size */ これはわからない…
81 unsigned ux_bsize; /* bss size */
82 unsigned ux_ssize; /* symbol table size */
実行するプログラムの
83 unsigned ux_entloc; /* entry location */ 情報(予備?)か何かか
84 unsigned ux_unused;
85 unsigned ux_relflg;
86 } u_exdata;
87 char u_comm[DIRSIZ];
88 time_t u_start;
89 char u_acflag;
90 short u_fpflag; /* unused now, will be later */ 予備用(互換性を取るため?)
91 short u_cmask; /* mask for file creation */
92 int u_stack[1];
93 /* kernel stack per user
94 * extends from u + USIZE*64
95 * backward not to reach here
96 */
97 };
98 15
17. 1 /*
2 * One structure allocated per active
3 * process. It contains all data needed
proc.h(1/3)
4 * about the process while the
5 * process may be swapped out. アクティブなプロセス毎に割り当てられる
6 * Other per process data (user.h) 構造体
7 * is swapped with the process. アクティブ=実行待ちと実行中のプロセス
8 */ running=実行中のプロセス
9 struct proc {
状態をあらわす で理解はあっているか?
10 char p_stat;
11 char p_flag; ようだが詳細不明 スワップアウトしても退避せず保持する?
12 char p_pri; /* priority, negative is high */
13 char p_time; /* resident time for scheduling */
14 char p_cpu; /* cpu usage for scheduling */
15 char p_nice; /* nice for cpu usage */
16 short p_sig; /* signals pending to this process */
17 short p_uid; /* user id, used to direct tty signals */
18 short p_pgrp; /* name of process group leader */
19 short p_pid; /* unique process id */
20 short p_ppid; /* process id of parent */
21 short p_addr; /* address of swappable image */
22 short p_size; /* size of swappable image (clicks) */
23 caddr_t p_wchan; /* event process is awaiting */
24 struct text *p_textp; /* pointer to text structure */
25 struct proc *p_link; /* linked list of running processes */
26 int p_clktim; /* time to alarm clock signal */
17
27 };
18. proc.h(2/3) プロセスの状態をあらわすマクロ定数
29 extern struct proc proc[]; /* the proc table itself */
30
31 /* stat codes */
32 #define SSLEEP 1 /* awaiting an event */
33 #define SWAIT 2 /* (abandoned state) */
34 #define SRUN 3 /* running */
35 #define SIDL 4 /* intermediate state in process creation */
36 #define SZOMB 5 /* intermediate state in process termination
*/
37 #define SSTOP 6 /* process being traced */
38
39 /* flag codes */
40 #define SLOAD 01 /* in core */
41 #define SSYS 02 /* scheduling process */
42 #define SLOCK 04 /* process cannot be swapped */
43 #define SSWAP 010 /* process is being swapped out */
44 #define STRC 020 /* process is being traced */
45 #define SWTED 040 /* another tracing flag */
46 #define SULOCK 0100 /* user settable lock in core */
47 18
19. proc.h(3/3)
49 * parallel proc structure
50 * to replace part with times
51 * to be passed to parent process
52 * in ZOMBIE state.
53 */
54 struct xproc {
ゾンビ(実行終了中)プロセス用構造体
55 char xp_stat; なぜわざわざ用意するのだろうか?
56 char xp_flag;
57 char xp_pri; /* priority, negative is high */
58 char xp_time; /* resident time for scheduling */
59 char xp_cpu; /* cpu usage for scheduling */
60 char xp_nice; /* nice for cpu usage */
61 short xp_sig; /* signals pending to this process */
62 short xp_uid; /* user id, used to direct tty signals */
63 short xp_pgrp; /* name of process group leader */
64 short xp_pid; /* unique process id */
65 short xp_ppid; /* process id of parent */
66 short xp_xstat; /* Exit status for wait */
67 time_t xp_utime; /* user time, this proc */
68 time_t xp_stime; /* system time, this proc */
69 };
19
21. 27 sleep(chan, pri)
/* */
28 caddr_t chan; sleep(1/2)
29 { 12 #define SQSIZE 0100 /* Must be power of 2 */
30 register struct proc *rp; 13 #define HASH(x) (( (int) x >> 5) & (SQSIZE-1))
31 register s, h; 14 struct proc *slpque[SQSIZE];
15
32 16 /*
33 rp = u.u_procp; 17 * Give up the processor till a wakeup occurs
プライオリティを上げて
34 s = spl6(); 18 * on chan, at which time the process
35 if (chan==0) 割り込みを禁止する 19 * enters the scheduling queue at priority pri.
20 * The most important effect of pri is that when
36 panic("zero wchan"); 21 * pri<=PZERO a signal cannot disturb the sleep;
37 rp->p_stat = SSLEEP; 22 * if pri>PZERO signals will be processed.
23 * Callers of this routine must be prepared for
38 rp->p_wchan = chan; 24 * premature return, and check that the reason for
39 if (chan==0) 25 * sleeping has gone away.
40 panic("Sleeping on wchan 0"); 26 */
41 rp->p_pri = pri;
42 h = HASH(chan); ここでいうハッシュは、5ビットシフトとマスク
43 rp->p_link = slpque[h]; プライオリティが低く
44 slpque[h] = rp; シグナルを受けている(??)時は次ページに飛んで
45 if(pri > PZERO) {
sleepのためにリジュームする
46 if(issig()) {
47 rp->p_wchan = 0;
48 rp->p_stat = SRUN;
49 slpque[h] = rp->p_link;
50 spl0();
51 goto psig;
21
52 }
22. 53 spl0();
54
55
if(runin != 0) {
runin = 0;
sleep(2/2)
56 wakeup((caddr_t)&runin); 走れるプロセスがあれば起こす
57 }
58 swtch();
59 if(issig())
60 goto psig; シグナルを受けていればリジュームする
61 } else {
62 spl0();
63 swtch();
64 }
65 splx(s);
プライオリティを元に戻す
66 return;
67
68 /*
69 * If priority was low (>PZERO) and 以降は、まだなぞの動作
70 * there has been a signal,
71 * execute non-local goto to
72 * the qsav location.
73 * (see trap1/trap.c)
74 */
75 psig:
76 resume(u.u_procp->p_addr, u.u_qsav);
77 }
22
24. 136 /*
137 * Set the process running;
138
139
140
* arrange for it to be swapped in if necessary.
*/
setrun(p)
setrun(1/1)
141 register struct proc *p;
142 {
143 register caddr_t w;
144
145 if (p->p_stat==0 || p->p_stat==SZOMB)
146 panic("Running a dead proc");
147 /*
148 * The assignment to w is necessary because of
149 * race conditions. (Interrupt between test and use)
150 */
151 if (w = p->p_wchan) {
152 wakeup(w); ここでプロセスを起こしている
153 return;
154 }
155 p->p_stat = SRUN;
156 setrq(p); プロセスを起こさない場合。
157 if(p->p_pri < curpri)
158 runrun++;
159 if(runout != 0 && (p->p_flag&SLOAD) == 0) {
160 runout = 0;
161 wakeup((caddr_t)&runout);
162 }
24
163 }
25. 165
166
/*
* Set user priority.
setpri
167 * The rescheduling flag (runrun)
168 * is set if the priority is better
169 * than the currently running process.
170 */
171 setpri(pp)
172 register struct proc *pp;
173 {
174 register p; 数値が8進であることに注意!
175
ユーザプロセスの優先度を設定する
176 p = (pp->p_cpu & 0377)/16;
177 p += PUSER + pp->p_nice - NZERO;
178 if(p > 127)
179 p = 127;
180 if(p < curpri)
181 runrun++;
182 pp->p_pri = p;
183 return(p);
184 }
185
25
26. 202 sched()
203 {
204 register struct proc *rp, *p;
sched(1/3)
205 register outage, inage; ところどころに出てくる、
206
207
int maxsize; プロセスのスワップをする関数。spl*の*が
208 /* 大きいほど優先度が高く、6が最高。
209 * find user to swap in;
210 * of users ready, select one out longest
他から割りこみが入って状態が
211 */ 変わらないようにしたい場合にこうする。
212
213 loop: ここでは最高優先度まで上げて以降の
214 spl6(); 操作を行っている
215 outage = -20000;
216 for (rp = &proc[0]; rp < &proc[NPROC]; rp++)
217 if (rp->p_stat==SRUN && (rp->p_flag&SLOAD)==0 && プロセスの状態を総なめして
218 rp->p_time - (rp->p_nice-NZERO)*8 > outage) {
219 p = rp; ステータスが実行可能状態で
220 outage = rp->p_time - (rp->p_nice-NZERO)*8; 優先度が一番高いものを検出
221 }
222 /* (スワップイン候補を探す)
223 * If there is no one there, wait.
224 */
225 if (outage == -20000) {
226 runout++; 上記条件にあうプロセスが検出できなけれ
227 sleep((caddr_t)&runout, PSWP);
228 goto loop; ば、sleepを呼び出して待つ
229 }
230 spl0();
231
232 /* 優先度を最低に戻す
233 * See if there is core for that process;
234 * if so, swap it in.
235 */
236
237 if (swapin(p)) プロセスに割り当てられる資源(メモリなど)
238 goto loop; があればスワップインする 26
27. 240 /*
sched(2/3)
241 * none found.
242 * look around for core.
243 * Select the largest of those sleeping
244 * at bad priority; if none, select the oldest.
245 */
246
247 spl6();
248 p = NULL;
249 maxsize = -1;
250 inage = -1;
251 for (rp = &proc[0]; rp < &proc[NPROC]; rp++) {
252 if (rp->p_stat==SZOMB
253 || (rp->p_flag&(SSYS|SLOCK|SULOCK|SLOAD))!=SLOAD)
254 continue; CPUに割り当
255 if (rp->p_textp && rp->p_textp->x_flag&XLOCK)
256 continue; てる候補と資
257 if (rp->p_stat==SSLEEP&&rp->p_pri>=PZERO || rp->p_stat==SSTOP) { 源がない状
258 if (maxsize < rp->p_size) {
259 p = rp; 態。一番最初
260 maxsize = rp->p_size; にsleepしたプ
261 }
262 } else if (maxsize<0 && (rp->p_stat==SRUN||rp->p_stat==SSLEEP)) { ロセスを総な
263 if (rp->p_time+rp->p_nice-NZERO > inage) { めして検出す
264 p = rp;
265 inage = rp->p_time+rp->p_nice-NZERO; る(優先的に
266 }
スワップさせ
267 }
268 } るため)
269 spl0();
270 /* 27
28. sched(3/3)
270 /*
271 * Swap found user out if sleeping at bad pri,
272 * or if he has spent at least 2 seconds in core and
273 * the swapped-out process has spent at least 3 seconds out.
274 * Otherwise wait a bit and try again.
275 */
276 if (maxsize>=0 || (outage>=3 && inage>=2)) {
CPUに割り当てられていた
277 p->p_flag &= ~SLOAD;
278 xswap(p, 1, 0);
時間が2秒以上、または
279 goto loop; 低い優先度でsleepしていれば
280 } スワップを行う
281 spl6();
282 runin++;
283 sleep((caddr_t)&runin, PSWP);
284 goto loop;
285 }
286
28
30. qswitch
324 /*
325 * put the current process on
326 * the Q of running processes and
327 * call the scheduler.
328 */
329 qswtch()
330 {
331
332 setrq(u.u_procp);
プロセスをキューに放り込む?
333 swtch();
334 }
335
30
31. 347 swtch()
348 {
349
350
352
register n;
register struct proc *p, *q, *pp, *pq;
/*
switch(1/2)
353 * If not the idle process, resume the idle process.
354 */
355 if (u.u_procp != &proc[0]) {
356 if (save(u.u_rsav)) {
357 sureg();
358 return;
359 }
360 if (u.u_fpsaved==0) {
361 savfp(&u.u_fps);
プロセスを切り替える。
362 u.u_fpsaved = 1; これは、最初に、sched()で呼ば
363 } れたswitchがproc0をresumeす
364 resume(proc[0].p_addr, u.u_qsav);
365 }
る場合のルーチン
366 /*
367 * The first save returns nonzero when proc 0 is resumed
368 * by another process (above); then the second is not done
369 * and the process-search loop is entered.
370 *
371 * The first save returns 0 when swtch is called in proc 0
372 * from sched(). The second save returns 0 immediately, so
373 * in this case too the process-search loop is entered.
374 * Thus when proc 0 is awakened by being made runnable, it will
375 * find itself and resume itself at rsav, and return to sched().
376 */
377 if (save(u.u_qsav)==0 && save(u.u_rsav)) 31
378 return;
33. 421 /*
422 * Create a new process-- the internal version of
423 * sys fork.
424 * It returns 1 in the new process, 0 in the old.
newproc(1/4)
425 */
426 newproc()
427 {
428 int a1, a2;
429 struct proc *p, *up;
430 register struct proc *rpp, *rip;
431 register n;
432
433 p = NULL;
434 /*
435 * First, just locate a slot for a process
436 * and copy the useful info from this process into it.
437 * The panic "cannot happen" because fork has already
438 * checked for the existence of a slot.
439 */
440 retry:
441 mpid++;
442 if(mpid >= 30000) { 30000の数字の意味が不明
443 mpid = 0;
444 goto retry;
445 }
446 for(rpp = &proc[0]; rpp < &proc[NPROC]; rpp++) {
447 if(rpp->p_stat == NULL && p==NULL)
448 p = rpp;
449 if (rpp->p_pid==mpid || rpp->p_pgrp==mpid)
450 goto retry;
451 } 新しいプロセスが割り当てられるか
452 if ((rpp = p)==NULL) pidを調べている 33
453 panic("no procs");
35. 478 for(n=0; n<NOFILE; n++)
479 if(u.u_ofile[n] != NULL)
480 u.u_ofile[n]->f_count++;
481 if(up->p_textp != NULL) {
482
483
up->p_textp->x_count++;
up->p_textp->x_ccount++;
newproc(3/4)
484 }
485 u.u_cdir->i_count++;
486 if (u.u_rdir)
487 u.u_rdir->i_count++;
488 /*
489 * Partially simulate the environment
490 * of the new process so that when it is actually
491 * created (by copying) it will look right.
492 */
493 rpp = p;
494 u.u_procp = rpp;
495 rip = up; ちょっとここ謎の動作
496 n = rip->p_size;
497 a1 = rip->p_addr;
498 rpp->p_size = n;
35
36. 499 /*
500 * When the resume is executed for the new process,
501 * here's where it will resume.
502 */
503 if (save(u.u_ssav)) {
504
505
sureg();
return(1);
newproc(4/4)
506 }
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 }
526 u.u_procp = rip;
527 setrq(rpp);
528 rpp->p_flag |= SSWAP;
529 return(0); 36
530 }
37. 545 expand(newsize) 532 /*
533 * Change the size of the data+stack regions of the process.
546 { 534 * If the size is shrinking, it's easy-- just release the extra core.
547 register i, n; 535 * If it's growing, and there is core, just allocate it
536 * and copy the image, taking care to reset registers to account
548 register struct proc *p; 537 * for the fact that the system's stack has moved.
549 register a1, a2; 538 * If there is no core, arrange for the process to be swapped
539 * out after adjusting the size requirement-- when it comes
550
540 * in, enough core will be allocated.
551 p = u.u_procp; 541 *
552 n = p->p_size; 542 * After the expansion, the caller will take care of copying
543 * the user's stack towards or away from the data area.
553 p->p_size = newsize; 544 */
554 a1 = p->p_addr;
555 if(n >= newsize) {
556 mfree(coremap, n-newsize, a1+newsize);
557 return;
558 }
559 if (save(u.u_ssav)) {
560
561
562 }
sureg();
return; expand(1/1)
563 a2 = malloc(coremap, newsize);
564 if(a2 == NULL) {
565 xswap(p, 1, n);
566 p->p_flag |= SSWAP;
確保しているメモリ領域(データとスタック)を
567 qswtch(); 変更したい時(拡張したいとき)、
568 /* no return */ malloc,freeで領域を取り直す
569 }
570 p->p_addr = a2;
571 for(i=0; i<n; i++)
572 copyseg(a1+i, a2+i);
573 mfree(coremap, n, a1);
574 resume(a2, u.u_ssav); 37
575 }
38. 112 /*
113 * when you are sure that it
114
115
* is impossible to get the
* 'proc on q' diagnostic, the
setrq(1/1)
116 * diagnostic loop can be removed.
117 */
118 setrq(p)
119 struct proc *p;
120 {
121 register struct proc *q;
122 register s;
123
124 s = spl6();
125 for(q=runq; q!=NULL; q=q->p_link)
126 if(q == p) {
127 printf("proc on qn");
すでに起動済みのプロセスかどうか
128 goto out;
129 } チェックしている?
130 p->p_link = runq;
131 runq = p;
132 out:
133 splx(s);
134 }
38
135