SlideShare uma empresa Scribd logo
1 de 39
V7から始めるUNIX
        まとめ
予備知識であるCPUアーキテクチャのほん
 のさわりを説明したあと、本題に入ります
予備知識
• コンピュータ・アーキテクチャについて
 – 低レイヤのプログラムの理解に欠かせない
 – 理想を言えば、網羅的に知っておくことが好ましい
   • ハードとソフトは両輪だから
 – ただし、技術の範囲が広大すぎて、とてもここでは扱いき
   れない
 – 疑問が出た都度、身近な専門家に声をかけて聞くと、きっ
   と親切に教えてくれる!←学校か職場の専門家が誰か、
   把握しておこう!
   • 私も知っている範囲で答えます
 – ここではCPUの基本構成、マシン語から演算器で実行さ
   れる手順にフォーカスして、次ページ以降で少しだけさわ
   る

                                2
CPUの基本構成、超ざっくり
• 参考情報※の本文が、非
  常に素晴らしいので、そち
  らに詳細の解説はゆずり
  ます
   – CPUは大きく、演算部と制
     御部から構成されます
   – CPUにはメモリが接続され
     ています
   – ROMには、コンパイラに
     よってプログラムから変換
     され、CPUが実行可能な
     マシン語に変換されたデー
     タが入っています

※参考:http://homepage2.nifty.com/ttoyoshima/Computer/Config.htm
                                                          3
マシン語
• プログラム言語はコンパイラによってCPUが直接理
  解し実行できるマシン語に変換される
• マシン語は、CPUで処理される(命令パイプライン)
• マシン語の例
参考情報
http://www.geocities.jp/mori_imms/asmDetail.html
http://msyk.net/keio/JavaBook/ch1.html




                                                   4
命令パイプライン(1/2)
• 汎用パイプラインについて説明する
• 次ページの図は、一般化した次のような4段のパイプライン
  を示している。
• フェッチ (Fetch):メモリから機械語を取り出してくる動作
• デコード (Decode):機械語を解読し、制御信号を送る
• 実行 (Execute):実行する
• ライトバック (Write-back):実行結果をファイルかメモリに書き
  込む
• 次ページの図の上にある灰色の矩形には実行を待っている
  命令が並んでいる。下の灰色の矩形には実行が完了した命
  令が並んでいる。真ん中の矩形がパイプラインを表している。
• 実行は次ページのようになる。
参考:Wikipedia
                                   5
命令パイプライン(2/2)
    説明
0   4つの命令が実行されるのを待っている。
1   緑の命令をメモリからフェッチする。
    緑の命令をデコードする。
2
    紫の命令をメモリからフェッチする。
    緑の命令を実行する(実際の命令処理を行う)
3   紫の命令をデコードする。
    青の命令をフェッチする。
    緑の命令の結果をレジスタファイルかメモリに書き込む
    紫の命令を実行する。
4
    青の命令をデコードする。
    赤の命令をフェッチする。
    緑の命令は完了した。
    紫の命令の結果を書き込む。
5
    青の命令を実行する。
    赤の命令をデコードする。
    紫の命令は完了した。
6   青の命令の結果を書き込む。
    赤の命令を実行する。
    青の命令は完了した。
7
    赤の命令の結果を書き込む。
8   赤の命令は完了した。
9   全命令を実行した。
                                6
• 示した例は、一般的な例です
• 実際はもっと複雑で、いろいろ工夫されています
• 例えば
 – http://www.slideshare.net/schnee_rosa/20110611-
   v7unixb
• 気に入っている、または気になるチップのアーキ
  テクチャを調べていくと、楽しいです
 – チップメーカーは大抵、開発者向けのホワイトペー
   パーを出しています
 – わからない専門用語は、専門家に聞こう!
    • 私も知っている範囲で答えます

                                                     7
V7の理解(1/4)
• 現在のLinuxの原点はV7
  – V7→BSD→Linux
• V7を読み解くことで、原理の理解を進めることを
  目的とする
• 今回は、V7の理解の一環として、まず
  root/h/user.hとroot/sys/slp.cの実装を読み解い
  ていく
  – slp.cはスワッピングについて記載されており、プロセ
    ス制御の基本です

   参照したソースコード: http://www.tamacom.com/tour/kernel/unix/
                                                          8
V7の理解(2/4)
• V7ではハードが限定されていたため、可搬性に
  ついて考慮していない
 – DECのPDP-11などで動作した
• しかしC言語で書かれているため、移植性は高
  い
• 歴史についての参考資料
 http://ja.wikipedia.org/wiki/Version_7_Unix
• ソースコードは簡単シンプル、注釈が丁寧で読
  みやすいです…
 – ただしK&Rで書かれているっぽい
 – マジックナンバーがあればそれは8進数
                                               9
全体の超概略(推測入ってるところ/未確認は
             V7の理解(3/4)            黄色でハッチ。習ってるところは赤ハッチ)

ソースファイル     役割                                        代表的な関数
acct.c      プロセスがCPUを使用した状況をファイルに記載するためのもの?           acct,sysacct
alloc.c     メモリディスク?の割りあて、解放を行う                       alloc,free
clock.c     ?(現在の役割と一緒か否か?)                           clock,timeout
fakemx.c    ユーザ定義関数か何かのような気がする
fio.c       ファイルに定義されている関数をロードするためのもの?                getf
iget.c      ファイル操作を行うため、パス名をinodeに変換する。               iget
machdep.c   ブートストラップを行う                               startup
main.c      システムの初期化を行う                               main
malloc.c    現在と定義が変わっていないだろうか?                        malloc,mfree
nami.c      inodeのパス名をポインタに変換。iget.cとペアか?             namei
pipe.c      パイプを行う                                    pipe
prf.c       標準出力を行う(なぜにパニックがここに)                      printf
prim.c      今の標準関数と同じなら、キャラクタリスト=文字列のgetとput          getc,putc
rdwri.c     inodeポインタに対する読み書き                         readi,writei
sig.c       シグナル。割り込みに使う。tty.cから呼ばれる                  signal
slp.c       資源を排他的に利用するため、カーネル内の同期を実現                 sleep,wakeup
subr.c      inodeのポインタに読み書き可能なブロックを割り当てる?             bmap
sys1.c      プロセス操作系システムコール                            exec,fork等
sys2.c      ファイル操作系システムコール                            read,write等
sys3.c      ファイルの状態(どこのデバイスか、所有者、アクセス権)を取得するシステムコール   fstat
sys4.c      上記以外のシステムコール                              いろいろ
text.c      プロセスのスワップアウトを行う                           xswap
trap.c      シグナルを補足し、指定の処理を行う                         trap
ureg.c      これよくわからない…                                sureg
                                                             10
V7の理解(4/4)
ヘッダファイル    役割                                    構造体
acct.h     プロセスのアカウント情報をファイルに書き出せるようにする          acct
buf.h      リングバッファ?ブロックデバイスのバッファ                 buf
callo.h    クロックから中断されコールアウトする?                   callo
conf.h     ブロックデバイス、キャラクタデバイスのスイッチングを宣言する        cdevsw,bdevsw
dir.h      ディレクトリ情報管理用?                          diect
fblk.h     ?                                     fblk
file.h     inodeのファイル管理用構造体?                     file
filsys.h   fileを束ねたもの?                           filsys
ino.h      disk block上でのinode用構造体                dinode
inode.h    inode構造体                              inode
map.h      メモリマップの構造体、coreとswapの2つ               map
mount.h    マウント用構造体(デバイスのか?)                     mount
mpx.h      これちょっとわからない
mx.h       これもちょっとわからない
pack.h     これもマジわからない                            pack
pk.h       上のpack.hと同じ構造体が入ってる??                 pack?
proc.h     プロセスの状態や管理情報を保持                       proc
pwd.h      ?全体の文脈からしてパスワードの変更ではなさそうな気が           passwd
stat.h     inodeの状態を知る?                          stat
system.h   システムエントリテーブルの定義(何か実行させたいときここを参照する)    sysent
text.h     スワップの際のディスクアドレスなどを格納                  text
timeb.h    ftimeシステムコールの戻り値(gettimeofdayの代わり?)   timeb
tty.h      キャラクタ端末制御用?                           tty
                                                                 11
user.h     プロセスが扱うプログラムやデータを保持                   user
user.h(1/5)
               冒頭の注釈
                                        (注釈のまんま)
 ↓左端の数値は行番号                             ・user構造体を定義している
                                        ・プロセスあたり1つ持つ
 1 /*                                   ・1プロセスあたりの全データであ
 2 * The user structure.                る
 3 * One allocated per process.         ・プロセスがスワップしている間は、
 4 * Contains all per process data      参照しなくてよい
                                        ・ユーザのブロック長はUSIZE×64
 5 * that doesn't need to be referenced
                                        でこれはスタックポインタ用に使わ
 6 * while the process is swapped.      れる
 7 * The user block is USIZE*64 bytes ・仮想カーネルのデータ長は
 8 * long; resides at virtual kernel    140000 (ユーザ毎のシステムス
 9 * loc 140000; contains the system    タック含む)
10 * stack per user; is cross referenced・同じプロセスの中では、proc構造
                                        と相互参照の関係にある
11   * with the proc structure for the
12   * same process.
13   */                                                12
14
15 #define EXCLOSE 01
                                                                  user.h(2/5)
 16
17 struct user
18 {
19            label_t u_rsav;                            /* save info when exchanging stacks */
20       int    u_fper;               /* FP error register */
                                                                             退避時にスタックポインタを格納
21       int    u_fpsaved;              /* FP regs saved for this proc */
22            struct {
23              int    u_fpsr;        /* FP status register */
24              double u_fpregs[6]; /* FP registers */                         ファイルI/O用の変数
25       } u_fps;
26       char u_segflg;                 /* IO flag: 0:user D; 1:system; 2:user I */ファイルI/Oの属性等
27       char u_error;                  /* return error code */                    Dはデータ、I、は命令
28       short u_uid;                  /* effective user id */                     systemはカーネルに相当
29       short u_gid;                  /* effective group id */
                                                                                   userはプロセスユーザと同義
30       short u_ruid;                 /* real user id */
31       short u_rgid;                 /* real group id */                              proc構造体ポインタ
32            struct proc *u_procp;                       /* pointer to proc structure */
33       int    *u_ap;                /* pointer to arglist */                 システムコールの引数リスト
34            union {                                     /* syscall return values */
35                       struct {
36                     int    r_val1;                               システムコールの戻り値
37                     int    r_val2;                               例えばLinuxのコマンド
38                       };                                         ls –laとかで得られる
39                       off_t      r_off;
                                                                    一覧のデータを格納
40                       time_t r_time;                                                           13
41       } u_r;                                                     しておく
user.h(3/5)
42       caddr_t u_base;                           /* base address for IO */
                                                                        プロセスユーザのI/Oの開始ア
43   unsigned int u_count;         /* bytes remaining for IO */
44       off_t       u_offset;
                                                                        ドレス、オフセット、どこのディ
                                                   /* offset in file for IO */
45       struct inode *u_cdir;                                          レクトリにあるか、パス名(この
                                                    /* pointer to inode of current directory */
46       struct inode *u_rdir;                                          ころは物理アドレス空間を直
                                                    /* root directory of current process */
47       char         u_dbuf[DIRSIZ];                                   接扱っていた?)
                                                    /* current pathname component */
48       caddr_t u_dirp;                           /* pathname pointer */
49       struct direct u_dent;                      /* current directory entry */
50       struct inode *u_pdir;                      /* inode of parent directory of dirp */
51   int     u_uisa[16];        /* prototype of segmentation addresses */
52   int     u_uisd[16];                                                ファイルI/O
                                /* prototype of segmentation descriptors */
53       struct file *u_ofile[NOFILE];              /* pointers to file structures of open files *
                                                                        (ちょっと詳細がわからない)
54       char         u_pofile[NOFILE];             /* per-process flags of open files */
55   int     u_arg[5];         /* arguments to current system call */
56   unsigned u_tsize;            /* text size (clicks) */
57   unsigned u_dsize;            /* data size (clicks) */              現在のシステムコール戻り値
58   unsigned u_ssize;            /* stack size (clicks) */
                                                                        テキスト(プログラム)、データ
59   label_t u_qsav;            /* label variable for quits and interrupts */
60   label_t u_ssav;            /* label variable for swapping */
                                                                        (固定値)、スタック(call時のP
61   int     u_signal[NSIG];     /* disposition of signals */           C値の格納等)のサイズ、ス
62   time_t u_utime;             /* this process user time */           ワップや退避時のラベル値
63   time_t u_stime;             /* this process system time */
64   time_t u_cutime;            /* sum of childs' utimes */            システムコールの戻り値
65   time_t u_cstime;            /* sum of childs' stimes */            プロセスおよび子プロセスの
66   int     *u_ar0;            /* address of users saved R0 */         CPU使用時間など         14
user.h(4/5)
75          struct tty *u_ttyp;                     /* controlling ttytty(キャラクタ端末)制御用ポイ
                                                                       pointer */
76          dev_t     u_ttyd;                      /* controlling tty ンタとデバイス制御用情報
                                                                      dev */
77          struct {                                /* header of executable file */
78            int    ux_mag;      /* magic number */
79            unsigned ux_tsize;   /* text size */
80            unsigned ux_dsize;    /* data size */                     これはわからない…
81            unsigned ux_bsize;    /* bss size */
82            unsigned ux_ssize;    /* symbol table size */
                                                                        実行するプログラムの
83            unsigned ux_entloc;   /* entry location */                情報(予備?)か何かか
84            unsigned ux_unused;
85            unsigned ux_relflg;
86      } u_exdata;
87          char       u_comm[DIRSIZ];
88          time_t u_start;
89      char u_acflag;
90      short u_fpflag;           /* unused now, will be later */    予備用(互換性を取るため?)
91      short u_cmask;             /* mask for file creation */
92      int    u_stack[1];
93                                       /* kernel stack per user
94                                        * extends from u + USIZE*64
95                                        * backward not to reach here
96                                        */
97 };
 98                                                                              15
