読者です 読者をやめる 読者になる 読者になる

Programmer's Note

コード読み書きの備忘録。

UNIX V6コードリーディング・メモ

UNIX

UNIX V6のコードをまじめに読み始めようかと。 去年から『はじめてのOSコードリーディング』をぽつぽつと読んで、UNIX V6のソースの理解をし始めてはいるが、やはり全体像を知るにはまだまだ道のりは遠い。 動かしながら読めるのが一番ベストなのだが、まあとりあえずはソースコードの構成から、改めて眺めてみようと。

ただ読んでも面白くないので、Shell遊びしながらデータをとってみる。

ソース構成:

├── buf.h
├── conf
│   ├── data.s
│   ├── m40.s
│   ├── m45.s
│   ├── mkconf.c
│   ├── sysfix
│   └── sysfix.c
├── conf.h
├── dmr
│   ├── bio.c
│   ├── cat.c
│   ├── dc.c
│   ├── dh.c
│   ├── dhdm.c
│   ├── dhfdm.c
│   ├── dn.c
│   ├── dp.c
│   ├── hp.c
│   ├── hs.c
│   ├── ht.c
│   ├── kl.c
│   ├── lp.c
│   ├── mem.c
│   ├── partab.c
│   ├── pc.c
│   ├── rf.c
│   ├── rk.c
│   ├── rp.c
│   ├── sys.c
│   ├── tc.c
│   ├── tm.c
│   ├── tty.c
│   ├── vs.c
│   └── vt.c
├── file.h
├── filsys.h
├── ino.h
├── inode.h
├── ken
│   ├── alloc.c
│   ├── clock.c
│   ├── fio.c
│   ├── iget.c
│   ├── main.c
│   ├── malloc.c
│   ├── nami.c
│   ├── pipe.c
│   ├── prf.c
│   ├── rdwri.c
│   ├── sig.c
│   ├── slp.c
│   ├── subr.c
│   ├── sys1.c
│   ├── sys2.c
│   ├── sys3.c
│   ├── sys4.c
│   ├── sysent.c
│   ├── text.c
│   └── trap.c
├── param.h
├── proc.h
├── reg.h
├── run
├── seg.h
├── systm.h
├── text.h
├── tty.h
└── user.h

行数とかはさておき、各ファイルの定義関数の一覧を得てみる。

$ for i in `find . -name "*.c"` ;do A=`grep "^[a-z]*(.*)" $i`; echo $i":"$A ;done

出力:

./conf/mkconf.c:main() puke(s, a) input() equal(a, b) getchar()
./conf/sysfix.c:main(argc, argv) getrel(r)
./dmr/bio.c:bread(dev, blkno) breada(adev, blkno, rablkno) bwrite(bp) bdwrite(bp) bawrite(bp) brelse(bp) incore(adev, blkno) getblk(dev, blkno) iowait(bp) notavail(bp) iodone(bp) clrbuf(bp) binit() devstart(bp, devloc, devblk, hbcom) rhstart(bp, devloc, devblk, abae) mapalloc(abp) mapfree(bp) swap(blkno, coreaddr, count, rdflg) bflush(dev) physio(strat, abp, dev, rw) geterror(abp)
./dmr/cat.c:ctopen(dev) ctclose() ctwrite(dev) catintr()
./dmr/dc.c:dcopen(dev, flag) dcclose(dev) dcread(dev) dcwrite(dev) dcxint(dev) dcrint(dev) dcsgtty(dev, av)
./dmr/dh.c:dhopen(dev, flag) dhclose(dev) dhread(dev) dhwrite(dev) dhrint() dhsgtty(dev, av) dhparam(atp) dhxint() dhstart(atp)
・・・

関数の数がよくわからないので、')' を数えて関数の数とする。

$ for i in `find . -name "*.c"` ;do FN=`grep "^[a-z]*(.*)" $i`; NF=`echo $FN | awk -F\) 'NF>0 {print NF-1}'`; echo $i": "$FN": "$NF ;done

結果:

./conf/mkconf.c: main() puke(s, a) input() equal(a, b) getchar(): 5
./conf/sysfix.c: main(argc, argv) getrel(r): 2
./dmr/bio.c: bread(dev, blkno) breada(adev, blkno, rablkno) bwrite(bp) bdwrite(bp) bawrite(bp) brelse(bp) incore(adev, blkno) getblk(dev, blkno) iowait(bp) notavail(bp) iodone(bp) clrbuf(bp) binit() devstart(bp, devloc, devblk, hbcom) rhstart(bp, devloc, devblk, abae) mapalloc(abp) mapfree(bp) swap(blkno, coreaddr, count, rdflg) bflush(dev) physio(strat, abp, dev, rw) geterror(abp): 21
./dmr/cat.c: ctopen(dev) ctclose() ctwrite(dev) catintr(): 4
./dmr/dc.c: dcopen(dev, flag) dcclose(dev) dcread(dev) dcwrite(dev) dcxint(dev) dcrint(dev) dcsgtty(dev, av): 7
./dmr/dh.c: dhopen(dev, flag) dhclose(dev) dhread(dev) dhwrite(dev) dhrint() dhsgtty(dev, av) dhparam(atp) dhxint() dhstart(atp): 9
./dmr/dhdm.c: dmopen(dev) dmclose(dev) dmint(): 3
./dmr/dhfdm.c: dmopen(dev) dmclose(dev): 2
・・・

さらに、この結果に対して、 定義関数の数字を奇麗に出してみる。

$ for i in `find . -name "*.c"` ;do FN=`grep "^[a-z]*(.*)" $i`; NF=`echo $FN | awk -F\) 'NF>0 {print NF-1}'`; echo $i": "$FN": "$NF ;done | awk -F: '{printf("%3d\t%s\n",$3,$1)}'

結果:

  5  ./conf/mkconf.c
  2 ./conf/sysfix.c
 21 ./dmr/bio.c
  4 ./dmr/cat.c
  7 ./dmr/dc.c
  9 ./dmr/dh.c
  3 ./dmr/dhdm.c
  2 ./dmr/dhfdm.c
  4 ./dmr/dn.c
 10 ./dmr/dp.c
  7 ./dmr/hp.c
  5 ./dmr/hs.c
  9 ./dmr/ht.c
  7 ./dmr/kl.c
  7 ./dmr/lp.c
・・・

関数名に数字[0-9]を入れるのを忘れてた、ということで以下修正版:

$ for i in `find . -name "*.c"` ;do FN=`grep "^[a-z0-9]*(.*)" $i`; NF=`echo $FN | awk -F\) 'NF>0 {print NF-1}'`; echo $i": "$FN": "$NF ;done | awk -F: '{printf("%3d\t%s\n",$3,$1)}'

まあ、細かいこと言うとアセンブラソースの中の定義関数は入ってないし、 行の先頭以外で定義した関数(あるかどうか知らないが)は関知してない。

※うーむ、はてなって長い行のソースコードは折り返して表示してくれないんだな。

(追記)以下のサイトのCSS使ったら、折り返してくれた。 preタグ内のコードをボックス枠内で折り返すcss | DAICHIFIVE blog

以上。