刘昆
《Linux内核分析》MOOC课程http://mooc.study.163.com/course/USTC-1000029000
内核init目录下的main.c文件定义了内核启动第二阶段的主干函数,start_kernel(),通过分析start_kernel的执行过程,将有助于切入内核架构的完整分析,时间仓促,仅分析了start_kernel的前半部分和最重要的rest_init().
/*
asmlinkage:被函数执行过程中,通过堆栈传参
__visible :新添宏,可能指symbol可标注debugger信息
__init: 该函数为主切入函数(模块入口函数等)
*/
asmlinkage __visible void __init start_kernel(void)
{
int i;
char *command_line;
char *after_dashes;
/*
* Need to run as early as possible, to initialize the
* lockdep hash:
*/
lockdep_init(); //哈希表初始化
set_task_stack_end_magic(&init_task);
/*init_task为结构体数据,内核运行栈信息相关初始化
struct task_struct {
u64 curr_chain_key;
int lockdep_depth;
unsigned int lockdep_recursion;
struct held_lock held_locks[MAX_LOCK_DEPTH];
gfp_t lockdep_reclaim_gfp;
int pid;
char comm[17];
};
*/
smp_setup_processor_id(); //预留接口,函数体无内容,但arch目录中个别平台代码有该函数定义
debug_objects_early_init(); //初始化操作object tracker
/*
* Set up the the initial canary ASAP:
*/
boot_init_stack_canary(); //一种堆栈保护算法
cgroup_init_early(); //加载内核态中完整subsystem信息
local_irq_disable(); //宏函数,start_kernel是内核启动的第二阶段,仍然需要disable中断请求
early_boot_irqs_disabled = true;
/*
* Interrupts are still disabled. Do necessary setups, then
* enable them
*/
boot_cpu_init(); //CPU相关初始化,如设置CPU的online、active、present以满足SMP等特殊需求
page_address_init();//CPU相关内存页相关检查
pr_notice("%s", linux_banner); //内核版本等相关信息,启动无关代码
setup_arch(&command_line); //设置内核启动时显示的command_line信息格式等
mm_init_cpumask(&init_mm); //CPU相关内存初始化相关
setup_command_line(command_line); //command_line虚拟内存与物理内存信息传递
setup_nr_cpu_ids(); //cpu相关初始化
setup_per_cpu_areas();
smp_prepare_boot_cpu(); /* arch-specific boot-cpu hooks */
build_all_zonelists(NULL, NULL); //初始化zonelist,set_node
page_alloc_init(); //仍然是CPU相关内存初始化
pr_notice("Kernel command line: %s\n", boot_command_line);
parse_early_param(); //command_line参数解析相关
after_dashes = parse_args("Booting kernel",
static_command_line, __start___param,
__stop___param - __start___param,
-1, -1, &unknown_bootoption);
if (!IS_ERR_OR_NULL(after_dashes))
parse_args("Setting init args", after_dashes, NULL, 0, -1, -1,
set_init_arg);
jump_label_init(); //添加label跳转标签
/*
* These use large bootmem allocations and must precede
* kmem_cache_init()
*/
setup_log_buf(0); //日志相关
pidhash_init(); //pidhash表初始化
vfs_caches_init_early(); //虚拟文件系统初始化前准备,dcash与inode相关hash表初始化
sort_main_extable(); //内核exception_table相关
trap_init(); //trap初始化
mm_init(); //内存完全初始化
/*
* Set up the scheduler prior starting any interrupts (such as the
* timer interrupt). Full topology setup happens at smp_init()
* time - but meanwhile we still have a functioning scheduler.
*/
sched_init(); //内核进程调度相关初始化
/*
* Disable preemption - early bootup scheduling is extremely
* fragile until we cpu_idle() for the first time.
*/
preempt_disable(); //禁用优先抢占模式
.........
/* Do the rest non-__init'ed, we're now alive */
rest_init();
/*内核启动的相关运行环境初始化完毕后,将
开始驱动模块初始化,
用户态运行环境相关初始化,
以及开启第一个用户态进程init进程,
SYSTEM状态由启动状态切换至运行状态,
内核进入轮转,由cpu_idle()主导执行流程*/
}