カーネルのソースコード

プロセスの状態の話が出てきたので,カーネルソースコードを眺め始めてみようかな.スケジューラから読み始めるのは割と定石だし(Plan9の場合はやっぱりファイルシステムじゃないか!?という気はするが).

最初にソースツリーの概略を示すと,/sys/src/9以下がカーネルソースコードになる.さらに/sys/src/9/portにはアーキテクチャ非依存コード,/sys/src/9/pcにはi386アーキテクチャ依存コードが含まれるようだ.ちなみにファイルシステムは/sys/src/fs,ネットワーキングは/sys/src/ip以下になる.

プロセス関係は/sys/src/9/port/proc.cあたりかな.

  • proc.c: スケジューラ
  • pgrp.c: プロセスグループ
  • devproc.c: プロセスデバイス
  • sysproc.c: システムコール(sysr1, sysrfork, sysexec, syssleep, sysalerm, sysexits, sys_wait, syswait, sysdeath, syserrstr, sys_errstr, sysnotify, sysnoted, syssegbrk, syssegattach, syssegdetach, syssegfree, sysrendezvous)
  • portdat.h: データ構造
  • portfns.h: 関数定義

dat.hにデータ構造,fns.hに関数の宣言をする規約になっているようなので,最初にこれらのヘッダファイルを読むと全体像が把握しやすいかも.

以下,まとまりのないメモ

  • spl*()で,割込み優先度制御をやっているのね.
    • splhiとsplloの2レベルで,splxで元の状態に戻る.実装はアーキテクチャ依存なのでpc/l.s.i386の場合はsplhiでcli,splloでstiが実行される.
  • UNIXの優先度は(nice)値が小さい方が高優先度だったが,Plan9は逆.
  • setlabel/gotolabel
    • setjmp/longjmpみたいな大域ジャンプする仕組み.実体はpc/l.sに定義されているアセンブリでPCとSPの退避,復帰を行なう.struct Procにはschedやerrlab[NERR]というラベルが含まれている.前者はプロセススイッチの肝になるコルーチンの実現,後者はエラー処理に使われる.
  • sched(スケジューラ関数)
    • 次に実行するプロセスの選択はrunprocで決定,アーキテクチャ依存のコンテキスト(レジスタ)の退避,復帰はprocsave/procrestore (pc/main.c)で,アドレス空間の切替えはmmuswitchで行なう.setlable/gotolabelでPCとSPを切り替えることでプロセスをスイッチする.
  • EDFスケジューリング(port/edf.c)の文字が.