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