原文地址: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内核开始真正进入初始化阶段,
下面我就顺这代码逐个函数的解释,但是这里并不会过于深入每个函数,因为这样就会只见树木,不见森林。分析代码首先要从构架上宏观地理解,然后再去考虑细节问题(这和小时候学语文要概括中心思想和段落大意是一个道理)。今后对于每个子系统的初始化,特别是内存子系统,有空都会分析一遍。
- asmlinkage void __init start_kernel(void)
- {
- char * command_line;
- extern const struct kernel_param __start___param[], __stop___param[];
-
- 这里关键是这两个变量的地址是如何确定的。
- 这两个变量为地址指针,指向内核启动参数处理相关结构体段在内存中的位置(虚拟地址)。
- 这里是外部变量,定义的位置在arch/../../vmlinux.lds.S,而大多数平台是放到kernel\include\asm-generic\vmlinux.lds.h中,定义如下:
-
-
- 362 /* 内建模块的参数处理段. */ \
- 363 __param : AT(ADDR(__param) - LOAD_OFFSET) { \
- 364 VMLINUX_SYMBOL(__start___param) = .; \
- 365 *(__param) \
- 366 VMLINUX_SYMBOL(__stop___param) = .; \
- 367 }
- 对于ARM平台,似乎位于 kernel\include\asm-generic\vmlinux.lds.h
-
- 这个段中数据的数据结构:
- kernel_param结构体的定义是:
- 36 struct kernel_param_ops {
- 37 /* Returns 0, or -errno. arg is in kp->arg. */
- 38 int (*set)(const char *val, const struct kernel_param *kp);
- 39 /* Returns length written or -errno. Buffer is 4k (ie. be */
- 40 int (*get)(char *buffer, const struct kernel_param *kp);
- 41 /* Optional function to free kp->arg when module unloaded. */
- 42 void (*free)(void *arg);
- 43 };
- 44
- 45 /* Flag bits for kernel_param.flags */
- 46 #define KPARAM_ISBOOL 2
- 47
- 48 struct kernel_param {
- 49 const char *name;
- 50 const struct kernel_param_ops *ops;
- 51 u16 perm;
- 52 u16 flags;
- 53 union {
- 54 void *arg;
- 55 const struct kparam_string *str;
- 56 const struct kparam_array *arr;
- 57 };
- 58 };
- 59
- 60 /* Special one for strings we want to copy into */
- 61 struct kparam_string {
- 62 unsigned int maxlen;
- 63 char *string;
- 64 };
- 65
- 66 /* Special one for arrays */
- 67 struct kparam_array
- 68 {
- 69 unsigned int max;
- 70 unsigned int elemsize;
- 71 unsigned int *num;
- 72 const struct kernel_param_ops *ops;
- 73 void *elem;
- 74 };
- smp_setup_processor_id();
-
- 这个函数是针对SMP处理器的,经查阅资料,其作用是获取当前CPU的的硬件ID。
- 如果不是多处理器构架,在其他文件中就不会定义这个函数,此时使用本文件定义的弱引用函数:
- void __init __weak smp_setup_processor_id(void)
- {
- }
- /*
- * 必须尽早运行这个程序, 作用是初始化
- * lockdep 模块的hash表:
- */
- lockdep_init();
-
- lockdep是一个内核调试模块,用来检查内核互斥机制(尤其是自旋锁)潜在的死锁问题。
-
- 由于自旋锁以查询方式等待,不释放处理器,比一般互斥机制更容易死锁,故引入lockdep检查以下几种可能的死锁情况:
- 同一个进程递归地加锁同一把锁;
- 一把锁既在中断(或中断下半部)使能的情况下执行过加锁操作, 又在中断(或中断下半部)里执行过加锁操作。这样该锁有可能在锁定时由于中断发生又试图在同一处理器上加锁;
- 加锁后导致依赖图产生成闭环,这是典型的死锁现象。
ItVuer - 免责声明 - 关于我们 - 联系我们
本网站信息来源于互联网,如有侵权请联系:561261067@qq.com
桂ICP备16001015号