陈可 原创作品转载请注明出处 《Linux内核分析》MOOC课程http://mooc.study.163.com/course/USTC-1000029000
Linux-2.6.20/init/main.c中的start_kernel(void)函数是Linux内核的入口,其前面的代码都是用汇编编写,Linux的第一个进程也是在这里产生,具体的来说是在start_kernel的最后会调用rest_init():
smlinkage void __init start_kernel(void) //该函数是Linux内核的入口,其前面的代码都是用汇编编写
{
...
...
...
rest_init();//这是Linux内核初始化的尾声
}
static void noinline rest_init(void)
__releases(kernel_lock)
{
kernel_thread(init, NULL, CLONE_FS | CLONE_SIGHAND);
/*创建一个内核线程,实际上就是内核进程,Linux内核是不支持类似Windows NT一样的线程概念的。
Linux本质上只支持进程。这里的 init只是一个函数,不要与init process搞淆了*/
numa_default_policy();
unlock_kernel();
/*
*The boot idle thread must execute schedule()
*at least one to get things moving:
*/
preempt_enable_no_resched();
schedule();
preempt_disable();
/* Call into cpu_idle with preempt disabled */
cpu_idle();
}
static int init(void * unused) // 内核创建的内核线程运行本函数,在本函数的结尾就是启动init process
{
...
...
...
run_init_process("/sbin/init");
run_init_process() //实际上是通过嵌入汇编构建一个类似用户态代码
run_init_process("/bin/init"); //是这里的init process在磁盘上的文件。
run_init_process("/bin/sh");
panic("No init found. Try passing init= option to kernel.");
}
tatic void run_init_process(char *init_filename)
{
kernel_execve(init_filename, argv_init, envp_init);
}
/*
*Do a system call from kernel instead of calling sys_execve so we
* end up with proper pt_regs.
*/ `//构造sys_execve系统调用
int kernel_execve(const char *filename, char *const argv[], char *const envp[])
{
long __res;
asm volatile ("push %%ebx ; movl %2,%%ebx ; int $0x80 ; pop %%ebx"
: "=a" (__res)
: "0" (__NR_execve),"ri" (filename),"c" (argv), "d" (envp) :"memory");
return __res;
}