### Linux的启动过程详解
#### 一、BootLoader阶段
**功能简述:**
BootLoader是Linux系统启动过程中的第一步,主要负责初始化硬件环境,并加载Linux内核映像到内存中。具体步骤包括:
1. **屏蔽所有中断:** 确保在加载内核过程中不会受到外部中断的影响。
2. **初始化GPIO:** 对通用输入输出接口进行配置。
3. **初始化SDRAM:** 配置系统的存储器。
4. **拷贝BootLoader到SDRAM:** 将BootLoader自身加载到SDRAM中以便后续执行。
5. **加载内核映像文件:** 从存储设备读取Linux内核映像,并将其加载到内存中。
6. **跳转到C程序:** BootLoader将执行权交给预先准备好的C语言程序。
7. **初始化串口和以太网:** 配置串行通信接口和网络接口。
8. **等待外部输入:** 如果用户不提供任何输入,则直接跳转到内核入口;如果有输入,则进入BootLoader模式。
9. **进入BootLoader模式:** 用户可以在此模式下执行一些命令,例如修改启动参数等。
**部分头文件解析:**
- `config.h` 定义了处理器PXA255的相关配置,包括各种内存区域的基地址和大小。
- SRAM(FLASH)基地址为:0x0000000
- SARM(FLASH)地址大小为:0x02000000 (32M)
- DRAM(SDRAM)基地址为:0xA0000000
- DRAM(SDRAM)地址大小为:0x020000000×2 (64M)
- `start_xscale.h` 包含了中断控制器、时钟管理控制器、通用GPIO和内存控制器的基地址定义。
**内存分配脚本文件:**
- `ld-xscale` 文件定义了ELF文件格式下的内存布局和分配规则。
**汇编语言初始化部分:**
这部分通常包含了一些基本的硬件初始化操作,例如设置CPU模式、查询处理器类型等。
**C语言代码部分:**
这部分负责更复杂的初始化工作,比如初始化串口和以太网接口等。
#### 二、内核代码部分
**汇编语言部分:**
- `head-armv.S` 文件是根据`autoconf.h` 配置执行的操作,主要包括设置处理器模式、查询处理器类型、创建页表等,并最终跳转到内核入口`start_kernel`。
**内核入口部分:**
- C语言代码部分对系统进行二次初始化,包括但不限于以下步骤:
- **内核加锁:** 确保多处理器环境下内核的一致性和安全性。
- **输出Linux版本信息:** 使用`printk(linux_banner)`打印出当前内核的版本信息。
- **设置与体系结构相关的环境:** 通过`setup_arch()` 函数完成这一任务。
- **提取并分析核心启动参数:** 从环境变量中读取参数,并设置相应的标志位,以便后续处理。
- **设置系统自陷入口:** 通过`trap_init()` 函数完成。
- **初始化系统IRQ:** 通过`init_IRQ()` 函数完成。
- **核心进程调度器初始化:** 包括初始化几个默认的Bottom-half,通过`sched_init()` 完成。
- **时间、定时器初始化:** 包括读取CMOS时钟、估计主频、初始化定时器中断等,由`time_init()` 完成。
- **控制台初始化:** 通过`console_init()` 完成。
- **模块初始化:** 通过`init_modules()` 完成。
- **剖析器数据结构初始化:** 初始化`prof_buffer` 和 `prof_len` 变量。
- **核心Cache初始化:** 通过`kmem_cache_init()` 完成。
- **延迟校准:** 通过`calibrate_delay()` 获取时钟jiffies与CPU主频ticks之间的延迟。
- **内存初始化:** 通过`mem_init()` 设置内存上下界和页表项初始值。
- **创建和设置内部及通用cache:** 通过`kmem_cache_sizes_init()` 创建“slab_cache”。
- **创建页cache:** 通过`pageable_cache_init()` 初始化内存页hash表。
- **检查体系结构漏洞:** 在某些架构上可能为空函数。
- **SMP机器其余CPU初始化:** 在非SMP配置的内核中,该函数为空。
- **启动init过程:** 创建第一个核心线程,调用`init()` 函数,并通过`rest_init()` 进入等待状态。
#### 三、文件系统部分
**文件系统初始化:**
在内核完成核内引导之后,会加载`init`程序(进程号为1),该程序负责系统的后续启动流程。`init`程序的行为主要由`/etc/inittab` 文件定义,该文件指定了不同的运行级别及其对应的启动顺序。
- 根据根文件系统下的`linuxrc` 脚本文件可知,它启动了`init`。
- `init` 进程读取`/etc/inittab` 文件,根据其中的配置启动相应的服务。
- `inittab` 文件按照`initdefault` 启动`runlevel 3`。
- 在`runlevel 3` 下,`init` 会执行`rc3.d` 目录下的脚本文件来启动系统服务,如网络服务、PCMCIA支持等。
- 最终,`init` 会执行`/bin/login` 文件,以便用户登录系统。
Linux的启动过程从BootLoader开始,经过内核加载和初始化,最终到达文件系统初始化和服务启动,整个过程环环相扣,确保了Linux系统的稳定启动和高效运行。