Linux内核源码分析--内核启动之(3)Image内核启动(C语言部分)(Linux-3.0 ARMv7) 【转】...

发布时间:2023-02-11 14:00

原文地址:Linux内核源码分析--内核启动之(3)Image内核启动(C语言部分)(Linux-3.0 ARMv7) 作者:tekkamanninja

 转自:http://blog.chinaunix.net/uid-25909619-id-4938390.html

  在构架相关的汇编代码运行完之后,程序跳入了构架无关的内核C语言代码:init/main.c中的start_kernel函数,在这个函数中Linux内核开始真正进入初始化阶段,
 
   下面我就顺这代码逐个函数的解释,但是这里并不会过于深入每个函数,因为这样就会只见树木,不见森林。分析代码首先要从构架上宏观地理解,然后再去考虑细节问题(这和小时候学语文要概括中心思想和段落大意是一个道理)。今后对于每个子系统的初始化,特别是内存子系统,有空都会分析一遍。

  1. asmlinkage void __init start_kernel(void)
  2. {
  3.     char * command_line;
  4.     extern const struct kernel_param __start___param[], __stop___param[];

  5. 点击(此处)折叠或打开

    1. 这里关键是这两个变量的地址是如何确定的。
    2. 这两个变量为地址指针,指向内核启动参数处理相关结构体段在内存中的位置(虚拟地址)。
    3. 这里是外部变量,定义的位置在arch/../../vmlinux.lds.S,而大多数平台是放到kernel\include\asm-generic\vmlinux.lds.h中,定义如下:

    4. 点击(此处)折叠或打开

      1. 362     /* 内建模块的参数处理段. */               \
      2. 363     __param : AT(ADDR(__param) - LOAD_OFFSET) {         \                                                                                                                    
      3. 364         VMLINUX_SYMBOL(__start___param) = .;            \                           
      4. 365         *(__param)                      \
      5. 366         VMLINUX_SYMBOL(__stop___param) = .;         \                               
      6. 367     } 
    5. 对于ARM平台,似乎位于 kernel\include\asm-generic\vmlinux.lds.h
    6. 这个段中数据的数据结构:
    7. kernel_param结构体的定义是:

    点击(此处)折叠或打开

    1. 36 struct kernel_param_ops {
    2.  37      /* Returns 0, or -errno. arg is in kp->arg. */
    3.  38      int (*set)(const char *val, const struct kernel_param *kp);
    4.  39      /* Returns length written or -errno. Buffer is 4k (ie. be */
    5.  40      int (*get)(char *buffer, const struct kernel_param *kp);
    6.  41      /* Optional function to free kp->arg when module unloaded. */
    7.  42      void (*free)(void *arg);
    8.  43  };
    9.  44  
    10.  45  /* Flag bits for kernel_param.flags */
    11.  46  #define KPARAM_ISBOOL 2
    12.  47  
    13.  48 struct kernel_param {
    14.  49      const char *name;
    15.  50      const struct kernel_param_ops *ops;
    16.  51       u16 perm;
    17.  52      u16 flags;
    18.  53      union {
    19.  54          void *arg;
    20.  55          const struct kparam_string *str;
    21.  56          const struct kparam_array *arr;
    22.  57      };
    23.  58 };
    24.  59  
    25.  60  /* Special one for strings we want to copy into */
    26.  61  struct kparam_string {
    27.  62      unsigned int maxlen;
    28.  63      char *string;
    29.  64  };
    30.  65 
    31.  66  /* Special one for arrays */
    32.  67  struct kparam_array
    33.  68  {
    34.  69      unsigned int max;
    35.  70      unsigned int elemsize;
    36.  71      unsigned int *num;
    37.  72      const struct kernel_param_ops *ops;
    38.  73      void *elem;
    39.  74  };
     
  6.     smp_setup_processor_id();

  7. 点击(此处)折叠或打开

    1. 这个函数是针对SMP处理器的,经查阅资料,其作用是获取当前CPU的的硬件ID。
    2. 如果不是多处理器构架,在其他文件中就不会定义这个函数,此时使用本文件定义的弱引用函数:
    3. void __init __weak smp_setup_processor_id(void)
    4. {
    5. }
  8.     /*
  9.      * 必须尽早运行这个程序, 作用是初始化
  10.      * lockdep 模块的hash表:
  11.      */
  12.     lockdep_init();

  13. 点击(此处)折叠或打开

    1. lockdep是一个内核调试模块,用来检查内核互斥机制(尤其是自旋锁)潜在的死锁问题。
    2. 由于自旋锁以查询方式等待,不释放处理器,比一般互斥机制更容易死锁,故引入lockdep检查以下几种可能的死锁情况:
    • 同一个进程递归地加锁同一把锁;
    • 一把锁既在中断(或中断下半部)使能的情况下执行过加锁操作, 又在中断(或中断下半部)里执行过加锁操作。这样该锁有可能在锁定时由于中断发生又试图在同一处理器上加锁;
    • 加锁后导致依赖图产生成闭环,这是典型的死锁现象。

ItVuer - 免责声明 - 关于我们 - 联系我们

本网站信息来源于互联网,如有侵权请联系:561261067@qq.com

桂ICP备16001015号