user.h(5/5)
                          エラーコードの定義

101 /* u_error codes */       118 #define EEXIST 17
102 #define EPERM 1           119 #define EXDEV 18
103 #define ENOENT 2          120 #define ENODEV 19
104 #define ESRCH 3           121 #define ENOTDIR 20
105 #define EINTR 4           122 #define EISDIR 21
106 #define EIO   5           123 #define EINVAL 22
107 #define ENXIO 6           124 #define ENFILE 23
108 #define E2BIG 7           125 #define EMFILE 24
109 #define ENOEXEC 8         126 #define ENOTTY 25
110 #define EBADF 9           127 #define ETXTBSY 26
111 #define ECHILD 10         128 #define EFBIG 27
112 #define EAGAIN 11         129 #define ENOSPC 28
113 #define ENOMEM 12         130 #define ESPIPE 29
114 #define EACCES 13         131 #define EROFS 30
115 #define EFAULT 14         132 #define EMLINK 31
116 #define ENOTBLK 15        133 #define EPIPE 32
117 #define EBUSY 16          134 #define EDOM       33
                              135 #define ERANGE 34
                                                          16
1 /*
2 * One structure allocated per active
3 * process. It contains all data needed
                                                  proc.h(1/3)
4 * about the process while the
5 * process may be swapped out.                              アクティブなプロセス毎に割り当てられる
6 * Other per process data (user.h)                          構造体
7 * is swapped with the process.                             アクティブ=実行待ちと実行中のプロセス
8 */                                                         running=実行中のプロセス
9 struct proc {
                               状態をあらわす                       で理解はあっているか?
10      char p_stat;
11      char p_flag;           ようだが詳細不明                      スワップアウトしても退避せず保持する?
12      char p_pri;        /* priority, negative is high */
13      char p_time;         /* resident time for scheduling */
14      char p_cpu;         /* cpu usage for scheduling */
15      char p_nice;        /* nice for cpu usage */
16      short p_sig;       /* signals pending to this process */
17      short p_uid;        /* user id, used to direct tty signals */
18      short p_pgrp;        /* name of process group leader */
19      short p_pid;        /* unique process id */
20      short p_ppid;        /* process id of parent */
21      short p_addr;        /* address of swappable image */
22      short p_size;       /* size of swappable image (clicks) */
23      caddr_t p_wchan;         /* event process is awaiting */
24      struct text *p_textp; /* pointer to text structure */
25      struct proc *p_link; /* linked list of running processes */
26      int p_clktim;       /* time to alarm clock signal */
                                                                              17
27 };
proc.h(2/3)                               プロセスの状態をあらわすマクロ定数

 29 extern struct proc proc[]; /* the proc table itself */
 30
 31 /* stat codes */
 32 #define SSLEEP 1           /* awaiting an event */
 33 #define SWAIT 2            /* (abandoned state) */
 34 #define SRUN 3            /* running */
 35 #define SIDL 4           /* intermediate state in process creation */
 36 #define SZOMB 5             /* intermediate state in process termination
*/
 37 #define SSTOP 6            /* process being traced */
 38
 39 /* flag codes */
 40 #define SLOAD 01            /* in core */
 41 #define SSYS 02           /* scheduling process */
 42 #define SLOCK 04            /* process cannot be swapped */
 43 #define SSWAP 010            /* process is being swapped out */
 44 #define STRC 020            /* process is being traced */
 45 #define SWTED 040             /* another tracing flag */
 46 #define SULOCK 0100            /* user settable lock in core */
 47                                                                            18
proc.h(3/3)
49 * parallel proc structure
50 * to replace part with times
51 * to be passed to parent process
52 * in ZOMBIE state.
53 */
54 struct xproc {
                                                          ゾンビ(実行終了中)プロセス用構造体
55      char xp_stat;                                     なぜわざわざ用意するのだろうか?
56      char xp_flag;
57      char xp_pri;       /* priority, negative is high */
58      char xp_time;        /* resident time for scheduling */
59      char xp_cpu;         /* cpu usage for scheduling */
60      char xp_nice;        /* nice for cpu usage */
61      short xp_sig;       /* signals pending to this process */
62      short xp_uid;       /* user id, used to direct tty signals */
63      short xp_pgrp;        /* name of process group leader */
64      short xp_pid;       /* unique process id */
65      short xp_ppid;        /* process id of parent */
66      short xp_xstat;      /* Exit status for wait */
67      time_t xp_utime;        /* user time, this proc */
68      time_t xp_stime;       /* system time, this proc */
69 };
                                                                         19
slp.c
• プロセスの制御を行う関数群(スリープと起動)
• 以下の関数について定義している(★は注目すべき関数)
 – ★sleep:プロセスの実行を中断し、プロセッサを明け渡す
 – ★wakeup:sleep中のプロセスを起こす
 – setrun:プロセスが実行できるようにする(スワップインできるよ
   うにする)
 – setpri:プロセスユーザの優先度をセットする関数
 – sched:スワッピングのメイン関数
 – swapin:プロセスをスワップインさせる関数
 – qswitch:プロセスキューの設定を行う関数
 – switch:CPUのリスケジュール(資源の再割り当て)を行う場合
   に呼び出す
 – newproc:新しいプロセスを立ち上げる(fork?)
 – expand:データとスタックのサイズを変える
 – setrq:
                                   20
27 sleep(chan, pri)
  /* */
28 caddr_t chan;                                                            sleep(1/2)
29 {                                               12 #define SQSIZE 0100 /* Must be power of 2 */
30      register struct proc *rp;                   13 #define HASH(x) (( (int) x >> 5) & (SQSIZE-1))
31      register s, h;                              14 struct proc *slpque[SQSIZE];
                                                    15
32                                                  16 /*
33      rp = u.u_procp;                             17 * Give up the processor till a wakeup occurs
                              プライオリティを上げて
34      s = spl6();                                 18 * on chan, at which time the process
35      if (chan==0)          割り込みを禁止する             19 * enters the scheduling queue at priority pri.
                                                    20 * The most important effect of pri is that when
36            panic("zero wchan");                  21 * pri<=PZERO a signal cannot disturb the sleep;
37      rp->p_stat = SSLEEP;                        22 * if pri>PZERO signals will be processed.
                                                    23 * Callers of this routine must be prepared for
38      rp->p_wchan = chan;                         24 * premature return, and check that the reason for
39      if (chan==0)                                25 * sleeping has gone away.
40            panic("Sleeping on wchan 0");         26 */
41      rp->p_pri = pri;
42      h = HASH(chan);              ここでいうハッシュは、5ビットシフトとマスク
43      rp->p_link = slpque[h];      プライオリティが低く
44      slpque[h] = rp;              シグナルを受けている(??)時は次ページに飛んで
45      if(pri > PZERO) {
                                     sleepのためにリジュームする
46            if(issig()) {
47                  rp->p_wchan = 0;
48                  rp->p_stat = SRUN;
49                  slpque[h] = rp->p_link;
50                  spl0();
51                  goto psig;
                                                                                                 21
52            }
53           spl0();
54
55
              if(runin != 0) {
                    runin = 0;
                                                    sleep(2/2)
56                  wakeup((caddr_t)&runin); 走れるプロセスがあれば起こす
57            }
58            swtch();
59            if(issig())
60                  goto psig; シグナルを受けていればリジュームする
61      } else {
62            spl0();
63            swtch();
64      }
65      splx(s);
                            プライオリティを元に戻す
66      return;
67
68      /*
69       * If priority was low (>PZERO) and   以降は、まだなぞの動作
70       * there has been a signal,
71       * execute non-local goto to
72       * the qsav location.
73       * (see trap1/trap.c)
74       */
75 psig:
76      resume(u.u_procp->p_addr, u.u_qsav);
77 }
                                                              22
82 wakeup(chan)
  /* */
83 register caddr_t chan;
84 {
85      register struct proc *p, *q;
                                                    wakeup(1/1)
86      register i;
87      int s;
88
89      s = spl6();
90      i = HASH(chan);
91      p = slpque[i];
92      q = NULL;
93      while(p != NULL) {
94           if(p->p_wchan==chan && p->p_stat!=SZOMB) {
95                 struct proc *sp;
96                                                    スリープキューに貯まっている
97                 if (q == NULL)                     プロセスを検出する(ゾンビ以外)
98                       sp = slpque[i] = p->p_link;
99                 else
100                       sp = q->p_link = p->p_link;
101                 p->p_wchan = 0;
102                 setrun(p);                ここでプロセスを起こしている?
103                 p = sp;
104                 continue;
105            }
106            q = p;
107            p = p->p_link;
108      }
109      splx(s);
110 }                                                                    23
136   /*
137     * Set the process running;
138
139
140
        * arrange for it to be swapped in if necessary.
        */
      setrun(p)
                                                          setrun(1/1)
141   register struct proc *p;
142   {
143            register caddr_t w;
144
145           if (p->p_stat==0 || p->p_stat==SZOMB)
146               panic("Running a dead proc");
147           /*
148             * The assignment to w is necessary because of
149             * race conditions. (Interrupt between test and use)
150             */
151           if (w = p->p_wchan) {
152                    wakeup(w);                ここでプロセスを起こしている
153                    return;
154           }
155           p->p_stat = SRUN;
156           setrq(p);                           プロセスを起こさない場合。
157           if(p->p_pri < curpri)
158               runrun++;
159           if(runout != 0 && (p->p_flag&SLOAD) == 0) {
160               runout = 0;
161                       wakeup((caddr_t)&runout);
162           }
                                                                        24
163 }
165
166
      /*
        * Set user priority.
                                                  setpri
167     * The rescheduling flag (runrun)
168     * is set if the priority is better
169     * than the currently running process.
170     */
171   setpri(pp)
172   register struct proc *pp;
173   {
174       register p;                      数値が8進であることに注意!
175
                                           ユーザプロセスの優先度を設定する
176            p = (pp->p_cpu & 0377)/16;
177            p += PUSER + pp->p_nice - NZERO;
178       if(p > 127)
179              p = 127;
180            if(p < curpri)
181             runrun++;
182            pp->p_pri = p;
183       return(p);
184 }
185
                                                           25
