linux的启动过程是一个很复杂的过程,从加电到登陆界面,涉及很多汇编的知识,但是现在我们只是关心
协议这一部分,所以就从 start_kernel 这个函数开始了,这是内核启动的第一个函数
但是从加电到到系统显示登陆界面涉及到的文件有,这一部分和系统的架构有关
- 汇编文件:arch/x86/kernelentry_32(64).S,
- init/main.c,这里涉及start_kernel 函数
声明一下:在这里我们先建立起初始化的大致框架,所以很多代码已经省略,详细的过程会在以后继续进行详细的分析
加入一段init/main.c
- asmlinkage void __init start_kernel(void)
- {
- …………
- /* Do the rest non-__init'ed, we're now alive */
- rest_init();
- }
这是一段start_kernel() 函数的代码,至于其他的,是系统启动过程中的一些初始化的过程包括:
- 中断系统的初始化
- 调度系统的初始化
- 文件系统的初始化
- 设备管理系统的初始化
上面的代码涉及网络协议系统的初始化,就是rest_init(); 这个函数和内核的网络部分的初始化有关,重点看一下吧,init/main.c
- static noinline void __init_refok rest_init(void)
- __releases(kernel_lock)
- {
- int pid;
- rcu_scheduler_starting();
- /*
- * We need to spawn init first so that it obtains pid 1, however
- * the init task will end up wanting to create kthreads, which, if
- * we schedule it before we create kthreadd, will OOPS.
- */
- /*
- * rest_init 调用 kernel_thread() 创建一个内核级的线程 接下来就开始网络部分的初始化了
- */
- kernel_thread(kernel_init, NULL, CLONE_FS | CLONE_SIGHAND);
- numa_default_policy();
- pid = kernel_thread(kthreadd, NULL, CLONE_FS | CLONE_FILES);
- rcu_read_lock();
- kthreadd_task = find_task_by_pid_ns(pid, &init_pid_ns);
- rcu_read_unlock();
- complete(&kthreadd_done);
- unlock_kernel();
- …………
- /* Call into cpu_idle with preempt disabled */
- cpu_idle();
- }
kernel_thread() 定义在arch/x86/kernel/process.c 中,rest_init()调用这个函数创建了一个内核级的线程,接下来的工作就是靠它网络协议部分的初始化,kernel_thread()创建 kernel_init 线程,关于这个函数我们来看一下, init/main.c kernel_init()
- static int __init kernel_init(void * unused)
- {
- /*
- * Wait until kthreadd is all set-up.
- */
- wait_for_completion(&kthreadd_done);
- lock_kernel();
- do_basic_setup();
- /* Open the /dev/console on the rootfs, this should never fail */
- if (sys_open((const char __user *) "/dev/console", O_RDWR, 0) < 0)
- printk(KERN_WARNING "Warning: unable to open an initial console.\n");
- init_post();
- return 0;
- }
这就是 kernel_init()函数的原型,这个函数可以在init/main.c中看到它的原型,这个函数条用了很多函数,但是我们只关心一个,就是和网络有关的的 do_basic_setup 这个函数,再来看一段代码
- static void __init do_basic_setup(void)
- {
- init_workqueues();
- cpuset_init_smp();
- usermodehelper_init();
- init_tmpfs();
- driver_init();
- init_irq_proc();
- do_ctors();
- do_initcalls();
- }
赢还是奇怪,因为么有看到任何和协议有关的代码,那么接下来就快了,看一下这段代码
- extern initcall_t __initcall_start[], __initcall_end[], __early_initcall_end[];
- static void __init do_initcalls(void)
- {
- initcall_t *fn;
- for (fn = __early_initcall_end; fn < __initcall_end; fn++)
- do_one_initcall(*fn);
- /* Make sure there is no pending stuff from the initcall sequence */
- flush_scheduled_work();
- }
到这个函数其实已经接近目标了,这里的 initcall_t 定义在 linux/init.h
- typedef int (*initcall_t)(void);
- typedef void (*exitcall_t)(void);
有一些细节上的问题,暂时先到这儿吧!
阅读(773) | 评论(0) | 转发(0) |