FreeBSDとNetBSDの初期化シーケンスの違い
FreeBSDもNetBSDも元を辿れば同じものから派生してるんだから、コードもさぞかし似ているんだろう。
とか思って、初期化シーケンスを見ていたら、見た目がかなり違っていてビビッた。
NetBSDでは先ほど書いた通り、kern/init_main.cのmain()から機種非依存な初期化コードが始まる。
こんな感じに素朴に関数呼び出しが並べてある:
/* * Attempt to find console and initialize * in case of early panic or other messages. */ consinit(); kernel_lock_init(); uvm_init(); kmem_init(); percpu_init(); /* Initialize lock caches. */ mutex_obj_init(); /* Initialize the extent manager. */ extent_init(); /* Do machine-dependent initialization. */ cpu_startup();
素朴でとても初心者に優しい。
一方、FreeBSDのはkern/init_main.cのmi_startup()にあって、こんな感じだ:
for (sipp = sysinit; sipp < sysinit_end; sipp++) { if ((*sipp)->subsystem == SI_SUB_DUMMY) continue; /* skip dummy task(s)*/ if ((*sipp)->subsystem == SI_SUB_DONE) continue; #if defined(VERBOSE_SYSINIT) if ((*sipp)->subsystem > last) { verbose = 1; last = (*sipp)->subsystem; printf("subsystem %x\n", last); } if (verbose) { #if defined(DDB) const char *name; c_db_sym_t sym; db_expr_t offset; sym = db_search_symbol((vm_offset_t)(*sipp)->func, DB_STGY_PROC, &offset); db_symbol_values(sym, &name, NULL); if (name != NULL) printf(" %s(%p)... ", name, (*sipp)->udata); else #endif printf(" %p(%p)... ", (*sipp)->func, (*sipp)->udata); } #endif /* Call function */ (*((*sipp)->func))((*sipp)->udata);
まぁ良く見るとテーブルらしきものに関数ポインタが登録されるようになってて、その為のマクロとかも用意されてて、、となってるっぽいんだが、カラクリを知らないとすっかりさっぱり追いにくくなってて困る。
こっちの方が拡張性とかあってクールだよ、とか言われれば、そうかもしれない、とも思うんだけれども。