Chapter 5 Intro & Overview¶
1 Intro¶
1. 1 Compiler basics - Behind gcc main.c¶
- 预处理(preprocess)
- 命令:
cpp main.c -o main.i - 作用:处理源代码中的预处理指令
- 展开
#include的头文件(如<stdio.h>) - 替换
#define的宏定义 - 处理
#if/#ifdef等条件编译逻辑 - 最终生成纯C代码的中间文件
main.i
- 展开
- 命令:
- 编译(compile)
- 命令:
gcc -S main.i -o main.s - 作用:将 C 代码翻译为汇编语言代码
- 编译器(
gcc)对main.i中的C代码进行语法分析、优化后,生成对应硬件架构的汇编指令(如x86或ARM汇编),输出文件main.s
- 编译器(
- 命令:
- 汇编(assemble)
- 命令:
as main.s -o main.o - 作用:将汇编代码转换为机器码
- 汇编器(
as)把main.s中的汇编指令翻译成二进制机器码,生成目标文件main.o(格式通常为ELF) - 目标文件是可重定位的,但还不能直接执行(需解决外部依赖)
- 汇编器(
- 命令:
- 链接(Link)
- 命令:
ld main.o -o a.out - 作用:将多个目标文件/库文件合并为可执行文件
- 链接器(
ld)解决符号引用(如函数调用、全局变量),把main.o和依赖的库(如标准库libc)链接起来,最终生成可执行文件a.out(可直接在操作系统中运行)
- 链接器(
- 命令:
- C 运行时(crt)
- 是 C 程序运行的基础环境,包含函数、初始化逻辑和启动例程,为程序执行提供底层支撑
- 启动例程(Startup Routines):在
main函数执行前自动运行,完成栈初始化、命令行参数解析等工作,为main执行铺路 - 简化开发:封装底层启动、参数传递、程序退出等细节,开发者只需关注main函数内的业务逻辑
1. 2 ELF binary basics - What’s a.out¶
- 核心结构:ELF 头、程序头表(供加载器使用)、段头表(供链接器使用)
- 关键段功能:
.text:存放可执行代码.rodata:存放常量等只读数据(如static const).data:存放已初始化的全局变量、静态变量(如static int x = 10).bss:存放未初始化的全局变量、静态变量(如static int x)

- 常见命令:
readelf -S a.out:查看可执行文件a.out的所有段(Sections)readelf -h a.out:读取并显示a.out的文件头(Header)objdump -d a.out:对a.out进行反汇编(Disassemble)
- 当操作系统加载并运行
a.out后,首先会跳转到__libc_start_main,完成一些准备工作:- 设置环境:比如设置好环境变量、命令行参数等
- 设置栈:为函数调用分配和初始化栈空间
- 调用
main
1. 3 Running a binary - Behind ./a.out¶
- ELF 初始化的分工:
- 内核:将ELF段映射到进程虚拟地址空间;初始化栈(存储参数、环境变量)与堆(动态内存基础)
- 加载器(动态链接场景):映射依赖库、解析符号、完成重定位
2 Overview¶
2. 1 What is an OS?¶
- 应用程序与硬件之间的软件层:简化硬件操作,避免用户直接面对复杂硬件
- 资源抽象器与资源分配器:
- 抽象:将物理资源(CPU、磁盘、RAM)映射为逻辑资源(进程、文件、数组),并定义逻辑资源的操作接口
- 分配:决定哪个运行程序(进程)获取何种资源、获取份额及获取时机
常见误区:OS 是始终运行的程序
内核并非运行中的程序,而是驻留内存的代码
2. 2 Booting and Execution of OS¶
-
引导程序(bootstrap program)
- 存储位置:非易失性内存(ROM 或闪存)
- 所属层级:系统固件的一部分,负责加载引导加载程序(bootloader)
- 实验工具:使用 OpenSBI(Supervisor Binary Interface)
- 核心功能:初始化硬件、准备系统环境、定位存储介质中的 OS 内核、加载内核至内存、移交控制权给内核
-
内核启动后流程
- 完成初始化:内存管理、设备驱动、系统服务的设置
- 启动首个用户态进程:Linux 为
/sbin/init(新版本为 systemd);Mac OS X 为launchd - 系统状态:启动后等待事件触发,无事件时处于空闲状态
-
多道程序设计(Multi-Programming)
- 定义:允许多个作业(运行中的程序)同时驻留内存
- 核心机制:当某个作业需等待(如 I/O 操作)时,OS 切换至另一个作业执行(上下文切换,context-switch)
- 优势:提升系统利用率,解决单用户模式(等待时 CPU 闲置)和批处理(I/O 时 CPU 空闲)的低效率问题
-
分时系统(Time-Sharing)
- 本质:基于快速上下文切换的多道程序设计
- 特性:作业运行时间受限,响应时间短,支持交互性,每个作业产生“独占系统”的错觉
- 现代概念中,作业称为进程(process),多个进程可并发驻留内存
-
OS 代码的运行特性
- 内核存储:OS 的代码由引导程序加载后,驻留在内存的指定地址处
- 执行触发:进程可调用 OS 代码段,执行后返回用户程序
- 内存保护:OS 确保进程间内存隔离,防止相互干扰
- 内核本质:非运行中的作业,而是驻留内存、可随时执行的代码,含数据段(data segment)和文本段(text segment),可执行硬件相关的特殊/危险操作
-
内核大小考量
- 设计内核时需避免占用过多内存,追求精简(lean)和专注(mean)
- 内核内部无内存保护机制,进程非法访问内存时内核会抛出段错误(segmentation fault)提示,开发时需极度谨慎
-
用户态 vs 内核态(User vs. Kernel Mode)
- 硬件支持:现代处理器至少支持两种执行模式,由控制寄存器中的状态位标识
特权指令(Protected Instructions)
- 定义:仅 OS 可执行的 CPU 指令子集
- 作用:隔离用户程序与系统核心功能,避免误操作或恶意攻击
典型示例
- 直接访问 I/O 设备(打印机、磁盘等)
- 操作内存管理状态
- 操作受保护的控制寄存器(如内核模式、中断级别设置)
- 执行处理器停机指令(halt)
- 模式差异:
- 用户态:无法执行特权指令,用户程序运行在此模式
- 内核态:可执行所有指令,OS代码运行在此模式
- 指令检查流程:
- CPU 解码指令,判断是否为特权指令
- 若为特权指令且当前为用户态,触发陷阱(trap),终止执行
如果系统仅支持一种模式会发生什么?
MS-DOS 系统是为 Intel 8088 处理器编写的,而该处理器没有模式位,故 MS-DOS 系统仅支持一种模式,存在严重的安全隐患:
- 用户程序的漏洞或恶意操作可能摧毁整个系统
- 多个用户程序可能并发写入同一设备,导致系统行为不一致
多模式扩展示例
ARM64 Modes 
RISCV Modes 
-
OS Events
- 控制流(Control Flow):程序中语句、指令或函数调用的执行顺序
- 事件(Events):控制流的异常变化,会停止当前执行、切换运行模式并切换上下文(触发内核代码并执行)
- 内核为每种事件类型定义专属处理器(handler),即一段在内核态执行的代码
- 系统启动后,所有内核访问均由事件触发
类型 产生原因 示例 中断(Interrupts) 外部硬件触发 设备控制器通知操作完成 异常/陷阱/故障(Exceptions/Traps/Faults) 指令执行触发(软件生成) 执行特权指令(用户态)、除零错误、段错误 - 中断响应:CPU 暂停当前操作,立即跳至内核固定地址执行事件处理代码
- 处理结果:内核执行相应操作、终止用户进程(如段错误)
内核故障会发生什么?
内核自身错误(如空指针解引用、除零)为致命故障,会导致系统崩溃(UNIX的Panic、Windows的蓝屏),最终会导致内核停止运行,系统状态转储到核心转储文件(core file)中,计算机陷入死机状态
-
系统调用(System Calls)
- 当用户程序需要执行某项特权操作(如创建进程、写入磁盘、从网卡读取数据等)时,会调用系统调用,其本质是一种特殊的陷阱
- 实现机制:
- ISA 提供系统调用指令(如x86-64的
syscall) - 通过寄存器传递系统调用编号(如
mov $0x1, $eax指定调用编号 1) - 保存调用者状态(程序计数器、寄存器、模式),便于后续恢复
- ISA 提供系统调用指令(如x86-64的

-
定时器(Timers)
- 为了确保 OS 对 CPU 的控制权,防止程序独占 CPU,定时器会定期触发中断
- OS 移交控制权给用户程序前,总会设置定时器,修改定时器的操作也需通过特权指令完成
内核事件处理伪代码
void processEvent(event) {
Timer.set(1000); // 1000时间单位后触发定时器事件
switch (event.type) {
case NETWORK_COMMUNICATION:
NetworkManager.handleEvent(event);
break;
case SEGMENTATION_FAULT:
case INVALID_MODE:
ProcessManager.handleEvent(event);
break;
case SYSTEM_CALL:
SystemCallManager.execute(event);
break;
case TIMER:
Timer.handleEvent(event);
break;
...
}
return;
}
2. 3 Resource Management in OS¶
2. 3. 1 Process Management¶
- 进程(Process)是运行中的程序,程序为被动实体,进程为主动实体
- OS 核心职责:
- 进程的创建与删除
- 进程的挂起与恢复
- 进程同步机制
- 进程通信机制
- 死锁处理机制
2. 3. 2 Memory Management¶
- 核心目标:决定内存中存放的内容及时机
- 内核始终驻留内存
- OS核心职责:
- 跟踪内存使用状态(占用区域及所属进程)
- 决定进程(或部分内容)与数据的内存交换(移入/移出)
- 内存空间的分配与释放
- 操作系统不负责内存缓存(memory caching)、缓存一致性(cache coherency)等功能,这些工作由硬件(如 CPU 缓存控制器)负责管理
2. 3. 3 Storage Management¶
- 将存储设备的物理特性(如磁盘扇区、内存地址)抽象为逻辑单元(如文件),提供统一视图
- OS 负责文件系统管理,核心职责包括:
- 文件与目录的创建、删除
- 文件与目录的操作
- 文件到二级存储的映射
- 文件备份至非易失性介质
- 空闲空间管理、存储分配、磁盘调度
2. 3. 4 I/O Management¶
- 作用:隐藏硬件设备特性,为用户提供统一接口
- OS 核心职责:
- I/O 内存管理:缓冲(数据传输时临时存储)、假脱机(作业输出与输入重叠)等
- 通用设备驱动接口:支持多种设备与同一内核兼容(需满足标准接口)
- 特定硬件设备的驱动程序开发
2. 3. 5 Protection and Security¶
- 保护(Protection):控制进程对 OS 定义资源的访问机制
- 安全(Security):防御系统内外攻击(如拒绝服务、蠕虫、病毒、身份盗窃等)
- OS 核心机制:
- 内存保护、设备保护
- 进程与文件关联的用户 ID(User IDs)
- 用户组 ID(Group IDs)
- 特权级别定义
思考:Which of these instructions should be privileged, and why?
- Set value of the system timer
- Read the clock
- Clear memory
- Issue a system call instruction
- Turn off interrupts
- Modify entries in device-status table
- Access I/O device
答案
1.3.5.6.7