v6 unix in okinawa

142
オペレーティングシステムの読み書き Rev.2.1 @magoroku15 2012/3/24 日本Androidの会 沖縄支部 workshop@Naha Vol.17 - v6 unix 勉強会 2012/3/24 1

Upload: magoroku-yamamoto

Post on 28-May-2015

11.028 views

Category:

Education


8 download

DESCRIPTION

pdp11 unix lions

TRANSCRIPT

Page 1: V6 unix in okinawa

オペ―レーティングシステムの読み書き Rev.2.1

@magoroku15

2012/3/24 日本Androidの会 沖縄支部 workshop@Naha Vol.17 - v6 unix 勉強会

2012/3/24 1

Page 2: V6 unix in okinawa

他人の作品を読まなかった偉大な作家,他人の筆づかいを研究しなかった偉大な画家,同僚の肩越しに技を盗まなかった腕のよい外科医,副操縦席で実地の経験を積まなかった767機長――果たして,

そんな人たちが本当にいるのでしょうか?

Dave Thomas著 Code Reading―オープンソースから学ぶソフトウェア開発技法 より

2012/3/24 2

Page 3: V6 unix in okinawa

最底辺活動

Lions本読書会に出てみた

本だけで読み解くのは大変

若干の解説を加えれば理解できる人は増えるはず

拙者のネタとしてGeekBarなどで話すことにした

これを最底辺活動と言っている

○ 他にもFPGAでPDP11を動かしたり、PICで遊んだり

UNIX v6を読む理由

最新のBSD, Linuxと実装は異なるが根幹は同じ

UNIX v6を読む事が現代のOSを理解する近道(だと思う)

2012/3/24 3

Page 4: V6 unix in okinawa

Lions’ Commentary on UNIX本読書会

月に1回貸し会議室(喫茶室ルノアール)にあつまってLions本の読書会

濃すぎる常連

@awazo

主催している人

@7shi

低レイヤ勉強会を多数主催、SilverLightで動くPDP-11のエミュレータ作った人

@xylnao11

古くからPDP-11とUNIXで遊んでて、最近安価なFPGAにPDP-11を載せてしまった人

@superhoge

Blogがすごい、JavaScriptで動くPDP-11のエミュレータを作った人

@toyoshim

一人で読み終えてしまった人

@pakuqi

v7講座を生徒役で参加してBlogに話した事の10倍くらいの内容をまとめてくれた人

@oraccha

PDP11に詳しくて、V1も読んでる人 2012/3/24 4

Page 5: V6 unix in okinawa

お勧めのBlogなど

http://d.hatena.ne.jp/takahirox/

http://www.tom-yam.or.jp/2238/index.html

http://d.hatena.ne.jp/n7shi/

http://xiangcai.at.webry.info/

http://d.hatena.ne.jp/oraccha/

2012/3/24 5

Page 6: V6 unix in okinawa

@magoroku15の最近のネタ

ADK互換モジュールを1200円で作る http://www.slideshare.net/magoroku15/poormans-adk-11350123

OpenCoresのw11を動かしてみる

http://www.slideshare.net/magoroku15/pdp11-onfpga

その他

横浜Android PF部,nagoyageekbar等で話したネタは以下に置いてあります

○ http://www.slideshare.net/magoroku15/

2012/3/24 6

Page 7: V6 unix in okinawa

教材

Unix version6

テキスト

○ Lions Commentary on UNIX / ASCII Books 3990円

原著online版

○ http://v6.cuzuco.com/v6.pdf

○ http://www.lemis.com/grog/Documentation/Lions/boo

k.pdf

PDP-11/40

PDP-11 Processor Handbook

http://pdos.csail.mit.edu/6.097/readings/pdp11-40.pdf

2012/3/24 7

Page 8: V6 unix in okinawa

ウォームアップ

OSの領域はプログラマにとっての最底辺部 アプリケーションプログラマ

○ 提供されるAPIを利用して、一般向けのサービス等を提供する人

システムプログラマ ○ ハードウェアの機能を利用して、API等プログラマ向け機能を提供する人

必要とされる前提知識が異なる

命令レベルで計算機を(ぼんやりと)理解する必要あり

アプリケーションプログラマ向けの準備運動 Lions本

○ 第2章 Fundamentals (PDFだとP4) 命令セット

○ 第9章 Hardware Interrupt and Traps (PDFのP42) 割り込み

PDP-11 Processor Handbook

2012/3/24 8

Page 9: V6 unix in okinawa

Lions本 2章

2012/3/24 9

Page 10: V6 unix in okinawa

システムプログラマから見た

計算機の構成要素

CPU

レジスタ

○ 汎用レジスタ 一般の演算命令に使用

○ スタックポインタ スタックの先頭位置

○ プログラムカウンタ 次に処理する命令の位置

フラグレジスタ 演算結果の一部を記憶

制御/状態レジスタ

Memory

外部記憶

2012/3/24 10

Page 11: V6 unix in okinawa

PDP-11/40

レジスタ

16bitのレジスタが8個

r0-r7

r6はspスタックポインタ

r7はpcプログラムカウンタ

Processor Status Word

フラグレジスタ+状態レジスタ

memory

仮想アドレス幅は16bit 最大 64kbyte

物理アドレス幅は18bit 最大 256kbyte

2012/3/24 11

Page 12: V6 unix in okinawa

レジスタ r0-r7

r0, r1

演算結果の一時的な保持、復帰値など

r2, r3, r4

関数内のローカル変数。呼ばれた関数で退避し、関数の終了時に復元

R5

フレームポインタ

r6 (sp)

スタックポインタ

r7 (pc)

実行する命令の位置(アドレス)

2012/3/24 12

Page 13: V6 unix in okinawa

Processor Status Word (PSW)

14-15 現在のモード (00 = kernel 11 = user)

12-13 以前のモード

5-7 プロセッサの優先度 (0~7)

4 トラップビット

3 N 演算結果が負

2 Z 演算結果が0

1 V 演算結果がオーバフロー

0 C 演算結果がキャリー 2012/3/24 13

Page 14: V6 unix in okinawa

CPUの処理

以下を繰り返す

1. PCの示す位置(アドレス)から命令を読み込む

2. 解析して

3. 実行

4. 実行の副作用として以下の事象が発生する

PSWを書き換え

PCを書き換え

レジスタの書き換え

メモリの内容を書き換えたりする

2012/3/24 14

Page 15: V6 unix in okinawa

CPUの処理 誤解しやすい点

PCもレジスタの一種

PC(r7)を書き換えると処理がジャンプ

比較と分岐は別命令

2012/3/24 15

Page 16: V6 unix in okinawa

UNIXカーネルを理解するための

2012/3/24 16

Page 17: V6 unix in okinawa

C言語の空間モデル

Text 命令列の格納領域

書き換え禁止

Data 非0で初期化されたデータ領域

Bss 0で初期化されたデータ領域

Stack 自動(auto)変数の格納領域

関数呼び出し時のレジスタ退避域

注)スレッドは、まだ存在しないので対象外

2012/3/24

text

data

bss

stack

17

Page 18: V6 unix in okinawa

変数の宣言と空間配置

int i; // Bss Int j = 1; // Data main() { static int k = 1; // Data int l = 1; // Stack int m; // Stack : }

2012/3/24

text

data

bss

stack

text

data

header

a.out形式

(ファイル) 実行時

(メモリ)

18

Page 19: V6 unix in okinawa

関数呼び出しとスタック C

main() { int e, f, r; e = 1; f = 2; r = func(e, f); } int c, d; func(a, b) { c = a; d = b; return c + d; }

2012/3/24 19

Page 20: V6 unix in okinawa

関数とスタック namelist

# nm -n a.out

000000a 0x00 crt0.o

000000t start

000004a a

000006a b

000030T 0x18 _main

000030a src.o

000030t ~main

000102T 0x42 _func

000102t ~func

000140T 0x60 _exit

000140a exit.o

000152T 0x6a csv

000152a csv.o

000170T cret 0x78

000206B _c

000210B _d

000212B savr5

177764a r

177766a f

177770a e

2012/3/24 20

Page 21: V6 unix in okinawa

関数呼び出しとスタック ASM

.globl _main

.text _main: ~~main: ~e=177770 ~f=177766 ~r=177764 jsr r5,csv sub $6,sp mov $1,-10(r5) mov $2,-12(r5) mov -12(r5),(sp) mov -10(r5),-(sp) jsr pc,*$_func tst (sp)+ mov r0,-14(r5) L1: jmp cret .globl _c

.comm _c,2

.globl _d

.comm _d,2

.globl _func

.text _func: ~~func: ~a=4 ~b=6 jsr r5,csv mov 4(r5),_c mov 6(r5),_d mov _c,r0 add _d,r0 jbr L2 L2: jmp cret .globl .data

2012/3/24 21

Page 22: V6 unix in okinawa

csv 関数の入り口

Main:

:

jsr r5,csv

:

csv:

mov r5,r0

mov sp,r5

mov r4,-(sp)

mov r3,-(sp)

mov r2,-(sp)

tst -(sp)

jmp (r0)

r0 r1 r2 r3 r4 r5 r6:sp r7:pc ---- 0484, 0000, 0000, 0000, 0000, 0000, 047e, 0018 jsr r5,006a ---- 0484, 0000, 0000, 0000, 0000, 001c, 047c, 006a mov r5,r0 ---- 001c, 0000, 0000, 0000, 0000, 001c, 047c, 006c mov sp,r5 ---- 001c, 0000, 0000, 0000, 0000, 047c, 047c, 006e mov r4,-(r6) -z-- 001c, 0000, 0000, 0000, 0000, 047c, 047a, 0070 mov r3,-(r6) -z-- 001c, 0000, 0000, 0000, 0000, 047c, 0478, 0072 mov r2,-(r6) -z-- 001c, 0000, 0000, 0000, 0000, 047c, 0476, 0074 tst -(r6) -z-- 001c, 0000, 0000, 0000, 0000, 047c, 0474, 0076 jmp (r0) 2012/3/24 22