202 sched()
203 {
204           register struct proc *rp, *p;
                                                                        sched(1/3)
205           register outage, inage;                                ところどころに出てくる、
206
207
         int maxsize;                                                プロセスのスワップをする関数。spl*の*が
208           /*                                                     大きいほど優先度が高く、6が最高。
209            * find user to swap in;
210            * of users ready, select one out longest
                                                                     他から割りこみが入って状態が
211            */                                                    変わらないようにしたい場合にこうする。
212
213 loop:                                                            ここでは最高優先度まで上げて以降の
214       spl6();                                                    操作を行っている
215       outage = -20000;
216           for (rp = &proc[0]; rp < &proc[NPROC]; rp++)
217           if (rp->p_stat==SRUN && (rp->p_flag&SLOAD)==0 &&         プロセスの状態を総なめして
218                rp->p_time - (rp->p_nice-NZERO)*8 > outage) {
219                    p = rp;                                         ステータスが実行可能状態で
220                    outage = rp->p_time - (rp->p_nice-NZERO)*8;     優先度が一番高いものを検出
221           }
222           /*                                                       (スワップイン候補を探す)
223             * If there is no one there, wait.
224             */
225      if (outage == -20000) {
226             runout++;                                      上記条件にあうプロセスが検出できなけれ
227                        sleep((caddr_t)&runout, PSWP);
228                goto loop;                                  ば、sleepを呼び出して待つ
229           }
230      spl0();
231
232           /*                                                     優先度を最低に戻す
233            * See if there is core for that process;
234            * if so, swap it in.
235            */
236
237           if (swapin(p))                                    プロセスに割り当てられる資源(メモリなど)
238                goto loop;                                   があればスワップインする     26
240        /*
                                                   sched(2/3)
241         * none found.
242         * look around for core.
243         * Select the largest of those sleeping
244         * at bad priority; if none, select the oldest.
245         */
246
247   spl6();
248        p = NULL;
249   maxsize = -1;
250   inage = -1;
251        for (rp = &proc[0]; rp < &proc[NPROC]; rp++) {
252                if (rp->p_stat==SZOMB
253                 || (rp->p_flag&(SSYS|SLOCK|SULOCK|SLOAD))!=SLOAD)
254                        continue;                                                   CPUに割り当
255                if (rp->p_textp && rp->p_textp->x_flag&XLOCK)
256                        continue;                                                   てる候補と資
257                if (rp->p_stat==SSLEEP&&rp->p_pri>=PZERO || rp->p_stat==SSTOP) {    源がない状
258                        if (maxsize < rp->p_size) {
259                                p = rp;                                             態。一番最初
260                                maxsize = rp->p_size;                               にsleepしたプ
261                        }
262                } else if (maxsize<0 && (rp->p_stat==SRUN||rp->p_stat==SSLEEP)) {   ロセスを総な
263                        if (rp->p_time+rp->p_nice-NZERO > inage) {                  めして検出す
264                                p = rp;
265                                inage = rp->p_time+rp->p_nice-NZERO;                る(優先的に
266                        }
                                                                                       スワップさせ
267                }
268        }                                                                           るため)
269   spl0();
270        /*                                                                               27
sched(3/3)
270         /*
271          * Swap found user out if sleeping at bad pri,
272          * or if he has spent at least 2 seconds in core and
273          * the swapped-out process has spent at least 3 seconds out.
274          * Otherwise wait a bit and try again.
275          */
276         if (maxsize>=0 || (outage>=3 && inage>=2)) {
                                                           CPUに割り当てられていた
277                 p->p_flag &= ~SLOAD;
278                 xswap(p, 1, 0);
                                                           時間が2秒以上、または
279             goto loop;                        低い優先度でsleepしていれば
280         }                                     スワップを行う
281     spl6();
282     runin++;
283         sleep((caddr_t)&runin, PSWP);
284     goto loop;
285 }
286




                                                                           28
292 swapin(p)
293 register struct proc *p;
294 {
                                                           swapin
295         register struct text *xp;
296     register int a;
297     int x;
298
299          if ((a = malloc(coremap, p->p_size)) == NULL)
300                  return(0);
301          if (xp = p->p_textp) {
302                  xlock(xp);
303                  if (xp->x_ccount==0) {
304                          if ((x = malloc(coremap, xp->x_size)) == NULL) {
305                                  xunlock(xp);
306                                  mfree(coremap, p->p_size, a);
307                                  return(0);
308                          }
309                          xp->x_caddr = x;
310                          if ((xp->x_flag&XLOAD)==0)
311                                  swap(xp->x_daddr,x,xp->x_size,B_READ);
312                  }
313                  xp->x_ccount++;                   スワップアウトしたプロセスを
314                  xunlock(xp);
                                                       スワップインさせている
315          }
316          swap(p->p_addr, a, p->p_size, B_READ);    coremap,swapmapとは何か?
317          mfree(swapmap, ctod(p->p_size), p->p_addr);
318          p->p_addr = a;
319          p->p_flag |= SLOAD;
320          p->p_time = 0;
321          return(1);                                                         29
qswitch
324 /*
325 * put the current process on
326 * the Q of running processes and
327 * call the scheduler.
328 */
329 qswtch()
330 {
331
332            setrq(u.u_procp);
                                   プロセスをキューに放り込む?
333      swtch();
334 }
335


                                                    30
347 swtch()
348 {
349
350
352
         register n;
              register struct proc *p, *q, *pp, *pq;
              /*
                                                                            switch(1/2)
353            * If not the idle process, resume the idle process.
354            */
355           if (u.u_procp != &proc[0]) {
356                   if (save(u.u_rsav)) {
357                    sureg();
358                               return;
359                      }
360                      if (u.u_fpsaved==0) {
361                              savfp(&u.u_fps);
                                                                            プロセスを切り替える。
362                              u.u_fpsaved = 1;                           これは、最初に、sched()で呼ば
363                      }                                                  れたswitchがproc0をresumeす
364                      resume(proc[0].p_addr, u.u_qsav);
365           }
                                                                            る場合のルーチン
366      /*
367       * The first save returns nonzero when proc 0 is resumed
368       * by another process (above); then the second is not done
369       * and the process-search loop is entered.
370       *
371       * The first save returns 0 when swtch is called in proc 0
372       * from sched(). The second save returns 0 immediately, so
373       * in this case too the process-search loop is entered.
374       * Thus when proc 0 is awakened by being made runnable, it will
375       * find itself and resume itself at rsav, and return to sched().
376       */
377      if (save(u.u_qsav)==0 && save(u.u_rsav))                                              31
378             return;
379 loop:
380       spl6();
381       runrun = 0;


                                                                                      switch(2/2)
382            pp = NULL;
383            q = NULL;
384       n = 128;
385            /*
386              * Search for highest-priority runnable process
387              */
388            for(p=runq; p!=NULL; p=p->p_link) {
389                     if((p->p_stat==SRUN) && (p->p_flag&SLOAD)) {
390                             if(p->p_pri < n) {
391                                     pp = p;
392                                     pq = q;
393                                     n = p->p_pri;
394                             }                                                順次プロセスの状態を調べ
395                     }
396                     q = p;                                                   て実行可能かつ最も優先
397
398
               }
               /*
                                                                                 度が高いプロセスを選択し
399              * If no process is runnable, idle.                              ている
400              */
401            p = pp;                                                           該当がない場合、いったん
402
403
               if(p == NULL) {
                    idle();
                                                                                 idle()してまたループする
404                 goto loop;
405            }
406            q = pq;
407            if(q == NULL)
408                    runq = p->p_link;
409            else
410                    q->p_link = p->p_link;
411            curpri = n;
412       spl0();
413            /*
414             * The rsav (ssav) contents are interpreted in the new address space
415             */
416            n = p->p_flag&SSWAP;
417            p->p_flag &= ~SSWAP;
418            resume(p->p_addr, n? u.u_ssav: u.u_rsav);
419 }                                                                                              32
421 /*
422 * Create a new process-- the internal version of
423 * sys fork.
424 * It returns 1 in the new process, 0 in the old.
                                                             newproc(1/4)
425 */
426 newproc()
427 {
428             int a1, a2;
429             struct proc *p, *up;
430             register struct proc *rpp, *rip;
431       register n;
432
433             p = NULL;
434             /*
435              * First, just locate a slot for a process
436              * and copy the useful info from this process into it.
437              * The panic "cannot happen" because fork has already
438              * checked for the existence of a slot.
439              */
440 retry:
441        mpid++;
442        if(mpid >= 30000) {        30000の数字の意味が不明
443               mpid = 0;
444               goto retry;
445             }
446             for(rpp = &proc[0]; rpp < &proc[NPROC]; rpp++) {
447                     if(rpp->p_stat == NULL && p==NULL)
448                             p = rpp;
449                     if (rpp->p_pid==mpid || rpp->p_pgrp==mpid)
450                     goto retry;
451             }                                    新しいプロセスが割り当てられるか
452             if ((rpp = p)==NULL)                 pidを調べている           33
453              panic("no procs");
455   /*
456    * make proc entry for new proc
457
458
       */
                              newproc(2/4)
459   rip = u.u_procp;
460   up = rip;
461   rpp->p_stat = SRUN;
462   rpp->p_clktim = 0;
463   rpp->p_flag = SLOAD;
464   rpp->p_uid = rip->p_uid;
                                     新しいプロセスの割りあて
                                     資源などの情報は
465   rpp->p_pgrp = rip->p_pgrp;
                                     親プロセスのをコピーしている
466   rpp->p_nice = rip->p_nice;
                                     forkのことか?
467   rpp->p_textp = rip->p_textp;
468   rpp->p_pid = mpid;
469   rpp->p_ppid = rip->p_pid;
470   rpp->p_time = 0;
471   rpp->p_cpu = 0;
472
473   /*
474    * make duplicate entries
475    * where needed
476    */
                                                 34
477
478   for(n=0; n<NOFILE; n++)
479            if(u.u_ofile[n] != NULL)
480                    u.u_ofile[n]->f_count++;
481   if(up->p_textp != NULL) {
482
483
               up->p_textp->x_count++;
               up->p_textp->x_ccount++;
                                          newproc(3/4)
484   }
485   u.u_cdir->i_count++;
486   if (u.u_rdir)
487            u.u_rdir->i_count++;
488   /*
489     * Partially simulate the environment
490     * of the new process so that when it is actually
491     * created (by copying) it will look right.
492     */
493   rpp = p;
494   u.u_procp = rpp;
495   rip = up;                         ちょっとここ謎の動作
496   n = rip->p_size;
497   a1 = rip->p_addr;
498   rpp->p_size = n;



                                                           35
499     /*
500      * When the resume is executed for the new process,
501      * here's where it will resume.
502      */
503     if (save(u.u_ssav)) {
504
505
         sureg();
                    return(1);
                                                      newproc(4/4)
506     }
507     a2 = malloc(coremap, n);
508     /*
509       * If there is not enough core for the
510       * new process, swap out the current process to generate the
511       * copy.
512       */
513     if(a2 == NULL) {
514               rip->p_stat = SIDL;
515               rpp->p_addr = a1;
516               xswap(rpp, 0, 0);
517               rip->p_stat = SRUN;
                                                   資源が足りなければ、
518     } else {                                   子プロセスの処理をするために
519               /*                               親側をいったんスワップアウトする?
520                * There is core, so just copy.
521                */
522               rpp->p_addr = a2;
523      while(n--)
524                        copyseg(a1++, a2++);
525     }
526     u.u_procp = rip;
527     setrq(rpp);
528     rpp->p_flag |= SSWAP;
529     return(0);                                                36
530 }
545 expand(newsize)                    532 /*
                                       533 * Change the size of the data+stack regions of the process.
546 {                                  534 * If the size is shrinking, it's easy-- just release the extra core.
547         register i, n;             535 * If it's growing, and there is core, just allocate it
                                       536 * and copy the image, taking care to reset registers to account
548         register struct proc *p;   537 * for the fact that the system's stack has moved.
549         register a1, a2;           538 * If there is no core, arrange for the process to be swapped
                                       539 * out after adjusting the size requirement-- when it comes
550
                                       540 * in, enough core will be allocated.
551         p = u.u_procp;             541 *
552         n = p->p_size;             542 * After the expansion, the caller will take care of copying
                                       543 * the user's stack towards or away from the data area.
553         p->p_size = newsize;       544 */
554         a1 = p->p_addr;
555         if(n >= newsize) {
556                 mfree(coremap, n-newsize, a1+newsize);
557                 return;
558         }
559         if (save(u.u_ssav)) {
560
561
562           }
                sureg();
                           return;                                  expand(1/1)
563           a2 = malloc(coremap, newsize);
564           if(a2 == NULL) {
565                   xswap(p, 1, n);
566                   p->p_flag |= SSWAP;
                                                        確保しているメモリ領域(データとスタック)を
567             qswtch();                               変更したい時(拡張したいとき)、
568                        /* no return */              malloc,freeで領域を取り直す
569           }
570           p->p_addr = a2;
571           for(i=0; i<n; i++)
572                   copyseg(a1+i, a2+i);
573           mfree(coremap, n, a1);
574           resume(a2, u.u_ssav);                                                                     37
575 }
112   /*
113     * when you are sure that it
114
115
        * is impossible to get the
        * 'proc on q' diagnostic, the
                                                     setrq(1/1)
116     * diagnostic loop can be removed.
117     */
118   setrq(p)
119   struct proc *p;
120   {
121            register struct proc *q;
122        register s;
123
124             s = spl6();
125             for(q=runq; q!=NULL; q=q->p_link)
126                     if(q == p) {
127                      printf("proc on qn");
                                                  すでに起動済みのプロセスかどうか
128                      goto out;
129                     }                         チェックしている?
130             p->p_link = runq;
131             runq = p;
132 out:
133             splx(s);
134 }
                                                                 38
