linux 内核启动流程


电源启动开始到BIOS

  1. 实时模式: 在此模式地址访问为真实内存地址所在位置,软件可以不受限制的操作所有的空间和IO设备
  2. 保护模式:全部使用虚拟内存和页等机制对内存进行保护,相比实时模式更为安全可靠,同时也增加拓展性和灵活性
  3. 从启动电源到BIOS: 按下电源-》主板会向电源组发出信号-》接受到信号后,当主板收到电源正常启动的信号之后,主板会启动cpu(cpu重置所有寄存器数据,并且初始化数据)比如32位系统:实模式采用内存端来管理0--0xFFFFF的这1MB内存空间,但是只有16位寄存器,所以最大地址只能是0xFFFFF(64kB)

从BIOS 到 BootLoader

  1. BIOS执行程序存储在 ROM中,起始位置位0xFFFF0,当CS:IP 指向此位置时,BIOS开始执行,主要包括内存映射
  2. BIOS 程序会选择恶一个启动设备,并将控制权转交给启动扇区的代码,主要工作:使用中断向量和中断服务程序完成BootLoader 的加载,最终将boot.img 加载到0x7c00的位置启动linux内核通过boot protocol 定义如何实现此引导程序

bootLoader 工作加载流程

boot.img 由boot.s编译而成 512字节,安装在启动盘的第一个扇区,即MBR 由于空间大小有限,代码简单只是作为一个引导的作用 加载core之后启动main()->初始化控制台,计算模块基地址,设置root设备,读取grub配置文件,加载模块, 总结为,按下电源开关加载完毕bootLoader整个过程,后面分析从实时模式进入保护模式,从而启动内核创建0号,1号,2号进程的整个过程。

Linux 内核运行原理机制

必须通过main()函数完成一系列的初始化之后才会打开新的中断,从而使内核模式正式运行,这个部分包括:

  1. 为进程0建立内核态堆栈
  2. 清零eflags寄存器
  3. 调用setup idt0 中断处理程序填充IDT
  4. 把BIOS 中获取的参数传递给第一个页框
  5. 用GDT和IDT表填充寄存器,完成整个工作之后内核就正式运行。(进入创建0号进程)

Linux 内核锁部分

  1. atomic 原子变量,spinlock 自旋锁 针对 cpu
  2. semaphore 信号量,mutex 互斥锁 针对 临界区
  3. rw-lock 读写锁,preempt 抢占锁
  4. per_cpu 变量, 针对cache ,RCU 机制(Read copy update) 针对内存
  5. 内存屏障(memory barrier) 针对内存

主要原因,程序运行中对内存访问不一定按照代码编写顺序来处理,主要因为编译器对代码进行优化,另外多cpu架构存在指令乱序访问内存的可能性。

os(操作系统)-》/boot-》执行init进程(如果不执行,其他部分都不会执行,读写配置文件)-》运行级别(windows 称呼 服务,Linux 称呼 守护进程) (级别0-6,0停机状态,1单用户模式 2,多用户模式,3.完全多用户状态,登录后进行shell界面 4. 暂时没有使用5.gui 模式6,正常关机模式) -》系统初始化(重要脚本,检查磁盘,激活交换分区,加载硬件模块)-》建立终端(用户登录界面)

Linux 启动核心函数 init->main->start-kernel(void),所有的启动从这开始
1. command_Line after_dashes;初始化的核心点,
2.设置系统任务栈结束魔术数,
3. 设置cpu的ID跟踪smp有关(多核处理器)
4. 设置一些和debug有关初始化
5. cgroup_init_early() cgroup初始化,cgroup 用于控制linux 系统资源
6. local_irq_disable() 关闭当前cpu中断
7. boot_cpu_init() 初始化跟cpu 有关
8. page_address_int() 页地址相关的初始化
9.pr_notice(输出版本号以及编译时间)
10.setup_arch(&command_line)架构相关
11.add_latent_entropy()
12.boot_init_stack_canary();//栈溢出检测初始化操作
13.mm_init_cpumask(&init_mm);//内存相关的初始化
14.setup_command_line(command_line) // 存储命令行参数
15.setup_nr_cpu_ids() //如果只是smp,获取cpu核心数量
16.setup_per_cpu_areas(),在smp系统当中游泳
17.build_all_zonelists()//建立系统内存页区链表
18.page_alloc_init();//处理用于热插拔cpu页面
19.打印命令行信息
10.setup_log_buf(0)设置日志缓存区操作
11.vfs_caches_init_early()//预先初始化vfs目录项目和索引节点缓存
定义内存异常列表sort_main_extable()
完成对系统保留终端向量的初始化trap_init()
mm_init() 内存管理初始化操作
sched_init() 初始化调试器,主要是初始化一些系统所用到的结构体
preempt_disable()关闭优先级抢占
检查中断是否关闭,如果没有就关闭中断,radix_tree_init()//基数树相关数据结构初始化
rcu_init() 初始化rcu(读 拷贝 修改)
trace_init() 跟踪调试相关初始化
early_irq_init() 初始中断相关初始化,主要是注册irp_desc结构体变量
init_IRQ()//中断初始化
tick_init()//tick初始化
init_timers()//初始化定时器
hrtimers_init() //初始化高精度定时器
softirq_init()//软终端初始化
time_init()//初始化系统时间
console_init()//初始化控制台print 打印信息都存放缓冲区当中