Page 23: V6 unix in okinawa

cret 関数の出口

main:

:

jmp cret

:

cret:

mov r5,r1

mov -(r1),r4

mov -(r1),r3

mov -(r1),r2

mov r5,sp

mov (sp)+,r5

rts pc

r0 r1 r2 r3 r4 r5 r6:sp r7:pc ---- 0003, 0462, 0000, 0000, 0000, 047c, 046e, 003e jmp 0078 ---- 0003, 0462, 0000, 0000, 0000, 047c, 046e, 0078 mov r5,r1 ---- 0003, 047c, 0000, 0000, 0000, 047c, 046e, 007a mov -(r1),r4 -z-- 0003, 047a, 0000, 0000, 0000, 047c, 046e, 007c mov -(r1),r3 -z-- 0003, 0478, 0000, 0000, 0000, 047c, 046e, 007e mov -(r1),r2 -z-- 0003, 0476, 0000, 0000, 0000, 047c, 046e, 0080 mov r5,r6 ---- 0003, 0476, 0000, 0000, 0000, 047c, 047c, 0082 mov (r6)+,r5 -z-- 0003, 0476, 0000, 0000, 0000, 0000, 047e, 0084 rts 0084

2012/3/24 23

Page 24: V6 unix in okinawa

JSR – Jump to SubRoutine

jsr src,dst 以下と等価

1. MOV src,-(R6) srcをスタックにpush

2. MOV PC,src 次の命令のPCをsrcに転送

3. JMP dst dstにジャンプ

jsr r5,0x006aの処理は以下

1. r5の値をstackに入れて、spを-2 (push)

2. Jsrの次に実行する(戻り先)アドレスをr5に入れて

3. PCにdstを入れてジャンプ

2012/3/24 24

Page 25: V6 unix in okinawa

RTS – ReTurn from Subroutine

rts src

以下と等価 1. MOV src,PC

2. MOV (R6)+,src

jsr r7の処理は以下

1. r7の値をPCに入れて(この場合は意味なし)

2. スタックの内容+2 (pop) してr7へ

pcの書き換えによりジャンプ

2012/3/24 25

Page 26: V6 unix in okinawa

main 引数の設定とfuncの呼出し

# r0 r1 r2 r3 r4 r5 r6 r7

15: 001c,0000,0000,0000,0000,047c,0474,001c sub $6,r6 main

16: 001c,0000,0000,0000,0000,047c,046e,0020 mov $1,-8(r5) main

17: 001c,0000,0000,0000,0000,047c,046e,0026 mov $2,-a(r5) main

18: 001c,0000,0000,0000,0000,047c,046e,002c mov -a(r5),(r6) main

19: 001c,0000,0000,0000,0000,047c,046e,0030 mov -8(r5),-(r6) main

20: 001c,0000,0000,0000,0000,047c,046c,0034 jsr r7,*$0x0040 main

21: 001c,0000,0000,0000,0000,047c,046a,0042 jsr r5,0x006a func

0x047c

0x047a

0x0478

0x0476

0x0474

0x0472

0x0470

0x046e

0x046c

r5→

r6→

#15

1

2

r5→

r6→

#16-17

1

2

2

r5→

r6→

#18

r6→

1

2

2

1

r5→

r6→

#19

0x046a

1

2

2

1

r5→

r6→

#20

0x0038

2012/3/24 26

Page 27: V6 unix in okinawa

funcの入り口 (func-csv)

# r0 r1 r2 r3 r4 r5 r6 r7

21: 001c,0000,0000,0000,0000,047c,046a,0042 jsr r5,0x006a func

22: 001c,0000,0000,0000,0000,0046,0468,006a mov r5,r0 func-csv

23: 0046,0000,0000,0000,0000,0046,0468,006c mov r6,r5 func-csv

24: 0046,0000,0000,0000,0000,0468,0468,006e mov r4,-(r6) func-csv

25: 0046,0000,0000,0000,0000,0468,0466,0070 mov r3,-(r6) func-csv

26: 0046,0000,0000,0000,0000,0468,0464,0072 mov r2,-(r6) func-csv

27: 0046,0000,0000,0000,0000,0468,0462,0074 tst -(r6) func-csv

28: 0046,0000,0000,0000,0000,0468,0460,0076 jmp (r0) func

0x046c

0x046a

0x0468

0x0466

0x0464

0x0462

0x0460

0x045e

0x045c

0x0038

0x047c

r6→

#21

0x0038

0x047c r6→

#23

0x0038

0x047c

r4

r3

r2

r5→

r6→

#24-26

r5,r6→

0x0038

0x047c

r4

r3

r2

r5→

r6→

#27

0x045a

2012/3/24 27

Page 28: V6 unix in okinawa

funcの出口 (func-cret) # r0 r1 r2 r3 r4 r5 r6 r7

34:0003,0000,0000,0000,0000,0468,0460,005c jmp 0x00078 func

35:0003,0000,0000,0000,0000,0468,0460,0078 mov r5,r1 func-cret

36:0003,0468,0000,0000,0000,0468,0460,007a mov -(r1),r4 func-cret

37:0003,0466,0000,0000,0000,0468,0460,007c mov -(r1),r3 func-cret

38:0003,0464,0000,0000,0000,0468,0460,007e mov -(r1),r2 func-cret

39:0003,0462,0000,0000,0000,0468,0460,0080 mov r5,r6 func-cret

40:0003,0462,0000,0000,0000,0468,0468,0082 mov (r6)+,r5 func-cret

41:0003,0462,0000,0000,0000,047c,046a,0084 rts r7 func-cret

42:0003,0462,0000,0000,0000,047c,046c,0038 tst (r6)+ main

0x046c

0x046a

0x0468

0x0466

0x0464

0x0462

0x0460

0x045e

0x045c

0x045a

0x0038

0x047c

r4

r3

r2

r5,r1→

r6→

#35

0x0038

0x047c

r4

r3

r2

r5→

r6→

#27-34

0x0038

0x047c

r4

r3

r2

r5→

r6→

#36-38

r1→

0x0038

0x047c r5,r6→

#39

0x0038

0x047c r6→

#40-41

r5→

r6→

r6→ 2012/3/24 28

Page 29: V6 unix in okinawa

関数とスタック

今のスタックr6:SP

前のスタックr5

r5:r6のペアでチェーン

0x047c

0x047a

0x0478

0x0476

0x0474

0x0472

0x0470

0x046e

0x046c

0x046a

1

2

2

1

r5→

#20

0x0038

0x0468

0x0466

0x0464

0x0462

0x0460

0x0038

0x047c

r4

r3

r2

r5→

r6→ #27

0x0038

0x047c

#21

r6→

2012/3/24 29

Page 30: V6 unix in okinawa

レジスタ r0-r7 もう一度

r0, r1

演算結果の一時的な保持、復帰値など

r2, r3, r4

関数内のローカル変数。呼ばれた関数で退避し、関数の終了時に復元

R5

フレームポインタ

r6 (sp)

スタックポインタ

r7 (pc)

実行する命令の位置(アドレス)

2012/3/24 30

Page 31: V6 unix in okinawa

C言語とasmの実行環境

asmから生成した命令列はスタックを必要としない

C言語から生成した命令列は、実行時にスタックを必要とする

引数の受け渡し利用領域

自動変数の領域

呼び出し元レジスタ(r2,r3,r4)の退避領域

呼び出し先からの復帰アドレスの退避領域

2012/3/24 31

Page 32: V6 unix in okinawa

UNIXカーネルを理解するための

2012/3/24 32

Page 33: V6 unix in okinawa

getpid(2)の呼び出し C言語

main()

{

int i;

i = getpid();

}

2012/3/24 33

Page 34: V6 unix in okinawa

getpid(2)の呼び出し ASM

.globl _main

.text

_main:

~~main:

~i=177770

jsr r5,csv

tst -(sp)

jsr pc,_getpid

mov r0,-10(r5)

L1: jmp cret

.globl

.data

2012/3/24 34

Page 35: V6 unix in okinawa

getpid.s /usr/source/s4/getpid.s

getpid = 20.

.globl _getpid

_getpid:

mov r5,-(sp)

mov sp,r5

sys getpid

mov (sp)+,r5

rts pc

2012/3/24 35

Page 36: V6 unix in okinawa

getpid.sの実行トレース

3: 001c, 0000, 0000, 0000, 0000, 0446, 043c, 001e jsr r7, 0x00034

4: 001c, 0000, 0000, 0000, 0000, 0446, 043a, 0034 mov r5, -(r6)

5: 001c, 0000, 0000, 0000, 0000, 0446, 0438, 0036 mov r6,r5

6: 001c, 0000, 0000, 0000, 0000, 0438, 0438, 0038 sys getpid

7: 001c, 0000, 0000, 0000, 0000, 0438, 0438, 003a mov (r6)+, r5

8: 001c, 0000, 0000, 0000, 0000, 0446, 043a, 003c rts r7

2012/3/24

なんか変じゃない

36

Page 37: V6 unix in okinawa

open(2)の呼び出し C言語

main()

{

int f;

f = open("hoge", 2);

}

2012/3/24 37

Page 38: V6 unix in okinawa

open(2)の呼び出し ASM

.globl _main

.text

_main:

~~main:

~f=177770

jsr r5,csv

tst -(sp)

mov $2,(sp)

mov $L2,-(sp)

jsr pc,*$_open

tst (sp)+