135
以降はしばらくお待ちください
次に記載するCソースファイルを
     選定中…




                  39

Mais conteúdo relacionado

Mais procurados

あるコンテキストスイッチの話
あるコンテキストスイッチの話あるコンテキストスイッチの話
あるコンテキストスイッチの話nullnilaki
 
デバドラを書いてみよう!
デバドラを書いてみよう!デバドラを書いてみよう!
デバドラを書いてみよう!Masami Ichikawa
 
【学習メモ#5th】12ステップで作る組込みOS自作入門
【学習メモ#5th】12ステップで作る組込みOS自作入門【学習メモ#5th】12ステップで作る組込みOS自作入門
【学習メモ#5th】12ステップで作る組込みOS自作入門sandai
 
【学習メモ#3rd】12ステップで作る組込みOS自作入門
【学習メモ#3rd】12ステップで作る組込みOS自作入門【学習メモ#3rd】12ステップで作る組込みOS自作入門
【学習メモ#3rd】12ステップで作る組込みOS自作入門sandai
 
Ylug 110th kpatch code reading
Ylug 110th kpatch code readingYlug 110th kpatch code reading
Ylug 110th kpatch code readingMasami Hiramatsu
 
Unixカーネルの設計 7 プロセスの制御
Unixカーネルの設計 7 プロセスの制御Unixカーネルの設計 7 プロセスの制御
Unixカーネルの設計 7 プロセスの制御Norito Agetsuma
 
本当にわかる Spectre と Meltdown
本当にわかる Spectre と Meltdown本当にわかる Spectre と Meltdown
本当にわかる Spectre と MeltdownHirotaka Kawata
 
Linuxのプロセススケジューラ(Reading the Linux process scheduler)
Linuxのプロセススケジューラ(Reading the Linux process scheduler)Linuxのプロセススケジューラ(Reading the Linux process scheduler)
Linuxのプロセススケジューラ(Reading the Linux process scheduler)Hiraku Toyooka
 
【学習メモ#7th】12ステップで作る組込みOS自作入門
【学習メモ#7th】12ステップで作る組込みOS自作入門 【学習メモ#7th】12ステップで作る組込みOS自作入門
【学習メモ#7th】12ステップで作る組込みOS自作入門 sandai
 
Basic of virtual memory of Linux
Basic of virtual memory of LinuxBasic of virtual memory of Linux
Basic of virtual memory of LinuxTetsuyuki Kobayashi
 
x86-64/Linuxに独自メモリ空間を勝手増設
x86-64/Linuxに独自メモリ空間を勝手増設x86-64/Linuxに独自メモリ空間を勝手増設
x86-64/Linuxに独自メモリ空間を勝手増設Minoru Nakamura
 
C++ Transactional Memory言語拡張の紹介
C++ Transactional Memory言語拡張の紹介C++ Transactional Memory言語拡張の紹介
C++ Transactional Memory言語拡張の紹介yohhoy
 
Introduction to Initramfs - Initramfs-tools and Dracut
Introduction to Initramfs - Initramfs-tools and DracutIntroduction to Initramfs - Initramfs-tools and Dracut
Introduction to Initramfs - Initramfs-tools and DracutTaisuke Yamada
 
mod_auth_ticket - Bringing Single-Sign-On to lighttpd
mod_auth_ticket - Bringing Single-Sign-On to lighttpdmod_auth_ticket - Bringing Single-Sign-On to lighttpd
mod_auth_ticket - Bringing Single-Sign-On to lighttpdTaisuke Yamada
 
パケットジェネレータipgenから見るnetmap
パケットジェネレータipgenから見るnetmapパケットジェネレータipgenから見るnetmap
パケットジェネレータipgenから見るnetmapfurandon_pig
 

Mais procurados (20)

あるコンテキストスイッチの話
あるコンテキストスイッチの話あるコンテキストスイッチの話
あるコンテキストスイッチの話
 
デバドラを書いてみよう!
デバドラを書いてみよう!デバドラを書いてみよう!
デバドラを書いてみよう!
 
【学習メモ#5th】12ステップで作る組込みOS自作入門
【学習メモ#5th】12ステップで作る組込みOS自作入門【学習メモ#5th】12ステップで作る組込みOS自作入門
【学習メモ#5th】12ステップで作る組込みOS自作入門
 
【学習メモ#3rd】12ステップで作る組込みOS自作入門
【学習メモ#3rd】12ステップで作る組込みOS自作入門【学習メモ#3rd】12ステップで作る組込みOS自作入門
【学習メモ#3rd】12ステップで作る組込みOS自作入門
 
Ylug 110th kpatch code reading
Ylug 110th kpatch code readingYlug 110th kpatch code reading
Ylug 110th kpatch code reading
 
Unixカーネルの設計 7 プロセスの制御
Unixカーネルの設計 7 プロセスの制御Unixカーネルの設計 7 プロセスの制御
Unixカーネルの設計 7 プロセスの制御
 
Ext4 filesystem(1)
Ext4 filesystem(1)Ext4 filesystem(1)
Ext4 filesystem(1)
 
本当にわかる Spectre と Meltdown
本当にわかる Spectre と Meltdown本当にわかる Spectre と Meltdown
本当にわかる Spectre と Meltdown
 
Linuxのプロセススケジューラ(Reading the Linux process scheduler)
Linuxのプロセススケジューラ(Reading the Linux process scheduler)Linuxのプロセススケジューラ(Reading the Linux process scheduler)
Linuxのプロセススケジューラ(Reading the Linux process scheduler)
 
【学習メモ#7th】12ステップで作る組込みOS自作入門
【学習メモ#7th】12ステップで作る組込みOS自作入門 【学習メモ#7th】12ステップで作る組込みOS自作入門
【学習メモ#7th】12ステップで作る組込みOS自作入門
 
Basic of virtual memory of Linux
Basic of virtual memory of LinuxBasic of virtual memory of Linux
Basic of virtual memory of Linux
 
Memory sanitizer
Memory sanitizerMemory sanitizer
Memory sanitizer
 
x86-64/Linuxに独自メモリ空間を勝手増設
x86-64/Linuxに独自メモリ空間を勝手増設x86-64/Linuxに独自メモリ空間を勝手増設
x86-64/Linuxに独自メモリ空間を勝手増設
 
Mincs 日本語版
Mincs 日本語版Mincs 日本語版
Mincs 日本語版
 
C++ Transactional Memory言語拡張の紹介
C++ Transactional Memory言語拡張の紹介C++ Transactional Memory言語拡張の紹介
C++ Transactional Memory言語拡張の紹介
 
Ext4 filesystem(2)
Ext4 filesystem(2)Ext4 filesystem(2)
Ext4 filesystem(2)
 
initramfsについて
initramfsについてinitramfsについて
initramfsについて
 
Introduction to Initramfs - Initramfs-tools and Dracut
Introduction to Initramfs - Initramfs-tools and DracutIntroduction to Initramfs - Initramfs-tools and Dracut
Introduction to Initramfs - Initramfs-tools and Dracut
 
mod_auth_ticket - Bringing Single-Sign-On to lighttpd
mod_auth_ticket - Bringing Single-Sign-On to lighttpdmod_auth_ticket - Bringing Single-Sign-On to lighttpd
mod_auth_ticket - Bringing Single-Sign-On to lighttpd
 
パケットジェネレータipgenから見るnetmap
パケットジェネレータipgenから見るnetmapパケットジェネレータipgenから見るnetmap
パケットジェネレータipgenから見るnetmap
 

Destaque

Kanters Familiedag 2011
Kanters Familiedag 2011Kanters Familiedag 2011
Kanters Familiedag 2011Hans Coolen
 
2011.06.03 v7から始めるunix まとめ
2011.06.03 v7から始めるunix まとめ2011.06.03 v7から始めるunix まとめ
2011.06.03 v7から始めるunix まとめMakiko Konoshima
 
食事写真集[ムール貝]
食事写真集[ムール貝]食事写真集[ムール貝]
食事写真集[ムール貝]Makiko Konoshima
 
Bent spreekbeurt drummen
Bent spreekbeurt drummenBent spreekbeurt drummen
Bent spreekbeurt drummenHans Coolen
 
食事写真集[エーデルワイス]
食事写真集[エーデルワイス]食事写真集[エーデルワイス]
食事写真集[エーデルワイス]Makiko Konoshima
 

Destaque (9)

Kanters Familiedag 2011
Kanters Familiedag 2011Kanters Familiedag 2011
Kanters Familiedag 2011
 
2011.06.03 v7から始めるunix まとめ
2011.06.03 v7から始めるunix まとめ2011.06.03 v7から始めるunix まとめ
2011.06.03 v7から始めるunix まとめ
 
Costcasamia.pps
Costcasamia.ppsCostcasamia.pps
Costcasamia.pps
 
食事写真集[ムール貝]
食事写真集[ムール貝]食事写真集[ムール貝]
食事写真集[ムール貝]
 
Bent spreekbeurt drummen
Bent spreekbeurt drummenBent spreekbeurt drummen
Bent spreekbeurt drummen
 
E rate presentation
E rate presentationE rate presentation
E rate presentation
 
E rate presentation
E rate presentationE rate presentation
E rate presentation
 
E rate presentation
E rate presentationE rate presentation
E rate presentation
 
食事写真集[エーデルワイス]
食事写真集[エーデルワイス]食事写真集[エーデルワイス]
食事写真集[エーデルワイス]
 

Semelhante a 2011.09.18 v7から始めるunix まとめ

Linux Kernel Seminar in tripodworks
Linux Kernel Seminar in tripodworksLinux Kernel Seminar in tripodworks
Linux Kernel Seminar in tripodworkstripodworks
 
Programming camp 2008, Codereading
Programming camp 2008, CodereadingProgramming camp 2008, Codereading
Programming camp 2008, CodereadingHiro Yoshioka
 
Programming camp Codereading
Programming camp CodereadingProgramming camp Codereading
Programming camp CodereadingHiro Yoshioka
 
PyOpenCLによるGPGPU入門
PyOpenCLによるGPGPU入門PyOpenCLによるGPGPU入門
PyOpenCLによるGPGPU入門Yosuke Onoue
 
Dalvikバイトコードリファレンスの読み方 改訂版
Dalvikバイトコードリファレンスの読み方 改訂版Dalvikバイトコードリファレンスの読み方 改訂版
Dalvikバイトコードリファレンスの読み方 改訂版Takuya Matsunaga
 
【学習メモ#8th】12ステップで作る組込みOS自作入門
【学習メモ#8th】12ステップで作る組込みOS自作入門 【学習メモ#8th】12ステップで作る組込みOS自作入門
【学習メモ#8th】12ステップで作る組込みOS自作入門 sandai
 
