电脑技术学习

FreeBSD的Loader和内核初始化

dn001

enum sysinit_sub_id {
  SI_SUB_DUMMY    = 0x0000000,  /* 不被执行,仅供链接器使用 */
  SI_SUB_DONE   = 0x0000001,  /* 已被处理*/
  SI_SUB_CONSOLE   = 0x0800000,  /* 控制台*/
  SI_SUB_COPYRIGHT  = 0x0800001,  /* 最早使用控制台的对象 */
...
  SI_SUB_RUN_SCHEDULER  = 0xfffffff /* 调度器:不返回 */
};
系统调度器sysinit对象定义在文件sys/vm/vm_glue.c中,这个对象的入口点是scheduler()。这个函数实际上是个无限循环,它表示那个进程标识(PID)为0的进程——swapper进程。前面提到的proc0结构正是用来描述这个进程。

  第一个用户进程是init,由sysinit对象init建立:sys/kern/init_main.c:

static void
create_init(const void *udata __unused)
{
  int error;
  int s;
  s = splhigh();
  error = fork1(&proc0, RFFDG | RFPROC, &initproc);
  if (error)
    panic("cannot fork init: %dn", error);
  initproc->p_flag |= P_INMEM | P_SYSTEM;
  CPU_set_fork_handler(initproc, start_init, NULL);
  remrunqueue(initproc);
  splx(s);
}

  SYSINIT(init,SI_SUB_CREATE_INIT, SI_ORDER_FIRST, create_init, NULL)

  create_init()通过调用fork1()分配一个新的进程,但并不将其标记为可运行。

  当这个新进程被调度器调度执行时,start_init()将会被调用。

  那个函数定义在init_main.c中。它尝试装载并执行二进制代码init,

  先尝试/sbin/init,然后是/sbin/oinit,/sbin/init.bak,

  最后是/stand/sysinstall:sys/kern/init_main.c:

static char init_path[MAXPATHLEN] =
#ifdef INIT_PATH
  __XSTRING(INIT_PATH);
#else
  "/sbin/init:/sbin/oinit:/sbin/init.bak:/stand/sysinstall";
#endif

标签: