Linux内核启动流程分析
作者:网络转载 发布时间:[ 2014/7/16 13:37:20 ] 推荐标签:软件开发 Linux 操作系统
|
mrc p15, 0, r9, c0, c0 @ get processor id
bl __lookup_processor_type
bl __lookup_machine_type //判断能否支持该cpu及machine,看①
bl __create_page_tables //因链接地址是(0xc0000000) + 0x00008000!=物理地址ox30000000
ldr r13, __switch_data @ address to jump to after mmu has been enabled
adr lr, __enable_mmu
|
__mmap_switched:
|
b start_kernel
start_kernel //第一个c函数,Main.c (init)
printk(linux_banner); //输出内核版本信息
setup_arch
parse_cmdline
setup_command_line //处理u-boot传入参数
do_early_param
//从__setup_start到__setup_end调用非early属性setup_func函数,看②
parse_early_param
unknown_bootoption
obsolete_checksetup
//从__setup_start到__setup_end调用early属性setup_func函数,看②
rest_init
kernel_thread(kernel_init,…
prepare_namespace // decide what/where to mount,看②
mount_root
init_post
sys_open((const char __user *) "/dev/console", O_RDWR, 0)
run_init_process("/etc/init");
——————/①
3: .long . //编译到此处时虚拟地址
.long __arch_info_begin
.long __arch_info_end
__lookup_machine_type: //arch/arm/kernel/head-common.S
adr r3, 3b //得到标号3所处物理地址,由pc+offset决定,此时mmu还未启动
ldmia r3, {r4, r5, r6} //分别存入
sub r3, r3, r4 @ get offset between virt&phys
add r5, r5, r3 @ convert virt addresses to,获得__arch_info_begin物理地址
add r6, r6, r3 @ physical address space
1: ldr r3, [r5, #MACHINFO_TYPE] @ get machine type
teq r3, r1 @ matches loader number? r1存放u-boot传入机器id
beq 2f @ found
add r5, r5, #SIZEOF_MACHINE_DESC @ next machine_desc
cmp r5, r6
blo 1b
mov r5, #0 @ unknown machine
2: mov pc, lr
__arch_info_begin = .; //arch/arm/kernel/vmlinux.lds
*(.arch.info.init)
__arch_info_end = .;
#define MACHINE_START(_type,_name) //include/asm-arm/mach/arch.h
static const struct machine_desc __mach_desc_##_type
__used
__attribute__((__section__(".arch.info.init"))) = {
.nr = MACH_TYPE_##_type,
.name = _name,
#define MACHINE_END };
MACHINE_START(S3C2440, "SMDK2440") //Mach-smdk2440.c (archarmmach-s3c2440)板文件
.phys_io = S3C2410_PA_UART,
.io_pg_offst = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
.boot_params = S3C2410_SDRAM_PA + 0x100,
.init_irq = s3c24xx_init_irq,
.map_io = smdk2440_map_io,
.init_machine = smdk2440_machine_init,
.timer = &s3c24xx_timer,
MACHINE_END
|
展开后为:
|
static const struct machine_desc __mach_desc_ S3C2440
__used
__attribute__((__section__(".arch.info.init"))) = {
.nr = MACH_TYPE_ S3C2440, //机器id
.name = "SMDK2440",
.phys_io = S3C2410_PA_UART,
.io_pg_offst = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
.boot_params = S3C2410_SDRAM_PA + 0x100, //u-boot传入参数位置
.init_irq = s3c24xx_init_irq,
.map_io = smdk2440_map_io,
.init_machine = smdk2440_machine_init,
.timer = &s3c24xx_timer,
};
|
内核配置结束,能支持几种单板,便有几个该结构,全部放于.arch.info.init段
内核启动时,将u-boot传入机器id与.arch.info.init段所有nr比较,若相等则调用对应初始化函数
|
——————/②
root_device_name = saved_root_name;
ROOT_DEV = name_to_dev_t(root_device_name);
mount_root();
搜saved_root_name:
static char __initdata saved_root_name[64];
static int __init root_dev_setup(char *line)
{
strlcpy(saved_root_name, line, sizeof(saved_root_name));
return 1;
}
__setup("root=", root_dev_setup);
//宏,据root=/dev/mtdblock3,调root_dev_setup,且line指向/dev/mtdblock3
#define __setup(str, fn) __setup_param(str, fn, fn, 0) //init.h
#define __setup_param(str, unique_id, fn, early)
static char __setup_str_##unique_id[] __initdata = str;
static struct obs_kernel_param __setup_##unique_id
__attribute_used__
__attribute__((__section__(".init.setup")))
__attribute__((aligned((sizeof(long)))))
= { __setup_str_##unique_id, fn, early }
解压后:
static char __setup_str_root_dev_setup[] __initdata = "root=";
static struct obs_kernel_param __setup_root_dev_setup
__attribute_used__
__attribute__((__section__(".init.setup")))
__attribute__((aligned((sizeof(long)))))
= { __setup_str_root_dev_setup, root_dev_setup, 0}
|
链接脚本中:
__setup_start.;
*(.init.setup);
__setup_end.;
本文内容不用于商业目的,如涉及知识产权问题,请权利人联系SPASVO小编(021-61079698-8054),我们将立即处理,马上删除。
相关推荐
Linux下开源的DDR压力测试工具曝Linux恶意软件:让树莓派设备挖掘数字货币linux系统中不同颜色的文件夹及根目录介绍软件测试工程师必知必会Linux命令Linux下DNS服务器配置如何成为不可替代的Linux运维工程师?详解Linux进程(作业)的查看和杀死Linux 日志定时轮询流程详解比特币勒索病毒不只Windows系统有,Linux版的来了Linux日志定时轮询流程详解Linux iommu和vfio概念空间解构Linux系统如何低于TCP洪水攻击Linux无损调整分区大小Linux下防火墙配置实例Linux使用Jexus托管Asp.Net Core应用程序Linux中引号的那些事

sales@spasvo.com