んとなく昨日の続きから。だいたいこんな流れ。
do_fork@servers/pm/forkexit.c -> sys_fork@lib/syslib/sys_fork.c -> do_fork@kernel/system /do_fork.c
servers/pm/forkexit.c
31 PUBLIC int do_fork() 32 { 中略 94 /* Tell kernel and file system about the (now successful) FORK. */ 95 sys_fork(who, child_nr);
lib/syslib/sys_fork.c
1 #include "syslib.h" 2 3 PUBLIC int sys_fork(parent, child) 4 int parent; /* process doing the fork */ 5 int child; /* which proc has been created by the fork */ 6 { 7 /* A process has forked. Tell the kernel. */ 8 9 message m; 10 11 m.PR_PPROC_NR = parent; 12 m.PR_PROC_NR = child; 13 return(_taskcall(SYSTASK, SYS_FORK, &m)); 14 }
kernel/system /do_fork.c
17 /*===========================================================================* 18 * do_fork * 19 *===========================================================================*/ 20 PUBLIC int do_fork(m_ptr) 21 register message *m_ptr; /* pointer to request message */ 22 { 23 /* Handle sys_fork(). PR_PPROC_NR has forked. The child is PR_PROC_NR. */ 24 #if (CHIP == INTEL) 25 reg_t old_ldt_sel; 26 #endif 27 register struct proc *rpc; /* child process pointer */ 28 struct proc *rpp; /* parent process pointer */ 29 int i; 30 31 rpp = proc_addr(m_ptr->PR_PPROC_NR); 32 rpc = proc_addr(m_ptr->PR_PROC_NR);
それで、サーバからカーネルに渡るデータはforkexit.cの95行目でsys_fork()の呼び出しに使用したwhoとchild_nr。この場合、whoはfork(2)を実行したプロセスなはずで、child_nrはこのような感じで、設定された値。
70 /* Set up the child and its memory map; copy its 'mproc' slot from parent. */ 71 child_nr = (int)(rmc - mproc); /* slot number of the child */
ここでrmcは何かというと子プロセス用のmproc構造体で、mprocはプロセスを格納する構造体の配列。
rmcは以下のように最初に見つかった未使用のデータを使う。オペレーティングシステム 第3版時点のコードでは最大プロセス数はNR_PROCSで定義されて、コンパイル時に配列サイズが決定してます。
66 /* Find a slot in 'mproc' for the child process. A slot must exist. */ 67 for (rmc = &mproc[0]; rmc mp_flags & IN_USE) == 0) break; 69
このsys_fork()で渡した引数はカーネルのdo_fork()の中でこんな感じで取得する。
31 rpp = proc_addr(m_ptr->PR_PPROC_NR); 32 rpc = proc_addr(m_ptr->PR_PROC_NR);
PR_PPROC_NRはマクロでwhoとchild_nrにアクセスしていると思ってください。ここはminixのメッセージの構造が絡んでますが、あまり気にしなくても良い部分だし。
proc_addrはマクロでkernel/proc.hで定義。
89 #define proc_addr(n) (pproc_addr + NR_TASKS)[(n)]
これでサーバからカーネルにデータが渡ってる流れが見えた( ´∀`)bグッ!