arm Linux系统启动之start_kernel函数
---具体做了哪些动作
---跳转到init/main.c
---b start_kernel
//关于start_kernel的强文深入理解linux内核,第八章
main.c
asmlinkage void __init start_kernel(void)
{
char * command_line;
extern struct kernel_param __start___param[], __stop___param[];
//来设置smp process id,当然目前看到的代码里面这里是空的
smp_setup_processor_id();
/*
* Need to run as early as possible, to initialize the
* lockdep hash:
*/
//lockdep是linux内核的一个调试模块,用来检查内核互斥机制尤其是自旋锁潜在的死锁问题。
//自旋锁由于是查询方式等待,不释放处理器,比一般的互斥机制更容易死锁,
//故引入lockdep检查以下几种情况可能的死锁(lockdep将有专门的文章详细介绍,在此只是简单列举):
//
//·同一个进程递归地加锁同一把锁;
//
//·一把锁既在中断(或中断下半部)使能的情况下执行过加锁操作,
// 又在中断(或中断下半部)里执行过加锁操作。这样该锁有可能在锁定时由于中断发生又试图在同一处理器上加锁;
//
//·加锁后导致依赖图产生成闭环,这是典型的死锁现象。
lockdep_init();
debug_objects_early_init();
/*
* Set up the the initial canary ASAP:
*/
//初始化stack_canary栈3
//stack_canary的是带防止栈溢出攻击保护的堆栈。
// 当user space的程序通过int 0x80进入内核空间的时候,CPU自动完成一次堆栈切换,
//从user space的stack切换到kernel space的stack。
// 在这个进程exit之前所发生的所有系统调用所使用的kernel stack都是同一个。
//kernel stack的大小一般为4096/8192,
//内核堆栈示意图帮助大家理解:
//
// 内存低址 内存高址
// | |<-----------------------------esp|
// +-----------------------------------4096-------------------------------+
// | 72 | 4 | x < 4016 | 4 |
// +------------------+-----------------+---------------------------------+
// |thread_info | | STACK_END_MAGIC | var/call chain |stack_canary |
// +------------------+-----------------+---------------------------------+
// | 28 | 44 | | |
// V | |
// restart_block V
//
//esp+0x0 +0x40
// +---------------------------------------------------------------------------+
// |ebx|ecx|edx|esi|edi|ebp|eax|ds|es|fs|gs|orig_eax|eip|cs|eflags|oldesp|oldss|
// +---------------------------------------------------------------------------+
// | kernel完成 | cpu自动完成 |
//http://hi.baidu.com/wzt85/blog/item/112a37132f6116c2f6039e44.html
boot_init_stack_canary();
// cgroup: 它的全称为control group.即一组进程的行为控制.
// 比如,我们限制进程/bin/sh的CPU使用为20%.我们就可以建一个cpu占用为20%的cgroup.
// 然后将/bin/sh进程添加到这个cgroup中.当然,一个cgroup可以有多个进程.
//http://blogold.chinaunix.net/u1/51562/showart_1736813.html
cgroup_init_early();
//更新kernel中的所有的立即数值,但是包括哪些需要再看?
core_imv_update();
//关闭当前CUP中断
local_irq_disable();
//修改标记early_boot_irqs_enabled;
//通过一个静态全局变量 early_boot_irqs_enabled来帮助我们调试代码,
//通过这个标记可以帮助我们知道是否在”early bootup code”,也可以通过这个标志警告是有无效的终端打开
early_boot_irqs_off();
//每一个中断都有一个IRQ描述符(struct irq_desc)来进行描述。
//这个函数的主要作用是设置所有的 IRQ描述符(struct irq_desc)的锁是统一的锁,
//还是每一个IRQ描述符(struct irq_desc)都有一个小锁。
early_init_irq_lock_class();
/*
* Interrupts are still disabled. Do necessary setups, then
* enable them
*/
// 大内核锁(BKL--Big Kernel Lock)
//大内核锁本质上也是自旋锁,但是它又不同于自旋锁,自旋锁是不可以递归获得锁的,因为那样会导致死锁。
//但大内核锁可以递归获得锁。大内核锁用于保护整个内核,而自旋锁用于保护非常特定的某一共享资源。
//进程保持大内核锁时可以发生调度,具体实现是:
//在执行schedule时,schedule将检查进程是否拥有大内
armLinux系统start_kernel函 相关文章:
- Windows CE 进程、线程和内存管理(11-09)
- RedHatLinux新手入门教程(5)(11-12)
- uClinux介绍(11-09)
- openwebmailV1.60安装教学(11-12)
- Linux嵌入式系统开发平台选型探讨(11-09)
- Windows CE 进程、线程和内存管理(二)(11-09)