在init/main.c文件中有个函数叫start_kernel,它是用来启动内核的主函数,我想大家都知道这个函数啦,而在该函数的最后将调用一个函数叫rest_init(),它执行完,内核就起来了,asmlinkage void __init start_kernel(void) { ...... /* Do the rest non-__init"ed, we"re now alive */ rest_init(); }现在我们来看一下rest_init()函数,它也在文件init/main.c中,它的前面几行是:static void noinline __init_refok rest_init(void) __releases(kernel_lock) { int pid; kernel_thread(kernel_init, NULL, CLONE_FS | CLONE_SIGHAND);其中函数kernel_thread定义在文件arch/ia64/kernel/process.c中,用来启动一个内核线程,这里的kernel_init是要执行的函数的指针,NULL表示传递给该函数的参数为空,CLONE_FS | CLONE_SIGHAND为do_fork产生线程时的标志,表示进程间的fs信息共享,信号处理和块信号共享,然后我就屁颠屁颠地追随到kernel_init函数了,现在来瞧瞧它都做了什么好事,它的完整代码如下:static int __init kernel_init(void * unused) { lock_kernel(); /* * init can run on any cpu. */ set_cpus_allowed_ptr(current, CPU_MASK_ALL_PTR); /* * Tell the world that we"re going to be the grim * reaper of innocent orphaned children. * We don"t want people to have to make incorrect * assumptions about where in the task array this * can be found. */ init_pid_ns.child_reaper = current; cad_pid = task_pid(current); smp_prepare_cpus(setup_max_cpus); do_pre_smp_initcalls(); smp_init(); sched_init_smp(); cpuset_init_smp(); do_basic_setup(); /* * check if there is an early userspace init. If yes, let it do all * the work */ if (!ramdisk_execute_command) ramdisk_execute_command = "/init"; if (sys_access((const char __user *) ramdisk_execute_command, 0) != 0) { ramdisk_execute_command = NULL; prepare_namespace(); } /* * Ok, we have completed the initial bootup, and * we"re essentially up and running. Get rid of the * initmem segments and start the user-mode stuff.. */ init_post(); return 0; }在kernel_init函数的一开始就调用了lock_kernel()函数,当编译时选上了CONFIG_LOCK_KERNEL,就加上大内核锁,否则啥也不做,紧接着就调用了函数set_cpus_allowed_ptr,由于这些函数对init进程的调起还是有影响的,我们还是一个一个来瞧瞧吧,不要忘了啥东东最好,static inline int set_cpus_allowed_ptr(struct task_struct *p, const cpumask_t *new_mask) { if (!cpu_isset(0, *new_mask)) return -EINVAL; return 0; }