mov r0,-10(r5)

L1: jmp cret

.globl

.data

L2:.byte 150,157,147,145,0

2012/3/24 38

Page 39: V6 unix in okinawa

open.s /usr/source/s5/open.s

globl _open, cerror

_open:

mov r5,-(sp)

mov sp,r5

mov 4(r5),0f

mov 6(r5),0f+2

sys 0; 9f

bec 1f

jmp cerror

1:

mov (sp)+,r5

rts pc

.data

9:

sys open;

0: ..;

.. 2012/3/24 39

Page 40: V6 unix in okinawa

open.sの実行トレース

# r0 r1 r2 r3 r4 r5 r6 r7

1: 001c, 0000, 0000, 0000, 0000, 0482, 0474, 0034 mov r5,-(r6)

2: 001c, 0000, 0000, 0000, 0000, 0482, 0472, 0036 mov r6,r5

3: 001c, 0000, 0000, 0000, 0000, 0472, 0472 0038 mov 4(r5), 0x008e

4: 001c, 0000, 0000, 0000, 0000, 0472, 0472, 003e mov 6(r5), 0x0090

5: 001c, 0000, 0000, 0000, 0000, 0472, 0472, 0044 sys indir 0x0008c

6: 0003, 0000, 0000, 0000, 0000, 0472, 0472, 0048 bcc 0x0004e

7: 0003, 0000, 0000, 0000, 0000, 0472, 0472, 004e mov (r6)+, r5

8: 0003, 0000, 0000, 0000, 0000, 0482, 0474, 0050 rts

2012/3/24

なんか変じゃない

40

Page 41: V6 unix in okinawa

システムコールとライブラリコール

ライブラリ

マニュアルセクション3

例 fopen(3)

ユーザプログラムの空間で動作

必要に応じてシステムコールを呼び出す

システムコール

マニュアルセクション2

例 open(2)

OS内部の処理を呼び出す

呼出し方法は通常のCall/Returnとは異なる 2012/3/24 41

Page 42: V6 unix in okinawa

OSを実装するための

2012/3/24 42

Page 43: V6 unix in okinawa

Q:CPUが想定外の状態になると

たとえば以下の場合

不正なアドレスを参照した

未定義の命令を実行しようとした

0で割り算した

次の命令はどこから取り出せばよいか?

2012/3/24 43

Page 44: V6 unix in okinawa

A: わな “Trap”を用意しておく

CPUが身動きが取れなかった場合に次に命令

を取り出す場所を“わな”として仕掛けておく

システムコールの呼び出しは特殊な「わな」

「わな」はCPUの処理過程に実行時の例外として発生する

「わな」に引っかかる事を「例外」と呼ぶ

2012/3/24 44

Page 45: V6 unix in okinawa

例外と割り込み

Lions本9章

Trap/例外

命令の実行に失敗した場合の「わな」仕掛ける

システムコールの呼び出しは特殊な「わな」

「わな」はCPUの処理過程で発生する

Interrupt/割り込み

CPUの処理に関係なく、外部からの「割り込み」

主に、外部装置の処理完了時に「割り込む」

外部装置の例

○ テレタイプ、紙テープ、ラインプリンタ、磁気ディスク、時計

2012/3/24 45

Page 46: V6 unix in okinawa

2012/3/24 46

Page 47: V6 unix in okinawa

例外の流れ

1. 例外/割り込みの発生 2. コンテキストの保存 ① PCとPSWをCPU内部に一時的に保存 ② 発生の要因を特定し、要因:アドレスの表(ベクター)を検索

③ ベクターをPCに設定 ④ 一時的に保存していたPC,PSWをカーネルスタックに退避(push)

3. ハンドラの実行 4. コンテキストの復元 ① カーネルスタックにPC,PSWが格納されている状態で

rtt命令を実行 ② rtt命令がカーネルスタックからPC,PSWを復元(pop)

5. 割り込み発生の次の命令を実行

2012/3/24 47

Page 48: V6 unix in okinawa

例外ベクタ

Vector

Location Trap type Priority

004 Bus timeout 7

010 Illegal instruction 7

014 bpt-trace 7

020 iot 7

024 Power failure 7

030 Emulator trap 7

034 Trap instruction/ system entry 7

114 11/70 parity 7

240 Programmed interrupt 7

244 Floating point error 7

250 Segmentation violation 7

2012/3/24 48

Page 49: V6 unix in okinawa

500 0500 / low core

0501

0505 br7 = 340

0506

0507 . = 0^.

0508 br 1f

0509 4

0510

0511 / trap vectors

0512 trap; br7+0. / bus error

0513 trap; br7+1. / illegal instruction

0514 trap; br7+2. / bpt-trace trap

0515 trap; br7+3. / iot trap

0516 trap; br7+4. / power fail

0517 trap; br7+5. / emulator trap

0518 trap; br7+6. / system entry 2012/3/24 49

Page 50: V6 unix in okinawa

752

0752 .globl trap, call

0753 /* -------------- */

0754 .globl _trap

0755 trap:

0756 mov PS,-4(sp)

0757 tst nofault

0758 bne 1f

0759 mov SSR0,ssr

0760 mov SSR2,ssr+4

0761 mov $1,SSR0

0762 jsr r0,call1; _trap

0763 / no return

2012/3/24 50

Page 51: V6 unix in okinawa

2693 2693 trap(dev, sp, r1, nps, r0, pc, ps)

