前置:这里使用的linux版本是4.8,x86体系。

这篇是 http://home.ustc.edu.cn/~boj/courses/linux_kernel/1_boot.html 的学习笔记。

linux的启动过程有点像是小鱼吃大鱼,最后吃成一个胖子。

计算机中的PC寄存器是用来指示下个执行程序。最开始的时候,pc寄存器都是指向0xfffffff0。这个程序是指向BIOS的POST程序的。POST全称是Power On Self Test,意思是加点自检。过程包括内存检查,系统总线检查等。

POST过程结束,就进入到了自举过程,自举过程把MBR(主引导扇区)加载到内存中,并且执行它。这个主引导扇区是第一个扇区的前512字节。

Master Boot Record过程是为了后面一个过程准备的。它主要做的是读入GRUB stage2所在的扇区。并且执行它。

GRUB stage2 将系统切换到保护模式。设置C运行环境。

然后进入到x86/boot/header.S中执行。在这里面,你能找到main的函数入口。这个对应到x86/boot/main.c的main函数。

这个main函数执行到最后会进入go_to_protected_mode(); 进入到pm.c的这个函数的定义,除了初始化一些逻辑以外,主要是protected_mode_jump

下面就进入到boot/pmjump.S的protected_mode_jump

29 protected_mode_jump:
30 movl %edx, %esi # Pointer to boot_params table
31
32 xorl %ebx, %ebx
33 movw %cs, %bx # 将实模式的代码段放入 bx
34 shll $4, %ebx # 转换为线性地址
35 addl %ebx, 2f # 将 in_pm32 的实模式地址转换为线性地址
36
37 movw $__BOOT_DS, %cx # ds 段选择子
38 movw $__BOOT_TSS, %di # tss 段选择子
39
40 movl %cr0, %edx
41 orb $X86_CR0_PE, %dl # Protected mode
42 movl %edx, %cr0 # 将 cr0 的0位置0是进入保护模式的标志
43 jmp 1f # Short jump to serialize on 386/486
44 1:
45 # 下面这段作用是跳转到 in_pm32,由于已经在保护模式,所以需要考虑段的问题
46 # Transition to 32-bit mode
47 .byte 0x66, 0xea # ljmpl opcode
48 2: .long in_pm32 # offset
49 .word __BOOT_CS # segment
50
51 .size protected_mode_jump, .-protected_mode_jump
52
53 .code32
54 .type in_pm32, @function
55 in_pm32: # 下面的注释挺清楚,就不翻译了
56 # Set up data segments for flat 32-bit mode
57 movl %ecx, %ds
58 movl %ecx, %es
59 movl %ecx, %fs
60 movl %ecx, %gs
61 movl %ecx, %ss
62 # The 32-bit code sets up its own stack, but this way we do have
63 # a valid stack if some debugging hack wants to use it.
64 addl %ebx, %esp
65
66 # Set up TR to make Intel VT happy
67 ltr %di # 这个比较有意思
68
69 # Clear registers to allow for future extensions to the
70 # 32-bit boot protocol
71 xorl %ecx, %ecx
72 xorl %edx, %edx
73 xorl %ebx, %ebx
74 xorl %ebp, %ebp
75 xorl %edi, %edi
76
77 # Set up LDTR to make Intel VT happy
78 lldt %cx # 又是一个骗 CPU 的东西 79 # eax 是 protected_mode_jump 的第一个参数,即 header.S 中定义的 boot_params.hdr.code32_start,即 vmlinux 的入口地址
80 jmpl *%eax # Jump to the 32-bit entrypoint
81
82 .size in_pm32, .-in_pm32

最后的jmpl就跳转到

arch/x86/kernel/head_32.S的startup_32

ENTRY(initial_code)
.long i386_start_kernel

进入到arch/x86/kernel/head32.c

asmlinkage __visible void __init i386_start_kernel(void)
{
cr4_init_shadow();
sanitize_boot_params(&boot_params); x86_early_init_platform_quirks(); /* Call the subarch specific early setup function */
switch (boot_params.hdr.hardware_subarch) {
case X86_SUBARCH_INTEL_MID:
x86_intel_mid_early_setup();
break;
case X86_SUBARCH_CE4100:
x86_ce4100_early_setup();
break;
default:
i386_default_early_setup();
break;
} start_kernel();
}

这里最后是调用了start_kernel,这里的start_kernel是与操作系统无关的init/main.c里面了。

参考

http://home.ustc.edu.cn/~boj/courses/linux_kernel/1_boot.html

http://blog.csdn.net/alais/article/details/5129005

最新文章

  1. Helpful Tool
  2. 记一次Runtime的巧用
  3. 李洪强漫谈iOS开发[C语言]-045-循环结构
  4. [问题2014A12] 复旦高等代数 I(14级)每周一题(第十四教学周)
  5. 如何把excel数据导入数据库
  6. 线段树区间求最大值(点更新)---I Hate It
  7. TopCoder 649 div1 & div2
  8. EE就业最好的方向是转CS,其次是VLSI/ASIC DESIGN & VERIFICATION
  9. 关于java中强制转换
  10. [Usaco2007 Jan]Telephone Lines架设电话线[二分答案+最短路思想]
  11. web.xml 中<context-param>与<init-param>的区别与作用
  12. header 头各种类型文件下载
  13. 安装linux环境及相关包方法
  14. 突破防盗链Referrer
  15. 清北澡堂 Day2 上午 一些比较重要的关于数论的知识整理
  16. Linux shell (6)
  17. mysubmail 短信报警
  18. [非常重要的总结] Linux C相关函数
  19. Linux学习总结(六)-su命令 sudo 命令 限制root远程登录
  20. HTML文本/文字竖直方向/纵向显示

热门文章

  1. Android课程---关于数据存储的学习(3)之数据库和事务
  2. docfx组件介绍--MarkdownLite
  3. 在MySQL的InnoDB存储引擎中count(*)函数的优化
  4. Google分布式构建软件之四:分发构建结果
  5. ios 避免循环引用
  6. 小学徒成长系列—StringBuilder & StringBuffer关键源码解析
  7. 《Entity Framework 6 Recipes》中文翻译系列 (29) ------ 第五章 加载实体和导航属性之过滤预先加载的实体集合和修改外键关联
  8. 《Entity Framework 6 Recipes》中文翻译系列 (45) ------ 第八章 POCO之获取原始对象与手工同步对象图和变化跟踪器
  9. web项目ajax技术一些总结
  10. 每天一个linux命令(23):Linux 目录结构