Chinaunix首页 | 论坛 | 博客
  • 博客访问: 381453
  • 博文数量: 69
  • 博客积分: 1486
  • 博客等级: 上尉
  • 技术积分: 630
  • 用 户 组: 普通用户
  • 注册时间: 2010-07-22 18:38
个人简介

...

文章分类
文章存档

2024年(1)

2021年(2)

2020年(2)

2016年(9)

2015年(34)

2011年(14)

2010年(7)

分类: LINUX

2011-09-10 10:52:35

linux的启动过程是一个很复杂的过程,从加电到登陆界面,涉及很多汇编的知识,但是现在我们只是关心
协议这一部分,所以就从 start_kernel 这个函数开始了,这是内核启动的第一个函数
但是从加电到到系统显示登陆界面涉及到的文件有,这一部分和系统的架构有关
  • 汇编文件:arch/x86/kernelentry_32(64).S,
  • init/main.c,这里涉及start_kernel 函数

声明一下:在这里我们先建立起初始化的大致框架,所以很多代码已经省略,详细的过程会在以后继续进行详细的分析

加入一段init/main.c

  1. asmlinkage void __init start_kernel(void)
  2. {
  3.     …………

  4.     /* Do the rest non-__init'ed, we're now alive */
  5.     rest_init();
  6. }

这是一段start_kernel() 函数的代码,至于其他的,是系统启动过程中的一些初始化的过程包括:

  • 中断系统的初始化
  • 调度系统的初始化
  • 文件系统的初始化
  • 设备管理系统的初始化

上面的代码涉及网络协议系统的初始化,就是rest_init(); 这个函数和内核的网络部分的初始化有关,重点看一下吧,init/main.c

  1. static noinline void __init_refok rest_init(void)
  2.     __releases(kernel_lock)
  3. {
  4.     int pid;

  5.     rcu_scheduler_starting();
  6.     /*
  7.      * We need to spawn init first so that it obtains pid 1, however
  8.      * the init task will end up wanting to create kthreads, which, if
  9.      * we schedule it before we create kthreadd, will OOPS.
  10.      */
  11.     /*
  12.      * rest_init 调用 kernel_thread() 创建一个内核级的线程 接下来就开始网络部分的初始化了
  13.      */

  14.     kernel_thread(kernel_init, NULL, CLONE_FS | CLONE_SIGHAND);

  15.     numa_default_policy();
  16.     pid = kernel_thread(kthreadd, NULL, CLONE_FS | CLONE_FILES);
  17.     rcu_read_lock();
  18.     kthreadd_task = find_task_by_pid_ns(pid, &init_pid_ns);
  19.     rcu_read_unlock();
  20.     complete(&kthreadd_done);
  21.     unlock_kernel();

  22.     …………
  23.     /* Call into cpu_idle with preempt disabled */
  24.     cpu_idle();
  25. }

kernel_thread() 定义在arch/x86/kernel/process.c 中,rest_init()调用这个函数创建了一个内核级的线程,接下来的工作就是靠它网络协议部分的初始化,kernel_thread()创建 kernel_init 线程,关于这个函数我们来看一下, init/main.c kernel_init()

  1. static int __init kernel_init(void * unused)
  2. {
  3.     /*
  4.      * Wait until kthreadd is all set-up.
  5.      */
  6.     wait_for_completion(&kthreadd_done);
  7.     lock_kernel();

  8.     do_basic_setup();

  9.     /* Open the /dev/console on the rootfs, this should never fail */
  10.     if (sys_open((const char __user *) "/dev/console", O_RDWR, 0) < 0)
  11.         printk(KERN_WARNING "Warning: unable to open an initial console.\n");

  12.     init_post();
  13.     return 0;
  14. }

这就是 kernel_init()函数的原型,这个函数可以在init/main.c中看到它的原型,这个函数条用了很多函数,但是我们只关心一个,就是和网络有关的的 do_basic_setup 这个函数,再来看一段代码

  1. static void __init do_basic_setup(void)
  2. {
  3.     init_workqueues();
  4.     cpuset_init_smp();
  5.     usermodehelper_init();
  6.     init_tmpfs();
  7.     driver_init();
  8.     init_irq_proc();
  9.     do_ctors();
  10.     do_initcalls();
  11. }

赢还是奇怪,因为么有看到任何和协议有关的代码,那么接下来就快了,看一下这段代码

  1. extern initcall_t __initcall_start[], __initcall_end[], __early_initcall_end[];

  2. static void __init do_initcalls(void)
  3. {
  4.     initcall_t *fn;

  5.     for (fn = __early_initcall_end; fn < __initcall_end; fn++)
  6.         do_one_initcall(*fn);

  7.     /* Make sure there is no pending stuff from the initcall sequence */
  8.     flush_scheduled_work();
  9. }

到这个函数其实已经接近目标了,这里的 initcall_t 定义在 linux/init.h

  1. typedef int (*initcall_t)(void);
  2. typedef void (*exitcall_t)(void);
有一些细节上的问题,暂时先到这儿吧!
阅读(1706) | 评论(0) | 转发(1) |
给主人留下些什么吧!~~