SlideShare una empresa de Scribd logo
1 de 142
Descargar para leer sin conexión
オペ―レーティングシステムの読み書き
                                             Rev.2.1
                                      @magoroku15
                                        2012/3/24
 日本Androidの会 沖縄支部 workshop@Naha Vol.17 - v6 unix 勉強会
2012/3/24                                              1
他人の作品を読まなかった偉
            大な作家,他人の筆づかいを
            研究しなかった偉大な画家,
            同僚の肩越しに技を盗まな
            かった腕のよい外科医,副操
            縦席で実地の経験を積まな
            かった767機長――果たして,
            そんな人たちが本当にいるの
            でしょうか?
      Dave Thomas著   Code Reading―オープンソースから学ぶソフトウェア開発技法 より

2012/3/24                                                2
最底辺活動
     Lions本読書会に出てみた
        本だけで読み解くのは大変
        若干の解説を加えれば理解できる人は増えるはず
        拙者のネタとしてGeekBarなどで話すことにした
        これを最底辺活動と言っている
         ○ 他にもFPGAでPDP11を動かしたり、PICで遊んだり

     UNIX v6を読む理由
        最新のBSD, Linuxと実装は異なるが根幹は同じ
        UNIX v6を読む事が現代のOSを理解する近道(だと
            思う)
2012/3/24                                 3
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
お勧めの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
@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
教材
     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
ウォームアップ
     OSの領域はプログラマにとっての最底辺部
        アプリケーションプログラマ
            ○ 提供されるAPIを利用して、一般向けのサービス等を提供する人
        システムプログラマ
            ○ ハードウェアの機能を利用して、API等プログラマ向け機能を提供
              する人
        必要とされる前提知識が異なる
        命令レベルで計算機を(ぼんやりと)理解する必要あり
     アプリケーションプログラマ向けの準備運動
        Lions本
            ○ 第2章 Fundamentals (PDFだとP4)
              命令セット
            ○ 第9章 Hardware Interrupt and Traps (PDFのP42)
              割り込み
        PDP-11 Processor Handbook


2012/3/24                                                  8
Lions本 2章




2012/3/24     9
システムプログラマから見た
計算機の構成要素
     CPU
        レジスタ
         ○ 汎用レジスタ      一般の演算命令に使用
         ○ スタックポインタ    スタックの先頭位置
         ○ プログラムカウンタ   次に処理する命令の位置
        フラグレジスタ       演算結果の一部を記憶
        制御/状態レジスタ
 Memory
 外部記憶

2012/3/24                            10
PDP-11/40
     レジスタ
           16bitのレジスタが8個
           r0-r7
           r6はspスタックポインタ
           r7はpcプログラムカウンタ
     Processor Status Word
        フラグレジスタ+状態レジスタ
     memory
        仮想アドレス幅は16bit        最大 64kbyte
        物理アドレス幅は18bit        最大 256kbyte

2012/3/24                                   11
レジスタ r0-r7
r0, r1
   演算結果の一時的な保持、復帰値など
r2, r3, r4
   関数内のローカル変数。呼ばれた関数で退避し、
   関数の終了時に復元
R5
   フレームポインタ
r6 (sp)
   スタックポインタ
r7 (pc)
   実行する命令の位置(アドレス)
2012/3/24               12
Processor Status Word (PSW)




            14-15   現在のモード (00 = kernel 11 = user)
            12-13   以前のモード
            5-7     プロセッサの優先度 (0~7)
            4       トラップビット
            3N      演算結果が負
            2Z      演算結果が0
            1V      演算結果がオーバフロー
            0C      演算結果がキャリー
2012/3/24                                            13
CPUの処理
   以下を繰り返す
  1. PCの示す位置(アドレス)から命令を読み込む
  2. 解析して
  3. 実行
  4. 実行の副作用として以下の事象が発生する
        PSWを書き換え
        PCを書き換え
        レジスタの書き換え
        メモリの内容を書き換えたりする

2012/3/24                  14
CPUの処理 誤解しやすい点
       PCもレジスタの一種
        PC(r7)を書き換えると処理がジャンプ
     比較と分岐は別命令




2012/3/24                       15
UNIXカーネルを理解するための




2012/3/24            16
C言語の空間モデル
     Text                 text
        命令列の格納領域
        書き換え禁止            data
     Data                 bss
        非0で初期化されたデータ領域
     Bss
        0で初期化されたデータ領域
     Stack
        自動(auto)変数の格納領域
        関数呼び出し時のレジスタ退避域   stack

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

2012/3/24                          17
変数の宣言と空間配置
int i;                // Bss     a.out形式    実行時
                                 (ファイル)    (メモリ)
Int j = 1;            // Data
                                 header
main()                            text     text
{
                                  data     data
  static int k = 1;   // Data
  int l = 1;          // Stack              bss
  int m;              // Stack
  :
}



                                           stack
2012/3/24                                          18
関数呼び出しとスタック 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
関数とスタック namelist
# nm -n a.out            000170T   cret 0x78
000000a 0x00    crt0.o   000206B   _c
000000t         start    000210B   _d
000004a         a        000212B   savr5
000006a         b        177764a   r
000030T 0x18    _main    177766a   f
000030a         src.o    177770a   e
000030t         ~main
000102T 0x42    _func
000102t         ~func
000140T 0x60    _exit
000140a         exit.o
000152T 0x6a    csv
000152a         csv.o

2012/3/24                                      20
関数呼び出しとスタック ASM
.globl _main                      .comm _c,2
.text                             .globl _d
          _main:                  .comm _d,2
          ~~main:                 .globl _func
          ~e=177770               .text
          ~f=177766                         _func:
          ~r=177764                         ~~func:
          jsr     r5,csv                    ~a=4
          sub     $6,sp                     ~b=6
          mov     $1,-10(r5)                jsr        r5,csv
          mov     $2,-12(r5)                mov        4(r5),_c
          mov     -12(r5),(sp)              mov        6(r5),_d
          mov     -10(r5),-(sp)             mov        _c,r0
          jsr     pc,*$_func                add        _d,r0
          tst     (sp)+                     jbr        L2
          mov     r0,-14(r5)      L2:       jmp cret
L1:       jmp     cret            .globl
.globl _c                         .data

2012/3/24                                                         21
csv 関数の入り口
Main:                    csv:
         :                      mov    r5,r0
        jsr   r5,csv            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
2012/3/24
                                                      jmp (r0)       22
cret 関数の出口
 main:                     cret:
     :                             mov    r5,r1
 jmp         cret                  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
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
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
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

                  #15          #16-17         #18          #19         #20
  0x046a                                                         r6→   0x0038
  0x046c                                             r6→    1             1
  0x046e    r6→          r6→            r6→    2            2             2
  0x0470
  0x0472                         2             2            2             2
  0x0474    r6→                  1             1            1             1
  0x0476
  0x0478
  0x047a
  0x047c    r5→          r5→            r5→          r5→         r5→
2012/3/24                                                                       26
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
                   #21             #23           #24-26           #27
  0x045a
  0x045c
  0x045e
  0x0460                                                   r6→
  0x0462                                   r6→      r2             r2
  0x0464                                            r3             r3
  0x0466                                            r4             r4
  0x0468    r6→   0x047c   r5,r6→ 0x047c   r5→    0x047c   r5→   0x047c
  0x046a    r6→   0x0038          0x0038          0x0038         0x0038
  0x046c
2012/3/24                                                                        27
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
                  #27-34           #35           #36-38           #39         #40-41
  0x045a
  0x045c
  0x045e
  0x0460    r6→             r6→            r6→
  0x0462          r2                r2     r1→   r2
  0x0464          r3                r3           r3
  0x0466          r4                r4           r4
  0x0468    r5→ 0x047c     r5,r1→ 0x047c   r5→ 0x047c     r5,r6→ 0x047c   r6→ 0x047c
  0x046a        0x0038            0x0038       0x0038            0x0038   r6→ 0x0038
  0x046c                                                                  r6→
2012/3/24                                                                                28
関数とスタック
 今のスタックr6:SP
 前のスタックr5
 r5:r6のペアでチェーン
                  #20             #21           #27
  0x0460                                  r6→
  0x0462                                          r2
  0x0464                                          r3
  0x0466                                          r4
  0x0468                   r6→   0x047c   r5→   0x047c
  0x046a          0x0038         0x0038         0x0038
  0x046c             1
  0x046e             2
  0x0470
  0x0472            2
  0x0474            1
  0x0476
  0x0478
  0x047a
  0x047c    r5→
2012/3/24                                                29
レジスタ r0-r7 もう一度
r0, r1
   演算結果の一時的な保持、復帰値など
r2, r3, r4
   関数内のローカル変数。呼ばれた関数で退避し、
   関数の終了時に復元
R5
   フレームポインタ
r6 (sp)
   スタックポインタ
r7 (pc)
   実行する命令の位置(アドレス)
2012/3/24               30
C言語とasmの実行環境
 asmから生成した命令列はスタックを必要と
  しない
 C言語から生成した命令列は、実行時にス
  タックを必要とする
        引数の受け渡し利用領域
        自動変数の領域
        呼び出し元レジスタ(r2,r3,r4)の退避領域
        呼び出し先からの復帰アドレスの退避領域



2012/3/24                           31
UNIXカーネルを理解するための




2012/3/24            32
getpid(2)の呼び出し C言語
main()
{
    int i;
    i = getpid();
}




2012/3/24            33
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
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
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
open(2)の呼び出し C言語
main()
{
    int f;
    f = open("hoge", 2);
}




2012/3/24                  37
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
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
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
システムコールとライブラリコール
     ライブラリ
        マニュアルセクション3
        例 fopen(3)
        ユーザプログラムの空間で動作
        必要に応じてシステムコールを呼び出す
     システムコール
        マニュアルセクション2
        例 open(2)
        OS内部の処理を呼び出す
        呼出し方法は通常のCall/Returnとは異なる
2012/3/24                            41
OSを実装するための




2012/3/24      42
Q:CPUが想定外の状態になると
     たとえば以下の場合
        不正なアドレスを参照した
        未定義の命令を実行しようとした
        0で割り算した


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




2012/3/24                  43
A: わな “Trap”を用意しておく
 CPUが身動きが取れなかった場合に次に命令
  を取り出す場所を“わな”として仕掛けてお
  く
 システムコールの呼び出しは特殊な「わな」
 「わな」はCPUの処理過程に実行時の例外と
  して発生する
 「わな」に引っかかる事を「例外」と呼ぶ




2012/3/24                 44
例外と割り込み
 Lions本9章
 Trap/例外
        命令の実行に失敗した場合の「わな」仕掛ける
        システムコールの呼び出しは特殊な「わな」
        「わな」はCPUの処理過程で発生する
     Interrupt/割り込み
        CPUの処理に関係なく、外部からの「割り込み」
        主に、外部装置の処理完了時に「割り込む」
        外部装置の例
         ○ テレタイプ、紙テープ、ラインプリンタ、磁気ディ
           スク、時計
2012/3/24                            45
2012/3/24   46
例外の流れ
1.      例外/割り込みの発生
2.      コンテキストの保存
     ① PCとPSWをCPU内部に一時的に保存
     ② 発生の要因を特定し、要因:アドレスの表(ベクター)を
       検索
     ③ ベクターをPCに設定
     ④ 一時的に保存していたPC,PSWをカーネルスタックに
       退避(push)
3.      ハンドラの実行
4.      コンテキストの復元
     ① カーネルスタックにPC,PSWが格納されている状態で
       rtt命令を実行
     ② rtt命令がカーネルスタックからPC,PSWを復元(pop)
5.      割り込み発生の次の命令を実行

2012/3/24                               47
例外ベクタ
        Vector
                                    Trap type      Priority
       Location
            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
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
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
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
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
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
システムコール番号
indir = 0.
exit = 1.
fork = 2.
read = 3.
write = 4.
open = 5.
close = 6.
wait = 7.
creat = 8.
   :
   :
2012/3/24    54
システムコール呼出し処理
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
2012/3/24   56
割り込みベクタ
 Vector
                                 device   priority
   Location
            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
Teletype ?




2012/3/24    58
Paper tape ?




2012/3/24      59
Clocks – line and programmable
     Line Clock
        電源の周期から生成
        AC>降圧(トランス)>整流(ダイオード)>コンデンサ
        電源周波数のパルスを取り出せる
        50HZで20ms間隔
        昔の電気式デジタル時計はパルスxHZで1秒を生成
 Programmable     clock
        指定の間隔でパルスを発生
 PDP-11ではどちらかが必要

2012/3/24                          60
525 low.s
0525:       . = 60^.          Vector          device        entry
0526:             klin; br4
0527:             klou; br4     060    Teletype input       klin
0528:
0529:       . = 70^.            064    Teletype output      klou
0530:             pcin; br4
0531:             pcou; br4
                                070    Paper tape input     pcin
0532:                           074    Paper tape output    pcou
0533:       . = 100^.
0534:             kwlp; br6     100    Line clock           kwlp
0535:             kwlp; br6
0539:
                                104    Programmable clock   kwlp
0540:       . = 200^.
0541:             lpou; br4     200    Line printer         lpou
0542:
0543:       . = 220^.           220    RK disk driver       rkio
0544:             rkio; br5
2012/3/24                                                           61
Line Clock
     外部にあるclockから毎秒50個のパルスがCPUに
      入る
     1パルス毎に割り込みベクタの処理を実行


       Clock

                      CPU

2012/3/24                          62
kwlp low.s
0568:
0569: .globl _clock
0570: kwlp: jsr r0,call; _clock

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




