Skip to content

Chapter 5 Intro & Overview

1 Intro

1. 1 Compiler basics - Behind gcc main.c

  1. 预处理(preprocess)
    • 命令:cpp main.c -o main.i
    • 作用:处理源代码中的预处理指令
      • 展开 #include 的头文件(如<stdio.h>
      • 替换 #define 的宏定义
      • 处理 #if/#ifdef 等条件编译逻辑
      • 最终生成纯C代码的中间文件 main.i
  2. 编译(compile)
    • 命令:gcc -S main.i -o main.s
    • 作用:将 C 代码翻译为汇编语言代码
      • 编译器(gcc)对 main.i 中的C代码进行语法分析、优化后,生成对应硬件架构的汇编指令(如x86或ARM汇编),输出文件 main.s
  3. 汇编(assemble)
    • 命令:as main.s -o main.o
    • 作用:将汇编代码转换为机器码
      • 汇编器(as)把 main.s 中的汇编指令翻译成二进制机器码,生成目标文件 main.o(格式通常为ELF)
      • 目标文件是可重定位的,但还不能直接执行(需解决外部依赖)
  4. 链接(Link)
    • 命令:ld main.o -o a.out
    • 作用:将多个目标文件/库文件合并为可执行文件
      • 链接器(ld)解决符号引用(如函数调用、全局变量),把 main.o 和依赖的库(如标准库 libc)链接起来,最终生成可执行文件 a.out(可直接在操作系统中运行)
  5. 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

  1. 引导程序(bootstrap program)

    • 存储位置:非易失性内存(ROM 或闪存)
    • 所属层级:系统固件的一部分,负责加载引导加载程序(bootloader)
    • 实验工具:使用 OpenSBI(Supervisor Binary Interface)
    • 核心功能:初始化硬件、准备系统环境、定位存储介质中的 OS 内核、加载内核至内存、移交控制权给内核
  2. 内核启动后流程

    • 完成初始化:内存管理、设备驱动、系统服务的设置
    • 启动首个用户态进程:Linux 为 /sbin/init(新版本为 systemd);Mac OS X 为 launchd
    • 系统状态:启动后等待事件触发,无事件时处于空闲状态
  3. 多道程序设计(Multi-Programming)

    • 定义:允许多个作业(运行中的程序)同时驻留内存
    • 核心机制:当某个作业需等待(如 I/O 操作)时,OS 切换至另一个作业执行(上下文切换,context-switch)
    • 优势:提升系统利用率,解决单用户模式(等待时 CPU 闲置)和批处理(I/O 时 CPU 空闲)的低效率问题
  4. 分时系统(Time-Sharing)

    • 本质:基于快速上下文切换的多道程序设计
    • 特性:作业运行时间受限,响应时间短,支持交互性,每个作业产生“独占系统”的错觉
    • 现代概念中,作业称为进程(process),多个进程可并发驻留内存
  5. OS 代码的运行特性

    • 内核存储:OS 的代码由引导程序加载后,驻留在内存的指定地址处
    • 执行触发:进程可调用 OS 代码段,执行后返回用户程序
    • 内存保护:OS 确保进程间内存隔离,防止相互干扰
    • 内核本质:非运行中的作业,而是驻留内存、可随时执行的代码,含数据段(data segment)和文本段(text segment),可执行硬件相关的特殊/危险操作
  6. 内核大小考量

    • 设计内核时需避免占用过多内存,追求精简(lean)专注(mean)
    • 内核内部无内存保护机制,进程非法访问内存时内核会抛出段错误(segmentation fault)提示,开发时需极度谨慎
  7. 用户态 vs 内核态(User vs. Kernel Mode)

    • 硬件支持:现代处理器至少支持两种执行模式,由控制寄存器中的状态位标识
    特权指令(Protected Instructions)
    • 定义:仅 OS 可执行的 CPU 指令子集
    • 作用:隔离用户程序与系统核心功能,避免误操作或恶意攻击
    典型示例
    • 直接访问 I/O 设备(打印机、磁盘等)
    • 操作内存管理状态
    • 操作受保护的控制寄存器(如内核模式、中断级别设置)
    • 执行处理器停机指令(halt)
    • 模式差异:
      • 用户态:无法执行特权指令,用户程序运行在此模式
      • 内核态:可执行所有指令,OS代码运行在此模式
    • 指令检查流程:
      1. CPU 解码指令,判断是否为特权指令
      2. 若为特权指令且当前为用户态,触发陷阱(trap),终止执行
    如果系统仅支持一种模式会发生什么?

    MS-DOS 系统是为 Intel 8088 处理器编写的,而该处理器没有模式位,故 MS-DOS 系统仅支持一种模式,存在严重的安全隐患:

    • 用户程序的漏洞或恶意操作可能摧毁整个系统
    • 多个用户程序可能并发写入同一设备,导致系统行为不一致
    多模式扩展示例
    ARM64 Modes
    RISCV Modes
  8. OS Events

    • 控制流(Control Flow):程序中语句、指令或函数调用的执行顺序
    • 事件(Events):控制流的异常变化,会停止当前执行、切换运行模式并切换上下文(触发内核代码并执行)
    • 内核为每种事件类型定义专属处理器(handler),即一段在内核态执行的代码
    • 系统启动后,所有内核访问均由事件触发
    类型 产生原因 示例
    中断(Interrupts) 外部硬件触发 设备控制器通知操作完成
    异常/陷阱/故障(Exceptions/Traps/Faults) 指令执行触发(软件生成) 执行特权指令(用户态)、除零错误、段错误
    • 中断响应:CPU 暂停当前操作,立即跳至内核固定地址执行事件处理代码
    • 处理结果:内核执行相应操作、终止用户进程(如段错误)
    内核故障会发生什么?

    内核自身错误(如空指针解引用、除零)为致命故障,会导致系统崩溃(UNIX的Panic、Windows的蓝屏),最终会导致内核停止运行,系统状态转储到核心转储文件(core file)中,计算机陷入死机状态

  9. 系统调用(System Calls)

    • 当用户程序需要执行某项特权操作(如创建进程、写入磁盘、从网卡读取数据等)时,会调用系统调用,其本质是一种特殊的陷阱
    • 实现机制:
      • ISA 提供系统调用指令(如x86-64的 syscall
      • 通过寄存器传递系统调用编号(如 mov $0x1, $eax 指定调用编号 1)
      • 保存调用者状态(程序计数器、寄存器、模式),便于后续恢复

  10. 定时器(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?
  1. Set value of the system timer
  2. Read the clock
  3. Clear memory
  4. Issue a system call instruction
  5. Turn off interrupts
  6. Modify entries in device-status table
  7. Access I/O device
答案

1.3.5.6.7