【linux内核专栏01】Linux 内核心智模型与设计哲学

本篇定位 :整个 Linux 内核专题的"灵魂"。不写一行代码,只建认知。读完你能 30 秒说清"Linux 内核是什么、为什么这么设计、和 FreeRTOS/RISC-V 本质差异在哪"。这层认知不建,后面 15 篇都是散的零件。
先打破一个误区

你可能以为学 Linux 内核 = 背 API。错。Linux 内核 API 几万个,背不完。学内核 = 学它的设计哲学 + 数据结构 + 控制流。哲学告诉你"为什么这么设计",数据结构告诉你"信息怎么组织",控制流告诉你"代码怎么跑"。这三层通了,API 查文档即可。本篇讲第一层------哲学。


目录

  • [一、宏内核 vs 微内核(第一个根本选择)](#一、宏内核 vs 微内核(第一个根本选择))
    • [1.1 什么是宏内核(Monolithic Kernel)](#1.1 什么是宏内核(Monolithic Kernel))
    • [1.2 为什么 Linux 选宏内核](#1.2 为什么 Linux 选宏内核)
    • [1.3 宏内核的"软化":模块化](#1.3 宏内核的"软化":模块化)
    • [1.4 你的对照锚点](#1.4 你的对照锚点)
  • [二、一切皆文件(Everything is a File)⭐](#二、一切皆文件(Everything is a File)⭐)
    • [2.1 这是 Unix/Linux 的灵魂](#2.1 这是 Unix/Linux 的灵魂)
    • [2.2 为什么这么设计](#2.2 为什么这么设计)
    • [2.3 VFS 是实现(12 篇详讲)](#2.3 VFS 是实现(12 篇详讲))
    • [2.4 "不是真文件"的例外](#2.4 "不是真文件"的例外)
  • [三、机制与策略分离(Mechanism vs Policy)](#三、机制与策略分离(Mechanism vs Policy))
    • [3.1 内核只提供机制,策略留给用户态](#3.1 内核只提供机制,策略留给用户态)
    • [3.2 为什么](#3.2 为什么)
    • [3.3 例外:内核也有策略](#3.3 例外:内核也有策略)
  • [四、可移植性:arch 抽象层](#四、可移植性:arch 抽象层)
    • [4.1 一套核心,多架构](#4.1 一套核心,多架构)
    • [4.2 对接 RISC-V 专栏](#4.2 对接 RISC-V 专栏)
    • [4.3 对接 FreeRTOS port 层](#4.3 对接 FreeRTOS port 层)
  • [五、向后兼容(不破坏用户态 ABI)](#五、向后兼容(不破坏用户态 ABI))
    • [5.1 内核 ABI 稳定承诺](#5.1 内核 ABI 稳定承诺)
    • [5.2 内核内部 API 不保证稳定](#5.2 内核内部 API 不保证稳定)
  • [六、惰性分配(Lazy Allocation)](#六、惰性分配(Lazy Allocation))
    • [6.1 核心思想:用到才给](#6.1 核心思想:用到才给)
    • [6.2 对照 MCU](#6.2 对照 MCU)
  • [七、进程为中心(task_struct 是宇宙中心)](#七、进程为中心(task_struct 是宇宙中心))
    • [7.1 一切以 task_struct 为单位](#7.1 一切以 task_struct 为单位)
    • [7.2 进程 vs 线程(在 Linux 里是同一个东西)](#7.2 进程 vs 线程(在 Linux 里是同一个东西))
    • [7.3 对照 FreeRTOS](#7.3 对照 FreeRTOS)
  • [八、四大"认知冲击"(从 MCU/RTOS 转 Linux 的心理建设)](#八、四大"认知冲击"(从 MCU/RTOS 转 Linux 的心理建设))
    • [8.1 冲击一:单任务裸机 → 多进程分时](#8.1 冲击一:单任务裸机 → 多进程分时)
    • [8.2 冲击二:直接硬件 → 框架化(经五层)](#8.2 冲击二:直接硬件 → 框架化(经五层))
    • [8.3 冲击三:ISR 直接做事 → 顶半部+下半部](#8.3 冲击三:ISR 直接做事 → 顶半部+下半部)
    • [8.4 冲击四:一个地址空间 → 每进程独立虚拟空间](#8.4 冲击四:一个地址空间 → 每进程独立虚拟空间)
  • [九、内核态 vs 用户态(特权边界)](#九、内核态 vs 用户态(特权边界))
    • [9.1 两个特权级](#9.1 两个特权级)
    • [9.2 上下文切换(特权切换)](#9.2 上下文切换(特权切换))
    • [9.3 为什么分两层](#9.3 为什么分两层)
  • 十、内核空间布局与源码地图
    • [10.1 内核镜像布局](#10.1 内核镜像布局)
    • [10.2 内核源码目录地图](#10.2 内核源码目录地图)
  • [十一、Linux vs FreeRTOS vs RISC-V bare-metal 总对照](#十一、Linux vs FreeRTOS vs RISC-V bare-metal 总对照)
  • 十二、本篇小结
  • 速查表

一、宏内核 vs 微内核(第一个根本选择)

1.1 什么是宏内核(Monolithic Kernel)

Linux 是宏内核 :内核是一个巨大的程序,进程管理/内存/文件系统/驱动/网络/IPC 全在同一个内核地址空间运行,全在内核态(S 态)。

复制代码
┌─────────────────────────────────┐
│         用户态(U 模式)           │  app1  app2  app3
├─────── syscall(唯一的门)─────────┤
│  内核态(S 模式,一个地址空间)     │
│  ┌──────┬──────┬──────┬───────┐  │
│  │ 进程 │ 内存 │ VFS  │ 驱动  │  │  ← 全在一起,函数直接调用
│  │ 调度 │ 管理 │      │ 网络  │  │
│  └──────┴──────┴──────┴───────┘  │
└─────────────────────────────────┘
              │ 系统调用(特权指令 ecall/syscall)
              ▼
         硬件(M 模式,BootROM/SBI/固件)

对照微内核 (Mach/L4/seL4):内核只留最小功能(调度/IPC/简单内存),文件系统/驱动/网络作为独立进程跑在用户态,靠 IPC 通信。

1.2 为什么 Linux 选宏内核

维度 宏内核(Linux) 微内核(seL4/L4)
性能 函数直接调用,快 IPC 消息传递,慢(跨地址空间)
模块化 弱(全在一起) 强(每服务独立)
隔离 弱(驱动 bug 拖垮全核) 强(驱动崩溃不影响内核)
开发 一切可见,易上手 接口严格,开发复杂
生态 驱动多(厂商愿意写) 驱动少(门槛高)

Linux 选宏内核 = 用性能和生态换隔离性 。Linus 当年和 Tanenbaum 的著名论战(1992)就是这个:Linus 认为宏内核实用、性能好、能跑起来才是王道;Tanenbaum 认为微内核才是学术正道。30 年过去,Linux 赢了,靠的是生态不是学术。

1.3 宏内核的"软化":模块化

纯宏内核的问题------驱动全编进内核,内核巨大。Linux 的折中:内核模块(LKM),驱动可动态加载,但仍跑在内核态(不是微内核的"用户态驱动")。

嵌入式视角:模块不是微内核

你写 Linux 驱动用 .ko 模块,这不是微内核 。模块加载后,代码进内核地址空间,和内核其他部分同特权同地址空间------一个模块 bug 照样 panic 全核。模块只是"运行时链接",不是"隔离" 。对照RISC-V 的 .o 链接进 ELF,LKM 是运行时做这事(09 篇详讲)。

1.4 你的对照锚点

FreeRTOS RISC-V bare-metal Linux
内核形态 宏内核(一坨) 你写的 App 就是"内核" 宏内核(巨大一坨)
特权层 无特权(全在 M) 你在 M 内核在 S,用户在 U
模块化 无(LKM 概念) 静态链接 LKM 动态加载

二、一切皆文件(Everything is a File)⭐

2.1 这是 Unix/Linux 的灵魂

Linux 承袭 Unix 哲学:所有资源都用文件抽象。

资源 文件路径 操作
普通文件 /home/me/a.txt open/read/write/close
设备(字符) /dev/ttyS0, /dev/i2c-0 open/read/write/ioctl
设备(块) /dev/mmcblk0 open/read/write
管道 pipe() 创建 read/write
套接字 socket() 创建 send/recv
进程信息 /proc/self/status read
内核参数 /proc/sys/..., /sys/... read/write
调试信息 /sys/kernel/debug/... read

统一的接口 :open → read/write → close。不管背后是磁盘、串口、还是内核数据结构,用户态看到的都是这个流程。

2.2 为什么这么设计

  1. 接口统一 :学一套 API 操作所有资源。新设备驱动实现 file_operations,用户态代码不用改。
  2. 可组合 :shell 管道 cat file | grep x | wc -l 能工作,因为都是文件读写。
  3. 工具复用 :cat/echo/grep 能操作任何文件类资源,不用为每资源写专用工具。

2.3 VFS 是实现(12 篇详讲)

"一切皆文件"靠 VFS(Virtual File System) 实现。VFS 定义四对象(superblock/inode/dentry/file),每个具体文件系统(ext4/proc/sysfs/设备驱动)实现这些对象的接口。用户 open("/dev/ttyS0") → VFS 路径解析 → 落到 tty 驱动的 file_operations.open。

嵌入式视角:MCU 没有"文件"这层

你裸机/FreeRTOS 访问 UART:uart_send(0x55),直接调函数。Linux 访问 UART:open("/dev/ttyS0") → write(fd, "\x55", 1)。多了一层文件抽象,看似啰嗦,但带来 :① 用户态不用知道驱动细节;② 权限控制(文件权限);③ 可用通用工具(cat/echo)测试;④ 重定向/管道。这是 Linux 给"设备访问"加的标准化外壳。

2.4 "不是真文件"的例外

  • 网络套接字:有 fd,但不是文件系统路径(bind/connect 用地址)
  • 匿名管道:有 fd,无路径
  • epoll/inotify:有 fd,无路径
  • timerfd/eventfd/signalfd:有 fd,无路径

这些是"文件描述符(fd)"抽象的扩展------fd 是"可读写的句柄"的泛化,不一定对应磁盘文件。这是"一切皆文件"的现代演化。


三、机制与策略分离(Mechanism vs Policy)

3.1 内核只提供机制,策略留给用户态

机制(Mechanism) = "能做什么"(能力)。策略(Policy)= "怎么做"(决定)。

Linux 原则:内核实现机制,策略尽量在用户态。

机制(内核) 策略(用户态)
进程调度器(CFS/EEVDF) 进程优先级/nice(用户设)
内存分配(buddy/slab) 分多少、何时分配(用户程序)
文件系统(ext4 接口) 挂载点/挂载选项(用户/mount)
网络协议栈 路由/防火墙规则(iptables)
设备驱动 用哪个设备/怎么用(应用)
cgroup 资源限额(用户配)

3.2 为什么

  1. 灵活性:同一个机制支持多种用法(调度器既跑桌面又跑服务器)。
  2. 内核精简:策略多变,放内核要重编;放用户态可热改。
  3. 避免争议:策略选择是"品味"问题,内核只给能力,不替你决定。

3.3 例外:内核也有策略

不是绝对。调度器的 CFS 算法本身是策略(选谁跑),但放内核(性能要求)。性能敏感的策略进内核,可配置/可变的策略留用户态。

嵌入式视角:FreeRTOS 策略更固化

FreeRTOS 调度策略(优先级抢占)写死在内核,你只能配优先级数值,不能换算法。Linux 给你 CFS/EEVDF/RT 多选,还能配调度参数。Linux 的"机制策略分离"给你更多控制权,但也更复杂。你转型时要适应"很多东西在用户态配,不是改内核"。


四、可移植性:arch 抽象层

4.1 一套核心,多架构

Linux 跑在 x86/ARM/RISC-V/MIPS/PowerPC... 几十种架构。靠 arch/ 目录隔离架构相关代码:

复制代码
linux/
├── arch/
│   ├── arm/          ← ARM 32
│   ├── arm64/        ← ARM 64
│   ├── riscv/        ← RISC-V(对接你的专题)
│   ├── x86/          ← x86
│   └── ...
├── kernel/           ← 架构无关(调度/信号/进程通用)
├── mm/               ← 架构无关(内存管理通用)
├── drivers/          ← 驱动(大部分架构无关)
└── fs/               ← 文件系统(架构无关)

arch/<arch>/ 里放:启动汇编、trap entry、上下文切换、TLB 管理、原子操作实现、DMA 抽象等必须用具体 ISA 指令的代码。其余用 C 写,跨架构共享。

4.2 对接 RISC-V 专栏

arch/riscv/ 就是 \[00-RISC-V架构专题总目录\|RISC-V 专题] 讲的那些机制在 Linux 里的落地:

RISC-V 专题概念 Linux arch/riscv 落地
\[04-trap 机制详解] arch/riscv/kernel/entry.S(trap entry)
\[03-CSR 速查与特权架构 M-S-U] Linux 在 S 态,用 sstatus/stvec/sepc
\[05-中断系统 PLIC-CLINT-AIA] arch/riscv/kernel/irq.c + irqchip 驱动
\[06-内存 PMP-MMU-RVWMO] Sv39 arch/riscv/mm/(页表、sfence.vma)
\[07-启动与 bare-metal 流程] arch/riscv/kernel/head.S(启动汇编)

你的 RISC-V 专题是读 arch/riscv 的钥匙

你刚啃完 RISC-V 专题------trap/CSR/PLIC/Sv39/启动汇编。这些正是 arch/riscv/ 的全部内容 。普通 Linux 学习者卡在"arch 层看不懂",你能直接看懂。这是你的优势,学 Linux 内核比纯软件背景的人快,就快在这。

4.3 对接 FreeRTOS port 层

你深到 FreeRTOS V11.1 的 port 层------port.c/portASM.s。FreeRTOS 的 port 层 = Linux 的 arch 层,职责完全一样:隔离架构差异。区别:FreeRTOS port 小(几百行),Linux arch 大(几万行),但抽象思路同。


五、向后兼容(不破坏用户态 ABI)

5.1 内核 ABI 稳定承诺

Linux 承诺:用户态程序不会被内核升级破坏。一个 10 年前编译的二进制,在新内核上照样跑。这靠:

  • syscall 编号稳定(sys_open 永远是那个号)
  • syscall 参数语义稳定(不悄悄改含义)
  • 数据结构 UABI 稳定 (struct stat 布局不变)

5.2 内核内部 API 不保证稳定

注意区分:

  • UABI(用户态接口):稳定,不破坏
  • 内核内部 API(驱动用的) :不稳定,版本间可改

你写驱动用的 register_chrdev/file_operations 等内核 API,版本升级可能改签名。这是写驱动要跟内核版本对齐的原因。

嵌入式视角:和你 ROM 固化的 ABI 稳定同构

如果做过ROM固化,可知ROM 固化函数的 ABI 不能变,调用方和固化方 -march/-mabi 必须一致。Linux 的 UABI 稳定和ROM 固化 ABI 稳定是同一个道理------接口稳定,实现可换。区别:Linux 的 UABI 跨版本跨设备,ROM ABI 跨固件版本。


六、惰性分配(Lazy Allocation)

6.1 核心思想:用到才给

Linux 大量用"惰性"------资源用到才真正分配,不用省着。

惰性机制 是什么 好处
COW(Copy-On-Write) fork fork 不真复制页表,父子共享,写时才复制 fork 快,省内存
Demand paging mmap/分配不立即给物理页,访问时缺页才分配 启动快,省内存
Lazy file mapping mmap 文件不立即读盘,访问缺页才读 大文件不用全加载
Lazy thread clone 线程栈按需扩展 省栈空间
Slab 缓存 对象池,分配过的不销毁,留着复用 快

6.2 对照 MCU

MCU 是"立即分配"------malloc(100) 立刻给 100 字节,fork 不存在(没进程概念)。Linux 惰性是因为有虚拟内存和 page fault 机制撑腰:可以"先承诺,后兑现",访问时缺页中断进内核补上。

缺页(page fault)是 Linux 内存管理的发动机

\[04-trap 机制详解] 学过 trap,page fault 是其中一类(mcause 13/15)。Linux 内存管理的核心机制------demand paging/COW/mmap/swap------全靠 page fault 触发 。内核:① 承诺地址(改页表标记"未分配");② 用户访问 → page fault;③ 内核分配物理页、填页表、返回重试。理解 page fault,就理解 Linux 内存管理的一半(04 篇详讲)。


七、进程为中心(task_struct 是宇宙中心)

7.1 一切以 task_struct 为单位

Linux 内核里,进程(线程)是核心数据结构 task_struct。所有子系统都围绕它:

  • 调度器:选 task_struct 跑
  • 内存:每个 task_struct 有 mm_struct(地址空间)
  • 文件:每个 task_struct 有 files_struct(打开的文件)
  • 信号:每个 task_struct 有信号挂起位
  • 审计/cgroup/命名空间:都挂在 task_struct

7.2 进程 vs 线程(在 Linux 里是同一个东西)

Linux 不区分进程线程------都是 task_struct。

  • "进程":一组共享 mm_struct 的 task_struct 只有一个
  • "线程":一组共享 mm_struct 的 task_struct 有多个(clone 时共享 mm)

这和 Windows/传统 Unix 不同(Linux 线程叫"轻量进程")。统一抽象简化内核(03 篇详讲)。

7.3 对照 FreeRTOS

FreeRTOS Linux
任务单位 TCB(小,几百字节) task_struct(大,几 KB)
任务数据 栈/优先级/状态 栈/优先级/状态 + mm + files + signals + ...
进程/线程 只有任务 都是 task_struct(共享 mm 与否区分)

嵌入式视角:task_struct 是"胖 TCB"

你熟 FreeRTOS TCB。Linux 的 task_struct 是"胖版 TCB"------多了 mm(地址空间)、files(文件表)、signals(信号)、namespace(容器)等。因为 Linux 任务要独立地址空间和文件上下文,FreeRTOS 任务全在一个地址空间共享一切。03 篇会逐字段拆 task_struct。


八、四大"认知冲击"(从 MCU/RTOS 转 Linux 的心理建设)

这是你转型最痛的四点,先打预防针:

8.1 冲击一:单任务裸机 → 多进程分时

你的惯性 :main() 一个死循环,跑完所有事,独占 CPU。

Linux 现实:你的程序只是千百个进程之一,调度器随时切走 CPU。你不能假设"我跑着没人打断我"------别的进程在跑,中断在来,内核在调度。

适应:

  • 别用"独占 CPU"思维写代码(无脑忙等)
  • 用阻塞 API(read 没数据会睡,不是忙等)
  • 共享数据要同步(别的进程/线程可能同时访问)

8.2 冲击二:直接硬件 → 框架化(经五层)

你的惯性 :写 UART 驱动,直接 *(volatile uint32_t*)UART_BASE = 0x55;。

Linux 现实 :用户态不能直接访问硬件(用户态没权限)。你要写内核驱动,经框架:

复制代码
用户 write(fd, "\x55", 1)
  → VFS(sys_write)
  → 文件系统/设备层
  → 驱动的 file_operations.write
  → 你终于碰寄存器

五层抽象。看似啰嗦,但带来权限/安全/通用/可组合。

适应:接受框架开销,学会在框架里写(drivers/ 目录),不绕框架。

8.3 冲击三:ISR 直接做事 → 顶半部+下半部

你的惯性 :FreeRTOS ISR 里处理完,xQueueSendFromISR 通知任务。

Linux 现实 :中断顶半部不能睡眠、不能耗时 (关中断影响全系统)。耗时/可睡眠的活推迟到下半部(softirq/workqueue/threaded irq)。这是硬规则,违反会死机。

适应:中断驱动要分"哪些必须顶半部做(确认/拷贝数据),哪些推下半部(处理/通知)"(05 篇详讲)。

8.4 冲击四:一个地址空间 → 每进程独立虚拟空间

你的惯性:FreeRTOS 所有任务共享一个地址空间,指针随便传。

Linux 现实 :每个进程有独立虚拟地址空间,你的指针到另一个进程是无效地址。内核态地址空间全局共享,但用户态隔离。驱动在内核态,要小心用户态指针不能直接解引用(用 copy_to_user/copy_from_user)。

适应:

  • 用户态↔内核态传数据用专用 API(copy_to_user/copy_from_user)
  • 不要假设两个进程的指针互通
  • DMA buffer 要在内核态分配/映射(04 篇详讲)

四大冲击的本质

这四个冲击,本质都是**"隔离"**带来的:Linux 要隔离进程、隔离用户/内核、隔离中断上下文、隔离地址空间------为了安全/稳定/多用户。MCU 不要隔离(单一职责),Linux 必须隔离(多用途)。理解"为什么隔离",就理解 Linux 大部分设计。


九、内核态 vs 用户态(特权边界)

9.1 两个特权级

复制代码
用户态(U 模式)  ← app 运行,权限受限
   │  syscall(ecall/syscall 指令)
   ▼
内核态(S 模式)  ← 内核运行,全权(除 M 模式保留)
   │  SBI 调用(ecall to M)
   ▼
M 模式          ← SBI/OpenSBI/固件,硬件层
  • 用户态:不能直接访问硬件、不能执行特权指令、不能访问内核内存。要这些,走 syscall 进内核。
  • 内核态:全权访问硬件(经驱动)、内核内存、特权指令。Linux 内核在这层(RISC-V 上是 S 态,不是 M 态------M 态留给 SBI)。

9.2 上下文切换(特权切换)

每次 syscall/中断/异常,用户态↔内核态切换,要保存上下文:

  • 保存用户态寄存器(到内核栈)
  • 切到内核栈
  • 切特权级(S→U 或 U→S)
  • 执行内核代码
  • 返回时恢复

这正是你 \[04-trap 机制详解] 学的 trap 机制,Linux 在 arch/riscv/kernel/entry.S 实现。

9.3 为什么分两层

  1. 安全:恶意/bug 程序不能直接搞挂系统
  2. 多用户:进程隔离,互不干扰
  3. 资源管理:内核统一管硬件,仲裁访问

嵌入式视角:RISC-V 专题的 S/U 层落地

\[03-CSR 速查与特权架构 M-S-U] 讲过 M/S/U 金字塔。Linux 内核在 S 态 ,不在 M 态------M 态给 SBI(OpenSBI)做最底层时钟/复位/console。\[04-trap 机制详解] trap entry,在 Linux 里就是 arch/riscv/kernel/entry.S,处理 U→S 的 syscall 和中断。学的 RISC-V S 态机制,就是 Linux 内核运行的环境。


十、内核空间布局与源码地图

10.1 内核镜像布局

复制代码
内核镜像(物理/虚拟):
┌──────────────┐ 高地址
│  _end         │
├──────────────┤
│  .bss         │ 未初始化全局(启动清零)
├──────────────┤
│  .data        │ 已初始化全局
├──────────────┤
│  .rodata      │ 只读(常量/页表)
├──────────────┤
│  .text        │ 代码
├──────────────┤
│  _stext       │
├──────────────┤
│  (modules 区) │ LKM 加载区(独立虚拟区)
└──────────────┘ 低地址

和 \[09-工具链深挖 relaxation-ELF] 学的 ELF 段一致------内核也是 ELF。区别:内核有特殊段(.init.text 启动后丢弃、.percpu 每 CPU 数据、__ex_table 异常表)。

10.2 内核源码目录地图

复制代码
linux/
├── arch/          架构相关(riscv/arm64/x86...)  ← 你能看懂
├── kernel/        核心子系统(调度/信号/进程)
├── mm/            内存管理
├── fs/            文件系统(VFS + 各 fs)
├── drivers/       驱动(大头,占代码量 70%+)
├── net/           网络协议栈
├── ipc/           进程间通信
├── security/      安全框架(selinux/capabilities)
├── block/         块 IO 层
├── lib/           内核通用库
├── init/          启动(start_kernel)
├── include/       头文件
├── scripts/       kbuild 脚本
└── Makefile, Kconfig  构建系统

读源码的入口顺序

别从 init/main.c 的 start_kernel 一行行读(会迷路)。建议:

  1. 先读本专题 16 篇,建模块地图
  2. 读 arch/riscv/kernel/head.S(启动,你能懂)
  3. 读 init/main.c 的 start_kernel(看子系统初始化顺序)
  4. 按兴趣读子模块(从 kernel/ 开始)
  5. 读驱动从 drivers/ 找一个简单的(misc 目录)

十一、Linux vs FreeRTOS vs RISC-V bare-metal 总对照

三大对照锚点的全景表:

维度 FreeRTOS RISC-V bare-metal Linux
内核形态 宏(小) 你的 App 宏(大)
特权 无(M 全权) 你在 M S(内核)+ U(用户)
任务单位 TCB 无(单 main) task_struct
调度 优先级抢占 无/你写 CFS/EEVDF 公平
地址空间 一个共享 一个物理 每进程虚拟
中断 ISR+FromISR 你写 trap 顶半部+下半部
文件系统 无 无 VFS(一切皆文件)
设备访问 直接函数 直接寄存器 框架化(经 VFS)
驱动 函数集合 你写 模块+框架
同步 信号量/互斥 关中断/原子 spinlock/mutex/RCU
启动 reset→main BootROM→BL→_start BootROM→U-Boot→start_kernel→init
内存分配 heap策略(1~5) 静态/你写 buddy/slab/kmalloc
tick mtimecmp 你配 hrtimer+tick+nohz

这张表是你的"翻译字典"

学 Linux 每个概念,回这表查 FreeRTOS/RISC-V 对应物。你的知识不是白学,是 Linux 的子集和前身。带着这表读后面 15 篇,速度翻倍。


十二、本篇小结

  • 宏内核:Linux 是一坨大内核,全在 S 态,函数直接调用,性能好但隔离弱;LKM 是软化不是微内核
  • 一切皆文件:设备/管道/socket/proc 都是文件,VFS 统一 open/read/write 接口
  • 机制与策略分离:内核给机制(调度器/分配器),策略留用户态(优先级/用量);性能敏感策略例外进内核
  • 可移植性:arch/ 隔离架构差异,你 RISC-V 专题正是读 arch/riscv 的钥匙
  • 向后兼容:UABI 稳定(用户程序不破坏),内核内部 API 不稳定(驱动要跟版本)
  • 惰性分配:COW fork/demand paging/mmap,全靠 page fault 发动机
  • 进程为中心:task_struct 是宇宙中心,进程线程统一抽象
  • 四大冲击:单任务→多进程分时、直接硬件→框架化、ISR→顶半部+下半部、一地址空间→每进程虚拟
  • 特权边界:内核 S 态,用户 U 态,syscall 是唯一的门
  • 源码地图:arch/(架构) + kernel/mm/fs/drivers/net(子系统)

速查表

想干啥 看哪
理解 Linux 为什么这么设计 本篇
找架构相关代码 arch//
找启动代码 arch//kernel/head.S + init/main.c
找调度器 kernel/sched/
找内存管理 mm/
找驱动框架 drivers/base/
找一个驱动示例 drivers/misc/ 或 drivers/char/
用户态访问设备 open("/dev/xxx") → read/write/ioctl
用户态↔内核态传数据 copy_to_user / copy_from_user
找 RISC-V 专题对应 arch/riscv/ 全目录

💡技术之路漫漫,分享是为了更好地交流。如果本文的内容对你有启发,希望能得到你的 点赞 👍 和 收藏 ⭐。

如果你在调试过程中遇到了其他问题,欢迎在 评论区 💬 留言,我们一起探讨。也欢迎 关注 👀 我,一起交流底层开发的那些事儿。


相关推荐
脏脏a1 小时前
极空间部署 Dashlet:Docker 搭建私人导航仪表盘,再配置固定公网访问
运维·docker·容器
中电金信1 小时前
中电金信参编的团体标准《商业银行应用程序接口治理能力要求》正式发布
大数据·运维·人工智能
码完就睡1 小时前
Linux——socket网络编程
linux·运维·网络
道尔柯南1 小时前
【Linux】网络基础概念
linux·运维·网络
傲世仙尊2 小时前
从抢票事故到锁的原理-互斥条件变量与生产消费模型
linux·驱动开发
AI+程序员在路上2 小时前
AP6275S蓝牙双接口解析:HCI UART与PCM的分工与协同
linux·c语言·物联网
小此方2 小时前
Linux网络(十八):TCP连接管理详解:从三次握手、四次挥手到CLOSE_WAIT与TIME_WAIT,深入理解2MSL与端口复用
linux·网络·网络协议·tcp/ip
进击的荆棘2 小时前
Linux系统——文件(上)
linux·运维·服务器·文件
k4m7v2pz2 小时前
ThinkPad E490 风扇 “转两秒就停“ 实录:迟滞曲线 + 最短运转时间
linux·脚本·archlinux·thinkpad·风扇·散热