最新消息:20210816 当前crifan.com域名已被污染,为防止失联,请关注(页面右下角的)公众号

嵌入式Linux内核启动顺序【简析】

工作和技术 crifan 2772浏览 0评论

嵌入式Linux内核启动顺序【简析】

看了点代码,就我了解的kernel启动的顺序,说说情况:

从initmain.c中的start_kernel()开始:
该函数中,主要做了下列事情:

(1)先是
boot_cpu_init();
初始化了启动相关的内容后
然后
printk(KERN_NOTICE);
printk(linux_banner);
打印内核信息,比如我这里的:
Linux version 2.6.22.2 ([email protected]) (gcc version 4.3.2 (GCC) ) #89 Fri May 15 11:25:09 CST 2009

(2)
其后主要初始化了中断,时钟等:
init_IRQ();
init_timers();
softirq_init();
(3)
再打印出命令行:
printk(KERN_NOTICE "Kernel command line: %sn", boot_command_line);
如此处的:
Kernel command line: root=/dev/mtdblock2 rw init=/linuxrc console=ttyS0,115200 mem=64M rootfstype=jffs2

(4)
后来才是调用
console_init();
去初始化Uart的,就是调用uart的probe函数。

(5)
先预初始化:
cpuset_init_early();

(6)
初始化内存:
mem_init();

(7)
初始化buffer:
buffer_init();
再初始化cpu(组):
cpuset_init();

(8)
用check_bugs();
去测试CPU的相关情况:
CPU: Testing write buffer coherency: ok

(9)
最后调用:
rest_init();
去启动线程
kernel_init
{
。。。
do_basic_setup();
。。。
init_post();

}

其中调用
do_basic_setup();
{
。。。
driver_init();
。。。
do_initcalls();
。。。
}
去初始化Linux kernel相关的内容

其中
driver_init()
{
/* These are the core pieces */
devices_init();
buses_init();
classes_init();
firmware_init();
hypervisor_init();

/* These are also core pieces, but must come after the
* core core pieces.
*/
platform_bus_init();
system_bus_init();
cpu_dev_init();
memory_dev_init();
attribute_container_init();
}
初始化真正的系统的
device,bus,class等等内容,

然后的
do_initcalls()
{
//从__Start 开始 到 __End 结束,
//以此调用之前内核中相关的__init前缀的那些初始化函数
}

其中,这些用__init标明的函数,可以在system.map中看到对应的信息,
包括对应的变量和其对应的地址

c001d164 t __initcall_ptrace_break_init1
c001d164 T __initcall_start
c001d168 t __initcall_consistent_init1
c001d16c t __initcall_sysctl_init1
c001d170 t __initcall_init_jiffies_clocksource1
c001d174 t __initcall_pm_init1
c001d178 t __initcall_ksysfs_init1
。。。。。。。。。。。。。。。
c001d194 t __initcall_sock_init1
c001d198 t __initcall_netlink_proto_init1
c001d19c t __initcall_kobject_uevent_init2
c001d1a0 t __initcall_amba_init2
c001d1a4 t __initcall_tty_class_init2
c001d1a8 t __initcall_vtconsole_class_init2
c001d1ac t __initcall_customize_machine3
。。。。。。。。。。。
c001d1b0 t __initcall_clk_init3
c001d1b4 t __initcall_dma_init3
c001d1bc t __initcall_topology_init4
c001d1c0 t __initcall_param_sysfs_init4
。。。。。。。。。。。。。
c001d200 t __initcall_init_pipe_fs5
c001d204 t __initcall_eventpoll_init5
。。。。。。。。。。。。。。
c001d24c t __initcall_init6
c001d250 t __initcall_kallsyms_init6
c001d254 t __initcall_utsname_sysctl_init6
c001d258 t __initcall_init_per_zone_pages_min6
c001d25c t __initcall_pdflush_init6
。。。。。。。。。。
c001d2e8 t __initcall_loop_init6
c001d2ec t __initcall_net_olddevs_init6
c001d2f0 t __initcall_loopback_init6
c001d2f4 t __initcall_init_mtd6
c001d2f8 t __initcall_afs_parser_init6
c001d2fc t __initcall_init_mtdchar6
c001d300 t __initcall_init_mtdblock6
c001d304 t __initcall_init_nftl6
。。。。。。。。。。。。
c001d388 t __initcall_ip_auto_config7
。。。。。。。。。。。

可以看出,这些函数经过系统处理后,
加了前缀__initcall_和后缀的数字,看起来是表示启动的阶段。
也就是加了和函数对应的一个个变量(标示)。

当然,也可以找到函数对应的首地址,比如
变量
c001d1b0 t __initcall_clk_init3
对应的函数clk_init放在c000e624 :
c000e624 t clk_init

然后,调用
init_post()
{
1.打开console:
sys_open("/dev/console", O_RDWR, 0)

2.运行命令:
run_init_process(ramdisk_execute_command);

run_init_process(execute_command);

3.运行系统初始化文件:
run_init_process("/sbin/init");
run_init_process("/etc/init");
run_init_process("/bin/init");
run_init_process("/bin/sh");

}
最后,我们才进入我们熟悉的嵌入式Linux环境,
才能输入用户名和密码(如果有的话),比如:
Welcome to Embedded Linux
(none) login: root
Dec 31 17:00:11 login[704]: root login on ‘ttyS0’
# cd /
。。。

【附录】
关于系统架构中,如何把函数和系统联系起来

注:我这里是arm架构的板子

在archarmkernelsetup.c 的
void __init setup_arch(char **cmdline_p)
{
init_arch_irq = mdesc->init_irq;
system_timer = mdesc->timer;
init_machine = mdesc->init_machine;
}

而mdesc即使machine description,
对应的是你在archarmmach-XXXXXXX_pb.c
中定义的,类似于如下的内容:

MACHINE_START(XXXX, "XXXX PB")
/* Maintainer: Austriamicrosystems Ltd */
.phys_io = XXXX,
.io_pg_offst = XXXX,
.boot_params = XXXX,
.map_io   = XXXX_map_io,
.init_irq = XXXX_init_irq,
.timer   = &XXXX_timer,
.init_machine = XXXX_init,
MACHINE_END

其中XXX代表你的板子(架构)名字。
而XXXX_init就赋值给上面的init_machine了,对应的这些函数放在
archarmmach-XXXcore.c

转载请注明:在路上 » 嵌入式Linux内核启动顺序【简析】

发表我的评论
取消评论

表情

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址
79 queries in 0.159 seconds, using 22.08MB memory