224
225 /*if判断中断是否打开,如果已经打开,打印数据*/
226 if (!irqs_disabled())
227 printk(KERN_CRIT 'start_kernel(): bug: interrupts were enabled early/n');
228
229 //与开始的early_boot_irqs_off相对应
230 early_boot_irqs_on();
231
232 //与local_irq_disbale相对应,开CPU中断
233 local_irq_enable();
234
235 /*
236 * HACK ALERT! This is early. We're enabling the console before
237 * we've done PCI setups etc, and console_init() must be aware of
238 * this. But we do want output early, in case something goes wrong.
239 */
240 //初始化控制台以显示printk的内容,在此之前调用的printk,只是把数据存到缓冲区里,
241 //只有在这个函数调用后,才会在控制台打印出内容
242 //该函数执行后可调用printk()函数将log_buf中符合打印级别要求的系统信息打印到控制台上。
243 console_init();
244
245 if (panic_later)
246 panic(panic_later, panic_param);
247
248 //如果定义了CONFIG_LOCKDEP宏,那么就打印锁依赖信息,否则什么也不做
249 lockdep_info();
250
251 /*
252 * Need to run this when irqs are enabled, because it wants
253 * to self-test [hard/soft]-irqs on/off lock inversion bugs
254 * too:
255 */
256 //如果定义CONFIG_DEBUG_LOCKING_API_SELFTESTS宏
257 //则locking_selftest()是一个空函数,否则执行锁自测
258 locking_selftest();
259
260 #ifdef CONFIG_BLK_DEV_INITRD
261 if (initrd_start && !initrd_below_start_ok &&
262 page_to_pfn(virt_to_page((void *)initrd_start)) < min_low_pfn) {
263 printk(KERN_CRIT 'initrd overwritten (0x%08lx < 0x%08lx) - '
264 'disabling it./n',
265 page_to_pfn(virt_to_page((void *)initrd_start)),
266 min_low_pfn);
267 initrd_start = 0;
268 }
269 #endif
270
271 /* 虚拟文件系统的初始化 */
272 vfs_caches_init_early();
273 cpuset_init_early();
274 mem_init();
275
276 /* slab初始化 */
277 kmem_cache_init();
278
279 //是否是对SMP的支持,单核是否需要??这个要分析
280 setup_per_cpu_pageset();
281
282 numa_policy_init();
283
284 if (late_time_init)
285 late_time_init();
286
287 //calibrate_delay()函数可以计算出cpu在一秒钟内执行了多少次一个极短的循环,
288 //计算出来的值经过处理后得到BogoMIPS 值,
289 //Bogo是Bogus(伪)的意思,MIPS是millions of instructions per second(百万条指令每秒)的缩写。
290 //这样我们就知道了其实这个函数是linux内核中一个cpu性能测试函数。
291 //http://blogold.chinaunix.net/u2/86768/showart_2196664.html
292 calibrate_delay();
293
294 //PID是process id的缩写
295 //http://blog.csdn.net/satanwxd/archive/2010/03/27/5422053.aspx
296 pidmap_init();
297
298 /* 接下来的函数中,大多数都是为有关的管理机制建立专用的slab缓存 */
299 pgtable_cache_init();
300
301 /* 初始化优先级树index_bits_to_maxindex数组 */
302 prio_tree_init();
303
304 //来自mm/rmap.c
305 //分配一个anon_vma_cachep作为anon_vma的slab缓存。
306 //这个技术是PFRA(页框回收算法)技术中的组成部分。
307 //这个技术为定位而生——快速的定位指向同一页框的所有页表项。
308 anon_vma_init();
309
310 #ifdef CONFIG_X86
311 if (efi_enabled)
312 efi_enter_virtual_mode();
313 #endif
314
315 //根据物理内存大小计算允许创建进程的数量
316 //http://www.jollen.org/blog/2006/11/jollen_linux_3_fork_init.html
317 fork_init(totalram_pages);
318
319 //给进程的各种资源管理结构分配了相应的对象缓存区
320 //http://www.shangshuwu.cn/index.php/Linux内核的进程创建
321 proc_caches_init();
322
323 //创建 buffer_head SLAB 缓存
324 buffer_init();
325
326 unnamed_dev_init();
327
328 //初始化key的management stuff
329 key_init();
330
331 //关于系统安全的初始化,主要是访问控制
332 //http://blog.csdn.net/nhczp/archive/2008/04/29/2341194.aspx
333 security_init();
334
335 //调用kmem_cache_create()函数来为VFS创建各种SLAB分配器缓存
336 //包括:names_cachep、filp_cachep、dquot_cachep和bh_cachep等四个SLAB分配器缓存
337 vfs_caches_init(totalram_pages);
338
339 radix_tree_init();
340
341 //创建信号队列
342 signals_init();
343
344 /* rootfs populating might need page-writeback */
345 //回写相关的初始化
346 //http://blog.csdn.net/yangp01/archive/2010/04/06/5454822.aspx
347 page_writeback_init();
348
349 #ifdef CONFIG_PROC_FS
350 proc_root_init();
351 #endif
352
353 //http://blogold.chinaunix.net/u1/51562/showart_1777937.html
354 cpuset_init();
355
356 ////进程状态初始化,实际上就是分配了一个存储线程状态的高速缓存
357 taskstats_init_early();
358
359 delayacct_init();
360
361 //测试CPU的各种缺陷,记录检测到的缺陷,以便于内核的其他部分以后可以使用他们工作。
362 check_bugs();
363
364 //电源相关的初始化
365 //http://blogold.chinaunix.net/u/548/showart.php?id=377952
366 acpi_early_init(); /* before LAPIC and SMP init */
367
368 //接着进入rest_init()创建init进程,创建根文件系统,启动应用程序
369 rest_init();
370 }
2、start_kernel调用层次。简略的写出start_kernel函数的调用层次后面一步步分析它。其实可以概括为读取uboot传入的tag参数并且处理它们。
假设uboot传入的命令行参数为bootargs=noinitrd root=/dev/mtdblock3 init=/linuxrc console=ttySAC0。
a、其中setup_arch、setup_command_line 、do_early_para、unknown_bootoption这几个函数可以概括为处理uboot传入的tag参数。主要处理ATAG_MEM参数、ATAG_CMDLINE参数部分参数
b、console_init根据处理后的console=ttySAC0命令行参数选择合适的控制台
c、其中rest_init是start_kernel调用的最后一个函数主要用来根据 处理后的root=/dev/mtdblock3、init=/linuxrc命令后参数分别挂接合适的根文件系统与第一个init进程的启动。
start_kernel
setup_arch //解析UBOOT传入的启动参数
setup_command_line //解析UBOOT传入的启动参数
do_early_param //解析early参数,uboot中没传这个参数
unknown_bootoption//解析到了命令行参数,saved_root_name在这块初始化
console_init();//控制台初始化
rest_init
kernel_thread
kernel_init
prepare_namespace //解析命令行参数解析成功挂接在哪个分区
mount_root//挂接根文件系统
init_post
//执行应用程序
上一篇:Linux移植之tag参数列表解析过程分析
下一篇:Linux移植之内核启动过程引导阶段分析
推荐阅读最新更新时间:2024-11-06 01:16
设计资源 培训 开发板 精华推荐
- 用于 DDR 电源的 LTC3634HUFD 双路 3A 单片式降压稳压器的典型应用电路
- 基于 Teseo-VIC3D 和 Teseo-VIC3DA 的 GNSS 航位推算模块评估板
- 基于IIS2ICLX的MEMS测斜仪套件
- L78L09AB 电流调节器的典型应用
- NCV2001SN2T1G 0.9V单电源高顺从电流吸收器的典型应用电路
- 使用 NXP Semiconductors 的 PCF85263AT 的参考设计
- LTC2945IUD 在 -48V 系统中进行电源监控的典型应用,该系统使用外部线性稳压器为光耦合器和 SCL/SDA 电阻上拉供电
- LTC3621EMS8E-5 1.2Vout、强制连续模式、1MHz 同步降压稳压器的典型应用
- EVAL-AD7621CB,AD7621 评估板,48 引脚,16 位 PulSAR 模数转换器
- LTC3419IMS 双路 600mA 降压转换器的典型应用电路
- HP8712ET/E4407B/HP8711B/TDS3014/HP8713B/HP8711C/13168727426
- DSP builder中的MegaCore Function没有任何东西
- STM8207的PA1和PA2使用不顺畅
- 整流后可否不滤波,直接将脉动直流输入三相逆变桥
- 【Altera soc 体验之旅】+基于自组网的无线路由设计在FPGA-SOC上的实现(4)
- wince flash播放器spark例子修改成边解析边显示
- 求通过蓝牙蓝牙控制一些装置的方法
- 【LPC54100】iic读取MPU6050相关数据
- s3c2440或s3c2410芯片怎么辨别全新的还是旧的
- ADC12 疑问