ROP Illmatic: Exploring Universal ROP on glibc x86-64 (ja)
ROP Illmatic: Exploring Universal ROP on glibc x86-64 (ja)ROP Illmatic: Exploring Universal ROP on glibc x86-64 (ja)
ROP Illmatic: Exploring Universal ROP on glibc x86-64 (ja)inaz2
 
スタート低レイヤー #0
スタート低レイヤー #0スタート低レイヤー #0
スタート低レイヤー #0Kiwamu Okabe
 
PEZY-SC programming overview
PEZY-SC programming overviewPEZY-SC programming overview
PEZY-SC programming overviewRyo Sakamoto
 
CLUB DB2 第137回:基礎から再入門!DB2モニタリング入門
CLUB DB2 第137回:基礎から再入門!DB2モニタリング入門CLUB DB2 第137回:基礎から再入門!DB2モニタリング入門
CLUB DB2 第137回:基礎から再入門!DB2モニタリング入門Akira Shimosako
 
オペレーティングシステム 第1回-公開用
オペレーティングシステム 第1回-公開用オペレーティングシステム 第1回-公開用
オペレーティングシステム 第1回-公開用Ruo Ando
 
ふつうのLinuxプログラミング
ふつうのLinuxプログラミングふつうのLinuxプログラミング
ふつうのLinuxプログラミングShuhei KONDO
 
OpenStackクラウド基盤構築ハンズオンセミナー 第1日:ハンズオンNo1
OpenStackクラウド基盤構築ハンズオンセミナー 第1日:ハンズオンNo1OpenStackクラウド基盤構築ハンズオンセミナー 第1日:ハンズオンNo1
OpenStackクラウド基盤構築ハンズオンセミナー 第1日:ハンズオンNo1Etsuji Nakai
 
LPICレベル1技術解説セミナー(2012/11/11)
LPICレベル1技術解説セミナー(2012/11/11)LPICレベル1技術解説セミナー(2012/11/11)
LPICレベル1技術解説セミナー(2012/11/11)Kazuko Itoda
 
dofilewrite and vn_write
dofilewrite and vn_writedofilewrite and vn_write
dofilewrite and vn_writekusabanachi
 
MINCS – containers in the shell script
MINCS – containers in the shell scriptMINCS – containers in the shell script
MINCS – containers in the shell scriptMasami Hiramatsu
 
あるmmapの話
あるmmapの話あるmmapの話
あるmmapの話nullnilaki
 
Serfが面白いと俺の中で話題にwwwwww 【改訂版】
Serfが面白いと俺の中で話題にwwwwww 【改訂版】Serfが面白いと俺の中で話題にwwwwww 【改訂版】
Serfが面白いと俺の中で話題にwwwwww 【改訂版】Masahito Zembutsu
 
Programming camp code reading
Programming camp code readingProgramming camp code reading
Programming camp code readingHiro Yoshioka
 

Semelhante a 2011.09.18 v7から始めるunix まとめ (20)

Linux Kernel Seminar in tripodworks
Linux Kernel Seminar in tripodworksLinux Kernel Seminar in tripodworks
Linux Kernel Seminar in tripodworks
 
Programming camp 2008, Codereading
Programming camp 2008, CodereadingProgramming camp 2008, Codereading
Programming camp 2008, Codereading
 
Programming camp Codereading
Programming camp CodereadingProgramming camp Codereading
Programming camp Codereading
 
PyOpenCLによるGPGPU入門
PyOpenCLによるGPGPU入門PyOpenCLによるGPGPU入門
PyOpenCLによるGPGPU入門
 
Dalvikバイトコードリファレンスの読み方 改訂版
Dalvikバイトコードリファレンスの読み方 改訂版Dalvikバイトコードリファレンスの読み方 改訂版
Dalvikバイトコードリファレンスの読み方 改訂版
 
【学習メモ#8th】12ステップで作る組込みOS自作入門
【学習メモ#8th】12ステップで作る組込みOS自作入門 【学習メモ#8th】12ステップで作る組込みOS自作入門
【学習メモ#8th】12ステップで作る組込みOS自作入門
 
ROP Illmatic: Exploring Universal ROP on glibc x86-64 (ja)
ROP Illmatic: Exploring Universal ROP on glibc x86-64 (ja)ROP Illmatic: Exploring Universal ROP on glibc x86-64 (ja)
ROP Illmatic: Exploring Universal ROP on glibc x86-64 (ja)
 
スタート低レイヤー #0
スタート低レイヤー #0スタート低レイヤー #0
スタート低レイヤー #0
 
PEZY-SC programming overview
PEZY-SC programming overviewPEZY-SC programming overview
PEZY-SC programming overview
 
CLUB DB2 第137回:基礎から再入門!DB2モニタリング入門
CLUB DB2 第137回:基礎から再入門!DB2モニタリング入門CLUB DB2 第137回:基礎から再入門!DB2モニタリング入門
CLUB DB2 第137回:基礎から再入門!DB2モニタリング入門
 
オペレーティングシステム 第1回-公開用
オペレーティングシステム 第1回-公開用オペレーティングシステム 第1回-公開用
オペレーティングシステム 第1回-公開用
 
ふつうのLinuxプログラミング
ふつうのLinuxプログラミングふつうのLinuxプログラミング
ふつうのLinuxプログラミング
 
仮想記憶の構築法
仮想記憶の構築法仮想記憶の構築法
仮想記憶の構築法
 
OpenStackクラウド基盤構築ハンズオンセミナー 第1日:ハンズオンNo1
OpenStackクラウド基盤構築ハンズオンセミナー 第1日:ハンズオンNo1OpenStackクラウド基盤構築ハンズオンセミナー 第1日:ハンズオンNo1
OpenStackクラウド基盤構築ハンズオンセミナー 第1日:ハンズオンNo1
 
LPICレベル1技術解説セミナー(2012/11/11)
LPICレベル1技術解説セミナー(2012/11/11)LPICレベル1技術解説セミナー(2012/11/11)
LPICレベル1技術解説セミナー(2012/11/11)
 
dofilewrite and vn_write
dofilewrite and vn_writedofilewrite and vn_write
dofilewrite and vn_write
 
MINCS – containers in the shell script
MINCS – containers in the shell scriptMINCS – containers in the shell script
MINCS – containers in the shell script
 
あるmmapの話
あるmmapの話あるmmapの話
あるmmapの話
 
Serfが面白いと俺の中で話題にwwwwww 【改訂版】
Serfが面白いと俺の中で話題にwwwwww 【改訂版】Serfが面白いと俺の中で話題にwwwwww 【改訂版】
Serfが面白いと俺の中で話題にwwwwww 【改訂版】
 
Programming camp code reading
Programming camp code readingProgramming camp code reading
Programming camp code reading
 

Último

Open Source UN-Conference 2024 Kawagoe - 独自OS「DaisyOS GB」の紹介
Open Source UN-Conference 2024 Kawagoe - 独自OS「DaisyOS GB」の紹介Open Source UN-Conference 2024 Kawagoe - 独自OS「DaisyOS GB」の紹介
Open Source UN-Conference 2024 Kawagoe - 独自OS「DaisyOS GB」の紹介Yuma Ohgami
 
Postman LT Fukuoka_Quick Prototype_By Daniel
Postman LT Fukuoka_Quick Prototype_By DanielPostman LT Fukuoka_Quick Prototype_By Daniel
Postman LT Fukuoka_Quick Prototype_By Danieldanielhu54
 
論文紹介:Semantic segmentation using Vision Transformers: A survey
論文紹介:Semantic segmentation using Vision Transformers: A survey論文紹介:Semantic segmentation using Vision Transformers: A survey
論文紹介:Semantic segmentation using Vision Transformers: A surveyToru Tamaki
 
TSAL operation mechanism and circuit diagram.pdf
TSAL operation mechanism and circuit diagram.pdfTSAL operation mechanism and circuit diagram.pdf
TSAL operation mechanism and circuit diagram.pdftaisei2219
 
論文紹介:Content-Aware Token Sharing for Efficient Semantic Segmentation With Vis...
論文紹介:Content-Aware Token Sharing for Efficient Semantic Segmentation With Vis...論文紹介:Content-Aware Token Sharing for Efficient Semantic Segmentation With Vis...
論文紹介:Content-Aware Token Sharing for Efficient Semantic Segmentation With Vis...Toru Tamaki
 
論文紹介:Automated Classification of Model Errors on ImageNet
論文紹介:Automated Classification of Model Errors on ImageNet論文紹介:Automated Classification of Model Errors on ImageNet
論文紹介:Automated Classification of Model Errors on ImageNetToru Tamaki
 
[DevOpsDays Tokyo 2024] 〜デジタルとアナログのはざまに〜 スマートビルディング爆速開発を支える 自動化テスト戦略
[DevOpsDays Tokyo 2024] 〜デジタルとアナログのはざまに〜 スマートビルディング爆速開発を支える 自動化テスト戦略[DevOpsDays Tokyo 2024] 〜デジタルとアナログのはざまに〜 スマートビルディング爆速開発を支える 自動化テスト戦略
[DevOpsDays Tokyo 2024] 〜デジタルとアナログのはざまに〜 スマートビルディング爆速開発を支える 自動化テスト戦略Ryo Sasaki
 
スマートフォンを用いた新生児あやし動作の教示システム
スマートフォンを用いた新生児あやし動作の教示システムスマートフォンを用いた新生児あやし動作の教示システム
スマートフォンを用いた新生児あやし動作の教示システムsugiuralab
 
SOPを理解する 2024/04/19 の勉強会で発表されたものです
SOPを理解する       2024/04/19 の勉強会で発表されたものですSOPを理解する       2024/04/19 の勉強会で発表されたものです
SOPを理解する 2024/04/19 の勉強会で発表されたものですiPride Co., Ltd.
 

Último (9)

Open Source UN-Conference 2024 Kawagoe - 独自OS「DaisyOS GB」の紹介
Open Source UN-Conference 2024 Kawagoe - 独自OS「DaisyOS GB」の紹介Open Source UN-Conference 2024 Kawagoe - 独自OS「DaisyOS GB」の紹介
Open Source UN-Conference 2024 Kawagoe - 独自OS「DaisyOS GB」の紹介
 
Postman LT Fukuoka_Quick Prototype_By Daniel
Postman LT Fukuoka_Quick Prototype_By DanielPostman LT Fukuoka_Quick Prototype_By Daniel
Postman LT Fukuoka_Quick Prototype_By Daniel
 
論文紹介:Semantic segmentation using Vision Transformers: A survey
論文紹介:Semantic segmentation using Vision Transformers: A survey論文紹介:Semantic segmentation using Vision Transformers: A survey
論文紹介:Semantic segmentation using Vision Transformers: A survey
 
TSAL operation mechanism and circuit diagram.pdf
TSAL operation mechanism and circuit diagram.pdfTSAL operation mechanism and circuit diagram.pdf
TSAL operation mechanism and circuit diagram.pdf
 
論文紹介:Content-Aware Token Sharing for Efficient Semantic Segmentation With Vis...
論文紹介:Content-Aware Token Sharing for Efficient Semantic Segmentation With Vis...論文紹介:Content-Aware Token Sharing for Efficient Semantic Segmentation With Vis...
論文紹介:Content-Aware Token Sharing for Efficient Semantic Segmentation With Vis...
 
論文紹介:Automated Classification of Model Errors on ImageNet
論文紹介:Automated Classification of Model Errors on ImageNet論文紹介:Automated Classification of Model Errors on ImageNet
論文紹介:Automated Classification of Model Errors on ImageNet
 
[DevOpsDays Tokyo 2024] 〜デジタルとアナログのはざまに〜 スマートビルディング爆速開発を支える 自動化テスト戦略
[DevOpsDays Tokyo 2024] 〜デジタルとアナログのはざまに〜 スマートビルディング爆速開発を支える 自動化テスト戦略[DevOpsDays Tokyo 2024] 〜デジタルとアナログのはざまに〜 スマートビルディング爆速開発を支える 自動化テスト戦略
[DevOpsDays Tokyo 2024] 〜デジタルとアナログのはざまに〜 スマートビルディング爆速開発を支える 自動化テスト戦略
 