2012/3/24                         63
clock
3725: clock(dev, sp, r1, nps, r0, pc, ps)          3761:                                                           3797:     if(++lbolt >= HZ) {
3726: {                                            3762:      /*                                                   3798:           if((ps&0340) != 0)
3727:      register struct callo *p1, *p2;         3763:       * callout                                           3799:                  return;
3728:      register struct proc *pp;               3764:       */                                                  3800:           lbolt =- HZ;
3729:                                              3765:                                                           3801:           if(++time[1] == 0)
3730:      /*                                      3766:      spl5();                                              3802:                  ++time[0];
3731:       * restart clock                        3767:      if(callout[0].c_time <= 0) {                         3803:           spl1();
3732:       */                                     3768:             p1 = &callout[0];                             3804:           if(time[1]==tout[1] && time[0]==tout[0])
3733:                                              3769:             while(p1->c_func != 0 && p1->c_time <= 0) {   3805:                  wakeup(tout);
3734:      *lks = 0115;                            3770:                   (*p1->c_func)(p1->c_arg);               3806:           if((time[1]&03) == 0) {
3735:                                              3771:                   p1++;                                   3807:                  runrun++;
3736:      /*                                      3772:             }                                             3808:                  wakeup(&lbolt);
3737:       * display register                     3773:             p2 = &callout[0];                             3809:           }
3738:       */                                     3774:             while(p2->c_func = p1->c_func) {              3810:           for(pp = &proc[0]; pp < &proc[NPROC]; pp++)
3739:                                              3775:                   p2->c_time = p1->c_time;                3811:           if (pp->p_stat) {
3740:      display();                              3776:                   p2->c_arg = p1->c_arg;                  3812:                  if(pp->p_time != 127)
3741:                                              3777:                   p1++;                                   3813:                         pp->p_time++;
3742:      /*                                      3778:                   p2++;                                   3814:                  if((pp->p_cpu & 0377) > SCHMAG)
3743:       * callouts                             3779:             }                                             3815:                         pp->p_cpu =- SCHMAG; else
3744:       * if none, just return                 3780:      }                                                    3816:                         pp->p_cpu = 0;
3745:       * else update first non-zero time      3781:                                                           3817:                  if(pp->p_pri > PUSER)
3746:       */                                     3782:      /*                                                   3818:                         setpri(pp);
3747:                                              3783:       * lightning bolt time-out                           3819:           }
3748:      if(callout[0].c_func == 0)              3784:       * and time of day                                   3820:           if(runin!=0) {
3749:             goto out;                        3785:       */                                                  3821:                  runin = 0;
3750:      p2 = &callout[0];                       3786:                                                           3822:                  wakeup(&runin);
3751:      while(p2->c_time<=0 && p2->c_func!=0)   3787: out:                                                      3823:           }
3752:             p2++;                            3788:      if((ps&UMODE) == UMODE) {                            3824:           if((ps&UMODE) == UMODE) {
3753:      p2->c_time--;                           3789:             u.u_utime++;                                  3825:                  u.u_ar0 = &r0;
3754:                                              3790:             if(u.u_prof[3])                               3826:                  if(issig())
3755:      /*                                      3791:                   incupc(pc, u.u_prof);                   3827:                         psig();
3756:       * if ps is high, just return           3792:      } else                                               3828:                  setpri(u.u_procp);
3757:       */                                     3793:             u.u_stime++;                                  3829:           }
3758:                                              3794:      pp = u.u_procp;                                      3830:     }
3759:      if((ps&0340) != 0)                      3795:      if(++pp->p_cpu == 0)                                 3831: }
3760:             goto out;                        3796:             pp->p_cpu--;

   2012/3/24                                                                                                                                                              64
clock
3725: clock(dev, sp, r1, nps, r0, pc, ps)          3761:                                                           3797:     if(++lbolt >= HZ) {
3726: {                                            3762:      /*                                                   3798:           if((ps&0340) != 0)
3727:      register struct callo *p1, *p2;         3763:       * callout                                           3799:                  return;
3728:      register struct proc *pp;               3764:       */                                                  3800:           lbolt =- HZ;
3729:                                              3765:                                                           3801:           if(++time[1] == 0)
3730:      /*                                      3766:      spl5();                                              3802:                  ++time[0];
3731:       * restart clock                        3767:      if(callout[0].c_time <= 0) {                         3803:           spl1();
3732:       */                                     3768:             p1 = &callout[0];                             3804:           if(time[1]==tout[1] && time[0]==tout[0])
3733:                                              3769:             while(p1->c_func != 0 && p1->c_time <= 0) {   3805:                  wakeup(tout);
3734:      *lks = 0115;                            3770:                   (*p1->c_func)(p1->c_arg);               3806:           if((time[1]&03) == 0) {
3735:                                              3771:                   p1++;                                   3807:                  runrun++;




                               Callout
3736:      /*                                      3772:             }                                             3808:                  wakeup(&lbolt);
3737:       * display register                     3773:             p2 = &callout[0];                             3809:           }
3738:       */                                     3774:             while(p2->c_func = p1->c_func) {              3810:           for(pp = &proc[0]; pp < &proc[NPROC]; pp++)
3739:                                              3775:                   p2->c_time = p1->c_time;                3811:           if (pp->p_stat) {




                                                                                                                             Sched
3740:      display();                              3776:                   p2->c_arg = p1->c_arg;                  3812:                  if(pp->p_time != 127)
3741:                                              3777:                   p1++;                                   3813:                         pp->p_time++;
3742:      /*                                      3778:                   p2++;                                   3814:                  if((pp->p_cpu & 0377) > SCHMAG)
3743:       * callouts                             3779:             }                                             3815:                         pp->p_cpu =- SCHMAG; else
3744:       * if none, just return                 3780:      }                                                    3816:                         pp->p_cpu = 0;
3745:       * else update first non-zero time      3781:                                                           3817:                  if(pp->p_pri > PUSER)




                                                                                                                             の入り口
3746:       */                                     3782:      /*                                                   3818:                         setpri(pp);
3747:                                              3783:       * lightning bolt time-out                           3819:           }
3748:      if(callout[0].c_func == 0)              3784:       * and time of day                                   3820:           if(runin!=0) {
3749:             goto out;                        3785:       */                                                  3821:                  runin = 0;
3750:      p2 = &callout[0];                       3786:                                                           3822:                  wakeup(&runin);




                                                                Acct
3751:      while(p2->c_time<=0 && p2->c_func!=0)   3787: out:                                                      3823:           }
3752:             p2++;                            3788:      if((ps&UMODE) == UMODE) {                            3824:           if((ps&UMODE) == UMODE) {
3753:      p2->c_time--;                           3789:             u.u_utime++;                                  3825:                  u.u_ar0 = &r0;
3754:                                              3790:             if(u.u_prof[3])                               3826:                  if(issig())
3755:      /*                                      3791:                   incupc(pc, u.u_prof);                   3827:                         psig();
3756:       * if ps is high, just return           3792:      } else                                               3828:                  setpri(u.u_procp);
3757:       */                                     3793:             u.u_stime++;                                  3829:           }
3758:                                              3794:      pp = u.u_procp;                                      3830:     }
3759:      if((ps&0340) != 0)                      3795:      if(++pp->p_cpu == 0)                                 3831: }
3760:             goto out;                        3796:             pp->p_cpu--;

   2012/3/24                                                                                                                                                              65
謎の変数
 u.u_time
 u.u_stime
 pp->p_time
 lbolt
 time[2]
 tout[2]




2012/3/24      66
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
clock callout (1/2)
                                           先頭のcalloutが未
3748:       if(callout[0].c_func == 0)
                                           登録なら、後続の
3749:              goto out;
3750:       p2 = &callout[0];
                                           calloutも未登録と
                                            判断して,Callout
                                            処理をスキップ

3751:       while(p2->c_time<=0 && p2->c_func!=0)
3752:             p2++;                           最初にc_timeが0
3753:       p2->c_time--;                       より大きいCallout
3758:                                        を見つけて、
3759:       if((ps&0340) != 0)                 c_timeを-1
3760:             goto out;
                                             ここより前の
3761:
                                           calloutはこの後処
                                                理される

2012/3/24                                                       68
clock callout (2/2)                            先頭に登録時間が
                                               過ぎているcallout
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;     Callout配列を詰め
3776:                    p2->c_arg = p1->c_arg;                る
3777:                    p1++;
3778:                    p2++;
3779:              }
3780:       }

2012/3/24                                                       69
clock acct
                                                  USERモードから
3787: out:                                        割り込まれたら、
3788:        if((ps&UMODE) == UMODE) {              uのuser時間
3789:              u.u_utime++;                    u_utimeを+1
3790:              if(u.u_prof[3])
3791:                     incupc(pc, u.u_prof);   KERNELモードか
3792:        } else                               ら割り込まれたら、
3793:              u.u_stime++;                    uのsystem時間
                                                    u_stimeを+1
3794:        pp = u.u_procp;
3795:        if(++pp->p_cpu == 0)
                                                  Procのp_cpuを加
3796:              pp->p_cpu--;                   算。オーバフロー
                                                  しないように調整
ppはproc構造のポインタ、uはuser構造。共
にプロセスの管理構造1プロセスに1個づつ
2012/3/24                                                        70
clock schedの入り口(1/2)
                                       clockが呼ばれると、ここまでは必
3797:        if(++lbolt >= HZ) {
                                                ず実行。lboltを+1して、HZ(50)を
3798:              if((ps&0340) != 0)
3799:                     return;
                                                超過したら、すなわち1秒経過し
3800:              lbolt =- HZ;
                                                たら、
3801:              if(++time[1] == 0)
3802:                     ++time[0];           lboltをリセット
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:              }                           4秒ごとにlboltで待ってるプロセ
                                       スを起こす


            今回はさらりと流す
2012/3/24                                                           71
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) p_statに値が入っている=プロ
 3815:                        pp->p_cpu =- SCHMAG; elseセスが存在したら、p_timeを
 3816:                        pp->p_cpu = 0;           +1
 3817:                 if(pp->p_pri > PUSER)
 3818:                        setpri(pp);
 3819:          }
 3820:          if(runin!=0) {
 3821:                 runin = 0;
 3822:                 wakeup(&runin);
                                                       runinが真なら、runinで待って
 3823:          }                                      るプロセスをwakeup
 3824:          if((ps&UMODE) == UMODE) {
 3825:                 u.u_ar0 = &r0;
 3826:                 if(issig())
 3827:                        psig();
 3828:                 setpri(u.u_procp);
 3829:          }
 3830:
2012/3/24   }                                                                72
謎の変数 回答
 u.u_time     USER時間
 u.u_stime    SYSTEM時間
 pp->p_time   プロセス起動からの時間
 lbolt        毎秒60回++
 time[2]      1970年からの秒
 tout[2]      sleep(2)が起きる時間




2012/3/24                       73
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
2012/3/24   75
a.outと空間の関係                                        CPU
                                                     PC
                        a.out

                       header               text

                         text               data

                        data
                                  exec(2)   bss           ・関数を呼
                                                          び出すと自
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                     stack         ジスタの内
3083   */                                                 容を退避。

  2012/3/24                                                   76
例外/割り込みが起こると……..
                                     •PSWのモードがユーザモー
                    CPU
                     PC              ドからカーネルモードに変わ
                                     り、空間が切り替わる。
                ①          ②
                                     •事象に応じて、ベクター
                                     テーブルの値がPCに書き込
         text             ③ text
           A                         まれる。
        data                data     •例外/割り込み発生時のPSW
                                     とPC(図中A)をスタックに
                                     pushする
         bss                   bss


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


                                        アプリケーションと
       stack                stack          カーネル
                                         2つの空間??
 2012/3/24                                             77
仮想アドレスと物理アドレス
     現在の一般的な仮想記憶
        仮想アドレス>物理アドレス
        仮想メモリ量>物理メモリ量
        実メモリ不足時は固定長(ページ)単位で2次記憶に退避
            し必要時に復元
            →ページング
     PDP-11の仮想記憶
        仮想アドレス<物理アドレス
        仮想メモリ量<物理メモリ量
        実メモリ不足時はプロセス全体を2次記憶に退避し実行
            を抑止、一定時間経過後に全体を復元し実行可能に
            →スワッピング
2012/3/24                             78
仮想記憶のための仕組み
 ハードウェアのサポートが必要
 仮想アドレス→物理アドレスの変換機構


            CPU            memory


                  変換機構なし



            CPU   変換表      memory


                  変換機構あり

2012/3/24                           79
アドレス変換機構の制御
 リセット後は変換機構OFFで動作
 OSの初期化時にプログラムで
       1. 変換表を初期化
       2. 変換機構をON
           新しいプロセスの生成とメモリ獲得時に
           OSが変換表を編集
           プロセスの切り替え時に
           変換表を入れ替え


2012/3/24                        80
PDP-11/40のメモリ管理機構
 8個のカーネルモードページ
 8個のユーザモードページ
 1ページは最大8Kbyteの可変長
 モード切り替えはPSWのモードに連動




2012/3/24              81
Active Page Registers (APR)




2012/3/24                     82
APR- PARとPDRのペア



            PAR ベースアドレスを指定




            PDR メモリ属性を指定




2012/3/24                    83
仮想記憶の有効化




     bit0 ENABLE MANAGEMENTを1で有効




2012/3/24                           84
重要なアドレス m40.s
  USIZE     =   16       Size of User Block (*64 = 1024 B)
  PS        =   177776   Program Status Word
  SSR0      =   177572   Status Register
  KISA0     =   172340   Kernel Segment Address Register #0
  KISA6     =   172354   Kernel Segment Address Register #6
  KISD0     =   172300   Kernel Segment Descriptor Register #0
  UISA0     =   177640   User Segment Address Register #0
  UISA1     =   177642   User Segment Address Register #1
  UISD0     =   177600   User Segment Descriptor Register #0
  UISD1     =   177602   User Segment Descriptor Register #1
  IO        =   7600     I/O Segment Register




2012/3/24                                                        85
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
ユーザ空間の初期化 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
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
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
最初のプロセスを生成
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
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,
                                                          char* init = “/etc/init”;
1521:      0000777,         /* br . */
1522:      0000014,         /* initp: init; 0 */          main( ) {
1523:      0000000,                                                 execl( init, init, 0 );
1524:      0062457,         /* init: </etc/init¥0> */               while( 1 ) ;
1525:      0061564,
1526:      0064457,
                                                          }
1527:      0064556,
1528:      0000164,
1529: };




2012/3/24                                                                                     91
Bootと空間の初期化
Boot直後       仮想記憶有効    最初のnewproc     最初のexec       Initの実行
 text          text    text           text          text
 data          data    data           data          data
               bss     bss            bss           bss

                u      user   user    user   user   user   user

              IOレジスタ   IOレジスタ         IOレジスタ        IOレジスタ


                              icode          exec          text
                                                           data
                                                           bss

                                                           stack


 2012/3/24                                                         92
Unixの空間モデル
     アプリとカーネルのアドレス域は分離
        後に完全な仮想記憶サポートで少し変わる
        各アプリケーションの空間は独立
     カーネルの空間は
        Text,Data,Bssは一部を除いて共有
        Stackはアプリ毎に個別
        Stackはstruct userのページの後半




2012/3/24                           93
UNIXカーネルの構造




2012/3/24       94
PPDA - Per Processor Data Area
 OSを読み解く場合に最初に注目する構造
 プロセスなどの実行単位毎に割り当てる領域
 UNIXの場合はuserとproc




2012/3/24                        95
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
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
空間の切り替え機構
                       CPU
                       PC
アプリケーション                             カーネル
                       PSW
                       00: カーネルモード
         text          11: ユーザモード
                                        text

        data    11用          00用        data
                APR0         APR0
                APR1         APR1
         bss    APR2         APR2       bss
                APR3         APR3
                APR4         APR4
                APR5         APR5
                APR6         APR6    struct user
       stack    APR7         APR7
                                       stack



                                     I/Oレジスタ
 2012/3/24                                         98
アプリケーションの動作時
             PSW         PC            •PSWのモードはユーザ
                                       •PCはアプリのtextセグメントを指す
            text
            data
            bss

                     user      user      user     user
                    kstack    kstack    kstack   kstack
            IOレジスタ

                   1 text     text       text    text
                     data     data       data    data
                     bss      bss        bss     bss

                     stack    stack      stack   stack


2012/3/24                                                 99
割り込みの発生-空間の切り替え
             PSW         PC
                                         •PSWのモードがカーネルに
                                         •アドレス空間の制御レジスタ
            text                         がカーネルモードに切り替わる
            data
            bss

                     user      user     user     user
                    kstack    kstack   kstack   kstack
            IOレジスタ

                   1 text     text     text     text
                     data     data     data     data
                     bss      bss      bss      bss

                     stack    stack    stack    stack


2012/3/24                                                100
割り込みの発生-割り込みベクタ
             PSW        PC
                                        •割り込みベクタのエントリを
            text                        選択してPCに
            data
            bss

                     user     user     user     user
                    kstack   kstack   kstack   kstack

            IOレジスタ

                   1 text    text     text     text
                     data    data     data     data
                     bss     bss      bss      bss

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


2012/3/24                                               101
割り込みの発生-割り込みベクタ
             PSW         PC
                                                          •割り込みベクタのエントリを
            text                                          選択してPCに
            data
            bss               Vector             device

                                004      Bus Timeout

                     user        user Illegal instruction
                                010                 user             user
                    kstack      kstackBpt-trace kstack
                                014                                 kstack
                                024      iot              Vector            device      entry
            IOレジスタ              034      Power failur       060    Teletype input       klin

                                114      Emulator tarp      064    Teletype output      klou
                                         instruction
                   1 text         text                 text 070       text
                                                                   Paper tape input     pcin
                                240      11/10 parity
                     data        data                 data 074        data
                                                                   Paper tape output    pcou
                                244      Floting point error
                     bss          bss                  bss 100         bss
                                                                   Line clock           kwlp
                                250      Segmentation violation
                                                             104   Programmable clock   kwlp

                     stack       stack              stack200         stack
                                                                   Line printer         lpou

                                                            220    RK disk driver       rkio


2012/3/24                                                                                  102
割り込みの発生ーハンドラの処理
             PSW       PC

                            2
            text
            data
            bss

                    user         user     user     user
                   kstack       kstack   kstack   kstack
            IOレジスタ

                   text         text     text     text
                   data         data     data     data
                   bss          bss      bss      bss

                   stack        stack    stack    stack


2012/3/24                                                  103
割り込みのからの復帰
              PSW            PC
カーネル用
 APR0        text
 APR1        data
 APR2
 APR3        bss
 APR4
 APR5
 APR6                 user         user      user     user
 APR7                kstack       kstack    kstack   kstack
             IOレジスタ
アプリ用                                       •処理が終わったら、スタックのPCと
                    1 text        text
                                           PSW復元して割り込み時点に復帰
                                              text text
 APR0
 APR1                 data        data        data data
 APR2
 APR3                 bss         bss         bss  bss
 APR4
 APR5
 APR6                stack        stack     stack    stack
 APR7

 2012/3/24                                                    104
 以上の説明は、割り込み発生時から、復帰ま
  でにプロセスの切り替えが発生しない場合
 条件によっては以下の処理でプロセスの切り
  替えが発生
       1. procの検索と選択
       2. user構造の切り替え
       3. User構造+kstackに退避した状態の復元
       4. アプリへの復帰




2012/3/24                           105
プロセスの切り替えー選択
             PSW       PC
                               Procの検索(スケジューラ)
            text
            data                     ↑次に動かすアプリ(プロセス)
            bss                      のprocを見つける

                    user     user      user     user
                   kstack   kstack    kstack   kstack
            IOレジスタ

                   text     text      text     text
                   data     data      data     data
                   bss      bss       bss      bss

                   stack    stack     stack    stack


2012/3/24                                               106
プロセスの切り替えーuserの切り替え
             PSW       PC

            text
            data            proc
            bss

                    user            user     user     user
                   kstack          kstack   kstack   kstack
            IOレジスタ

                   text            text     text     text
                   data            data     data     data
                   bss             bss      bss      bss

                   stack           stack    stack    stack


2012/3/24                                                     107
プロセスの切り替えーuserの切り替え
              PSW       PC

             text
             data            proc
             bss

                     user            user     user     user
                    kstack          kstack   kstack   kstack
             IOレジスタ
アプリ用
             空間管理用のレジスタを更新
 APR0               text            text     text     text
 APR1               data            data     data     data
 APR2
 APR3               bss             bss      bss      bss
 APR4
 APR5
 APR6               stack           stack    stack    stack
 APR7

 2012/3/24                                                     108
プロセスの切り替えーモードの切り替え
                                       •PSWをユーザに切り替え
              PSW       PC             •PCを復元
                                       •退避していた、PCとレジスタを復元
             text
             data            proc
             bss

                     user            user     user     user
                    kstack          kstack   kstack   kstack
             IOレジスタ
アプリ用
 APR0               text            text     text     text
 APR1               data            data     data     data
 APR2
 APR3               bss             bss      bss      bss
 APR4
 APR5
 APR6               stack           stack    stack    stack
 APR7

 2012/3/24                                                     109
プロセスの切り替えー完了
              PSW       PC

             text
             data            proc
             bss

                     user            user     user     user
                    kstack          kstack   kstack   kstack
             IOレジスタ
アプリ用
 APR0               text            text     text     text
 APR1               data            data     data     data
 APR2
 APR3               bss             bss      bss      bss
 APR4
 APR5
 APR6               stack           stack    stack    stack
 APR7

 2012/3/24                                                     110
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
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
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
あやしい関数
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
savu
 0725: _savu:
 0726:        bis      $340,PS
 0727:        mov       (sp)+,r1
 0728:        mov       (sp),r0
 0729:        mov       sp,(r0)+
 0730:        mov       r5,(r0)+
                                                        bis     $340,PSでbit5-7を1に
                                                        bic     $340,PSでbit5-7を0に
 0731:        bic      $340,PS
 0732:        jmp      (r1)
             725:            727-728:        729-730:         732:
                                        r0   u.u_rsav    r1   戻り先


r6→         戻り先               戻り先
                                                 u.
            u.u_rsav   r6→   u.u_rsav
                                                sp
                                                r5


                        r1    戻り先



2012/3/24                                                                           115
retu
 0740: _retu:                                       0745: 1:
 0741:        bis          $340,PS                  0746:              mov          (r0)+,sp
 0742:        mov           (sp)+,r1                0747:              mov          (r0)+,r5
 0743:        mov           (sp),KISA6              0748:              bic         $340,PS
 0744:        mov           $_u,r0                  0749:              jmp         (r1)

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


             742:          743-744:                                746-747:
                                                                                    u.
                                                                                    sp
r6→         戻り先             戻り先                                                     r5
r6→         p_addr   r6→    p_addr     カーネル用      r6→   p_addr
                                         APR0
                                         APR1
                                         APR2
                                         APR3
                                         APR4
            戻り先       r1    戻り先          APR5
                                         p_addr
                                                   r1   戻り先               r6        sp

                      r0    u.u_rsav     APR7
                                                   r0   u.u_rsav          r5         r5


2012/3/24                                                                                                                  116
sureg
1739: sureg()                           1747:          up =- 8;
1740: {                                 1748:          rp =- 8;
1741:       register *up, *rp, a;       1749:     }
1742:                                   1750:     while(rp > &UISA->r[0])
1743:       a = u.u_procp->p_addr;      1751:           *--rp = *--up + a;
1744:       up = &u.u_uisa[16];         1754:     up = &u.u_uisd[16];
1745:       rp = &UISA->r[16];          1755:     rp = &UISD->r[16];
1746:       if(cputype == 40) {         1765: }

                                     アプリ用
                                      APR0
            u.u_uisa[0-7]             APR1
                                      APR2
                                      APR3
            u.u_uisd[0-7]             APR4           アプリの空間を設定
                                      APR5
                                      APR6
                                      APR7

2012/3/24                                                                    117
2012/3/24   118
勉強会の記録
     日本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
付録2 よくわかんない人のための




2012/3/24            120
Simhのインストールと起動
     Ubuntuの場合
       $ sudo apt-get install simh
     pdp-11のシュミレーション
       $ pdp11
       PDP-11 simulator V3.8-1
       sim>




2012/3/24                            121
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
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
設定ファイルの作成
     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
Simhの起動
$ pdp11 unixv6.cfg

PDP-11 simulator V3.8-1
Disabling XQ
@unix

Login: root
#

2012/3/24                 125
Simhのdebug機能
     simhモードへの移行と復帰
       # Ctrl+E
       Simulation stopped, PC: 021630 (MOV
         (SP)+,177776)
       sim> c
       #
        simhモードへはCtrl+Eで
        シミュレーションモードへはcで



2012/3/24                                    126
ディバック機能を使う
  カーネルのシンボルアドレスを調べる
# 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)              savu()で止まった
sim>

2012/3/24                                                 127
step実行
Breakpoint, PC: 021636 (SPL 6)
sim> e r5,sp,pc
R5: 141742
SP: 141730
PC: 021636
sim> s
                                          0725: _savu:
Step expired, PC: 021640 (MOV (SP)+,R1)
sim> s                                    0726:        bis   $340,PS
Step expired, PC: 021642 (MOV (SP),R0)
sim> s                                    0727:        mov    (sp)+,r1
Step expired, PC: 021644 (MOV SP,(R0)+)
sim> s
                                          0728:        mov    (sp),r0
Step expired, PC: 021646 (MOV R5,(R0)+)   0729:        mov    sp,(r0)+
sim> s
                                          0730:        mov    r5,(r0)+
Step expired, PC: 021650 (SPL 0)
sim> s                                    0731:        bic   $340,PS
Step expired, PC: 021652 (JMP (R1))
                                          0732:        jmp   (r1)

2012/3/24                                                            128
レジスタの調べ方
/usr/share/doc/simh/simh_doc.pdfで説明
e {xamine} <list> examine memory or registers
sim> e state // レジスタ等すべてを表示
PC:         021630   V:        0             KIPDR4:   077406   SIPDR4:   000000   UIPDR4:       000000
R0:         140004   C:        0             KIPAR5:   001416   SIPAR5:   000000   UIPAR5:       000000
R1:         034272   PIRQ:     000000        KIPDR5:   077406   SIPDR5:   000000   UIPDR5:       000000
R2:         005336   STKLIM:   000000        KIPAR6:   001616   SIPAR6:   000000   UIPAR6:       000000
R3:         000200   FAC0H:    00000000000   KIPDR6:   077406   SIPDR6:   000000   UIPDR6:       000000
R4:         000000   FAC0L:    00000000000   KIPAR7:   007600   SIPAR7:   000000   UIPAR7:       001541
R5:         141724   FAC1H:    00000000000   KIPDR7:   077506   SIPDR7:   000000   UIPDR7:       066016
SP:         141710   FAC1L:    00000000000   KDPAR0:   000000   SDPAR0:   000000   UDPAR0:       001714
R00:        140004   FAC2H:    00000000000   KDPDR0:   077506   SDPDR0:   000000   UDPDR0:       000006
R01:        034272   FAC2L:    00000000000   KDPAR1:   000200   SDPAR1:   000000   UDPAR1:       000000
R02:        005336   FAC3H:    00000000000   KDPDR1:   077506   SDPDR1:   000000   UDPDR1:       000000
R03:        000200   FAC3L:    00000000000   KDPAR2:   000400   SDPAR2:   000000   UDPAR2:       000000
R04:        000000   FAC4H:    00000000000   KDPDR2:   077506   SDPDR2:   000000   UDPDR2:       000000
R05:        141724   FAC4L:    00000000000   KDPAR3:   000600   SDPAR3:   000000   UDPAR3:       000000
R10:        000000   FAC5H:    00000000000   KDPDR3:   077406   SDPDR3:   000000   UDPDR3:       000000
R11:        000000   FAC5L:    00000000000   KDPAR4:   001000   SDPAR4:   000000   UDPAR4:       000000
R12:        000000   FPS:      000004        KDPDR4:   077406   SDPDR4:   000000   UDPDR4:       000000
R13:        000000   FEA:      000000        KDPAR5:   001200   SDPAR5:   000000   UDPAR5:       000000
R14:        000000   FEC:      00            KDPDR5:   077406   SDPDR5:   000000   UDPDR5:       000000
R15:        000000   MMR0:     000201        KDPAR6:   001171   SDPAR6:   000000   UDPAR6:       000000
KSP:        141710   MMR1:     000000        KDPDR6:   077506   SDPDR6:   000000   UDPDR6:       000000
SSP:        000000   MMR2:     021626        KDPAR7:   007600   SDPAR7:   000000   UDPAR7:       001541
USP:        177756   MMR3:     000005        KDPDR7:   077506   SDPDR7:   000000   UDPDR7:       066016
PSW:        030000   KIPAR0:   000000        SIPAR0:   003612   UIPAR0:   001714   IREQ[0]:      00000000000
CM:         0        KIPDR0:   077406        SIPDR0:   000106   UIPDR0:   000006   TRAPS:        00000
PM:         3        KIPAR1:   000416        SIPAR1:   003700   UIPAR1:   000000   WAIT:         1
RS:         0        KIPDR1:   077506        SIPDR1:   000106   UIPDR1:   000000   STOP_TRAPS:   00001
FPD:        0        KIPAR2:   000616        SIPAR2:   000000   UIPAR2:   000000   STOP_VECA:    1
IPL:        0        KIPDR2:   077506        SIPDR2:   000000   UIPDR2:   000000   STOP_SPA:     1
T:          0        KIPAR3:   001016        SIPAR3:   000000   UIPAR3:   000000   PCQ[0]:       034412
N:          0        KIPDR3:   077506        SIPDR3:   000000   UIPDR3:   000000   WRU:          005
Z:          0        KIPAR4:   001216        SIPAR4:   000000   UIPAR4:   000000




2012/3/24                                                                                                      129
必要な内容に絞り込む
PC,R0~R5,SP(KSP,USP)
PSW
KDPAR0~7
UDPAR0~7
PC:         021630   V:        0             KIPDR4:   077406   SIPDR4:   000000   UIPDR4:       000000
R0:         140004   C:        0             KIPAR5:   001416   SIPAR5:   000000   UIPAR5:       000000
R1:         034272   PIRQ:     000000        KIPDR5:   077406   SIPDR5:   000000   UIPDR5:       000000
R2:         005336   STKLIM:   000000        KIPAR6:   001616   SIPAR6:   000000   UIPAR6:       000000
R3:         000200   FAC0H:    00000000000   KIPDR6:   077406   SIPDR6:   000000   UIPDR6:       000000
R4:         000000   FAC0L:    00000000000   KIPAR7:   007600   SIPAR7:   000000   UIPAR7:       001541
R5:         141724   FAC1H:    00000000000   KIPDR7:   077506   SIPDR7:   000000   UIPDR7:       066016
SP:         141710   FAC1L:    00000000000   KDPAR0:   000000   SDPAR0:   000000   UDPAR0:       001714
R00:        140004   FAC2H:    00000000000   KDPDR0:   077506   SDPDR0:   000000   UDPDR0:       000006
R01:        034272   FAC2L:    00000000000   KDPAR1:   000200   SDPAR1:   000000   UDPAR1:       000000
R02:        005336   FAC3H:    00000000000   KDPDR1:   077506   SDPDR1:   000000   UDPDR1:       000000
R03:        000200   FAC3L:    00000000000   KDPAR2:   000400   SDPAR2:   000000   UDPAR2:       000000
R04:        000000   FAC4H:    00000000000   KDPDR2:   077506   SDPDR2:   000000   UDPDR2:       000000
R05:        141724   FAC4L:    00000000000   KDPAR3:   000600   SDPAR3:   000000   UDPAR3:       000000
R10:        000000   FAC5H:    00000000000   KDPDR3:   077406   SDPDR3:   000000   UDPDR3:       000000
R11:        000000   FAC5L:    00000000000   KDPAR4:   001000   SDPAR4:   000000   UDPAR4:       000000
R12:        000000   FPS:      000004        KDPDR4:   077406   SDPDR4:   000000   UDPDR4:       000000
R13:        000000   FEA:      000000        KDPAR5:   001200   SDPAR5:   000000   UDPAR5:       000000
R14:        000000   FEC:      00            KDPDR5:   077406   SDPDR5:   000000   UDPDR5:       000000
R15:        000000   MMR0:     000201        KDPAR6:   001171   SDPAR6:   000000   UDPAR6:       000000
KSP:        141710   MMR1:     000000        KDPDR6:   077506   SDPDR6:   000000   UDPDR6:       000000
SSP:        000000   MMR2:     021626        KDPAR7:   007600   SDPAR7:   000000   UDPAR7:       001541
USP:        177756   MMR3:     000005        KDPDR7:   077506   SDPDR7:   000000   UDPDR7:       066016
PSW:        030000   KIPAR0:   000000        SIPAR0:   003612   UIPAR0:   001714   IREQ[0]:      00000000000
CM:         0        KIPDR0:   077406        SIPDR0:   000106   UIPDR0:   000006   TRAPS:        00000
PM:         3        KIPAR1:   000416        SIPAR1:   003700   UIPAR1:   000000   WAIT:         1
RS:         0        KIPDR1:   077506        SIPDR1:   000106   UIPDR1:   000000   STOP_TRAPS:   00001
FPD:        0        KIPAR2:   000616        SIPAR2:   000000   UIPAR2:   000000   STOP_VECA:    1
IPL:        0        KIPDR2:   077506        SIPDR2:   000000   UIPDR2:   000000   STOP_SPA:     1
T:          0        KIPAR3:   001016        SIPAR3:   000000   UIPAR3:   000000   PCQ[0]:       034412
N:          0        KIPDR3:   077506        SIPDR3:   000000   UIPDR3:   000000   WRU:          005
Z:          0        KIPAR4:   001216        SIPAR4:   000000   UIPAR4:   000000



2012/3/24                                                                                                      130
レジスタの指定方法
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
MMUレジスタの指定方法
Stateの表示順に’-’で範囲を指定
sim> e KDPAR0-KDPDR7
KDPAR0:        000000
KDPDR0:        077506
KDPAR1:        000200
KDPDR1:        077506   Pdp11/40では、
KDPAR2:        000400
KDPDR2:        077506   KPAR,KPDRと呼んでい
KDPAR3:
KDPDR3:
               000600
               077406
                        たが、simhでは上位機種
KDPAR4:        001000   のレジスタ名で表示され
KDPDR4:        077406
KDPAR5:        001200   るので、KDPAR,KDPDR
KDPDR5:
KDPAR6:
               077406
               001171
                        と読み替える
KDPDR6:        077506
KDPAR7:        007600
KDPDR7:        077506

2012/3/24                                 132
メモリの調べ方
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
表示フォーマットの指定
-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
シンボルからアドレスを調べる
sim> c                   //unixに戻る
# nm /unix | grep main   // mainのアドレス
022272T _main
# nm /unix | grep proc
034476T _newproc
005206B _proc
043170T _procxmt


2012/3/24                               135
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
自分のprocを見る#1
# nm /unix | grep _write
054124T _write
                            Shellが#をwriteする箇所(カーネ
031700T _writei               ルのエントリ)でbreakする
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
自分の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
自分のprocを見る#3
 sim> e 147700/100
147700: 141746 u_rsav[0]
147702: 141756 u_rsav[1]
147704: 000200 u_fsav[0]           0413: struct user
                                   0414: {
147706: 000000 1                   0415:      int u_rsav[2];    /* save r5,r6 when exchanging stacks */
147710: 000000 2                   0416:      int u_fsav[25];   /* save fp registers */
                                   0417:                        /* rsav and fsav must be first in structure */
147712: 000000 3                   0418:      char u_segflg;    /* flag for IO; user or kernel space */
                                   0419:      char u_error;     /* return error code */
147714: 000000 4                   0420:      char u_uid;       /* effective user id */
                                   0421:      char u_gid;        /* effective group id */
147716: 000000 5                   0422:      char u_ruid;       /* real user id */
                                   0423:      char u_rgid;       /* real group id */
   :                               0424:      int u_procp;        /* pointer to proc structure */
   :
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
自分のprocを見る#4
sim> e -h 5262/40
5262:    0103 p_flag/p_stat
                                0358: struct proc
5264:    0064 p_sig/p_pri       0359: {
5266:    7F00 p_time/p_uid      0360:      char p_stat;
5270:    0000 p_cpu             0361:      char p_flag;
                                0362:      char p_pri;       /* priority, negative is high */
5272:    42F2 p_ttyp            0363:      char p_sig;        /* signal number sent to this process *
5274:    000E p_pid             0364:      char p_uid;        /* user id, used to direct tty signals */
                                0365:      char p_time;        /* resident time for scheduling */
5276:    0001 p_ppid            0366:      char p_cpu;         /* cpu usage for scheduling */
5300:    033F                   0367:      char p_nice;        /* nice for scheduling */
5302:    0048                   0368:      int p_ttyp;     /* controlling tty */
                                0369:      int p_pid;      /* unique process id */
5304:    0000                   0370:      int p_ppid;      /* process id of parent */
5306:    0EDC                   0371:      int p_addr;       /* address of swappable image */
                                0372:      int p_size;      /* size of swappable image (*64 bytes)
5310:    0000                   0373:      int p_wchan;         /* event process is awaiting */
5312:    00CE                   0374:      int *p_textp;     /* pointer to text structure */
                                0375:
5314:    0000 pidは0xe=14(10進)   0376: } proc[NPROC];
5316:    0000
5320:    0000


2012/3/24                                                                                     140
自分のprocを見る#5
Breakpoint, PC: 054104 (JSR R5,22240)
sim> nobreak 54104
sim> c
# ps
 14 -
 29 ps
#       pidは0xe=14(10進)




2012/3/24                               141
だらだらつづくよ




2012/3/24              142

Más contenido relacionado

La actualidad más candente

新しい並列for構文のご提案
新しい並列for構文のご提案新しい並列for構文のご提案
新しい並列for構文のご提案yohhoy
 
プログラミングコンテストでのデータ構造 2 ~平衡二分探索木編~
プログラミングコンテストでのデータ構造 2 ~平衡二分探索木編~プログラミングコンテストでのデータ構造 2 ~平衡二分探索木編~
プログラミングコンテストでのデータ構造 2 ~平衡二分探索木編~Takuya Akiba
 
競技プログラミングにおけるコードの書き方とその利便性
競技プログラミングにおけるコードの書き方とその利便性競技プログラミングにおけるコードの書き方とその利便性
競技プログラミングにおけるコードの書き方とその利便性Hibiki Yamashiro
 
研究者のための Python による FPGA 入門
研究者のための Python による FPGA 入門研究者のための Python による FPGA 入門
研究者のための Python による FPGA 入門ryos36
 
プログラムを高速化する話Ⅱ 〜GPGPU編〜
プログラムを高速化する話Ⅱ 〜GPGPU編〜プログラムを高速化する話Ⅱ 〜GPGPU編〜
プログラムを高速化する話Ⅱ 〜GPGPU編〜京大 マイコンクラブ
 
計算機アーキテクチャを考慮した高能率画像処理プログラミング
計算機アーキテクチャを考慮した高能率画像処理プログラミング計算機アーキテクチャを考慮した高能率画像処理プログラミング
計算機アーキテクチャを考慮した高能率画像処理プログラミングNorishige Fukushima
 
いまさら聞けないarmを使ったNEONの基礎と活用事例
いまさら聞けないarmを使ったNEONの基礎と活用事例いまさら聞けないarmを使ったNEONの基礎と活用事例
いまさら聞けないarmを使ったNEONの基礎と活用事例Fixstars Corporation
 
Introduction to OpenCL (Japanese, OpenCLの基礎)
Introduction to OpenCL (Japanese, OpenCLの基礎)Introduction to OpenCL (Japanese, OpenCLの基礎)
Introduction to OpenCL (Japanese, OpenCLの基礎)Takahiro Harada
 
目grep入門 +解説
目grep入門 +解説目grep入門 +解説
目grep入門 +解説murachue
 
Haswellサーベイと有限体クラスの紹介
Haswellサーベイと有限体クラスの紹介Haswellサーベイと有限体クラスの紹介
Haswellサーベイと有限体クラスの紹介MITSUNARI Shigeo
 
いまさら聞けない!CUDA高速化入門
いまさら聞けない!CUDA高速化入門いまさら聞けない!CUDA高速化入門
いまさら聞けない!CUDA高速化入門Fixstars Corporation
 
Pythonの理解を試みる 〜バイトコードインタプリタを作成する〜
Pythonの理解を試みる 〜バイトコードインタプリタを作成する〜Pythonの理解を試みる 〜バイトコードインタプリタを作成する〜
Pythonの理解を試みる 〜バイトコードインタプリタを作成する〜Preferred Networks
 
SAT/SMTソルバの仕組み
SAT/SMTソルバの仕組みSAT/SMTソルバの仕組み
SAT/SMTソルバの仕組みMasahiro Sakai
 

La actualidad más candente (20)

新しい並列for構文のご提案
新しい並列for構文のご提案新しい並列for構文のご提案
新しい並列for構文のご提案
 
プログラミングコンテストでのデータ構造 2 ~平衡二分探索木編~
プログラミングコンテストでのデータ構造 2 ~平衡二分探索木編~プログラミングコンテストでのデータ構造 2 ~平衡二分探索木編~
プログラミングコンテストでのデータ構造 2 ~平衡二分探索木編~
 
競技プログラミングにおけるコードの書き方とその利便性
競技プログラミングにおけるコードの書き方とその利便性競技プログラミングにおけるコードの書き方とその利便性
競技プログラミングにおけるコードの書き方とその利便性
 
研究者のための Python による FPGA 入門
研究者のための Python による FPGA 入門研究者のための Python による FPGA 入門
研究者のための Python による FPGA 入門
 
llvm入門
llvm入門llvm入門
llvm入門
 
Plan 9のお話
Plan 9のお話Plan 9のお話
Plan 9のお話
 
プログラムを高速化する話Ⅱ 〜GPGPU編〜
プログラムを高速化する話Ⅱ 〜GPGPU編〜プログラムを高速化する話Ⅱ 〜GPGPU編〜
プログラムを高速化する話Ⅱ 〜GPGPU編〜
 
計算機アーキテクチャを考慮した高能率画像処理プログラミング
計算機アーキテクチャを考慮した高能率画像処理プログラミング計算機アーキテクチャを考慮した高能率画像処理プログラミング
計算機アーキテクチャを考慮した高能率画像処理プログラミング
 
画像処理の高性能計算
画像処理の高性能計算画像処理の高性能計算
画像処理の高性能計算
 
いまさら聞けないarmを使ったNEONの基礎と活用事例
いまさら聞けないarmを使ったNEONの基礎と活用事例いまさら聞けないarmを使ったNEONの基礎と活用事例
いまさら聞けないarmを使ったNEONの基礎と活用事例
 
Introduction to OpenCL (Japanese, OpenCLの基礎)
Introduction to OpenCL (Japanese, OpenCLの基礎)Introduction to OpenCL (Japanese, OpenCLの基礎)
Introduction to OpenCL (Japanese, OpenCLの基礎)
 
直交領域探索
直交領域探索直交領域探索
直交領域探索
 
Glibc malloc internal
Glibc malloc internalGlibc malloc internal
Glibc malloc internal
 
目grep入門 +解説
目grep入門 +解説目grep入門 +解説
目grep入門 +解説
 
Haswellサーベイと有限体クラスの紹介
Haswellサーベイと有限体クラスの紹介Haswellサーベイと有限体クラスの紹介
Haswellサーベイと有限体クラスの紹介
 
いまさら聞けない!CUDA高速化入門
いまさら聞けない!CUDA高速化入門いまさら聞けない!CUDA高速化入門
いまさら聞けない!CUDA高速化入門
 
Pythonの理解を試みる 〜バイトコードインタプリタを作成する〜
Pythonの理解を試みる 〜バイトコードインタプリタを作成する〜Pythonの理解を試みる 〜バイトコードインタプリタを作成する〜
Pythonの理解を試みる 〜バイトコードインタプリタを作成する〜
 
線形計画法入門
線形計画法入門線形計画法入門
線形計画法入門
 
SAT/SMTソルバの仕組み
SAT/SMTソルバの仕組みSAT/SMTソルバの仕組み
SAT/SMTソルバの仕組み
 
CVPR 2018 速報
CVPR 2018 速報CVPR 2018 速報
CVPR 2018 速報
 

Destacado

Oscar compiler for power reduction
Oscar compiler for power reduction Oscar compiler for power reduction
Oscar compiler for power reduction magoroku Yamamoto
 
ELFの動的リンク
ELFの動的リンクELFの動的リンク
ELFの動的リンク7shi
 
バイナリアンを目指して For a binaryen
バイナリアンを目指して For a binaryenバイナリアンを目指して For a binaryen
バイナリアンを目指して For a binaryenEyes, JAPAN
 
自動並列化コンパイラをAndroidに適用してみた
自動並列化コンパイラをAndroidに適用してみた自動並列化コンパイラをAndroidに適用してみた
自動並列化コンパイラをAndroidに適用してみたmagoroku Yamamoto
 
V6 Interpreter (Nagoya Geek Bar 2011-05-02)
V6 Interpreter (Nagoya Geek Bar 2011-05-02)V6 Interpreter (Nagoya Geek Bar 2011-05-02)
V6 Interpreter (Nagoya Geek Bar 2011-05-02)7shi
 
Unixファイルシステムの歴史
Unixファイルシステムの歴史Unixファイルシステムの歴史
Unixファイルシステムの歴史magoroku Yamamoto
 
PDP-11のインタプリタを作った話
PDP-11のインタプリタを作った話PDP-11のインタプリタを作った話
PDP-11のインタプリタを作った話kanorimon
 
Android IPC Mechanism
Android IPC MechanismAndroid IPC Mechanism
Android IPC MechanismLihan Chen
 
[AWSマイスターシリーズ] AWS CLI / AWS Tools for Windows PowerShell
[AWSマイスターシリーズ] AWS CLI / AWS Tools for Windows PowerShell[AWSマイスターシリーズ] AWS CLI / AWS Tools for Windows PowerShell
[AWSマイスターシリーズ] AWS CLI / AWS Tools for Windows PowerShellAmazon Web Services Japan
 

Destacado (16)

Oscar compiler for power reduction
Oscar compiler for power reduction Oscar compiler for power reduction
Oscar compiler for power reduction
 
波形で見るBig.little
波形で見るBig.little波形で見るBig.little
波形で見るBig.little
 
Unix v6 セミナー vol. 5
Unix v6 セミナー vol. 5Unix v6 セミナー vol. 5
Unix v6 セミナー vol. 5
 
ELFの動的リンク
ELFの動的リンクELFの動的リンク
ELFの動的リンク
 
バイナリアンを目指して For a binaryen
バイナリアンを目指して For a binaryenバイナリアンを目指して For a binaryen
バイナリアンを目指して For a binaryen
 
Android binder-ipc
Android binder-ipcAndroid binder-ipc
Android binder-ipc
 
自動並列化コンパイラをAndroidに適用してみた
自動並列化コンパイラをAndroidに適用してみた自動並列化コンパイラをAndroidに適用してみた
自動並列化コンパイラをAndroidに適用してみた
 
Deep learning入門
Deep learning入門Deep learning入門
Deep learning入門
 
Android ipm 20110409
Android ipm 20110409Android ipm 20110409
Android ipm 20110409
 
V6 Interpreter (Nagoya Geek Bar 2011-05-02)
V6 Interpreter (Nagoya Geek Bar 2011-05-02)V6 Interpreter (Nagoya Geek Bar 2011-05-02)
V6 Interpreter (Nagoya Geek Bar 2011-05-02)
 
Unixファイルシステムの歴史
Unixファイルシステムの歴史Unixファイルシステムの歴史
Unixファイルシステムの歴史
 
PDP-11のインタプリタを作った話
PDP-11のインタプリタを作った話PDP-11のインタプリタを作った話
PDP-11のインタプリタを作った話
 
Android IPC Mechanism
Android IPC MechanismAndroid IPC Mechanism
Android IPC Mechanism
 
Android IPC Mechanism
Android IPC MechanismAndroid IPC Mechanism
Android IPC Mechanism
 
Making Linux do Hard Real-time
Making Linux do Hard Real-timeMaking Linux do Hard Real-time
Making Linux do Hard Real-time
 
[AWSマイスターシリーズ] AWS CLI / AWS Tools for Windows PowerShell
[AWSマイスターシリーズ] AWS CLI / AWS Tools for Windows PowerShell[AWSマイスターシリーズ] AWS CLI / AWS Tools for Windows PowerShell
[AWSマイスターシリーズ] AWS CLI / AWS Tools for Windows PowerShell
 

Similar a V6 unix in okinawa

ただのリンカを書いた話.pdf
ただのリンカを書いた話.pdfただのリンカを書いた話.pdf
ただのリンカを書いた話.pdfsimotin13 Miyazaki
 
ROS Tutorial 02 - CIT
ROS Tutorial 02 - CITROS Tutorial 02 - CIT
ROS Tutorial 02 - CITDaiki Maekawa
 
Tokyo r25 hiro_macchan
Tokyo r25 hiro_macchanTokyo r25 hiro_macchan
Tokyo r25 hiro_macchanHiroki Matsui
 
ラズパイでデバイスドライバを作ってみた。
ラズパイでデバイスドライバを作ってみた。ラズパイでデバイスドライバを作ってみた。
ラズパイでデバイスドライバを作ってみた。Kazuki Onishi
 
セキュアVMの構築 (IntelとAMDの比較、あともうひとつ...) - AVTokyo 2009
セキュアVMの構築 (IntelとAMDの比較、あともうひとつ...) - AVTokyo 2009セキュアVMの構築 (IntelとAMDの比較、あともうひとつ...) - AVTokyo 2009
セキュアVMの構築 (IntelとAMDの比較、あともうひとつ...) - AVTokyo 2009Tsukasa Oi
 
Raspberry pi 用 toppers ssp シュリンク版(海賊版)の紹介
Raspberry pi 用 toppers ssp シュリンク版(海賊版)の紹介Raspberry pi 用 toppers ssp シュリンク版(海賊版)の紹介
Raspberry pi 用 toppers ssp シュリンク版(海賊版)の紹介Kazuhiro Takahashi
 
LLVMで遊ぶ(整数圧縮とか、x86向けの自動ベクトル化とか)
LLVMで遊ぶ(整数圧縮とか、x86向けの自動ベクトル化とか)LLVMで遊ぶ(整数圧縮とか、x86向けの自動ベクトル化とか)
LLVMで遊ぶ(整数圧縮とか、x86向けの自動ベクトル化とか)Takeshi Yamamuro
 
PBL1-v1-003j.pptx
PBL1-v1-003j.pptxPBL1-v1-003j.pptx
PBL1-v1-003j.pptxNAIST
 
160705-03 RTミドルウエア講習会・名城大
160705-03 RTミドルウエア講習会・名城大160705-03 RTミドルウエア講習会・名城大
160705-03 RTミドルウエア講習会・名城大openrtm
 
そろそろRStudioの話
そろそろRStudioの話そろそろRStudioの話
そろそろRStudioの話Kazuya Wada
 
ROS 2 Client Library for E^2
ROS 2 Client Library for E^2ROS 2 Client Library for E^2
ROS 2 Client Library for E^2Hideki Takase
 
Yet another Intel Chipset Internal SMBus device’s driver: ismt(4) (and spdmem...
Yet another Intel Chipset Internal SMBus device’s driver: ismt(4)(and spdmem...Yet another Intel Chipset Internal SMBus device’s driver: ismt(4)(and spdmem...
Yet another Intel Chipset Internal SMBus device’s driver: ismt(4) (and spdmem...Masanobu Saitoh
 
【学習メモ#3rd】12ステップで作る組込みOS自作入門
【学習メモ#3rd】12ステップで作る組込みOS自作入門【学習メモ#3rd】12ステップで作る組込みOS自作入門
【学習メモ#3rd】12ステップで作る組込みOS自作入門sandai
 
2017年11月02日「radare2」トーク/ワークショップAVTokyo 2017
2017年11月02日「radare2」トーク/ワークショップAVTokyo 2017 2017年11月02日「radare2」トーク/ワークショップAVTokyo 2017
2017年11月02日「radare2」トーク/ワークショップAVTokyo 2017 unixfreaxjp
 
ロボットシステムのつくりかた 〜Robot Operating Systemというアプローチ〜
ロボットシステムのつくりかた 〜Robot Operating Systemというアプローチ〜ロボットシステムのつくりかた 〜Robot Operating Systemというアプローチ〜
ロボットシステムのつくりかた 〜Robot Operating Systemというアプローチ〜Hideki Takase
 
XLWrapについてのご紹介
XLWrapについてのご紹介XLWrapについてのご紹介
XLWrapについてのご紹介Ohsawa Goodfellow
 

Similar a V6 unix in okinawa (20)

ただのリンカを書いた話.pdf
ただのリンカを書いた話.pdfただのリンカを書いた話.pdf
ただのリンカを書いた話.pdf
 
ROS Tutorial 02 - CIT
ROS Tutorial 02 - CITROS Tutorial 02 - CIT
ROS Tutorial 02 - CIT
 
Tokyo r25 hiro_macchan
Tokyo r25 hiro_macchanTokyo r25 hiro_macchan
Tokyo r25 hiro_macchan
 
ラズパイでデバイスドライバを作ってみた。
ラズパイでデバイスドライバを作ってみた。ラズパイでデバイスドライバを作ってみた。
ラズパイでデバイスドライバを作ってみた。
 
セキュアVMの構築 (IntelとAMDの比較、あともうひとつ...) - AVTokyo 2009
セキュアVMの構築 (IntelとAMDの比較、あともうひとつ...) - AVTokyo 2009セキュアVMの構築 (IntelとAMDの比較、あともうひとつ...) - AVTokyo 2009
セキュアVMの構築 (IntelとAMDの比較、あともうひとつ...) - AVTokyo 2009
 
Raspberry pi 用 toppers ssp シュリンク版(海賊版)の紹介
Raspberry pi 用 toppers ssp シュリンク版(海賊版)の紹介Raspberry pi 用 toppers ssp シュリンク版(海賊版)の紹介
Raspberry pi 用 toppers ssp シュリンク版(海賊版)の紹介
 
LLVMで遊ぶ(整数圧縮とか、x86向けの自動ベクトル化とか)
LLVMで遊ぶ(整数圧縮とか、x86向けの自動ベクトル化とか)LLVMで遊ぶ(整数圧縮とか、x86向けの自動ベクトル化とか)
LLVMで遊ぶ(整数圧縮とか、x86向けの自動ベクトル化とか)
 
PBL1-v1-003j.pptx
PBL1-v1-003j.pptxPBL1-v1-003j.pptx
PBL1-v1-003j.pptx
 
160705-03 RTミドルウエア講習会・名城大
160705-03 RTミドルウエア講習会・名城大160705-03 RTミドルウエア講習会・名城大
160705-03 RTミドルウエア講習会・名城大
 
そろそろRStudioの話
そろそろRStudioの話そろそろRStudioの話
そろそろRStudioの話
 
ROS 2 Client Library for E^2
ROS 2 Client Library for E^2ROS 2 Client Library for E^2
ROS 2 Client Library for E^2
 
Yet another Intel Chipset Internal SMBus device’s driver: ismt(4) (and spdmem...
Yet another Intel Chipset Internal SMBus device’s driver: ismt(4)(and spdmem...Yet another Intel Chipset Internal SMBus device’s driver: ismt(4)(and spdmem...
Yet another Intel Chipset Internal SMBus device’s driver: ismt(4) (and spdmem...
 
【学習メモ#3rd】12ステップで作る組込みOS自作入門
【学習メモ#3rd】12ステップで作る組込みOS自作入門【学習メモ#3rd】12ステップで作る組込みOS自作入門
【学習メモ#3rd】12ステップで作る組込みOS自作入門
 
2017年11月02日「radare2」トーク/ワークショップAVTokyo 2017
2017年11月02日「radare2」トーク/ワークショップAVTokyo 2017 2017年11月02日「radare2」トーク/ワークショップAVTokyo 2017
2017年11月02日「radare2」トーク/ワークショップAVTokyo 2017
 
ロボットシステムのつくりかた 〜Robot Operating Systemというアプローチ〜
ロボットシステムのつくりかた 〜Robot Operating Systemというアプローチ〜ロボットシステムのつくりかた 〜Robot Operating Systemというアプローチ〜
ロボットシステムのつくりかた 〜Robot Operating Systemというアプローチ〜
 
about dakota6.7 gui
about dakota6.7 guiabout dakota6.7 gui
about dakota6.7 gui
 
osoljp 2011.08
osoljp 2011.08osoljp 2011.08
osoljp 2011.08
 
Tokyo.R#16 wdkz
Tokyo.R#16 wdkzTokyo.R#16 wdkz
Tokyo.R#16 wdkz
 
XLWrapについてのご紹介
XLWrapについてのご紹介XLWrapについてのご紹介
XLWrapについてのご紹介
 
0622
06220622
0622
 

Más de magoroku Yamamoto (20)

仮想記憶入門 BSD-4.3を例題に
仮想記憶入門 BSD-4.3を例題に仮想記憶入門 BSD-4.3を例題に
仮想記憶入門 BSD-4.3を例題に
 
V6 unix vol.2 in okinawa
V6 unix vol.2 in okinawaV6 unix vol.2 in okinawa
V6 unix vol.2 in okinawa
 
Adk2012
Adk2012Adk2012
Adk2012
 
ぐだ生システム#2
ぐだ生システム#2ぐだ生システム#2
ぐだ生システム#2
 
ぐだ生って何
ぐだ生って何ぐだ生って何
ぐだ生って何
 
Android builders summit slide tour
Android builders summit slide tourAndroid builders summit slide tour
Android builders summit slide tour
 
第4回名古屋Android勉強会資料
第4回名古屋Android勉強会資料第4回名古屋Android勉強会資料
第4回名古屋Android勉強会資料
 
Poorman’s adk トレーナ
Poorman’s adk トレーナPoorman’s adk トレーナ
Poorman’s adk トレーナ
 
20分でわかった事にするパワーマネジメント
20分でわかった事にするパワーマネジメント20分でわかった事にするパワーマネジメント
20分でわかった事にするパワーマネジメント
 
Poormans sdk
Poormans sdkPoormans sdk
Poormans sdk
 
Ngk2011 b
Ngk2011 bNgk2011 b
Ngk2011 b
 
オレオレ家電
オレオレ家電オレオレ家電
オレオレ家電
 
V6read#4
V6read#4V6read#4
V6read#4
 
V6read#3
V6read#3V6read#3
V6read#3
 
Pdp11 on-fpga
Pdp11 on-fpgaPdp11 on-fpga
Pdp11 on-fpga
 
V6read#2
V6read#2V6read#2
V6read#2
 
Androidの入力システム
Androidの入力システムAndroidの入力システム
Androidの入力システム
 
ぐだ生システム再構成4
ぐだ生システム再構成4ぐだ生システム再構成4
ぐだ生システム再構成4
 
20分で理解する仮想記憶
20分で理解する仮想記憶20分で理解する仮想記憶
20分で理解する仮想記憶
 
Android のusb support
Android のusb supportAndroid のusb support
Android のusb support
 

V6 unix in okinawa

  • 1. オペ―レーティングシステムの読み書き Rev.2.1 @magoroku15 2012/3/24 日本Androidの会 沖縄支部 workshop@Naha Vol.17 - v6 unix 勉強会 2012/3/24 1
  • 2. 他人の作品を読まなかった偉 大な作家,他人の筆づかいを 研究しなかった偉大な画家, 同僚の肩越しに技を盗まな かった腕のよい外科医,副操 縦席で実地の経験を積まな かった767機長――果たして, そんな人たちが本当にいるの でしょうか? Dave Thomas著 Code Reading―オープンソースから学ぶソフトウェア開発技法 より 2012/3/24 2
  • 3. 最底辺活動  Lions本読書会に出てみた  本だけで読み解くのは大変  若干の解説を加えれば理解できる人は増えるはず  拙者のネタとしてGeekBarなどで話すことにした  これを最底辺活動と言っている ○ 他にもFPGAでPDP11を動かしたり、PICで遊んだり  UNIX v6を読む理由  最新のBSD, Linuxと実装は異なるが根幹は同じ  UNIX v6を読む事が現代のOSを理解する近道(だと 思う) 2012/3/24 3
  • 4. 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
  • 5. お勧めの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
  • 6. @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
  • 7. 教材  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
  • 8. ウォームアップ  OSの領域はプログラマにとっての最底辺部  アプリケーションプログラマ ○ 提供されるAPIを利用して、一般向けのサービス等を提供する人  システムプログラマ ○ ハードウェアの機能を利用して、API等プログラマ向け機能を提供 する人  必要とされる前提知識が異なる  命令レベルで計算機を(ぼんやりと)理解する必要あり  アプリケーションプログラマ向けの準備運動  Lions本 ○ 第2章 Fundamentals (PDFだとP4) 命令セット ○ 第9章 Hardware Interrupt and Traps (PDFのP42) 割り込み  PDP-11 Processor Handbook 2012/3/24 8
  • 10. システムプログラマから見た 計算機の構成要素  CPU  レジスタ ○ 汎用レジスタ 一般の演算命令に使用 ○ スタックポインタ スタックの先頭位置 ○ プログラムカウンタ 次に処理する命令の位置  フラグレジスタ 演算結果の一部を記憶  制御/状態レジスタ  Memory  外部記憶 2012/3/24 10
  • 11. PDP-11/40  レジスタ  16bitのレジスタが8個  r0-r7  r6はspスタックポインタ  r7はpcプログラムカウンタ  Processor Status Word  フラグレジスタ+状態レジスタ  memory  仮想アドレス幅は16bit 最大 64kbyte  物理アドレス幅は18bit 最大 256kbyte 2012/3/24 11
  • 12. レジスタ r0-r7 r0, r1 演算結果の一時的な保持、復帰値など r2, r3, r4 関数内のローカル変数。呼ばれた関数で退避し、 関数の終了時に復元 R5 フレームポインタ r6 (sp) スタックポインタ r7 (pc) 実行する命令の位置(アドレス) 2012/3/24 12
  • 13. Processor Status Word (PSW) 14-15 現在のモード (00 = kernel 11 = user) 12-13 以前のモード 5-7 プロセッサの優先度 (0~7) 4 トラップビット 3N 演算結果が負 2Z 演算結果が0 1V 演算結果がオーバフロー 0C 演算結果がキャリー 2012/3/24 13
  • 14. CPUの処理  以下を繰り返す 1. PCの示す位置(アドレス)から命令を読み込む 2. 解析して 3. 実行 4. 実行の副作用として以下の事象が発生する  PSWを書き換え  PCを書き換え  レジスタの書き換え  メモリの内容を書き換えたりする 2012/3/24 14
  • 15. CPUの処理 誤解しやすい点  PCもレジスタの一種  PC(r7)を書き換えると処理がジャンプ  比較と分岐は別命令 2012/3/24 15
  • 17. C言語の空間モデル  Text text  命令列の格納領域  書き換え禁止 data  Data bss  非0で初期化されたデータ領域  Bss  0で初期化されたデータ領域  Stack  自動(auto)変数の格納領域  関数呼び出し時のレジスタ退避域 stack 注)スレッドは、まだ存在しないので対象外 2012/3/24 17
  • 18. 変数の宣言と空間配置 int i; // Bss a.out形式 実行時 (ファイル) (メモリ) Int j = 1; // Data header main() text text { data data static int k = 1; // Data int l = 1; // Stack bss int m; // Stack : } stack 2012/3/24 18
  • 19. 関数呼び出しとスタック 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
  • 20. 関数とスタック namelist # nm -n a.out 000170T cret 0x78 000000a 0x00 crt0.o 000206B _c 000000t start 000210B _d 000004a a 000212B savr5 000006a b 177764a r 000030T 0x18 _main 177766a f 000030a src.o 177770a e 000030t ~main 000102T 0x42 _func 000102t ~func 000140T 0x60 _exit 000140a exit.o 000152T 0x6a csv 000152a csv.o 2012/3/24 20
  • 21. 関数呼び出しとスタック ASM .globl _main .comm _c,2 .text .globl _d _main: .comm _d,2 ~~main: .globl _func ~e=177770 .text ~f=177766 _func: ~r=177764 ~~func: jsr r5,csv ~a=4 sub $6,sp ~b=6 mov $1,-10(r5) jsr r5,csv mov $2,-12(r5) mov 4(r5),_c mov -12(r5),(sp) mov 6(r5),_d mov -10(r5),-(sp) mov _c,r0 jsr pc,*$_func add _d,r0 tst (sp)+ jbr L2 mov r0,-14(r5) L2: jmp cret L1: jmp cret .globl .globl _c .data 2012/3/24 21
  • 22. csv 関数の入り口 Main: csv: : mov r5,r0 jsr r5,csv 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 2012/3/24 jmp (r0) 22
  • 23. cret 関数の出口 main: cret: : mov r5,r1 jmp cret 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
  • 24. 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
  • 25. 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
  • 26. 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 #15 #16-17 #18 #19 #20 0x046a r6→ 0x0038 0x046c r6→ 1 1 0x046e r6→ r6→ r6→ 2 2 2 0x0470 0x0472 2 2 2 2 0x0474 r6→ 1 1 1 1 0x0476 0x0478 0x047a 0x047c r5→ r5→ r5→ r5→ r5→ 2012/3/24 26
  • 27. 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 #21 #23 #24-26 #27 0x045a 0x045c 0x045e 0x0460 r6→ 0x0462 r6→ r2 r2 0x0464 r3 r3 0x0466 r4 r4 0x0468 r6→ 0x047c r5,r6→ 0x047c r5→ 0x047c r5→ 0x047c 0x046a r6→ 0x0038 0x0038 0x0038 0x0038 0x046c 2012/3/24 27
  • 28. 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 #27-34 #35 #36-38 #39 #40-41 0x045a 0x045c 0x045e 0x0460 r6→ r6→ r6→ 0x0462 r2 r2 r1→ r2 0x0464 r3 r3 r3 0x0466 r4 r4 r4 0x0468 r5→ 0x047c r5,r1→ 0x047c r5→ 0x047c r5,r6→ 0x047c r6→ 0x047c 0x046a 0x0038 0x0038 0x0038 0x0038 r6→ 0x0038 0x046c r6→ 2012/3/24 28
  • 29. 関数とスタック  今のスタックr6:SP  前のスタックr5  r5:r6のペアでチェーン #20 #21 #27 0x0460 r6→ 0x0462 r2 0x0464 r3 0x0466 r4 0x0468 r6→ 0x047c r5→ 0x047c 0x046a 0x0038 0x0038 0x0038 0x046c 1 0x046e 2 0x0470 0x0472 2 0x0474 1 0x0476 0x0478 0x047a 0x047c r5→ 2012/3/24 29
  • 30. レジスタ r0-r7 もう一度 r0, r1 演算結果の一時的な保持、復帰値など r2, r3, r4 関数内のローカル変数。呼ばれた関数で退避し、 関数の終了時に復元 R5 フレームポインタ r6 (sp) スタックポインタ r7 (pc) 実行する命令の位置(アドレス) 2012/3/24 30
  • 31. C言語とasmの実行環境  asmから生成した命令列はスタックを必要と しない  C言語から生成した命令列は、実行時にス タックを必要とする  引数の受け渡し利用領域  自動変数の領域  呼び出し元レジスタ(r2,r3,r4)の退避領域  呼び出し先からの復帰アドレスの退避領域 2012/3/24 31
  • 33. getpid(2)の呼び出し C言語 main() { int i; i = getpid(); } 2012/3/24 33
  • 34. 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
  • 35. 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
  • 36. 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
  • 37. open(2)の呼び出し C言語 main() { int f; f = open("hoge", 2); } 2012/3/24 37
  • 38. 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
  • 39. 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
  • 40. 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
  • 41. システムコールとライブラリコール  ライブラリ  マニュアルセクション3  例 fopen(3)  ユーザプログラムの空間で動作  必要に応じてシステムコールを呼び出す  システムコール  マニュアルセクション2  例 open(2)  OS内部の処理を呼び出す  呼出し方法は通常のCall/Returnとは異なる 2012/3/24 41
  • 43. Q:CPUが想定外の状態になると  たとえば以下の場合  不正なアドレスを参照した  未定義の命令を実行しようとした  0で割り算した  次の命令はどこから取り出せばよいか? 2012/3/24 43
  • 44. A: わな “Trap”を用意しておく  CPUが身動きが取れなかった場合に次に命令 を取り出す場所を“わな”として仕掛けてお く  システムコールの呼び出しは特殊な「わな」  「わな」はCPUの処理過程に実行時の例外と して発生する  「わな」に引っかかる事を「例外」と呼ぶ 2012/3/24 44
  • 45. 例外と割り込み  Lions本9章  Trap/例外  命令の実行に失敗した場合の「わな」仕掛ける  システムコールの呼び出しは特殊な「わな」  「わな」はCPUの処理過程で発生する  Interrupt/割り込み  CPUの処理に関係なく、外部からの「割り込み」  主に、外部装置の処理完了時に「割り込む」  外部装置の例 ○ テレタイプ、紙テープ、ラインプリンタ、磁気ディ スク、時計 2012/3/24 45
  • 46. 2012/3/24 46
  • 47. 例外の流れ 1. 例外/割り込みの発生 2. コンテキストの保存 ① PCとPSWをCPU内部に一時的に保存 ② 発生の要因を特定し、要因:アドレスの表(ベクター)を 検索 ③ ベクターをPCに設定 ④ 一時的に保存していたPC,PSWをカーネルスタックに 退避(push) 3. ハンドラの実行 4. コンテキストの復元 ① カーネルスタックにPC,PSWが格納されている状態で rtt命令を実行 ② rtt命令がカーネルスタックからPC,PSWを復元(pop) 5. 割り込み発生の次の命令を実行 2012/3/24 47
  • 48. 例外ベクタ Vector Trap type Priority Location 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
  • 49. 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
  • 50. 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
  • 51. 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
  • 52. 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
  • 53. 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
  • 54. システムコール番号 indir = 0. exit = 1. fork = 2. read = 3. write = 4. open = 5. close = 6. wait = 7. creat = 8. : : 2012/3/24 54
  • 55. システムコール呼出し処理 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
  • 56. 2012/3/24 56
  • 57. 割り込みベクタ Vector device priority Location 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
  • 60. Clocks – line and programmable  Line Clock  電源の周期から生成  AC>降圧(トランス)>整流(ダイオード)>コンデンサ  電源周波数のパルスを取り出せる  50HZで20ms間隔  昔の電気式デジタル時計はパルスxHZで1秒を生成  Programmable clock  指定の間隔でパルスを発生  PDP-11ではどちらかが必要 2012/3/24 60
  • 61. 525 low.s 0525: . = 60^. Vector device entry 0526: klin; br4 0527: klou; br4 060 Teletype input klin 0528: 0529: . = 70^. 064 Teletype output klou 0530: pcin; br4 0531: pcou; br4 070 Paper tape input pcin 0532: 074 Paper tape output pcou 0533: . = 100^. 0534: kwlp; br6 100 Line clock kwlp 0535: kwlp; br6 0539: 104 Programmable clock kwlp 0540: . = 200^. 0541: lpou; br4 200 Line printer lpou 0542: 0543: . = 220^. 220 RK disk driver rkio 0544: rkio; br5 2012/3/24 61
  • 62. Line Clock  外部にあるclockから毎秒50個のパルスがCPUに 入る  1パルス毎に割り込みベクタの処理を実行 Clock CPU 2012/3/24 62
  • 63. kwlp low.s 0568: 0569: .globl _clock 0570: kwlp: jsr r0,call; _clock Cで書かれたclock()を呼ぶ 2012/3/24 63
  • 64. clock 3725: clock(dev, sp, r1, nps, r0, pc, ps) 3761: 3797: if(++lbolt >= HZ) { 3726: { 3762: /* 3798: if((ps&0340) != 0) 3727: register struct callo *p1, *p2; 3763: * callout 3799: return; 3728: register struct proc *pp; 3764: */ 3800: lbolt =- HZ; 3729: 3765: 3801: if(++time[1] == 0) 3730: /* 3766: spl5(); 3802: ++time[0]; 3731: * restart clock 3767: if(callout[0].c_time <= 0) { 3803: spl1(); 3732: */ 3768: p1 = &callout[0]; 3804: if(time[1]==tout[1] && time[0]==tout[0]) 3733: 3769: while(p1->c_func != 0 && p1->c_time <= 0) { 3805: wakeup(tout); 3734: *lks = 0115; 3770: (*p1->c_func)(p1->c_arg); 3806: if((time[1]&03) == 0) { 3735: 3771: p1++; 3807: runrun++; 3736: /* 3772: } 3808: wakeup(&lbolt); 3737: * display register 3773: p2 = &callout[0]; 3809: } 3738: */ 3774: while(p2->c_func = p1->c_func) { 3810: for(pp = &proc[0]; pp < &proc[NPROC]; pp++) 3739: 3775: p2->c_time = p1->c_time; 3811: if (pp->p_stat) { 3740: display(); 3776: p2->c_arg = p1->c_arg; 3812: if(pp->p_time != 127) 3741: 3777: p1++; 3813: pp->p_time++; 3742: /* 3778: p2++; 3814: if((pp->p_cpu & 0377) > SCHMAG) 3743: * callouts 3779: } 3815: pp->p_cpu =- SCHMAG; else 3744: * if none, just return 3780: } 3816: pp->p_cpu = 0; 3745: * else update first non-zero time 3781: 3817: if(pp->p_pri > PUSER) 3746: */ 3782: /* 3818: setpri(pp); 3747: 3783: * lightning bolt time-out 3819: } 3748: if(callout[0].c_func == 0) 3784: * and time of day 3820: if(runin!=0) { 3749: goto out; 3785: */ 3821: runin = 0; 3750: p2 = &callout[0]; 3786: 3822: wakeup(&runin); 3751: while(p2->c_time<=0 && p2->c_func!=0) 3787: out: 3823: } 3752: p2++; 3788: if((ps&UMODE) == UMODE) { 3824: if((ps&UMODE) == UMODE) { 3753: p2->c_time--; 3789: u.u_utime++; 3825: u.u_ar0 = &r0; 3754: 3790: if(u.u_prof[3]) 3826: if(issig()) 3755: /* 3791: incupc(pc, u.u_prof); 3827: psig(); 3756: * if ps is high, just return 3792: } else 3828: setpri(u.u_procp); 3757: */ 3793: u.u_stime++; 3829: } 3758: 3794: pp = u.u_procp; 3830: } 3759: if((ps&0340) != 0) 3795: if(++pp->p_cpu == 0) 3831: } 3760: goto out; 3796: pp->p_cpu--; 2012/3/24 64
  • 65. clock 3725: clock(dev, sp, r1, nps, r0, pc, ps) 3761: 3797: if(++lbolt >= HZ) { 3726: { 3762: /* 3798: if((ps&0340) != 0) 3727: register struct callo *p1, *p2; 3763: * callout 3799: return; 3728: register struct proc *pp; 3764: */ 3800: lbolt =- HZ; 3729: 3765: 3801: if(++time[1] == 0) 3730: /* 3766: spl5(); 3802: ++time[0]; 3731: * restart clock 3767: if(callout[0].c_time <= 0) { 3803: spl1(); 3732: */ 3768: p1 = &callout[0]; 3804: if(time[1]==tout[1] && time[0]==tout[0]) 3733: 3769: while(p1->c_func != 0 && p1->c_time <= 0) { 3805: wakeup(tout); 3734: *lks = 0115; 3770: (*p1->c_func)(p1->c_arg); 3806: if((time[1]&03) == 0) { 3735: 3771: p1++; 3807: runrun++; Callout 3736: /* 3772: } 3808: wakeup(&lbolt); 3737: * display register 3773: p2 = &callout[0]; 3809: } 3738: */ 3774: while(p2->c_func = p1->c_func) { 3810: for(pp = &proc[0]; pp < &proc[NPROC]; pp++) 3739: 3775: p2->c_time = p1->c_time; 3811: if (pp->p_stat) { Sched 3740: display(); 3776: p2->c_arg = p1->c_arg; 3812: if(pp->p_time != 127) 3741: 3777: p1++; 3813: pp->p_time++; 3742: /* 3778: p2++; 3814: if((pp->p_cpu & 0377) > SCHMAG) 3743: * callouts 3779: } 3815: pp->p_cpu =- SCHMAG; else 3744: * if none, just return 3780: } 3816: pp->p_cpu = 0; 3745: * else update first non-zero time 3781: 3817: if(pp->p_pri > PUSER) の入り口 3746: */ 3782: /* 3818: setpri(pp); 3747: 3783: * lightning bolt time-out 3819: } 3748: if(callout[0].c_func == 0) 3784: * and time of day 3820: if(runin!=0) { 3749: goto out; 3785: */ 3821: runin = 0; 3750: p2 = &callout[0]; 3786: 3822: wakeup(&runin); Acct 3751: while(p2->c_time<=0 && p2->c_func!=0) 3787: out: 3823: } 3752: p2++; 3788: if((ps&UMODE) == UMODE) { 3824: if((ps&UMODE) == UMODE) { 3753: p2->c_time--; 3789: u.u_utime++; 3825: u.u_ar0 = &r0; 3754: 3790: if(u.u_prof[3]) 3826: if(issig()) 3755: /* 3791: incupc(pc, u.u_prof); 3827: psig(); 3756: * if ps is high, just return 3792: } else 3828: setpri(u.u_procp); 3757: */ 3793: u.u_stime++; 3829: } 3758: 3794: pp = u.u_procp; 3830: } 3759: if((ps&0340) != 0) 3795: if(++pp->p_cpu == 0) 3831: } 3760: goto out; 3796: pp->p_cpu--; 2012/3/24 65
  • 66. 謎の変数  u.u_time  u.u_stime  pp->p_time  lbolt  time[2]  tout[2] 2012/3/24 66
  • 67. 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
  • 68. clock callout (1/2) 先頭のcalloutが未 3748: if(callout[0].c_func == 0) 登録なら、後続の 3749: goto out; 3750: p2 = &callout[0]; calloutも未登録と 判断して,Callout 処理をスキップ 3751: while(p2->c_time<=0 && p2->c_func!=0) 3752: p2++; 最初にc_timeが0 3753: p2->c_time--; より大きいCallout 3758: を見つけて、 3759: if((ps&0340) != 0) c_timeを-1 3760: goto out; ここより前の 3761: calloutはこの後処 理される 2012/3/24 68
  • 69. clock callout (2/2) 先頭に登録時間が 過ぎているcallout 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; Callout配列を詰め 3776: p2->c_arg = p1->c_arg; る 3777: p1++; 3778: p2++; 3779: } 3780: } 2012/3/24 69
  • 70. clock acct USERモードから 3787: out: 割り込まれたら、 3788: if((ps&UMODE) == UMODE) { uのuser時間 3789: u.u_utime++; u_utimeを+1 3790: if(u.u_prof[3]) 3791: incupc(pc, u.u_prof); KERNELモードか 3792: } else ら割り込まれたら、 3793: u.u_stime++; uのsystem時間 u_stimeを+1 3794: pp = u.u_procp; 3795: if(++pp->p_cpu == 0) Procのp_cpuを加 3796: pp->p_cpu--; 算。オーバフロー しないように調整 ppはproc構造のポインタ、uはuser構造。共 にプロセスの管理構造1プロセスに1個づつ 2012/3/24 70
  • 71. clock schedの入り口(1/2) clockが呼ばれると、ここまでは必 3797: if(++lbolt >= HZ) { ず実行。lboltを+1して、HZ(50)を 3798: if((ps&0340) != 0) 3799: return; 超過したら、すなわち1秒経過し 3800: lbolt =- HZ; たら、 3801: if(++time[1] == 0) 3802: ++time[0]; lboltをリセット 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: } 4秒ごとにlboltで待ってるプロセ スを起こす 今回はさらりと流す 2012/3/24 71
  • 72. 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) p_statに値が入っている=プロ 3815: pp->p_cpu =- SCHMAG; elseセスが存在したら、p_timeを 3816: pp->p_cpu = 0; +1 3817: if(pp->p_pri > PUSER) 3818: setpri(pp); 3819: } 3820: if(runin!=0) { 3821: runin = 0; 3822: wakeup(&runin); runinが真なら、runinで待って 3823: } るプロセスをwakeup 3824: if((ps&UMODE) == UMODE) { 3825: u.u_ar0 = &r0; 3826: if(issig()) 3827: psig(); 3828: setpri(u.u_procp); 3829: } 3830: 2012/3/24 } 72
  • 73. 謎の変数 回答  u.u_time USER時間  u.u_stime SYSTEM時間  pp->p_time プロセス起動からの時間  lbolt 毎秒60回++  time[2] 1970年からの秒  tout[2] sleep(2)が起きる時間 2012/3/24 73
  • 74. 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
  • 75. 2012/3/24 75
  • 76. a.outと空間の関係 CPU PC a.out header text text data data exec(2) bss ・関数を呼 び出すと自 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 stack ジスタの内 3083 */ 容を退避。 2012/3/24 76
  • 77. 例外/割り込みが起こると…….. •PSWのモードがユーザモー CPU PC ドからカーネルモードに変わ り、空間が切り替わる。 ① ② •事象に応じて、ベクター テーブルの値がPCに書き込 text ③ text A まれる。 data data •例外/割り込み発生時のPSW とPC(図中A)をスタックに pushする bss bss アプリケーション カーネル アプリケーションと stack stack カーネル 2つの空間?? 2012/3/24 77
  • 78. 仮想アドレスと物理アドレス  現在の一般的な仮想記憶  仮想アドレス>物理アドレス  仮想メモリ量>物理メモリ量  実メモリ不足時は固定長(ページ)単位で2次記憶に退避 し必要時に復元 →ページング  PDP-11の仮想記憶  仮想アドレス<物理アドレス  仮想メモリ量<物理メモリ量  実メモリ不足時はプロセス全体を2次記憶に退避し実行 を抑止、一定時間経過後に全体を復元し実行可能に →スワッピング 2012/3/24 78
  • 80. アドレス変換機構の制御  リセット後は変換機構OFFで動作  OSの初期化時にプログラムで 1. 変換表を初期化 2. 変換機構をON  新しいプロセスの生成とメモリ獲得時に  OSが変換表を編集  プロセスの切り替え時に  変換表を入れ替え 2012/3/24 80
  • 81. PDP-11/40のメモリ管理機構  8個のカーネルモードページ  8個のユーザモードページ  1ページは最大8Kbyteの可変長  モード切り替えはPSWのモードに連動 2012/3/24 81
  • 82. Active Page Registers (APR) 2012/3/24 82
  • 83. APR- PARとPDRのペア PAR ベースアドレスを指定 PDR メモリ属性を指定 2012/3/24 83
  • 84. 仮想記憶の有効化  bit0 ENABLE MANAGEMENTを1で有効 2012/3/24 84
  • 85. 重要なアドレス m40.s USIZE = 16 Size of User Block (*64 = 1024 B) PS = 177776 Program Status Word SSR0 = 177572 Status Register KISA0 = 172340 Kernel Segment Address Register #0 KISA6 = 172354 Kernel Segment Address Register #6 KISD0 = 172300 Kernel Segment Descriptor Register #0 UISA0 = 177640 User Segment Address Register #0 UISA1 = 177642 User Segment Address Register #1 UISD0 = 177600 User Segment Descriptor Register #0 UISD1 = 177602 User Segment Descriptor Register #1 IO = 7600 I/O Segment Register 2012/3/24 85
  • 86. 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
  • 87. ユーザ空間の初期化 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
  • 88. 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
  • 89. 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
  • 90. 最初のプロセスを生成 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
  • 91. 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, char* init = “/etc/init”; 1521: 0000777, /* br . */ 1522: 0000014, /* initp: init; 0 */ main( ) { 1523: 0000000, execl( init, init, 0 ); 1524: 0062457, /* init: </etc/init¥0> */ while( 1 ) ; 1525: 0061564, 1526: 0064457, } 1527: 0064556, 1528: 0000164, 1529: }; 2012/3/24 91
  • 92. Bootと空間の初期化 Boot直後 仮想記憶有効 最初のnewproc 最初のexec Initの実行 text text text text text data data data data data bss bss bss bss u user user user user user user IOレジスタ IOレジスタ IOレジスタ IOレジスタ icode exec text data bss stack 2012/3/24 92
  • 93. Unixの空間モデル  アプリとカーネルのアドレス域は分離  後に完全な仮想記憶サポートで少し変わる  各アプリケーションの空間は独立  カーネルの空間は  Text,Data,Bssは一部を除いて共有  Stackはアプリ毎に個別  Stackはstruct userのページの後半 2012/3/24 93
  • 95. PPDA - Per Processor Data Area  OSを読み解く場合に最初に注目する構造  プロセスなどの実行単位毎に割り当てる領域  UNIXの場合はuserとproc 2012/3/24 95
  • 96. 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
  • 97. 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
  • 98. 空間の切り替え機構 CPU PC アプリケーション カーネル PSW 00: カーネルモード text 11: ユーザモード text data 11用 00用 data APR0 APR0 APR1 APR1 bss APR2 APR2 bss APR3 APR3 APR4 APR4 APR5 APR5 APR6 APR6 struct user stack APR7 APR7 stack I/Oレジスタ 2012/3/24 98
  • 99. アプリケーションの動作時 PSW PC •PSWのモードはユーザ •PCはアプリのtextセグメントを指す text data bss user user user user kstack kstack kstack kstack IOレジスタ 1 text text text text data data data data bss bss bss bss stack stack stack stack 2012/3/24 99
  • 100. 割り込みの発生-空間の切り替え PSW PC •PSWのモードがカーネルに •アドレス空間の制御レジスタ text がカーネルモードに切り替わる data bss user user user user kstack kstack kstack kstack IOレジスタ 1 text text text text data data data data bss bss bss bss stack stack stack stack 2012/3/24 100
  • 101. 割り込みの発生-割り込みベクタ PSW PC •割り込みベクタのエントリを text 選択してPCに data bss user user user user kstack kstack kstack kstack IOレジスタ 1 text text text text data data data data bss bss bss bss •1のアドレスとpswをスタック に退避 stack stack stack stack 2012/3/24 101
  • 102. 割り込みの発生-割り込みベクタ PSW PC •割り込みベクタのエントリを text 選択してPCに data bss Vector device 004 Bus Timeout user user Illegal instruction 010 user user kstack kstackBpt-trace kstack 014 kstack 024 iot Vector device entry IOレジスタ 034 Power failur 060 Teletype input klin 114 Emulator tarp 064 Teletype output klou instruction 1 text text text 070 text Paper tape input pcin 240 11/10 parity data data data 074 data Paper tape output pcou 244 Floting point error bss bss bss 100 bss Line clock kwlp 250 Segmentation violation 104 Programmable clock kwlp stack stack stack200 stack Line printer lpou 220 RK disk driver rkio 2012/3/24 102
  • 103. 割り込みの発生ーハンドラの処理 PSW PC 2 text data bss user user user user kstack kstack kstack kstack IOレジスタ text text text text data data data data bss bss bss bss stack stack stack stack 2012/3/24 103
  • 104. 割り込みのからの復帰 PSW PC カーネル用 APR0 text APR1 data APR2 APR3 bss APR4 APR5 APR6 user user user user APR7 kstack kstack kstack kstack IOレジスタ アプリ用 •処理が終わったら、スタックのPCと 1 text text PSW復元して割り込み時点に復帰 text text APR0 APR1 data data data data APR2 APR3 bss bss bss bss APR4 APR5 APR6 stack stack stack stack APR7 2012/3/24 104
  • 105.  以上の説明は、割り込み発生時から、復帰ま でにプロセスの切り替えが発生しない場合  条件によっては以下の処理でプロセスの切り 替えが発生 1. procの検索と選択 2. user構造の切り替え 3. User構造+kstackに退避した状態の復元 4. アプリへの復帰 2012/3/24 105
  • 106. プロセスの切り替えー選択 PSW PC Procの検索(スケジューラ) text data ↑次に動かすアプリ(プロセス) bss のprocを見つける user user user user kstack kstack kstack kstack IOレジスタ text text text text data data data data bss bss bss bss stack stack stack stack 2012/3/24 106
  • 107. プロセスの切り替えーuserの切り替え PSW PC text data proc bss user user user user kstack kstack kstack kstack IOレジスタ text text text text data data data data bss bss bss bss stack stack stack stack 2012/3/24 107
  • 108. プロセスの切り替えーuserの切り替え PSW PC text data proc bss user user user user kstack kstack kstack kstack IOレジスタ アプリ用 空間管理用のレジスタを更新 APR0 text text text text APR1 data data data data APR2 APR3 bss bss bss bss APR4 APR5 APR6 stack stack stack stack APR7 2012/3/24 108
  • 109. プロセスの切り替えーモードの切り替え •PSWをユーザに切り替え PSW PC •PCを復元 •退避していた、PCとレジスタを復元 text data proc bss user user user user kstack kstack kstack kstack IOレジスタ アプリ用 APR0 text text text text APR1 data data data data APR2 APR3 bss bss bss bss APR4 APR5 APR6 stack stack stack stack APR7 2012/3/24 109
  • 110. プロセスの切り替えー完了 PSW PC text data proc bss user user user user kstack kstack kstack kstack IOレジスタ アプリ用 APR0 text text text text APR1 data data data data APR2 APR3 bss bss bss bss APR4 APR5 APR6 stack stack stack stack APR7 2012/3/24 110
  • 111. 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
  • 112. 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
  • 113. 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
  • 114. あやしい関数 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
  • 115. savu 0725: _savu: 0726: bis $340,PS 0727: mov (sp)+,r1 0728: mov (sp),r0 0729: mov sp,(r0)+ 0730: mov r5,(r0)+ bis $340,PSでbit5-7を1に bic $340,PSでbit5-7を0に 0731: bic $340,PS 0732: jmp (r1) 725: 727-728: 729-730: 732: r0 u.u_rsav r1 戻り先 r6→ 戻り先 戻り先 u. u.u_rsav r6→ u.u_rsav sp r5 r1 戻り先 2012/3/24 115
  • 116. retu 0740: _retu: 0745: 1: 0741: bis $340,PS 0746: mov (r0)+,sp 0742: mov (sp)+,r1 0747: mov (r0)+,r5 0743: mov (sp),KISA6 0748: bic $340,PS 0744: mov $_u,r0 0749: jmp (r1) 0413 struct user 0414 { 0415 int u_rsav[2]/* save r5,r6 when exchanging stacks */ 742: 743-744: 746-747: u. sp r6→ 戻り先 戻り先 r5 r6→ p_addr r6→ p_addr カーネル用 r6→ p_addr APR0 APR1 APR2 APR3 APR4 戻り先 r1 戻り先 APR5 p_addr r1 戻り先 r6 sp r0 u.u_rsav APR7 r0 u.u_rsav r5 r5 2012/3/24 116
  • 117. sureg 1739: sureg() 1747: up =- 8; 1740: { 1748: rp =- 8; 1741: register *up, *rp, a; 1749: } 1742: 1750: while(rp > &UISA->r[0]) 1743: a = u.u_procp->p_addr; 1751: *--rp = *--up + a; 1744: up = &u.u_uisa[16]; 1754: up = &u.u_uisd[16]; 1745: rp = &UISA->r[16]; 1755: rp = &UISD->r[16]; 1746: if(cputype == 40) { 1765: } アプリ用 APR0 u.u_uisa[0-7] APR1 APR2 APR3 u.u_uisd[0-7] APR4 アプリの空間を設定 APR5 APR6 APR7 2012/3/24 117
  • 118. 2012/3/24 118
  • 119. 勉強会の記録  日本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
  • 121. Simhのインストールと起動  Ubuntuの場合 $ sudo apt-get install simh  pdp-11のシュミレーション $ pdp11 PDP-11 simulator V3.8-1 sim> 2012/3/24 121
  • 122. 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
  • 123. 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
  • 124. 設定ファイルの作成  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
  • 125. Simhの起動 $ pdp11 unixv6.cfg PDP-11 simulator V3.8-1 Disabling XQ @unix Login: root # 2012/3/24 125
  • 126. Simhのdebug機能  simhモードへの移行と復帰 # Ctrl+E Simulation stopped, PC: 021630 (MOV (SP)+,177776) sim> c #  simhモードへはCtrl+Eで  シミュレーションモードへはcで 2012/3/24 126
  • 127. ディバック機能を使う  カーネルのシンボルアドレスを調べる # 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) savu()で止まった sim> 2012/3/24 127
  • 128. step実行 Breakpoint, PC: 021636 (SPL 6) sim> e r5,sp,pc R5: 141742 SP: 141730 PC: 021636 sim> s 0725: _savu: Step expired, PC: 021640 (MOV (SP)+,R1) sim> s 0726: bis $340,PS Step expired, PC: 021642 (MOV (SP),R0) sim> s 0727: mov (sp)+,r1 Step expired, PC: 021644 (MOV SP,(R0)+) sim> s 0728: mov (sp),r0 Step expired, PC: 021646 (MOV R5,(R0)+) 0729: mov sp,(r0)+ sim> s 0730: mov r5,(r0)+ Step expired, PC: 021650 (SPL 0) sim> s 0731: bic $340,PS Step expired, PC: 021652 (JMP (R1)) 0732: jmp (r1) 2012/3/24 128
  • 129. レジスタの調べ方 /usr/share/doc/simh/simh_doc.pdfで説明 e {xamine} <list> examine memory or registers sim> e state // レジスタ等すべてを表示 PC: 021630 V: 0 KIPDR4: 077406 SIPDR4: 000000 UIPDR4: 000000 R0: 140004 C: 0 KIPAR5: 001416 SIPAR5: 000000 UIPAR5: 000000 R1: 034272 PIRQ: 000000 KIPDR5: 077406 SIPDR5: 000000 UIPDR5: 000000 R2: 005336 STKLIM: 000000 KIPAR6: 001616 SIPAR6: 000000 UIPAR6: 000000 R3: 000200 FAC0H: 00000000000 KIPDR6: 077406 SIPDR6: 000000 UIPDR6: 000000 R4: 000000 FAC0L: 00000000000 KIPAR7: 007600 SIPAR7: 000000 UIPAR7: 001541 R5: 141724 FAC1H: 00000000000 KIPDR7: 077506 SIPDR7: 000000 UIPDR7: 066016 SP: 141710 FAC1L: 00000000000 KDPAR0: 000000 SDPAR0: 000000 UDPAR0: 001714 R00: 140004 FAC2H: 00000000000 KDPDR0: 077506 SDPDR0: 000000 UDPDR0: 000006 R01: 034272 FAC2L: 00000000000 KDPAR1: 000200 SDPAR1: 000000 UDPAR1: 000000 R02: 005336 FAC3H: 00000000000 KDPDR1: 077506 SDPDR1: 000000 UDPDR1: 000000 R03: 000200 FAC3L: 00000000000 KDPAR2: 000400 SDPAR2: 000000 UDPAR2: 000000 R04: 000000 FAC4H: 00000000000 KDPDR2: 077506 SDPDR2: 000000 UDPDR2: 000000 R05: 141724 FAC4L: 00000000000 KDPAR3: 000600 SDPAR3: 000000 UDPAR3: 000000 R10: 000000 FAC5H: 00000000000 KDPDR3: 077406 SDPDR3: 000000 UDPDR3: 000000 R11: 000000 FAC5L: 00000000000 KDPAR4: 001000 SDPAR4: 000000 UDPAR4: 000000 R12: 000000 FPS: 000004 KDPDR4: 077406 SDPDR4: 000000 UDPDR4: 000000 R13: 000000 FEA: 000000 KDPAR5: 001200 SDPAR5: 000000 UDPAR5: 000000 R14: 000000 FEC: 00 KDPDR5: 077406 SDPDR5: 000000 UDPDR5: 000000 R15: 000000 MMR0: 000201 KDPAR6: 001171 SDPAR6: 000000 UDPAR6: 000000 KSP: 141710 MMR1: 000000 KDPDR6: 077506 SDPDR6: 000000 UDPDR6: 000000 SSP: 000000 MMR2: 021626 KDPAR7: 007600 SDPAR7: 000000 UDPAR7: 001541 USP: 177756 MMR3: 000005 KDPDR7: 077506 SDPDR7: 000000 UDPDR7: 066016 PSW: 030000 KIPAR0: 000000 SIPAR0: 003612 UIPAR0: 001714 IREQ[0]: 00000000000 CM: 0 KIPDR0: 077406 SIPDR0: 000106 UIPDR0: 000006 TRAPS: 00000 PM: 3 KIPAR1: 000416 SIPAR1: 003700 UIPAR1: 000000 WAIT: 1 RS: 0 KIPDR1: 077506 SIPDR1: 000106 UIPDR1: 000000 STOP_TRAPS: 00001 FPD: 0 KIPAR2: 000616 SIPAR2: 000000 UIPAR2: 000000 STOP_VECA: 1 IPL: 0 KIPDR2: 077506 SIPDR2: 000000 UIPDR2: 000000 STOP_SPA: 1 T: 0 KIPAR3: 001016 SIPAR3: 000000 UIPAR3: 000000 PCQ[0]: 034412 N: 0 KIPDR3: 077506 SIPDR3: 000000 UIPDR3: 000000 WRU: 005 Z: 0 KIPAR4: 001216 SIPAR4: 000000 UIPAR4: 000000 2012/3/24 129
  • 130. 必要な内容に絞り込む PC,R0~R5,SP(KSP,USP) PSW KDPAR0~7 UDPAR0~7 PC: 021630 V: 0 KIPDR4: 077406 SIPDR4: 000000 UIPDR4: 000000 R0: 140004 C: 0 KIPAR5: 001416 SIPAR5: 000000 UIPAR5: 000000 R1: 034272 PIRQ: 000000 KIPDR5: 077406 SIPDR5: 000000 UIPDR5: 000000 R2: 005336 STKLIM: 000000 KIPAR6: 001616 SIPAR6: 000000 UIPAR6: 000000 R3: 000200 FAC0H: 00000000000 KIPDR6: 077406 SIPDR6: 000000 UIPDR6: 000000 R4: 000000 FAC0L: 00000000000 KIPAR7: 007600 SIPAR7: 000000 UIPAR7: 001541 R5: 141724 FAC1H: 00000000000 KIPDR7: 077506 SIPDR7: 000000 UIPDR7: 066016 SP: 141710 FAC1L: 00000000000 KDPAR0: 000000 SDPAR0: 000000 UDPAR0: 001714 R00: 140004 FAC2H: 00000000000 KDPDR0: 077506 SDPDR0: 000000 UDPDR0: 000006 R01: 034272 FAC2L: 00000000000 KDPAR1: 000200 SDPAR1: 000000 UDPAR1: 000000 R02: 005336 FAC3H: 00000000000 KDPDR1: 077506 SDPDR1: 000000 UDPDR1: 000000 R03: 000200 FAC3L: 00000000000 KDPAR2: 000400 SDPAR2: 000000 UDPAR2: 000000 R04: 000000 FAC4H: 00000000000 KDPDR2: 077506 SDPDR2: 000000 UDPDR2: 000000 R05: 141724 FAC4L: 00000000000 KDPAR3: 000600 SDPAR3: 000000 UDPAR3: 000000 R10: 000000 FAC5H: 00000000000 KDPDR3: 077406 SDPDR3: 000000 UDPDR3: 000000 R11: 000000 FAC5L: 00000000000 KDPAR4: 001000 SDPAR4: 000000 UDPAR4: 000000 R12: 000000 FPS: 000004 KDPDR4: 077406 SDPDR4: 000000 UDPDR4: 000000 R13: 000000 FEA: 000000 KDPAR5: 001200 SDPAR5: 000000 UDPAR5: 000000 R14: 000000 FEC: 00 KDPDR5: 077406 SDPDR5: 000000 UDPDR5: 000000 R15: 000000 MMR0: 000201 KDPAR6: 001171 SDPAR6: 000000 UDPAR6: 000000 KSP: 141710 MMR1: 000000 KDPDR6: 077506 SDPDR6: 000000 UDPDR6: 000000 SSP: 000000 MMR2: 021626 KDPAR7: 007600 SDPAR7: 000000 UDPAR7: 001541 USP: 177756 MMR3: 000005 KDPDR7: 077506 SDPDR7: 000000 UDPDR7: 066016 PSW: 030000 KIPAR0: 000000 SIPAR0: 003612 UIPAR0: 001714 IREQ[0]: 00000000000 CM: 0 KIPDR0: 077406 SIPDR0: 000106 UIPDR0: 000006 TRAPS: 00000 PM: 3 KIPAR1: 000416 SIPAR1: 003700 UIPAR1: 000000 WAIT: 1 RS: 0 KIPDR1: 077506 SIPDR1: 000106 UIPDR1: 000000 STOP_TRAPS: 00001 FPD: 0 KIPAR2: 000616 SIPAR2: 000000 UIPAR2: 000000 STOP_VECA: 1 IPL: 0 KIPDR2: 077506 SIPDR2: 000000 UIPDR2: 000000 STOP_SPA: 1 T: 0 KIPAR3: 001016 SIPAR3: 000000 UIPAR3: 000000 PCQ[0]: 034412 N: 0 KIPDR3: 077506 SIPDR3: 000000 UIPDR3: 000000 WRU: 005 Z: 0 KIPAR4: 001216 SIPAR4: 000000 UIPAR4: 000000 2012/3/24 130
  • 131. レジスタの指定方法 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
  • 132. MMUレジスタの指定方法 Stateの表示順に’-’で範囲を指定 sim> e KDPAR0-KDPDR7 KDPAR0: 000000 KDPDR0: 077506 KDPAR1: 000200 KDPDR1: 077506 Pdp11/40では、 KDPAR2: 000400 KDPDR2: 077506 KPAR,KPDRと呼んでい KDPAR3: KDPDR3: 000600 077406 たが、simhでは上位機種 KDPAR4: 001000 のレジスタ名で表示され KDPDR4: 077406 KDPAR5: 001200 るので、KDPAR,KDPDR KDPDR5: KDPAR6: 077406 001171 と読み替える KDPDR6: 077506 KDPAR7: 007600 KDPDR7: 077506 2012/3/24 132
  • 133. メモリの調べ方 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
  • 134. 表示フォーマットの指定 -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
  • 135. シンボルからアドレスを調べる sim> c //unixに戻る # nm /unix | grep main // mainのアドレス 022272T _main # nm /unix | grep proc 034476T _newproc 005206B _proc 043170T _procxmt 2012/3/24 135
  • 136. 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
  • 137. 自分のprocを見る#1 # nm /unix | grep _write 054124T _write Shellが#をwriteする箇所(カーネ 031700T _writei ルのエントリ)でbreakする 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
  • 138. 自分の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
  • 139. 自分のprocを見る#3 sim> e 147700/100 147700: 141746 u_rsav[0] 147702: 141756 u_rsav[1] 147704: 000200 u_fsav[0] 0413: struct user 0414: { 147706: 000000 1 0415: int u_rsav[2]; /* save r5,r6 when exchanging stacks */ 147710: 000000 2 0416: int u_fsav[25]; /* save fp registers */ 0417: /* rsav and fsav must be first in structure */ 147712: 000000 3 0418: char u_segflg; /* flag for IO; user or kernel space */ 0419: char u_error; /* return error code */ 147714: 000000 4 0420: char u_uid; /* effective user id */ 0421: char u_gid; /* effective group id */ 147716: 000000 5 0422: char u_ruid; /* real user id */ 0423: char u_rgid; /* real group id */ : 0424: int u_procp; /* pointer to proc structure */ : 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
  • 140. 自分のprocを見る#4 sim> e -h 5262/40 5262: 0103 p_flag/p_stat 0358: struct proc 5264: 0064 p_sig/p_pri 0359: { 5266: 7F00 p_time/p_uid 0360: char p_stat; 5270: 0000 p_cpu 0361: char p_flag; 0362: char p_pri; /* priority, negative is high */ 5272: 42F2 p_ttyp 0363: char p_sig; /* signal number sent to this process * 5274: 000E p_pid 0364: char p_uid; /* user id, used to direct tty signals */ 0365: char p_time; /* resident time for scheduling */ 5276: 0001 p_ppid 0366: char p_cpu; /* cpu usage for scheduling */ 5300: 033F 0367: char p_nice; /* nice for scheduling */ 5302: 0048 0368: int p_ttyp; /* controlling tty */ 0369: int p_pid; /* unique process id */ 5304: 0000 0370: int p_ppid; /* process id of parent */ 5306: 0EDC 0371: int p_addr; /* address of swappable image */ 0372: int p_size; /* size of swappable image (*64 bytes) 5310: 0000 0373: int p_wchan; /* event process is awaiting */ 5312: 00CE 0374: int *p_textp; /* pointer to text structure */ 0375: 5314: 0000 pidは0xe=14(10進) 0376: } proc[NPROC]; 5316: 0000 5320: 0000 2012/3/24 140
  • 141. 自分のprocを見る#5 Breakpoint, PC: 054104 (JSR R5,22240) sim> nobreak 54104 sim> c # ps 14 - 29 ps # pidは0xe=14(10進) 2012/3/24 141