2694 {

2695 register i, a;

2696 register struct sysent *callp;

2697

2698 savfp();

2699 if ((ps&UMODE) == UMODE)

2700 dev =| USER; 2750

2702 switch(dev) {

:

2715 default:

2716 printf("ka6 = %o¥n", *ka6);

2717 printf("aps = %o¥n", &ps);

2718 printf("trap type %o¥n", dev);

2719 panic("trap");

2721 case 0+USER: /* bus error *

2722 i = SIGBUS;

2723 break; 2012/3/24 51

Page 52: V6 unix in okinawa

2751

2751 case 6+USER: /* sys call */

2752 u.u_error = 0;

2753 ps =& ~EBIT;

2754 callp = &sysent[fuiword(pc-2)&077];

PCは”わな”に落ちた命令の次のアドレス

この命令は2バイトなので2を引いて

ユーザ空間からword(2バイト)を読み

下位6ビットを取り出す

この値をindexにしてsysentを見ると

2012/3/24 52

Page 53: V6 unix in okinawa

2906

2906 * to the appropriate routine for processing a system call.

2907 * Each row contains the number of arguments

2908 * and a pointer to the routine.

2909 */

2910 int sysent[]

2911 {

2912 0, &nullsys, /* 0 = indir */

2913 0, &rexit, /* 1 = exit */

2914 0, &fork, /* 2 = fork */

2915 2, &read, /* 3 = read */

2916 2, &write, /* 4 = write */

2917 2, &open, /* 5 = open */

2012/3/24 53

Page 54: V6 unix in okinawa

システムコール番号

indir = 0. exit = 1. fork = 2. read = 3. write = 4. open = 5. close = 6. wait = 7. creat = 8. : :

2012/3/24 54

Page 55: V6 unix in okinawa

システムコール呼出し処理

1. C言語で open(“aa”, 2)

2. Libcで sys 5 を実行

sysはemulator trap instruction

3. ユーザプログラム空間から5を取り出して

4. sysent[5]でカーネル内のopen処理を見つけ

5. カーネル内部のopen処理を呼ぶ

2012/3/24 55

Page 56: V6 unix in okinawa

2012/3/24 56

Page 57: V6 unix in okinawa

割り込みベクタ

Vector

Location device priority

060 Teletype input 4

064 Teletype output 4

070 Paper tape input 4

074 Paper tape output 4

100 Line clock 6

104 Programmable clock 6

200 Line printer 4

220 RK disk driver 5

2012/3/24 57

Page 58: V6 unix in okinawa

Teletype ?

2012/3/24 58

Page 59: V6 unix in okinawa

Paper tape ?

2012/3/24 59

Page 60: V6 unix in okinawa

Clocks – line and programmable

Line Clock

電源の周期から生成

AC>降圧(トランス)>整流(ダイオード)>コンデンサ

電源周波数のパルスを取り出せる

50HZで20ms間隔

昔の電気式デジタル時計はパルスxHZで1秒を生成

Programmable clock

指定の間隔でパルスを発生

PDP-11ではどちらかが必要

2012/3/24 60

Page 61: V6 unix in okinawa

525 low.s

0525: . = 60^.

0526: klin; br4

0527: klou; br4

0528:

0529: . = 70^.

0530: pcin; br4

0531: pcou; br4

0532:

0533: . = 100^.

0534: kwlp; br6

0535: kwlp; br6

0539:

0540: . = 200^.

0541: lpou; br4

0542:

0543: . = 220^.

0544: rkio; br5

Vector device entry

060 Teletype input klin

064 Teletype output klou

070 Paper tape input pcin

074 Paper tape output pcou

100 Line clock kwlp

104 Programmable clock kwlp

200 Line printer lpou

220 RK disk driver rkio

2012/3/24 61

Page 62: V6 unix in okinawa

Line Clock

外部にあるclockから毎秒50個のパルスがCPUに入る

1パルス毎に割り込みベクタの処理を実行

CPU

Clock

2012/3/24 62

Page 63: V6 unix in okinawa

kwlp low.s

0568:

0569: .globl _clock

0570: kwlp: jsr r0,call; _clock

Cで書かれたclock()を呼ぶ

2012/3/24 63

Page 64: V6 unix in okinawa

clock 3725: clock(dev, sp, r1, nps, r0, pc, ps)

3726: {

3727: register struct callo *p1, *p2;

3728: register struct proc *pp;

3729:

3730: /*

3731: * restart clock

3732: */

3733:

3734: *lks = 0115;

3735:

3736: /*

3737: * display register

3738: */

3739:

3740: display();

3741:

3742: /*

3743: * callouts

3744: * if none, just return

3745: * else update first non-zero time

3746: */

3747:

3748: if(callout[0].c_func == 0)

3749: goto out;

3750: p2 = &callout[0];

3751: while(p2->c_time<=0 && p2->c_func!=0)

3752: p2++;

3753: p2->c_time--;

3754:

3755: /*

3756: * if ps is high, just return

3757: */

3758:

3759: if((ps&0340) != 0)

3760: goto out;

3761:

3762: /*

3763: * callout

3764: */

3765:

3766: spl5();

3767: if(callout[0].c_time <= 0) {

3768: p1 = &callout[0];

3769: while(p1->c_func != 0 && p1->c_time <= 0) {

3770: (*p1->c_func)(p1->c_arg);

3771: p1++;

3772: }

3773: p2 = &callout[0];

3774: while(p2->c_func = p1->c_func) {

3775: p2->c_time = p1->c_time;

3776: p2->c_arg = p1->c_arg;

3777: p1++;

3778: p2++;

3779: }

3780: }

3781:

3782: /*

3783: * lightning bolt time-out

3784: * and time of day

3785: */

3786:

3787: out:

3788: if((ps&UMODE) == UMODE) {

3789: u.u_utime++;

3790: if(u.u_prof[3])

3791: incupc(pc, u.u_prof);

3792: } else

3793: u.u_stime++;

3794: pp = u.u_procp;

3795: if(++pp->p_cpu == 0)

3796: pp->p_cpu--;

3797: if(++lbolt >= HZ) {

3798: if((ps&0340) != 0)

3799: return;

3800: lbolt =- HZ;

3801: if(++time[1] == 0)

3802: ++time[0];

3803: spl1();

3804: if(time[1]==tout[1] && time[0]==tout[0])

3805: wakeup(tout);

3806: if((time[1]&03) == 0) {

3807: runrun++;

3808: wakeup(&lbolt);

3809: }

3810: for(pp = &proc[0]; pp < &proc[NPROC]; pp++)

3811: if (pp->p_stat) {

3812: if(pp->p_time != 127)

3813: pp->p_time++;

3814: if((pp->p_cpu & 0377) > SCHMAG)

3815: pp->p_cpu =- SCHMAG; else

3816: pp->p_cpu = 0;

3817: if(pp->p_pri > PUSER)

3818: setpri(pp);

3819: }

3820: if(runin!=0) {

3821: runin = 0;

3822: wakeup(&runin);

3823: }

3824: if((ps&UMODE) == UMODE) {

3825: u.u_ar0 = &r0;

3826: if(issig())

3827: psig();

3828: setpri(u.u_procp);

3829: }

3830: }

3831: }

2012/3/24 64

Page 65: V6 unix in okinawa

clock 3725: clock(dev, sp, r1, nps, r0, pc, ps)

3726: {

3727: register struct callo *p1, *p2;

3728: register struct proc *pp;

3729:

3730: /*

3731: * restart clock

3732: */

3733:

3734: *lks = 0115;

3735:

3736: /*

3737: * display register

3738: */

3739:

3740: display();

3741:

3742: /*

3743: * callouts

3744: * if none, just return

3745: * else update first non-zero time

3746: */

3747:

3748: if(callout[0].c_func == 0)

3749: goto out;

3750: p2 = &callout[0];

3751: while(p2->c_time<=0 && p2->c_func!=0)

3752: p2++;

3753: p2->c_time--;

3754:

3755: /*

3756: * if ps is high, just return

3757: */

3758:

3759: if((ps&0340) != 0)

3760: goto out;

3761:

3762: /*

3763: * callout

3764: */

3765:

3766: spl5();

3767: if(callout[0].c_time <= 0) {

3768: p1 = &callout[0];

3769: while(p1->c_func != 0 && p1->c_time <= 0) {

3770: (*p1->c_func)(p1->c_arg);

3771: p1++;

3772: }

3773: p2 = &callout[0];

3774: while(p2->c_func = p1->c_func) {

3775: p2->c_time = p1->c_time;

3776: p2->c_arg = p1->c_arg;

3777: p1++;

3778: p2++;

3779: }

3780: }

3781:

3782: /*

3783: * lightning bolt time-out

3784: * and time of day

3785: */

3786:

3787: out:

3788: if((ps&UMODE) == UMODE) {

3789: u.u_utime++;

3790: if(u.u_prof[3])

3791: incupc(pc, u.u_prof);

3792: } else

3793: u.u_stime++;

3794: pp = u.u_procp;

3795: if(++pp->p_cpu == 0)

3796: pp->p_cpu--;

3797: if(++lbolt >= HZ) {

3798: if((ps&0340) != 0)

3799: return;

3800: lbolt =- HZ;

3801: if(++time[1] == 0)

3802: ++time[0];

3803: spl1();

3804: if(time[1]==tout[1] && time[0]==tout[0])

3805: wakeup(tout);

3806: if((time[1]&03) == 0) {

3807: runrun++;

3808: wakeup(&lbolt);

3809: }

3810: for(pp = &proc[0]; pp < &proc[NPROC]; pp++)

3811: if (pp->p_stat) {

3812: if(pp->p_time != 127)

3813: pp->p_time++;

3814: if((pp->p_cpu & 0377) > SCHMAG)

3815: pp->p_cpu =- SCHMAG; else

3816: pp->p_cpu = 0;

3817: if(pp->p_pri > PUSER)

3818: setpri(pp);

3819: }

3820: if(runin!=0) {

3821: runin = 0;

3822: wakeup(&runin);

3823: }

3824: if((ps&UMODE) == UMODE) {

3825: u.u_ar0 = &r0;

3826: if(issig())

3827: psig();

3828: setpri(u.u_procp);

3829: }

3830: }

3831: }

Callout

Acct

Sched の入り口

2012/3/24 65

Page 66: V6 unix in okinawa

謎の変数

u.u_time

u.u_stime

pp->p_time

lbolt

time[2]

tout[2]

2012/3/24 66

Page 67: V6 unix in okinawa

callout 構造

struct callo

{

int c_time; /* ticks between events */

int c_arg; /* function argument */

int (*c_func)(); /* function pointer */

} callout[NCALL];

2012/3/24 67

Page 68: V6 unix in okinawa

clock callout (1/2) 3748: if(callout[0].c_func == 0)

3749: goto out;

3750: p2 = &callout[0];

3751: while(p2->c_time<=0 && p2->c_func!=0)

3752: p2++;

3753: p2->c_time--;

3758:

3759: if((ps&0340) != 0)

3760: goto out;

3761:

先頭のcalloutが未

登録なら、後続のcalloutも未登録と判断して,Callout

処理をスキップ

最初にc_timeが0

より大きいCallout

を見つけて、c_timeを-1

ここより前のcalloutはこの後処

理される

2012/3/24 68

Page 69: V6 unix in okinawa

clock callout (2/2) 3766: spl5();

3767: if(callout[0].c_time <= 0) {

3768: p1 = &callout[0];

3769: while(p1->c_func != 0 && p1->c_time <= 0) {

3770: (*p1->c_func)(p1->c_arg);

3771: p1++;

3772: }

3773: p2 = &callout[0];

3774: while(p2->c_func = p1->c_func) {

3775: p2->c_time = p1->c_time;

3776: p2->c_arg = p1->c_arg;

3777: p1++;

3778: p2++;

3779: }

3780: }

先頭に登録時間が過ぎているcallout

が存在したら、

処理を実行

Callout配列を詰める

2012/3/24 69

Page 70: V6 unix in okinawa

clock acct

3787: out:

3788: if((ps&UMODE) == UMODE) {

3789: u.u_utime++;

3790: if(u.u_prof[3])

3791: incupc(pc, u.u_prof);

3792: } else

3793: u.u_stime++;

3794: pp = u.u_procp;

3795: if(++pp->p_cpu == 0)

3796: pp->p_cpu--;

USERモードから

割り込まれたら、uのuser時間u_utimeを+1

KERNELモードか

ら割り込まれたら、uのsystem時間u_stimeを+1

Procのp_cpuを加算。オーバフローしないように調整

ppはproc構造のポインタ、uはuser構造。共にプロセスの管理構造1プロセスに1個づつ

2012/3/24 70

Page 71: V6 unix in okinawa

clock schedの入り口(1/2)

3797: if(++lbolt >= HZ) {

3798: if((ps&0340) != 0)

3799: return;

3800: lbolt =- HZ;

3801: if(++time[1] == 0)

3802: ++time[0];

3803: spl1();

3804: if(time[1]==tout[1] && time[0]==tout[0])

3805: wakeup(tout);

3806: if((time[1]&03) == 0) {

3807: runrun++;

3808: wakeup(&lbolt);

3809: }

clockが呼ばれると、ここまでは必ず実行。lboltを+1して、HZ(50)を

超過したら、すなわち1秒経過したら、

lboltをリセット

寝ているプロセスを起こす

4秒ごとにlboltで待ってるプロセスを起こす

今回はさらりと流す 2012/3/24 71

Page 72: V6 unix in okinawa

clock schedの入り口(2/2) 3810: for(pp = &proc[0]; pp < &proc[NPROC]; pp++)

3811: if (pp->p_stat) {

3812: if(pp->p_time != 127)

3813: pp->p_time++;

3814: if((pp->p_cpu & 0377) > SCHMAG)

3815: pp->p_cpu =- SCHMAG; else

3816: pp->p_cpu = 0;

3817: if(pp->p_pri > PUSER)

3818: setpri(pp);

3819: }

3820: if(runin!=0) {

3821: runin = 0;

3822: wakeup(&runin);

3823: }

3824: if((ps&UMODE) == UMODE) {

3825: u.u_ar0 = &r0;

3826: if(issig())

3827: psig();

3828: setpri(u.u_procp);

3829: }

3830: }

3831: }

プロセスの管理構造の配列をスキャン

p_statに値が入っている=プロセスが存在したら、p_timeを+1

runinが真なら、runinで待ってるプロセスをwakeup

2012/3/24 72

Page 73: V6 unix in okinawa

謎の変数 回答

u.u_time USER時間

u.u_stime SYSTEM時間

pp->p_time プロセス起動からの時間

lbolt 毎秒60回++

time[2] 1970年からの秒

tout[2] sleep(2)が起きる時間

2012/3/24 73

Page 74: V6 unix in okinawa

Unix のPPDA (PerProcDataArea)

User構造体 user.h

The user structure. One allocated per process.

Contains all per process data that doesn't need

to be referenced while the process is swapped.

Proc構造体 proc.h

One structure allocated per active process. It

contains all data needed about the process while

the process may be swapped out. Other per

process data (user.h) is swapped with the

process.

2012/3/24 74

Page 75: V6 unix in okinawa

2012/3/24 75

Page 76: V6 unix in okinawa

a.outと空間の関係

text

data

header

3076 /* read in first 8 bytes 3077 * of file for segment 3078 * sizes: 3079 * w0 = 407/410/411 3080 * w1 = text size 3081 * w2 = data size 3082 * w3 = bss size 3083 */

a.out

text

data

bss

stack

・関数を呼び出すと自動的に割り当てる。

・呼び出しからの復帰に備えてレジスタの内容を退避。

exec(2)

CPU PC

2012/3/24 76

Page 77: V6 unix in okinawa

例外/割り込みが起こると……..

text

data

bss

stack

CPU PC

text

data

bss

stack

•PSWのモードがユーザモー

ドからカーネルモードに変わり、空間が切り替わる。

•事象に応じて、ベクターテーブルの値がPCに書き込まれる。

① ②

アプリケーション カーネル

•例外/割り込み発生時のPSW

とPC(図中A)をスタックにpushする

A

アプリケーションと

カーネル

2つの空間??

2012/3/24 77

Page 78: V6 unix in okinawa

仮想アドレスと物理アドレス

現在の一般的な仮想記憶 仮想アドレス>物理アドレス

仮想メモリ量>物理メモリ量

実メモリ不足時は固定長(ページ)単位で2次記憶に退避し必要時に復元

→ページング

PDP-11の仮想記憶 仮想アドレス<物理アドレス

仮想メモリ量<物理メモリ量

実メモリ不足時はプロセス全体を2次記憶に退避し実行を抑止、一定時間経過後に全体を復元し実行可能に

→スワッピング

2012/3/24 78

Page 79: V6 unix in okinawa

仮想記憶のための仕組み

ハードウェアのサポートが必要

仮想アドレス→物理アドレスの変換機構

CPU memory

変換機構なし

変換機構あり

CPU memory 変換表

2012/3/24 79

Page 80: V6 unix in okinawa

アドレス変換機構の制御

リセット後は変換機構OFFで動作

OSの初期化時にプログラムで

1. 変換表を初期化

2. 変換機構をON

新しいプロセスの生成とメモリ獲得時に

OSが変換表を編集

プロセスの切り替え時に

変換表を入れ替え

2012/3/24 80

Page 81: V6 unix in okinawa

PDP-11/40のメモリ管理機構

8個のカーネルモードページ

8個のユーザモードページ

1ページは最大8Kbyteの可変長

モード切り替えはPSWのモードに連動

2012/3/24 81

Page 82: V6 unix in okinawa

Active Page Registers (APR)

2012/3/24 82

Page 83: V6 unix in okinawa

APR- PARとPDRのペア

PAR ベースアドレスを指定

PDR メモリ属性を指定

2012/3/24 83

Page 84: V6 unix in okinawa

仮想記憶の有効化

bit0 ENABLE MANAGEMENTを1で有効

2012/3/24 84

Page 85: V6 unix in okinawa

重要なアドレス m40.s

USIZE = 16

PS = 177776

SSR0 = 177572

KISA0 = 172340

KISA6 = 172354

KISD0 = 172300

UISA0 = 177640

UISA1 = 177642

UISD0 = 177600

UISD1 = 177602

IO = 7600

Size of User Block (*64 = 1024 B)

Program Status Word

Status Register

Kernel Segment Address Register #0

Kernel Segment Address Register #6

Kernel Segment Descriptor Register #0

User Segment Address Register #0

User Segment Address Register #1

User Segment Descriptor Register #0

User Segment Descriptor Register #1

I/O Segment Register

2012/3/24 85

Page 86: V6 unix in okinawa

start 仮想空間の設定

0612: start:

0613: bit $1,SSR0

0614: bne start / loop if restart

0615: reset

0616:

0617: / initialize systems segments

0618:

0619: mov $KISA0,r0

0620: mov $KISD0,r1

0621: mov $200,r4

0622: clr r2

0623: mov $6,r3

0624: 1:

0625: mov r2,(r0)+

0626: mov $77406,(r1)+ / 4k rw

0627: add r4,r2

0628: sob r3,1b

2012/3/24 86

Page 87: V6 unix in okinawa

ユーザ空間の初期化 start

0630: / initialize user segment

0631:

0632: mov $_end+63.,r2

0633: ash $-6,r2

0634: bic $!1777,r2

0635: mov r2,(r0)+ / ksr6 = sysu

0636: mov $usize-1¥<8|6,(r1)+

0637:

0638: / initialize io segment

0639: / set up counts on supervisor segments

0640:

0641: mov $IO,(r0)+

0642: mov $77406,(r1)+ / rw 4k

0643:

0644: / get a sp and start segmentation

0645:

0646: mov $_u+[usize*64.],sp

0647: inc SSR0

2012/3/24 87

Page 88: V6 unix in okinawa

bssとuのクリア

0646: mov $_u+[usize*64.],sp 0647: inc SSR0 0648: 0649: / clear bss 0650: 0651: mov $_edata,r0 0652: 1: 0653: clr (r0)+ 0654: cmp r0,$_end 0655: blo 1b 0656: 0657: / clear user block 0658: 0659: mov $_u,r0 0660: 1: 0661: clr (r0)+ 0662: cmp r0,$_u+[usize*64.] 0663: blo 1b

2012/3/24 88

Page 89: V6 unix in okinawa

mainの呼び出し

0665: / set up previous mode and call main

0666: / on return, enter user mode at 0R

0667:

0668: mov $30000,PS

0669: jsr pc,_main

0670: mov $170000,-(sp)

0671: clr -(sp)

0672: rtt

2012/3/24 89

Page 90: V6 unix in okinawa

最初のプロセスを生成

1627: if(newproc()) {

1628: expand(USIZE+1);

1629: estabur(0, 1, 0, 0);

1630: copyout(icode, 0, sizeof icode);

1631: /*

1632: * Return goes to loc. 0 of user init

1633: * code just copied out.

1634: */

1635: return;

1636: }

1637: sched();

2012/3/24 90

Page 91: V6 unix in okinawa

icode

1511: /* 1512: * Icode is the octal bootstrap 1513: * program executed in user mode 1514: * to bring up the system. 1515: */ 1516: int icode[] 1517: { 1518: 0104413, /* sys exec; init; initp */ 1519: 0000014, 1520: 0000010, 1521: 0000777, /* br . */ 1522: 0000014, /* initp: init; 0 */ 1523: 0000000, 1524: 0062457, /* init: </etc/init¥0> */ 1525: 0061564, 1526: 0064457, 1527: 0064556, 1528: 0000164, 1529: };

2012/3/24

char* init = “/etc/init”;

main( ) {

execl( init, init, 0 );

while( 1 ) ;

}

91

Page 92: V6 unix in okinawa

Bootと空間の初期化

text

data

text

data

bss

user

IOレジスタ

icode

user

2012/3/24

Boot直後

text

data

bss

u

仮想記憶有効

IOレジスタ

最初のnewproc

text

data

bss

user

IOレジスタ

exec

user

最初のexec

text

data

bss

user

IOレジスタ

user

Initの実行

text

data

bss

stack

92

Page 93: V6 unix in okinawa

Unixの空間モデル

アプリとカーネルのアドレス域は分離

後に完全な仮想記憶サポートで少し変わる

各アプリケーションの空間は独立

カーネルの空間は

Text,Data,Bssは一部を除いて共有

Stackはアプリ毎に個別

Stackはstruct userのページの後半

2012/3/24 93

Page 94: V6 unix in okinawa

UNIXカーネルの構造

2012/3/24 94

Page 95: V6 unix in okinawa

PPDA - Per Processor Data Area

OSを読み解く場合に最初に注目する構造

プロセスなどの実行単位毎に割り当てる領域

UNIXの場合はuserとproc

2012/3/24 95

Page 96: V6 unix in okinawa

struct user

0413 struct user

0414 {

0415 int u_rsav[2]; /* save r5,r6 when exchanging stacks */

0416 int u_fsav[25]; /* save fp registers */

0417 /* rsav and fsav must be first in structure */

0418 char u_segflg; /* flag for IO; user or kernel space */

0419 char u_error; /* return error code */

0420 char u_uid; /* effective user id */

0421 char u_gid; /* effective group id */

0422 char u_ruid; /* real user id */

0423 char u_rgid; /* real group id */

0424 int u_procp; /* pointer to proc structure */

0436 int u_uisa[16]; /* prototype of segmentation addresses */

043 int u_uisd[16]; /* prototype of segmentation descriptors */

2012/3/24 96

Page 97: V6 unix in okinawa

struct proc 0358 struct proc

0359 {

0360 char p_stat;

0361 char p_flag;

0362 char p_pri; /* priority, negative is high */

0363 char p_sig; /* signal number sent to this process */

0364 char p_uid; /* user id, used to direct tty signals */

0365 char p_time; /* resident time for scheduling */

0366 char p_cpu; /* cpu usage for scheduling */

0367 char p_nice; /* nice for scheduling */

0368 int p_ttyp; /* controlling tty */

0369 int p_pid; /* unique process id */

0370 int p_ppid; /* process id of parent */

0371 int p_addr; /* address of swappable image */

0372 int p_size; /* size of swappable image (*64 bytes) */

0373 int p_wchan; /* event process is awaiting */

0374 int *p_textp; /* pointer to text structure */

0376 } proc[NPROC];

2012/3/24 97

Page 98: V6 unix in okinawa

struct user

空間の切り替え機構

text

data

bss

stack

CPU PC

text

data

bss

アプリケーション カーネル PSW

APR0

APR1

APR2

APR3

APR4

APR5

APR6

APR7

APR0

APR1

APR2

APR3

APR4

APR5

APR6

APR7

00: カーネルモード

11: ユーザモード

11用 00用

stack

I/Oレジスタ

2012/3/24 98

Page 99: V6 unix in okinawa

アプリケーションの動作時

text

data

bss

stack

text

data

bss

user

IOレジスタ

text

data

bss

stack

user

text

data

bss

stack

user

text

data

bss

stack

user

•PSWのモードはユーザ

•PCはアプリのtextセグメントを指す

PSW PC

kstack kstack kstack kstack

2012/3/24 99

Page 100: V6 unix in okinawa

割り込みの発生-空間の切り替え

text

data

bss

stack

text

data

bss

user

IOレジスタ

text

data

bss

stack

user

text

data

bss

stack

user

text

data

bss

stack

user

•PSWのモードがカーネルに

•アドレス空間の制御レジスタがカーネルモードに切り替わる

PSW PC

kstack kstack kstack kstack

2012/3/24 100

Page 101: V6 unix in okinawa

text

data

bss

割り込みの発生-割り込みベクタ

text

data

bss

stack

user

IOレジスタ

text

data

bss

stack

user

text

data

bss

stack

user

text

data

bss

stack

user

•割り込みベクタのエントリを選択してPCに

PSW PC

kstack kstack kstack kstack

•1のアドレスとpswをスタックに退避

2012/3/24 101

Page 102: V6 unix in okinawa

text

data

bss

割り込みの発生-割り込みベクタ

text

data

bss

stack

user

IOレジスタ

text

data

bss

stack

user

text

data

bss

stack

user

text

data

bss

stack

user

•割り込みベクタのエントリを選択してPCに

PSW PC

kstack kstack kstack kstack

Vector device

004 Bus Timeout

010 Illegal instruction

014 Bpt-trace

024 iot

034 Power failur

114 Emulator tarp

instruction

240 11/10 parity

244 Floting point error

250 Segmentation violation

Vector device entry

060 Teletype input klin

064 Teletype output klou

070 Paper tape input pcin

074 Paper tape output pcou

100 Line clock kwlp

104 Programmable clock kwlp

200 Line printer lpou

220 RK disk driver rkio

2012/3/24 102

Page 103: V6 unix in okinawa

割り込みの発生ーハンドラの処理

text

data

bss

stack

text

data

bss

user

IOレジスタ

text

data

bss

stack

user

text

data

bss

stack

user

text

data

bss

stack

user

PSW PC

kstack kstack kstack kstack

2012/3/24 103

Page 104: V6 unix in okinawa

割り込みのからの復帰

text

data

bss

stack

text

data

bss

user

IOレジスタ

text

data

bss

stack

user

text

data

bss

stack

user

text

data

bss

stack

user

PSW PC

kstack kstack kstack kstack

APR0

APR1

APR2

APR3

APR4

APR5

APR6

APR7

カーネル用

APR0

APR1

APR2

APR3

APR4

APR5

APR6

APR7

アプリ用 •処理が終わったら、スタックのPCとPSW復元して割り込み時点に復帰

2012/3/24 104

Page 105: V6 unix in okinawa

以上の説明は、割り込み発生時から、復帰までにプロセスの切り替えが発生しない場合

条件によっては以下の処理でプロセスの切り替えが発生

1. procの検索と選択

2. user構造の切り替え

3. User構造+kstackに退避した状態の復元

4. アプリへの復帰

2012/3/24 105

Page 106: V6 unix in okinawa

プロセスの切り替えー選択

text

data

bss

stack

text

data

bss

user

IOレジスタ

text

data

bss

stack

user

text

data

bss

stack

user

text

data

bss

stack

user

PSW PC

kstack kstack kstack kstack

Procの検索(スケジューラ)

↑次に動かすアプリ(プロセス)のprocを見つける

2012/3/24 106

Page 107: V6 unix in okinawa

プロセスの切り替えーuserの切り替え

text

data

bss

stack

text

data

bss

user

IOレジスタ

text

data

bss

stack

user

text

data

bss

stack

user

text

data

bss

stack

user

PSW PC

kstack kstack kstack kstack

proc

2012/3/24 107

Page 108: V6 unix in okinawa

プロセスの切り替えーuserの切り替え

text

data

bss

stack

text

data

bss

user

IOレジスタ

text

data

bss

stack

user

text

data

bss

stack

user

text

data

bss

stack

user

PSW PC

kstack kstack kstack kstack

proc

APR0

APR1

APR2

APR3

APR4

APR5

APR6

APR7

アプリ用 空間管理用のレジスタを更新

2012/3/24 108

Page 109: V6 unix in okinawa

プロセスの切り替えーモードの切り替え

text

data

bss

stack

text

data

bss

user

IOレジスタ

text

data

bss

stack

user

text

data

bss

stack

user

text

data

bss

stack

user

PSW PC

kstack kstack kstack kstack

proc

APR0

APR1

APR2

APR3

APR4

APR5

APR6

APR7

アプリ用

•PSWをユーザに切り替え

•PCを復元

•退避していた、PCとレジスタを復元

2012/3/24 109

Page 110: V6 unix in okinawa

プロセスの切り替えー完了

text

data

bss

stack

text

data

bss

user

IOレジスタ

text

data

bss

stack

user

text

data

bss

stack

user

text

data

bss

stack

user

PSW PC

kstack kstack kstack kstack

proc

APR0

APR1

APR2

APR3

APR4

APR5

APR6

APR7

アプリ用

2012/3/24 110

Page 111: V6 unix in okinawa

swtch 1/3

2178: swtch()

2179: {

2180: static struct proc *p;

2181: register i, n;

2182: register struct proc *rp;

2183:

2184: if(p == NULL)

2185: p = &proc[0];

2186: /*

2187: * Remember stack of caller

2188: */

2189: savu(u.u_rsav); /* save r5,r6 when exchanging stacks */

2190: /*

2191: * Switch to scheduler's stack

2192: */

2193: retu(proc[0].p_addr); /* address of swappable image */

2012/3/24 111

Page 112: V6 unix in okinawa

swtch 2/3

2195: loop:

2196: runrun = 0;

2197: rp = p;

2198: p = NULL;

2199: n = 128;

2203: i = NPROC;

2204: do {

2205: rp++;

2206: if(rp >= &proc[NPROC])

2207: rp = &proc[0];

2208: if(rp->p_stat==SRUN && (rp->p_flag&SLOAD)!=0) {

2209: if(rp->p_pri < n) {

2210: p = rp;

2211: n = rp->p_pri;

2212: }

2213: }

2214: } while(--i); 2012/3/24 112

Page 113: V6 unix in okinawa

swtch 3/3

2223: rp = p;

2224: curpri = n;

2225: /* Switch to stack of the new process and set up

2226: * his segmentation registers.

2227: */

2228: retu(rp->p_addr); /* address of swappable image */

2229: sureg();

2247: return(1);

2012/3/24 113

Page 114: V6 unix in okinawa

あやしい関数

2189: savu(u.u_rsav); 今のプロセスのr5,r6をuに退避

2193: retu(proc[0].p_addr); uをproc0に

2228: retu(rp->p_addr); uを切り替えるプロセスに

2229: sureg(); uに退避してあるAPRをハードのARPに設定

2012/3/24 114

Page 115: V6 unix in okinawa

savu

0725: _savu:

0726: bis $340,PS

0727: mov (sp)+,r1

0728: mov (sp),r0

0729: mov sp,(r0)+

0730: mov r5,(r0)+

0731: bic $340,PS

0732: jmp (r1)

2012/3/24

bis $340,PSでbit5-7を1に bic $340,PSでbit5-7を0に

u.u_rsav

戻り先

725:

r6→ u.u_rsav

戻り先

727-728:

r6→

戻り先 r1

r0 u.u_rsav

729-730:

u. sp

r5

732:

戻り先 r1

115

Page 116: V6 unix in okinawa

retu

0740: _retu:

0741: bis $340,PS

0742: mov (sp)+,r1

0743: mov (sp),KISA6

0744: mov $_u,r0

0745: 1:

0746: mov (r0)+,sp

0747: mov (r0)+,r5

0748: bic $340,PS

0749: jmp (r1)

2012/3/24

p_addr

戻り先

742:

r6→ p_addr

戻り先

743-744:

r6→

戻り先 r1

r6→ APR0

APR1

APR2

APR3

APR4

APR5

p_addr

APR7

カーネル用

戻り先

r0 u.u_rsav

p_addr

746-747:

r1 戻り先

r0 u.u_rsav

r6→

0413 struct user 0414 { 0415 int u_rsav[2]/* save r5,r6 when exchanging stacks */

sp

r5

u.

sp

r5

r6

r5

116

Page 117: V6 unix in okinawa

sureg

1739: sureg()

1740: {

1741: register *up, *rp, a;

1742:

1743: a = u.u_procp->p_addr;

1744: up = &u.u_uisa[16];

1745: rp = &UISA->r[16];

1746: if(cputype == 40) {

1747: up =- 8;

1748: rp =- 8;

1749: }

1750: while(rp > &UISA->r[0])

1751: *--rp = *--up + a;

1754: up = &u.u_uisd[16];

1755: rp = &UISD->r[16];

1765: }

2012/3/24

APR0

APR1

APR2

APR3

APR4

APR5

APR6

APR7

アプリ用

u.u_uisa[0-7]

u.u_uisd[0-7] アプリの空間を設定

117

Page 118: V6 unix in okinawa

2012/3/24 118

Page 119: V6 unix in okinawa

勉強会の記録

日本Androidの会 沖縄支部 workshop@Naha Vol.17

http://atnd.org/events/25533

http://togetter.com/li/278270

横浜Androidプラットフォーム第19回勉強会

http://atnd.org/events/26444

http://togetter.com/li/281856

2012/3/24 119

Page 120: V6 unix in okinawa

付録2 よくわかんない人のための

2012/3/24 120

Page 121: V6 unix in okinawa

Simhのインストールと起動

Ubuntuの場合

$ sudo apt-get install simh

pdp-11のシュミレーション

$ pdp11

PDP-11 simulator V3.8-1

sim>

2012/3/24 121

Page 122: V6 unix in okinawa

Unix v6のダウンロード

simh用Diskイメージのアーカイブ

http://simh.trailing-edge.com/software.html

V6のイメージは以下

http://simh.trailing-edge.com/kits/uv6swre.zip

ダウンロード

$ wget http://simh.trailing-edge.com/kits/uv6swre.zip

2012/3/24 122

Page 123: V6 unix in okinawa

Diskイメージの展開

$ unzip uv6swre.zip

Archive: uv6swre.zip

inflating: README.txt

inflating: unix3_v6_rk.dsk

inflating: unix1_v6_rk.dsk

inflating: unix2_v6_rk.dsk

inflating: unix0_v6_rk.dsk

inflating: AncientUnix.pdf

$

2012/3/24 123

Page 124: V6 unix in okinawa

設定ファイルの作成

uv6swre.zipを展開したディレクトリで以下のファイルunixv6.cfを作成 $cat unixv6.cfg

set cpu 11/40

set cpu u18

att rk0 unix0_v6_rk.dsk

att rk1 unix1_v6_rk.dsk

att rk2 unix2_v6_rk.dsk

att rk3 unix3_v6_rk.dsk

boot rk0

$

2012/3/24 124

Page 125: V6 unix in okinawa

Simhの起動

$ pdp11 unixv6.cfg

PDP-11 simulator V3.8-1

Disabling XQ

@unix

Login: root

#

2012/3/24 125

Page 126: V6 unix in okinawa

Simhのdebug機能

simhモードへの移行と復帰

# Ctrl+E

Simulation stopped, PC: 021630 (MOV

(SP)+,177776)

sim> c

#

simhモードへはCtrl+Eで

シミュレーションモードへはcで

2012/3/24 126

Page 127: V6 unix in okinawa

ディバック機能を使う

カーネルのシンボルアドレスを調べる

# chdir /

# nm unix | grep savu

021636T _savu

#

savu()のアドレスは021636, breakpointを指定する

# Ctrl+E

Simulation stopped, PC: 021630 (MOV (SP)+,177776)

sim> break 021636

sim> c

Breakpoint, PC: 021636 (SPL 6)

sim>

2012/3/24 127

savu()で止まった

Page 128: V6 unix in okinawa

step実行

Breakpoint, PC: 021636 (SPL 6)

sim> e r5,sp,pc

R5: 141742

SP: 141730

PC: 021636

sim> s

Step expired, PC: 021640 (MOV (SP)+,R1)

sim> s

Step expired, PC: 021642 (MOV (SP),R0)

sim> s

Step expired, PC: 021644 (MOV SP,(R0)+)

sim> s

Step expired, PC: 021646 (MOV R5,(R0)+)

sim> s

Step expired, PC: 021650 (SPL 0)

sim> s

Step expired, PC: 021652 (JMP (R1))

2012/3/24 128

0725: _savu:

0726: bis $340,PS

0727: mov (sp)+,r1

0728: mov (sp),r0

0729: mov sp,(r0)+

0730: mov r5,(r0)+

0731: bic $340,PS

0732: jmp (r1)

Page 129: V6 unix in okinawa

レジスタの調べ方

/usr/share/doc/simh/simh_doc.pdfで説明

e {xamine} <list> examine memory or registers

sim> e state // レジスタ等すべてを表示

2012/3/24 129

PC: 021630

R0: 140004

R1: 034272

R2: 005336

R3: 000200

R4: 000000

R5: 141724

SP: 141710

R00: 140004

R01: 034272

R02: 005336

R03: 000200

R04: 000000

R05: 141724

R10: 000000

R11: 000000

R12: 000000

R13: 000000

R14: 000000

R15: 000000

KSP: 141710

SSP: 000000

USP: 177756

PSW: 030000

CM: 0

PM: 3

RS: 0

FPD: 0

IPL: 0

T: 0

N: 0

Z: 0

V: 0

C: 0

PIRQ: 000000

STKLIM: 000000

FAC0H: 00000000000

FAC0L: 00000000000

FAC1H: 00000000000

FAC1L: 00000000000

FAC2H: 00000000000

FAC2L: 00000000000

FAC3H: 00000000000

FAC3L: 00000000000

FAC4H: 00000000000

FAC4L: 00000000000

FAC5H: 00000000000

FAC5L: 00000000000

FPS: 000004

FEA: 000000

FEC: 00

MMR0: 000201

MMR1: 000000

MMR2: 021626

MMR3: 000005

KIPAR0: 000000

KIPDR0: 077406

KIPAR1: 000416

KIPDR1: 077506

KIPAR2: 000616

KIPDR2: 077506

KIPAR3: 001016

KIPDR3: 077506

KIPAR4: 001216

KIPDR4: 077406

KIPAR5: 001416

KIPDR5: 077406

KIPAR6: 001616

KIPDR6: 077406

KIPAR7: 007600

KIPDR7: 077506

KDPAR0: 000000

KDPDR0: 077506

KDPAR1: 000200

KDPDR1: 077506

KDPAR2: 000400

KDPDR2: 077506

KDPAR3: 000600

KDPDR3: 077406

KDPAR4: 001000

KDPDR4: 077406

KDPAR5: 001200

KDPDR5: 077406

KDPAR6: 001171

KDPDR6: 077506

KDPAR7: 007600

KDPDR7: 077506

SIPAR0: 003612

SIPDR0: 000106

SIPAR1: 003700

SIPDR1: 000106

SIPAR2: 000000

SIPDR2: 000000

SIPAR3: 000000

SIPDR3: 000000

SIPAR4: 000000

SIPDR4: 000000

SIPAR5: 000000

SIPDR5: 000000

SIPAR6: 000000

SIPDR6: 000000

SIPAR7: 000000

SIPDR7: 000000

SDPAR0: 000000

SDPDR0: 000000

SDPAR1: 000000

SDPDR1: 000000

SDPAR2: 000000

SDPDR2: 000000

SDPAR3: 000000

SDPDR3: 000000

SDPAR4: 000000

SDPDR4: 000000

SDPAR5: 000000

SDPDR5: 000000

SDPAR6: 000000

SDPDR6: 000000

SDPAR7: 000000

SDPDR7: 000000

UIPAR0: 001714

UIPDR0: 000006

UIPAR1: 000000

UIPDR1: 000000

UIPAR2: 000000

UIPDR2: 000000

UIPAR3: 000000

UIPDR3: 000000

UIPAR4: 000000

UIPDR4: 000000

UIPAR5: 000000

UIPDR5: 000000

UIPAR6: 000000

UIPDR6: 000000

UIPAR7: 001541

UIPDR7: 066016

UDPAR0: 001714

UDPDR0: 000006

UDPAR1: 000000

UDPDR1: 000000

UDPAR2: 000000

UDPDR2: 000000

UDPAR3: 000000

UDPDR3: 000000

UDPAR4: 000000

UDPDR4: 000000

UDPAR5: 000000

UDPDR5: 000000

UDPAR6: 000000

UDPDR6: 000000

UDPAR7: 001541

UDPDR7: 066016

IREQ[0]: 00000000000

TRAPS: 00000

WAIT: 1

STOP_TRAPS: 00001

STOP_VECA: 1

STOP_SPA: 1

PCQ[0]: 034412

WRU: 005

Page 130: V6 unix in okinawa

必要な内容に絞り込む

PC,R0~R5,SP(KSP,USP)

PSW

KDPAR0~7

UDPAR0~7

2012/3/24 130

PC: 021630

R0: 140004

R1: 034272

R2: 005336

R3: 000200

R4: 000000

R5: 141724

SP: 141710

R00: 140004

R01: 034272

R02: 005336

R03: 000200

R04: 000000

R05: 141724

R10: 000000

R11: 000000

R12: 000000

R13: 000000

R14: 000000

R15: 000000

KSP: 141710

SSP: 000000

USP: 177756

PSW: 030000

CM: 0

PM: 3

RS: 0

FPD: 0

IPL: 0

T: 0

N: 0

Z: 0

V: 0

C: 0

PIRQ: 000000

STKLIM: 000000

FAC0H: 00000000000

FAC0L: 00000000000

FAC1H: 00000000000

FAC1L: 00000000000

FAC2H: 00000000000

FAC2L: 00000000000

FAC3H: 00000000000

FAC3L: 00000000000

FAC4H: 00000000000

FAC4L: 00000000000

FAC5H: 00000000000

FAC5L: 00000000000

FPS: 000004

FEA: 000000

FEC: 00

MMR0: 000201

MMR1: 000000

MMR2: 021626

MMR3: 000005

KIPAR0: 000000

KIPDR0: 077406

KIPAR1: 000416

KIPDR1: 077506

KIPAR2: 000616

KIPDR2: 077506

KIPAR3: 001016

KIPDR3: 077506

KIPAR4: 001216

KIPDR4: 077406

KIPAR5: 001416

KIPDR5: 077406

KIPAR6: 001616

KIPDR6: 077406

KIPAR7: 007600

KIPDR7: 077506

KDPAR0: 000000

KDPDR0: 077506

KDPAR1: 000200

KDPDR1: 077506

KDPAR2: 000400

KDPDR2: 077506

KDPAR3: 000600

KDPDR3: 077406

KDPAR4: 001000

KDPDR4: 077406

KDPAR5: 001200

KDPDR5: 077406

KDPAR6: 001171

KDPDR6: 077506

KDPAR7: 007600

KDPDR7: 077506

SIPAR0: 003612

SIPDR0: 000106

SIPAR1: 003700

SIPDR1: 000106

SIPAR2: 000000

SIPDR2: 000000

SIPAR3: 000000

SIPDR3: 000000

SIPAR4: 000000

SIPDR4: 000000

SIPAR5: 000000

SIPDR5: 000000

SIPAR6: 000000

SIPDR6: 000000

SIPAR7: 000000

SIPDR7: 000000

SDPAR0: 000000

SDPDR0: 000000

SDPAR1: 000000

SDPDR1: 000000

SDPAR2: 000000

SDPDR2: 000000

SDPAR3: 000000

SDPDR3: 000000

SDPAR4: 000000

SDPDR4: 000000

SDPAR5: 000000

SDPDR5: 000000

SDPAR6: 000000

SDPDR6: 000000

SDPAR7: 000000

SDPDR7: 000000

UIPAR0: 001714

UIPDR0: 000006

UIPAR1: 000000

UIPDR1: 000000

UIPAR2: 000000

UIPDR2: 000000

UIPAR3: 000000

UIPDR3: 000000

UIPAR4: 000000

UIPDR4: 000000

UIPAR5: 000000

UIPDR5: 000000

UIPAR6: 000000

UIPDR6: 000000

UIPAR7: 001541

UIPDR7: 066016

UDPAR0: 001714

UDPDR0: 000006

UDPAR1: 000000

UDPDR1: 000000

UDPAR2: 000000

UDPDR2: 000000

UDPAR3: 000000

UDPDR3: 000000

UDPAR4: 000000

UDPDR4: 000000

UDPAR5: 000000

UDPDR5: 000000

UDPAR6: 000000

UDPDR6: 000000

UDPAR7: 001541

UDPDR7: 066016

IREQ[0]: 00000000000

TRAPS: 00000

WAIT: 1

STOP_TRAPS: 00001

STOP_VECA: 1

STOP_SPA: 1

PCQ[0]: 034412

WRU: 005

Page 131: V6 unix in okinawa

レジスタの指定方法

Stateの表示順に’-’で範囲を指定

sim> e pc-sp

PC: 021630

R0: 140004

R1: 034272

R2: 005336

R3: 000200

R4: 000000

R5: 141724

SP: 141710

2012/3/24 131

Page 132: V6 unix in okinawa

MMUレジスタの指定方法

Stateの表示順に’-’で範囲を指定

sim> e KDPAR0-KDPDR7

KDPAR0: 000000

KDPDR0: 077506

KDPAR1: 000200

KDPDR1: 077506

KDPAR2: 000400

KDPDR2: 077506

KDPAR3: 000600

KDPDR3: 077406

KDPAR4: 001000

KDPDR4: 077406

KDPAR5: 001200

KDPDR5: 077406

KDPAR6: 001171

KDPDR6: 077506

KDPAR7: 007600

KDPDR7: 077506

2012/3/24 132

Pdp11/40では、KPAR,KPDRと呼んでいたが、simhでは上位機種のレジスタ名で表示されるので、KDPAR,KDPDR

と読み替える

Page 133: V6 unix in okinawa

メモリの調べ方

sim> e 0 // アドレス0を表示

0: 000417

sim> e 0/4 // アドレス0から4バイトを表示

0: 000417

2: 000004

sim> e 0-2 // アドレス0から2までを表示

0: 000417

2: 000004

2012/3/24 133

Page 134: V6 unix in okinawa

表示フォーマットの指定

-a ASCIIで表示

-c 文字列で表示

-m 命令列で表示

-o 8進で表示

-x 16進で表示

sim> e -m 54104/20

54104: 000013

54106: MOV R0,-(SP)

54110: BIC #177400,(SP)

54114: JSR PC,@#22100

54120: ADD #6,SP

2012/3/24 134

Page 135: V6 unix in okinawa

シンボルからアドレスを調べる

sim> c //unixに戻る

# nm /unix | grep main // mainのアドレス

022272T _main

# nm /unix | grep proc

034476T _newproc

005206B _proc

043170T _procxmt

2012/3/24 135

Page 136: V6 unix in okinawa

mainでbreakしてMMUを調べる

sim> break 022272

sim> boot rk0

@unix

Breakpoint, PC: 022272 (JSR R5,22240)

sim> e KDPAR0-KDPDR7

KDPAR0: 000000

KDPDR0: 077506

KDPAR1: 000200

KDPDR1: 077506

KDPAR2: 000400

KDPDR2: 077506

KDPAR3: 000600

KDPDR3: 077406

KDPAR4: 001000

KDPDR4: 077406

KDPAR5: 001200

KDPDR5: 077406

KDPAR6: 001171

KDPDR6: 077506

KDPAR7: 007600

KDPDR7: 077506

sim>

2012/3/24 136

Page 137: V6 unix in okinawa

自分のprocを見る#1

# nm /unix | grep _write

054124T _write

031700T _writei

050176T _writep

#

Simulation stopped, PC: 021630 (MOV (SP)+,177776)

sim> break 54124

sim> c

[Enter]

Breakpoint, PC: 054124 (JSR R5,22240)

sim>

2012/3/24 137

Shellが#をwriteする箇所(カーネルのエントリ)でbreakする

Page 138: V6 unix in okinawa

自分のprocを見る#2

procのアドレスはu.u_procpでわかる

uは常にカーネル仮想の140000番地

一方でsimhのdebug機能は仮想アドレスを扱えない

自分で変換する

sim> e KDPAR6

KDPAR6: 001477 // 64バイトを1単位とした値

64バイト=6ビットシフト=8進数で00

Userは00147700にあるはず

2012/3/24 138

Page 139: V6 unix in okinawa

自分のprocを見る#3

sim> e 147700/100

147700: 141746 u_rsav[0]

147702: 141756 u_rsav[1]

147704: 000200 u_fsav[0]

147706: 000000 1

147710: 000000 2

147712: 000000 3

147714: 000000 4

147716: 000000 5

:

:

147764: 000000 24

147766: 000000 u_segflag/u_error

147770: 001400 u_uid/u_gid

147772: 001400 u_ruid/u_rgid

147774: 005262 u_procp

147776: 177737

2012/3/24 139

0413: struct user

0414: {

0415: int u_rsav[2]; /* save r5,r6 when exchanging stacks */

0416: int u_fsav[25]; /* save fp registers */

0417: /* rsav and fsav must be first in structure */

0418: char u_segflg; /* flag for IO; user or kernel space */

0419: char u_error; /* return error code */

0420: char u_uid; /* effective user id */

0421: char u_gid; /* effective group id */

0422: char u_ruid; /* real user id */

0423: char u_rgid; /* real group id */

0424: int u_procp; /* pointer to proc structure */

Page 140: V6 unix in okinawa

自分のprocを見る#4

sim> e -h 5262/40

5262: 0103 p_flag/p_stat

5264: 0064 p_sig/p_pri

5266: 7F00 p_time/p_uid

5270: 0000 p_cpu

5272: 42F2 p_ttyp

5274: 000E p_pid

5276: 0001 p_ppid

5300: 033F

5302: 0048

5304: 0000

5306: 0EDC

5310: 0000

5312: 00CE

5314: 0000

5316: 0000

5320: 0000

2012/3/24 140

0358: struct proc

0359: {

0360: char p_stat;

0361: char p_flag;

0362: char p_pri; /* priority, negative is high */

0363: char p_sig; /* signal number sent to this process */

0364: char p_uid; /* user id, used to direct tty signals */

0365: char p_time; /* resident time for scheduling */

0366: char p_cpu; /* cpu usage for scheduling */

0367: char p_nice; /* nice for scheduling */

0368: int p_ttyp; /* controlling tty */

0369: int p_pid; /* unique process id */

0370: int p_ppid; /* process id of parent */

0371: int p_addr; /* address of swappable image */

0372: int p_size; /* size of swappable image (*64 bytes) */

0373: int p_wchan; /* event process is awaiting */

0374: int *p_textp; /* pointer to text structure */

0375:

0376: } proc[NPROC]; pidは0xe=14(10進)

Page 141: V6 unix in okinawa

自分のprocを見る#5

Breakpoint, PC: 054104 (JSR R5,22240)

sim> nobreak 54104

sim> c

# ps

14 -

29 ps

#

2012/3/24 141

pidは0xe=14(10進)

Page 142: V6 unix in okinawa

だらだらつづくよ

2012/3/24 142