スマートフォンを用いた新生児あやし動作の教示システム
スマートフォンを用いた新生児あやし動作の教示システムスマートフォンを用いた新生児あやし動作の教示システム
スマートフォンを用いた新生児あやし動作の教示システム
 
SOPを理解する 2024/04/19 の勉強会で発表されたものです
SOPを理解する       2024/04/19 の勉強会で発表されたものですSOPを理解する       2024/04/19 の勉強会で発表されたものです
SOPを理解する 2024/04/19 の勉強会で発表されたものです
 

2011.09.18 v7から始めるunix まとめ

  • 1. V7から始めるUNIX まとめ 予備知識であるCPUアーキテクチャのほん のさわりを説明したあと、本題に入ります
  • 2. 予備知識 • コンピュータ・アーキテクチャについて – 低レイヤのプログラムの理解に欠かせない – 理想を言えば、網羅的に知っておくことが好ましい • ハードとソフトは両輪だから – ただし、技術の範囲が広大すぎて、とてもここでは扱いき れない – 疑問が出た都度、身近な専門家に声をかけて聞くと、きっ と親切に教えてくれる!←学校か職場の専門家が誰か、 把握しておこう! • 私も知っている範囲で答えます – ここではCPUの基本構成、マシン語から演算器で実行さ れる手順にフォーカスして、次ページ以降で少しだけさわ る 2
  • 3. CPUの基本構成、超ざっくり • 参考情報※の本文が、非 常に素晴らしいので、そち らに詳細の解説はゆずり ます – CPUは大きく、演算部と制 御部から構成されます – CPUにはメモリが接続され ています – ROMには、コンパイラに よってプログラムから変換 され、CPUが実行可能な マシン語に変換されたデー タが入っています ※参考:http://homepage2.nifty.com/ttoyoshima/Computer/Config.htm 3
  • 4. マシン語 • プログラム言語はコンパイラによってCPUが直接理 解し実行できるマシン語に変換される • マシン語は、CPUで処理される(命令パイプライン) • マシン語の例 参考情報 http://www.geocities.jp/mori_imms/asmDetail.html http://msyk.net/keio/JavaBook/ch1.html 4
  • 5. 命令パイプライン(1/2) • 汎用パイプラインについて説明する • 次ページの図は、一般化した次のような4段のパイプライン を示している。 • フェッチ (Fetch):メモリから機械語を取り出してくる動作 • デコード (Decode):機械語を解読し、制御信号を送る • 実行 (Execute):実行する • ライトバック (Write-back):実行結果をファイルかメモリに書き 込む • 次ページの図の上にある灰色の矩形には実行を待っている 命令が並んでいる。下の灰色の矩形には実行が完了した命 令が並んでいる。真ん中の矩形がパイプラインを表している。 • 実行は次ページのようになる。 参考:Wikipedia 5
  • 6. 命令パイプライン(2/2) 説明 0 4つの命令が実行されるのを待っている。 1 緑の命令をメモリからフェッチする。 緑の命令をデコードする。 2 紫の命令をメモリからフェッチする。 緑の命令を実行する(実際の命令処理を行う) 3 紫の命令をデコードする。 青の命令をフェッチする。 緑の命令の結果をレジスタファイルかメモリに書き込む 紫の命令を実行する。 4 青の命令をデコードする。 赤の命令をフェッチする。 緑の命令は完了した。 紫の命令の結果を書き込む。 5 青の命令を実行する。 赤の命令をデコードする。 紫の命令は完了した。 6 青の命令の結果を書き込む。 赤の命令を実行する。 青の命令は完了した。 7 赤の命令の結果を書き込む。 8 赤の命令は完了した。 9 全命令を実行した。 6
  • 7. • 示した例は、一般的な例です • 実際はもっと複雑で、いろいろ工夫されています • 例えば – http://www.slideshare.net/schnee_rosa/20110611- v7unixb • 気に入っている、または気になるチップのアーキ テクチャを調べていくと、楽しいです – チップメーカーは大抵、開発者向けのホワイトペー パーを出しています – わからない専門用語は、専門家に聞こう! • 私も知っている範囲で答えます 7
  • 8. V7の理解(1/4) • 現在のLinuxの原点はV7 – V7→BSD→Linux • V7を読み解くことで、原理の理解を進めることを 目的とする • 今回は、V7の理解の一環として、まず root/h/user.hとroot/sys/slp.cの実装を読み解い ていく – slp.cはスワッピングについて記載されており、プロセ ス制御の基本です 参照したソースコード: http://www.tamacom.com/tour/kernel/unix/ 8
  • 9. V7の理解(2/4) • V7ではハードが限定されていたため、可搬性に ついて考慮していない – DECのPDP-11などで動作した • しかしC言語で書かれているため、移植性は高 い • 歴史についての参考資料 http://ja.wikipedia.org/wiki/Version_7_Unix • ソースコードは簡単シンプル、注釈が丁寧で読 みやすいです… – ただしK&Rで書かれているっぽい – マジックナンバーがあればそれは8進数 9
  • 10. 全体の超概略(推測入ってるところ/未確認は V7の理解(3/4) 黄色でハッチ。習ってるところは赤ハッチ) ソースファイル 役割 代表的な関数 acct.c プロセスがCPUを使用した状況をファイルに記載するためのもの? acct,sysacct alloc.c メモリディスク?の割りあて、解放を行う alloc,free clock.c ?(現在の役割と一緒か否か?) clock,timeout fakemx.c ユーザ定義関数か何かのような気がする fio.c ファイルに定義されている関数をロードするためのもの? getf iget.c ファイル操作を行うため、パス名をinodeに変換する。 iget machdep.c ブートストラップを行う startup main.c システムの初期化を行う main malloc.c 現在と定義が変わっていないだろうか? malloc,mfree nami.c inodeのパス名をポインタに変換。iget.cとペアか? namei pipe.c パイプを行う pipe prf.c 標準出力を行う(なぜにパニックがここに) printf prim.c 今の標準関数と同じなら、キャラクタリスト=文字列のgetとput getc,putc rdwri.c inodeポインタに対する読み書き readi,writei sig.c シグナル。割り込みに使う。tty.cから呼ばれる signal slp.c 資源を排他的に利用するため、カーネル内の同期を実現 sleep,wakeup subr.c inodeのポインタに読み書き可能なブロックを割り当てる? bmap sys1.c プロセス操作系システムコール exec,fork等 sys2.c ファイル操作系システムコール read,write等 sys3.c ファイルの状態(どこのデバイスか、所有者、アクセス権)を取得するシステムコール fstat sys4.c 上記以外のシステムコール いろいろ text.c プロセスのスワップアウトを行う xswap trap.c シグナルを補足し、指定の処理を行う trap ureg.c これよくわからない… sureg 10
  • 11. V7の理解(4/4) ヘッダファイル 役割 構造体 acct.h プロセスのアカウント情報をファイルに書き出せるようにする acct buf.h リングバッファ?ブロックデバイスのバッファ buf callo.h クロックから中断されコールアウトする? callo conf.h ブロックデバイス、キャラクタデバイスのスイッチングを宣言する cdevsw,bdevsw dir.h ディレクトリ情報管理用? diect fblk.h ? fblk file.h inodeのファイル管理用構造体? file filsys.h fileを束ねたもの? filsys ino.h disk block上でのinode用構造体 dinode inode.h inode構造体 inode map.h メモリマップの構造体、coreとswapの2つ map mount.h マウント用構造体(デバイスのか?) mount mpx.h これちょっとわからない mx.h これもちょっとわからない pack.h これもマジわからない pack pk.h 上のpack.hと同じ構造体が入ってる?? pack? proc.h プロセスの状態や管理情報を保持 proc pwd.h ?全体の文脈からしてパスワードの変更ではなさそうな気が passwd stat.h inodeの状態を知る? stat system.h システムエントリテーブルの定義(何か実行させたいときここを参照する) sysent text.h スワップの際のディスクアドレスなどを格納 text timeb.h ftimeシステムコールの戻り値(gettimeofdayの代わり?) timeb tty.h キャラクタ端末制御用? tty 11 user.h プロセスが扱うプログラムやデータを保持 user
  • 12. user.h(1/5) 冒頭の注釈 (注釈のまんま) ↓左端の数値は行番号 ・user構造体を定義している ・プロセスあたり1つ持つ 1 /* ・1プロセスあたりの全データであ 2 * The user structure. る 3 * One allocated per process. ・プロセスがスワップしている間は、 4 * Contains all per process data 参照しなくてよい ・ユーザのブロック長はUSIZE×64 5 * that doesn't need to be referenced でこれはスタックポインタ用に使わ 6 * while the process is swapped. れる 7 * The user block is USIZE*64 bytes ・仮想カーネルのデータ長は 8 * long; resides at virtual kernel 140000 (ユーザ毎のシステムス 9 * loc 140000; contains the system タック含む) 10 * stack per user; is cross referenced・同じプロセスの中では、proc構造 と相互参照の関係にある 11 * with the proc structure for the 12 * same process. 13 */ 12
  • 13. 14 15 #define EXCLOSE 01 user.h(2/5) 16 17 struct user 18 { 19 label_t u_rsav; /* save info when exchanging stacks */ 20 int u_fper; /* FP error register */ 退避時にスタックポインタを格納 21 int u_fpsaved; /* FP regs saved for this proc */ 22 struct { 23 int u_fpsr; /* FP status register */ 24 double u_fpregs[6]; /* FP registers */ ファイルI/O用の変数 25 } u_fps; 26 char u_segflg; /* IO flag: 0:user D; 1:system; 2:user I */ファイルI/Oの属性等 27 char u_error; /* return error code */ Dはデータ、I、は命令 28 short u_uid; /* effective user id */ systemはカーネルに相当 29 short u_gid; /* effective group id */ userはプロセスユーザと同義 30 short u_ruid; /* real user id */ 31 short u_rgid; /* real group id */ proc構造体ポインタ 32 struct proc *u_procp; /* pointer to proc structure */ 33 int *u_ap; /* pointer to arglist */ システムコールの引数リスト 34 union { /* syscall return values */ 35 struct { 36 int r_val1; システムコールの戻り値 37 int r_val2; 例えばLinuxのコマンド 38 }; ls –laとかで得られる 39 off_t r_off; 一覧のデータを格納 40 time_t r_time; 13 41 } u_r; しておく
  • 14. user.h(3/5) 42 caddr_t u_base; /* base address for IO */ プロセスユーザのI/Oの開始ア 43 unsigned int u_count; /* bytes remaining for IO */ 44 off_t u_offset; ドレス、オフセット、どこのディ /* offset in file for IO */ 45 struct inode *u_cdir; レクトリにあるか、パス名(この /* pointer to inode of current directory */ 46 struct inode *u_rdir; ころは物理アドレス空間を直 /* root directory of current process */ 47 char u_dbuf[DIRSIZ]; 接扱っていた?) /* current pathname component */ 48 caddr_t u_dirp; /* pathname pointer */ 49 struct direct u_dent; /* current directory entry */ 50 struct inode *u_pdir; /* inode of parent directory of dirp */ 51 int u_uisa[16]; /* prototype of segmentation addresses */ 52 int u_uisd[16]; ファイルI/O /* prototype of segmentation descriptors */ 53 struct file *u_ofile[NOFILE]; /* pointers to file structures of open files * (ちょっと詳細がわからない) 54 char u_pofile[NOFILE]; /* per-process flags of open files */ 55 int u_arg[5]; /* arguments to current system call */ 56 unsigned u_tsize; /* text size (clicks) */ 57 unsigned u_dsize; /* data size (clicks) */ 現在のシステムコール戻り値 58 unsigned u_ssize; /* stack size (clicks) */ テキスト(プログラム)、データ 59 label_t u_qsav; /* label variable for quits and interrupts */ 60 label_t u_ssav; /* label variable for swapping */ (固定値)、スタック(call時のP 61 int u_signal[NSIG]; /* disposition of signals */ C値の格納等)のサイズ、ス 62 time_t u_utime; /* this process user time */ ワップや退避時のラベル値 63 time_t u_stime; /* this process system time */ 64 time_t u_cutime; /* sum of childs' utimes */ システムコールの戻り値 65 time_t u_cstime; /* sum of childs' stimes */ プロセスおよび子プロセスの 66 int *u_ar0; /* address of users saved R0 */ CPU使用時間など 14
  • 15. user.h(4/5) 75 struct tty *u_ttyp; /* controlling ttytty(キャラクタ端末)制御用ポイ pointer */ 76 dev_t u_ttyd; /* controlling tty ンタとデバイス制御用情報 dev */ 77 struct { /* header of executable file */ 78 int ux_mag; /* magic number */ 79 unsigned ux_tsize; /* text size */ 80 unsigned ux_dsize; /* data size */ これはわからない… 81 unsigned ux_bsize; /* bss size */ 82 unsigned ux_ssize; /* symbol table size */ 実行するプログラムの 83 unsigned ux_entloc; /* entry location */ 情報(予備?)か何かか 84 unsigned ux_unused; 85 unsigned ux_relflg; 86 } u_exdata; 87 char u_comm[DIRSIZ]; 88 time_t u_start; 89 char u_acflag; 90 short u_fpflag; /* unused now, will be later */ 予備用(互換性を取るため?) 91 short u_cmask; /* mask for file creation */ 92 int u_stack[1]; 93 /* kernel stack per user 94 * extends from u + USIZE*64 95 * backward not to reach here 96 */ 97 }; 98 15
  • 16. user.h(5/5) エラーコードの定義 101 /* u_error codes */ 118 #define EEXIST 17 102 #define EPERM 1 119 #define EXDEV 18 103 #define ENOENT 2 120 #define ENODEV 19 104 #define ESRCH 3 121 #define ENOTDIR 20 105 #define EINTR 4 122 #define EISDIR 21 106 #define EIO 5 123 #define EINVAL 22 107 #define ENXIO 6 124 #define ENFILE 23 108 #define E2BIG 7 125 #define EMFILE 24 109 #define ENOEXEC 8 126 #define ENOTTY 25 110 #define EBADF 9 127 #define ETXTBSY 26 111 #define ECHILD 10 128 #define EFBIG 27 112 #define EAGAIN 11 129 #define ENOSPC 28 113 #define ENOMEM 12 130 #define ESPIPE 29 114 #define EACCES 13 131 #define EROFS 30 115 #define EFAULT 14 132 #define EMLINK 31 116 #define ENOTBLK 15 133 #define EPIPE 32 117 #define EBUSY 16 134 #define EDOM 33 135 #define ERANGE 34 16
  • 17. 1 /* 2 * One structure allocated per active 3 * process. It contains all data needed proc.h(1/3) 4 * about the process while the 5 * process may be swapped out. アクティブなプロセス毎に割り当てられる 6 * Other per process data (user.h) 構造体 7 * is swapped with the process. アクティブ=実行待ちと実行中のプロセス 8 */ running=実行中のプロセス 9 struct proc { 状態をあらわす で理解はあっているか? 10 char p_stat; 11 char p_flag; ようだが詳細不明 スワップアウトしても退避せず保持する? 12 char p_pri; /* priority, negative is high */ 13 char p_time; /* resident time for scheduling */ 14 char p_cpu; /* cpu usage for scheduling */ 15 char p_nice; /* nice for cpu usage */ 16 short p_sig; /* signals pending to this process */ 17 short p_uid; /* user id, used to direct tty signals */ 18 short p_pgrp; /* name of process group leader */ 19 short p_pid; /* unique process id */ 20 short p_ppid; /* process id of parent */ 21 short p_addr; /* address of swappable image */ 22 short p_size; /* size of swappable image (clicks) */ 23 caddr_t p_wchan; /* event process is awaiting */ 24 struct text *p_textp; /* pointer to text structure */ 25 struct proc *p_link; /* linked list of running processes */ 26 int p_clktim; /* time to alarm clock signal */ 17 27 };
  • 18. proc.h(2/3) プロセスの状態をあらわすマクロ定数 29 extern struct proc proc[]; /* the proc table itself */ 30 31 /* stat codes */ 32 #define SSLEEP 1 /* awaiting an event */ 33 #define SWAIT 2 /* (abandoned state) */ 34 #define SRUN 3 /* running */ 35 #define SIDL 4 /* intermediate state in process creation */ 36 #define SZOMB 5 /* intermediate state in process termination */ 37 #define SSTOP 6 /* process being traced */ 38 39 /* flag codes */ 40 #define SLOAD 01 /* in core */ 41 #define SSYS 02 /* scheduling process */ 42 #define SLOCK 04 /* process cannot be swapped */ 43 #define SSWAP 010 /* process is being swapped out */ 44 #define STRC 020 /* process is being traced */ 45 #define SWTED 040 /* another tracing flag */ 46 #define SULOCK 0100 /* user settable lock in core */ 47 18
  • 19. proc.h(3/3) 49 * parallel proc structure 50 * to replace part with times 51 * to be passed to parent process 52 * in ZOMBIE state. 53 */ 54 struct xproc { ゾンビ(実行終了中)プロセス用構造体 55 char xp_stat; なぜわざわざ用意するのだろうか? 56 char xp_flag; 57 char xp_pri; /* priority, negative is high */ 58 char xp_time; /* resident time for scheduling */ 59 char xp_cpu; /* cpu usage for scheduling */ 60 char xp_nice; /* nice for cpu usage */ 61 short xp_sig; /* signals pending to this process */ 62 short xp_uid; /* user id, used to direct tty signals */ 63 short xp_pgrp; /* name of process group leader */ 64 short xp_pid; /* unique process id */ 65 short xp_ppid; /* process id of parent */ 66 short xp_xstat; /* Exit status for wait */ 67 time_t xp_utime; /* user time, this proc */ 68 time_t xp_stime; /* system time, this proc */ 69 }; 19
  • 20. slp.c • プロセスの制御を行う関数群(スリープと起動) • 以下の関数について定義している(★は注目すべき関数) – ★sleep:プロセスの実行を中断し、プロセッサを明け渡す – ★wakeup:sleep中のプロセスを起こす – setrun:プロセスが実行できるようにする(スワップインできるよ うにする) – setpri:プロセスユーザの優先度をセットする関数 – sched:スワッピングのメイン関数 – swapin:プロセスをスワップインさせる関数 – qswitch:プロセスキューの設定を行う関数 – switch:CPUのリスケジュール(資源の再割り当て)を行う場合 に呼び出す – newproc:新しいプロセスを立ち上げる(fork?) – expand:データとスタックのサイズを変える – setrq: 20
  • 21. 27 sleep(chan, pri) /* */ 28 caddr_t chan; sleep(1/2) 29 { 12 #define SQSIZE 0100 /* Must be power of 2 */ 30 register struct proc *rp; 13 #define HASH(x) (( (int) x >> 5) & (SQSIZE-1)) 31 register s, h; 14 struct proc *slpque[SQSIZE]; 15 32 16 /* 33 rp = u.u_procp; 17 * Give up the processor till a wakeup occurs プライオリティを上げて 34 s = spl6(); 18 * on chan, at which time the process 35 if (chan==0) 割り込みを禁止する 19 * enters the scheduling queue at priority pri. 20 * The most important effect of pri is that when 36 panic("zero wchan"); 21 * pri<=PZERO a signal cannot disturb the sleep; 37 rp->p_stat = SSLEEP; 22 * if pri>PZERO signals will be processed. 23 * Callers of this routine must be prepared for 38 rp->p_wchan = chan; 24 * premature return, and check that the reason for 39 if (chan==0) 25 * sleeping has gone away. 40 panic("Sleeping on wchan 0"); 26 */ 41 rp->p_pri = pri; 42 h = HASH(chan); ここでいうハッシュは、5ビットシフトとマスク 43 rp->p_link = slpque[h]; プライオリティが低く 44 slpque[h] = rp; シグナルを受けている(??)時は次ページに飛んで 45 if(pri > PZERO) { sleepのためにリジュームする 46 if(issig()) { 47 rp->p_wchan = 0; 48 rp->p_stat = SRUN; 49 slpque[h] = rp->p_link; 50 spl0(); 51 goto psig; 21 52 }
  • 22. 53 spl0(); 54 55 if(runin != 0) { runin = 0; sleep(2/2) 56 wakeup((caddr_t)&runin); 走れるプロセスがあれば起こす 57 } 58 swtch(); 59 if(issig()) 60 goto psig; シグナルを受けていればリジュームする 61 } else { 62 spl0(); 63 swtch(); 64 } 65 splx(s); プライオリティを元に戻す 66 return; 67 68 /* 69 * If priority was low (>PZERO) and 以降は、まだなぞの動作 70 * there has been a signal, 71 * execute non-local goto to 72 * the qsav location. 73 * (see trap1/trap.c) 74 */ 75 psig: 76 resume(u.u_procp->p_addr, u.u_qsav); 77 } 22
  • 23. 82 wakeup(chan) /* */ 83 register caddr_t chan; 84 { 85 register struct proc *p, *q; wakeup(1/1) 86 register i; 87 int s; 88 89 s = spl6(); 90 i = HASH(chan); 91 p = slpque[i]; 92 q = NULL; 93 while(p != NULL) { 94 if(p->p_wchan==chan && p->p_stat!=SZOMB) { 95 struct proc *sp; 96 スリープキューに貯まっている 97 if (q == NULL) プロセスを検出する(ゾンビ以外) 98 sp = slpque[i] = p->p_link; 99 else 100 sp = q->p_link = p->p_link; 101 p->p_wchan = 0; 102 setrun(p); ここでプロセスを起こしている? 103 p = sp; 104 continue; 105 } 106 q = p; 107 p = p->p_link; 108 } 109 splx(s); 110 } 23
  • 24. 136 /* 137 * Set the process running; 138 139 140 * arrange for it to be swapped in if necessary. */ setrun(p) setrun(1/1) 141 register struct proc *p; 142 { 143 register caddr_t w; 144 145 if (p->p_stat==0 || p->p_stat==SZOMB) 146 panic("Running a dead proc"); 147 /* 148 * The assignment to w is necessary because of 149 * race conditions. (Interrupt between test and use) 150 */ 151 if (w = p->p_wchan) { 152 wakeup(w); ここでプロセスを起こしている 153 return; 154 } 155 p->p_stat = SRUN; 156 setrq(p); プロセスを起こさない場合。 157 if(p->p_pri < curpri) 158 runrun++; 159 if(runout != 0 && (p->p_flag&SLOAD) == 0) { 160 runout = 0; 161 wakeup((caddr_t)&runout); 162 } 24 163 }
  • 25. 165 166 /* * Set user priority. setpri 167 * The rescheduling flag (runrun) 168 * is set if the priority is better 169 * than the currently running process. 170 */ 171 setpri(pp) 172 register struct proc *pp; 173 { 174 register p; 数値が8進であることに注意! 175 ユーザプロセスの優先度を設定する 176 p = (pp->p_cpu & 0377)/16; 177 p += PUSER + pp->p_nice - NZERO; 178 if(p > 127) 179 p = 127; 180 if(p < curpri) 181 runrun++; 182 pp->p_pri = p; 183 return(p); 184 } 185 25
  • 26. 202 sched() 203 { 204 register struct proc *rp, *p; sched(1/3) 205 register outage, inage; ところどころに出てくる、 206 207 int maxsize; プロセスのスワップをする関数。spl*の*が 208 /* 大きいほど優先度が高く、6が最高。 209 * find user to swap in; 210 * of users ready, select one out longest 他から割りこみが入って状態が 211 */ 変わらないようにしたい場合にこうする。 212 213 loop: ここでは最高優先度まで上げて以降の 214 spl6(); 操作を行っている 215 outage = -20000; 216 for (rp = &proc[0]; rp < &proc[NPROC]; rp++) 217 if (rp->p_stat==SRUN && (rp->p_flag&SLOAD)==0 && プロセスの状態を総なめして 218 rp->p_time - (rp->p_nice-NZERO)*8 > outage) { 219 p = rp; ステータスが実行可能状態で 220 outage = rp->p_time - (rp->p_nice-NZERO)*8; 優先度が一番高いものを検出 221 } 222 /* (スワップイン候補を探す) 223 * If there is no one there, wait. 224 */ 225 if (outage == -20000) { 226 runout++; 上記条件にあうプロセスが検出できなけれ 227 sleep((caddr_t)&runout, PSWP); 228 goto loop; ば、sleepを呼び出して待つ 229 } 230 spl0(); 231 232 /* 優先度を最低に戻す 233 * See if there is core for that process; 234 * if so, swap it in. 235 */ 236 237 if (swapin(p)) プロセスに割り当てられる資源(メモリなど) 238 goto loop; があればスワップインする 26
  • 27. 240 /* sched(2/3) 241 * none found. 242 * look around for core. 243 * Select the largest of those sleeping 244 * at bad priority; if none, select the oldest. 245 */ 246 247 spl6(); 248 p = NULL; 249 maxsize = -1; 250 inage = -1; 251 for (rp = &proc[0]; rp < &proc[NPROC]; rp++) { 252 if (rp->p_stat==SZOMB 253 || (rp->p_flag&(SSYS|SLOCK|SULOCK|SLOAD))!=SLOAD) 254 continue; CPUに割り当 255 if (rp->p_textp && rp->p_textp->x_flag&XLOCK) 256 continue; てる候補と資 257 if (rp->p_stat==SSLEEP&&rp->p_pri>=PZERO || rp->p_stat==SSTOP) { 源がない状 258 if (maxsize < rp->p_size) { 259 p = rp; 態。一番最初 260 maxsize = rp->p_size; にsleepしたプ 261 } 262 } else if (maxsize<0 && (rp->p_stat==SRUN||rp->p_stat==SSLEEP)) { ロセスを総な 263 if (rp->p_time+rp->p_nice-NZERO > inage) { めして検出す 264 p = rp; 265 inage = rp->p_time+rp->p_nice-NZERO; る(優先的に 266 } スワップさせ 267 } 268 } るため) 269 spl0(); 270 /* 27
  • 28. sched(3/3) 270 /* 271 * Swap found user out if sleeping at bad pri, 272 * or if he has spent at least 2 seconds in core and 273 * the swapped-out process has spent at least 3 seconds out. 274 * Otherwise wait a bit and try again. 275 */ 276 if (maxsize>=0 || (outage>=3 && inage>=2)) { CPUに割り当てられていた 277 p->p_flag &= ~SLOAD; 278 xswap(p, 1, 0); 時間が2秒以上、または 279 goto loop; 低い優先度でsleepしていれば 280 } スワップを行う 281 spl6(); 282 runin++; 283 sleep((caddr_t)&runin, PSWP); 284 goto loop; 285 } 286 28
  • 29. 292 swapin(p) 293 register struct proc *p; 294 { swapin 295 register struct text *xp; 296 register int a; 297 int x; 298 299 if ((a = malloc(coremap, p->p_size)) == NULL) 300 return(0); 301 if (xp = p->p_textp) { 302 xlock(xp); 303 if (xp->x_ccount==0) { 304 if ((x = malloc(coremap, xp->x_size)) == NULL) { 305 xunlock(xp); 306 mfree(coremap, p->p_size, a); 307 return(0); 308 } 309 xp->x_caddr = x; 310 if ((xp->x_flag&XLOAD)==0) 311 swap(xp->x_daddr,x,xp->x_size,B_READ); 312 } 313 xp->x_ccount++; スワップアウトしたプロセスを 314 xunlock(xp); スワップインさせている 315 } 316 swap(p->p_addr, a, p->p_size, B_READ); coremap,swapmapとは何か? 317 mfree(swapmap, ctod(p->p_size), p->p_addr); 318 p->p_addr = a; 319 p->p_flag |= SLOAD; 320 p->p_time = 0; 321 return(1); 29
  • 30. qswitch 324 /* 325 * put the current process on 326 * the Q of running processes and 327 * call the scheduler. 328 */ 329 qswtch() 330 { 331 332 setrq(u.u_procp); プロセスをキューに放り込む? 333 swtch(); 334 } 335 30
  • 31. 347 swtch() 348 { 349 350 352 register n; register struct proc *p, *q, *pp, *pq; /* switch(1/2) 353 * If not the idle process, resume the idle process. 354 */ 355 if (u.u_procp != &proc[0]) { 356 if (save(u.u_rsav)) { 357 sureg(); 358 return; 359 } 360 if (u.u_fpsaved==0) { 361 savfp(&u.u_fps); プロセスを切り替える。 362 u.u_fpsaved = 1; これは、最初に、sched()で呼ば 363 } れたswitchがproc0をresumeす 364 resume(proc[0].p_addr, u.u_qsav); 365 } る場合のルーチン 366 /* 367 * The first save returns nonzero when proc 0 is resumed 368 * by another process (above); then the second is not done 369 * and the process-search loop is entered. 370 * 371 * The first save returns 0 when swtch is called in proc 0 372 * from sched(). The second save returns 0 immediately, so 373 * in this case too the process-search loop is entered. 374 * Thus when proc 0 is awakened by being made runnable, it will 375 * find itself and resume itself at rsav, and return to sched(). 376 */ 377 if (save(u.u_qsav)==0 && save(u.u_rsav)) 31 378 return;
  • 32. 379 loop: 380 spl6(); 381 runrun = 0; switch(2/2) 382 pp = NULL; 383 q = NULL; 384 n = 128; 385 /* 386 * Search for highest-priority runnable process 387 */ 388 for(p=runq; p!=NULL; p=p->p_link) { 389 if((p->p_stat==SRUN) && (p->p_flag&SLOAD)) { 390 if(p->p_pri < n) { 391 pp = p; 392 pq = q; 393 n = p->p_pri; 394 } 順次プロセスの状態を調べ 395 } 396 q = p; て実行可能かつ最も優先 397 398 } /* 度が高いプロセスを選択し 399 * If no process is runnable, idle. ている 400 */ 401 p = pp; 該当がない場合、いったん 402 403 if(p == NULL) { idle(); idle()してまたループする 404 goto loop; 405 } 406 q = pq; 407 if(q == NULL) 408 runq = p->p_link; 409 else 410 q->p_link = p->p_link; 411 curpri = n; 412 spl0(); 413 /* 414 * The rsav (ssav) contents are interpreted in the new address space 415 */ 416 n = p->p_flag&SSWAP; 417 p->p_flag &= ~SSWAP; 418 resume(p->p_addr, n? u.u_ssav: u.u_rsav); 419 } 32
  • 33. 421 /* 422 * Create a new process-- the internal version of 423 * sys fork. 424 * It returns 1 in the new process, 0 in the old. newproc(1/4) 425 */ 426 newproc() 427 { 428 int a1, a2; 429 struct proc *p, *up; 430 register struct proc *rpp, *rip; 431 register n; 432 433 p = NULL; 434 /* 435 * First, just locate a slot for a process 436 * and copy the useful info from this process into it. 437 * The panic "cannot happen" because fork has already 438 * checked for the existence of a slot. 439 */ 440 retry: 441 mpid++; 442 if(mpid >= 30000) { 30000の数字の意味が不明 443 mpid = 0; 444 goto retry; 445 } 446 for(rpp = &proc[0]; rpp < &proc[NPROC]; rpp++) { 447 if(rpp->p_stat == NULL && p==NULL) 448 p = rpp; 449 if (rpp->p_pid==mpid || rpp->p_pgrp==mpid) 450 goto retry; 451 } 新しいプロセスが割り当てられるか 452 if ((rpp = p)==NULL) pidを調べている 33 453 panic("no procs");
  • 34. 455 /* 456 * make proc entry for new proc 457 458 */ newproc(2/4) 459 rip = u.u_procp; 460 up = rip; 461 rpp->p_stat = SRUN; 462 rpp->p_clktim = 0; 463 rpp->p_flag = SLOAD; 464 rpp->p_uid = rip->p_uid; 新しいプロセスの割りあて 資源などの情報は 465 rpp->p_pgrp = rip->p_pgrp; 親プロセスのをコピーしている 466 rpp->p_nice = rip->p_nice; forkのことか? 467 rpp->p_textp = rip->p_textp; 468 rpp->p_pid = mpid; 469 rpp->p_ppid = rip->p_pid; 470 rpp->p_time = 0; 471 rpp->p_cpu = 0; 472 473 /* 474 * make duplicate entries 475 * where needed 476 */ 34 477
  • 35. 478 for(n=0; n<NOFILE; n++) 479 if(u.u_ofile[n] != NULL) 480 u.u_ofile[n]->f_count++; 481 if(up->p_textp != NULL) { 482 483 up->p_textp->x_count++; up->p_textp->x_ccount++; newproc(3/4) 484 } 485 u.u_cdir->i_count++; 486 if (u.u_rdir) 487 u.u_rdir->i_count++; 488 /* 489 * Partially simulate the environment 490 * of the new process so that when it is actually 491 * created (by copying) it will look right. 492 */ 493 rpp = p; 494 u.u_procp = rpp; 495 rip = up; ちょっとここ謎の動作 496 n = rip->p_size; 497 a1 = rip->p_addr; 498 rpp->p_size = n; 35
  • 36. 499 /* 500 * When the resume is executed for the new process, 501 * here's where it will resume. 502 */ 503 if (save(u.u_ssav)) { 504 505 sureg(); return(1); newproc(4/4) 506 } 507 a2 = malloc(coremap, n); 508 /* 509 * If there is not enough core for the 510 * new process, swap out the current process to generate the 511 * copy. 512 */ 513 if(a2 == NULL) { 514 rip->p_stat = SIDL; 515 rpp->p_addr = a1; 516 xswap(rpp, 0, 0); 517 rip->p_stat = SRUN; 資源が足りなければ、 518 } else { 子プロセスの処理をするために 519 /* 親側をいったんスワップアウトする? 520 * There is core, so just copy. 521 */ 522 rpp->p_addr = a2; 523 while(n--) 524 copyseg(a1++, a2++); 525 } 526 u.u_procp = rip; 527 setrq(rpp); 528 rpp->p_flag |= SSWAP; 529 return(0); 36 530 }
  • 37. 545 expand(newsize) 532 /* 533 * Change the size of the data+stack regions of the process. 546 { 534 * If the size is shrinking, it's easy-- just release the extra core. 547 register i, n; 535 * If it's growing, and there is core, just allocate it 536 * and copy the image, taking care to reset registers to account 548 register struct proc *p; 537 * for the fact that the system's stack has moved. 549 register a1, a2; 538 * If there is no core, arrange for the process to be swapped 539 * out after adjusting the size requirement-- when it comes 550 540 * in, enough core will be allocated. 551 p = u.u_procp; 541 * 552 n = p->p_size; 542 * After the expansion, the caller will take care of copying 543 * the user's stack towards or away from the data area. 553 p->p_size = newsize; 544 */ 554 a1 = p->p_addr; 555 if(n >= newsize) { 556 mfree(coremap, n-newsize, a1+newsize); 557 return; 558 } 559 if (save(u.u_ssav)) { 560 561 562 } sureg(); return; expand(1/1) 563 a2 = malloc(coremap, newsize); 564 if(a2 == NULL) { 565 xswap(p, 1, n); 566 p->p_flag |= SSWAP; 確保しているメモリ領域(データとスタック)を 567 qswtch(); 変更したい時(拡張したいとき)、 568 /* no return */ malloc,freeで領域を取り直す 569 } 570 p->p_addr = a2; 571 for(i=0; i<n; i++) 572 copyseg(a1+i, a2+i); 573 mfree(coremap, n, a1); 574 resume(a2, u.u_ssav); 37 575 }
  • 38. 112 /* 113 * when you are sure that it 114 115 * is impossible to get the * 'proc on q' diagnostic, the setrq(1/1) 116 * diagnostic loop can be removed. 117 */ 118 setrq(p) 119 struct proc *p; 120 { 121 register struct proc *q; 122 register s; 123 124 s = spl6(); 125 for(q=runq; q!=NULL; q=q->p_link) 126 if(q == p) { 127 printf("proc on qn"); すでに起動済みのプロセスかどうか 128 goto out; 129 } チェックしている? 130 p->p_link = runq; 131 runq = p; 132 out: 133 splx(s); 134 } 38 135