操作系统第一讲复习:为什么学习操作系统,以及操作系统到底在做什么?
课程来源:Operating Systems Lecture 1, Why Learn Operating System? And How?
核心主线:操作系统是什么 → OS 的三种角色 → CPU/内存虚拟化 → OS 与 kernel → OS 为什么难 → OS 历史 → 计算机组成基础 → Hello World 的一生。
0. 这一讲到底在讲什么?
第一讲不是马上进入某个具体机制,而是在帮我们建立操作系统课程的"大地图"。后面的进程、线程、地址翻译、调度、锁、文件系统,本质上都可以从第一讲的几个核心问题展开:
- 操作系统为什么存在?
- 操作系统到底管什么?
- 为什么应用程序不能直接操作硬件?
- 为什么多个程序可以"同时运行"?
- 为什么不同进程可以看到相同地址,却互不影响?
- OS 和 kernel 到底是不是一回事?
- 一个 Hello World 程序从写出来到跑起来,中间经历了什么?
这一讲最核心的一句话是:
操作系统是硬件和应用/用户之间的软件层,它负责管理硬件资源,并向应用提供安全、方便、高效的抽象接口。
1. 按 PPT 页码快速索引
这一部分适合复习时查漏补缺。
| 页码 | 内容 | 复习重要性 |
|---|---|---|
| 1 | 课程标题:Why Learn Operating System? And How? | 了解 |
| 2 | 提问:人类构建过最重要的软件是什么? | 了解 |
| 3 | 操作系统发展谱系图 | 了解,不用背细节 |
| 4--5 | 第一讲目录 | 重要,知道本讲结构 |
| 11--12 | 什么是 OS | 核心 |
| 13--16 | OS 的三种角色:referee / illusionist / glue | 核心 |
| 17--19 | CPU virtualization 代码例子 | 核心 |
| 20--22 | Memory virtualization 代码例子 | 核心 |
| 23 | OS 的目标 | 重要 |
| 24--25 | OS 概念扩展;OS vs kernel | 核心 |
| 26--30 | 为什么学习 OS | 重要,但偏动机 |
| 31--33 | OS 的挑战和学习方法 | 重要,帮助理解后续难点 |
| 34--40 | OS 历史:串行、批处理、多道、分时、实时、分布式、微内核 | 重要,理解演化逻辑 |
| 41--49 | 计算机组成、CPU、ISA、汇编、寄存器、内存 | 重要预备知识 |
| 50--53 | Hello World 的一生 | 核心 |
| 54--56 | Linux CLI、GUI、LLM 辅助 | 了解 |
| 57 | Calling Convention 调用约定 | 重要预备知识 |
| 58 | 杂项:硬件支持、byte/bit/word、指针 | 了解但要会基本概念 |
| 59 | 工具:Compiler Explorer、xv6 labs | 了解 |
2. 什么是操作系统?
PPT 给出的定义很直接:
OS is a bridge between hardware and apps/users.
也就是:
操作系统是硬件和应用/用户之间的桥梁。
更具体一点:
操作系统是一个特殊的软件层,它管理应用程序对硬件资源的访问,例如 CPU、内存、磁盘、I/O 设备等。
一台计算机大致可以这样分层:
text
Users
↓
Applications: 浏览器、微信、Office、游戏、编译器
↓
Operating System: Windows、Linux、Android、iOS、HarmonyOS
↓
Hardware Resources: CPU、GPU、内存、磁盘、网卡、键盘、鼠标、显示器
为什么中间必须有 OS?因为应用程序如果直接操作硬件,会出现三个严重问题:
- 不安全:一个程序可能随便读写别人的内存。
- 不公平:一个程序可能一直占着 CPU,不让别人运行。
- 太复杂:每个应用都要自己适配磁盘、网卡、显卡、键盘,开发成本巨大。
所以 OS 站在中间,提供统一接口,管理资源,并建立保护边界。
3. OS 的三个角色:裁判、魔术师、胶水
第一讲最重要的框架是:
text
OS as referee
OS as illusionist
OS as glue
中文可以理解为:
text
OS 是裁判
OS 是魔术师
OS 是胶水
3.1 OS as referee:操作系统是裁判
作为裁判,OS 要解决的是资源分配和安全问题。
它需要决定:
- 多个程序都想用 CPU,谁先运行?
- 多个程序都想申请内存,怎么分配?
- 一个程序死循环了,能不能把 CPU 拿回来?
- 一个程序崩溃了,会不会影响其他程序?
- 一个恶意程序能不能偷看别人的数据?
PPT 里把 referee 的职责概括为三个方面:
-
Resource allocation:资源分配
在有限资源上运行多个任务。
-
Isolation:隔离
一个应用的错误不应该拖垮整个机器,也不能随便攻击别的应用。
-
Communication:通信
程序之间要能可靠、安全、快速地通信。
后续课程里,调度、进程、地址空间、文件系统、同步机制,都和"裁判"角色有关。
3.2 OS as illusionist:操作系统是魔术师
操作系统会制造一些"并不真实存在,但对程序员很好用"的假象。
最典型的两个假象:
-
每个程序好像都有自己的 CPU
实际上 CPU 数量有限,OS 通过调度让多个程序轮流运行。
-
每个程序好像都有一整片连续内存
实际上物理内存是共享的、有限的,OS 和硬件通过虚拟地址机制隔离不同进程。
PPT 里提到的资源假象包括:
- Processor
- Memory
- Screen
- Disk
再进一步,就是虚拟机。虚拟机让整个操作系统都以为自己独占了一套硬件。
3.3 OS as glue:操作系统是胶水
OS 还提供一系列公共服务,把硬件和应用粘合起来。
例如:
- read/write files
- share memory
- pass messages
- UI
程序员不需要自己写磁盘驱动,不需要自己处理键盘中断,也不需要自己实现跨进程通信。OS 提供统一抽象,让应用开发和硬件细节解耦。
一句话总结三种角色:
裁判负责公平和安全,魔术师负责抽象和虚拟化,胶水负责提供统一服务。
4. CPU Virtualization:为什么多个程序看起来能同时运行?
PPT 的 CPU virtualization 例子中,程序大概是这样:
c
int main(int argc, char *argv[]) {
char *str = argv[1];
while (1) {
Spin(1);
printf("%s\n", str);
}
return 0;
}
如果只运行一个程序:
bash
./cpu A
屏幕会不断输出:
text
A
A
A
A
...
如果同时运行多个程序:
bash
./cpu A & ./cpu B & ./cpu C & ./cpu D &
屏幕可能会交替输出:
text
A
B
D
C
A
B
C
A
...
这说明什么?
表面上看,A、B、C、D 四个程序都在运行。实际上,如果 CPU 核心数量有限,它们并不一定真的同时占用 CPU。OS 会让 CPU 运行 A 一小段时间,再保存 A 的状态,切换到 B,再切换到 C,再切换到 D。
这就是:
text
CPU virtualization = OS 让多个程序都以为自己拥有 CPU
背后依赖两个概念:
- Scheduling 调度:决定下一个运行谁。
- Context Switch 上下文切换:保存当前程序状态,恢复另一个程序状态。
后面学习进程、线程和调度时,这个例子会反复出现。
5. Memory Virtualization:为什么两个进程能看到同一个地址?
PPT 的 memory virtualization 例子中,程序大概是这样:
c
int *p = malloc(sizeof(int));
printf("address pointed to by p: %p\n", p);
*p = 0;
while (1) {
Spin(1);
*p = *p + 1;
printf("p: %d\n", *p);
}
如果运行一个进程,它可能输出:
text
address pointed to by p: 0x200000
p: 1
p: 2
p: 3
...
更有意思的是,同时运行两个相同程序时,两个进程可能都打印:
text
address pointed to by p: 0x200000
但是它们的 p 值互不干扰。进程 A 的 p 在增长,进程 B 的 p 也在增长,但它们不是共享同一块真实内存。
原因是:
进程看到的是虚拟地址,不是物理地址。
可以理解成:
text
进程 A 的虚拟地址 0x200000 → 物理内存位置 X
进程 B 的虚拟地址 0x200000 → 物理内存位置 Y
也就是说,两个进程看到的地址一样,但背后映射到不同的物理内存。
这就是:
text
Memory virtualization = OS 让每个进程都以为自己拥有独立内存空间
后面学习地址翻译、页表、TLB、缺页异常时,本质上都在解释这件事是怎么实现的。
6. OS 的目标
PPT 把 OS 的目标分为三类。
6.1 管理硬件资源
包括:
- CPU 分配
- 内存分配
- 磁盘管理
- I/O 设备状态管理
- CPU 频率管理
6.2 方便应用开发者
OS 给开发者提供抽象,例如:
- 大内存假象
- 应用隔离
- 跨应用通信
- 文件读写接口
这样开发者不需要直接面对硬件细节。
6.3 方便用户
OS 也要提供用户能感知的功能,例如:
- UI 组件
- 图形渲染
- 文件浏览
- 程序启动
所以 OS 既要面对硬件,也要面对应用,还要面对用户。
7. OS 和 Kernel 的区别
PPT 第 24--25 页提到:OS 的概念正在扩展,比如 Android、TensorFlow、WeChat 都有一些"操作系统式"的资源管理能力。但课程重点是传统意义上的 OS,尤其是 kernel。
7.1 Kernel 是什么?
Kernel 是操作系统最核心、最底层、拥有最高权限的部分。
它负责:
- 进程管理
- CPU 调度
- 内存管理
- 文件系统核心逻辑
- 设备驱动
- 中断处理
- 系统调用入口
- 权限保护
普通应用不能直接操作硬件。应用要读文件、申请内存、创建进程、发送网络数据,通常要通过 syscall 请求 kernel 帮忙。
7.2 完整 OS 是什么?
完整 OS 通常不只有 kernel,还包括:
- 系统库,例如 libc
- shell,例如 bash、zsh
- GUI,例如桌面环境、窗口管理器
- 系统服务,例如日志、网络、登录服务
- 文件管理器、设置界面、包管理器
- 默认应用和工具
7.3 例子:Linux kernel vs Ubuntu
严格来说:
text
Linux = kernel
Ubuntu = 一个基于 Linux kernel 的完整操作系统
Linux kernel 负责调度、内存、进程、文件系统、驱动、网络协议栈等。Ubuntu 在此基础上加入 GNU 工具、glibc、bash、systemd、GNOME 桌面、apt 包管理器等。
所以:
Kernel 让机器能被安全管理;完整 OS 让用户能方便使用机器。
8. 为什么学习操作系统?
PPT 给了三个层次。
8.1 OS 是 CS 的基础
操作系统广泛使用计算机科学中的核心概念:
- 抽象
- 并发
- 缓存
- 虚拟化
- 调度
- 隔离
- 安全
- 持久化
它还和硬件、编译器、编程语言、运行时系统密切交互。
8.2 OS 很有用
无论你做什么方向,都可能遇到 OS 问题:
- HPC
- 移动端
- 边缘计算
- 云计算
- ML/AI 系统
- 安全
- 数据库
- 分布式系统
比如程序跑得慢,可能不是算法问题,而是 cache miss、I/O 阻塞、线程同步、内存分配或者调度问题。
8.3 OS 很酷
OS 可能是普通学生接触过最复杂的软件之一。理解 OS,是理解计算机真正如何工作的关键路径。
9. 操作系统难在哪里?
PPT 总结了几个挑战。
9.1 复杂度高
Windows 10 大约有千万行代码。操作系统既大又复杂,而且很多 bug 很难定位。
9.2 直接面对硬件
普通应用崩溃,可能只是一个窗口关闭;OS 崩溃,可能就是整个系统蓝屏、死机、重启。
9.3 并发非常难
PPT 给了一个经典例子:
c
int counter = 0;
// Thread 1
counter++;
// Thread 2
counter++;
看起来两个线程各加一次,结果应该是 2。但 counter++ 通常不是一条不可分割的原子操作,而是类似:
text
load counter
add 1
store counter
如果两个线程交错执行,最后结果可能不是 2。
这就是后面同步、锁、条件变量要解决的问题。
9.4 指标很多
OS 不只追求快,还要考虑:
- reliability 可靠性
- availability 可用性
- performance 性能
- energy 能耗
- security 安全
- usability 易用性
很多时候这些目标互相冲突。
10. OS 历史:为什么 OS 会演化成今天这样?
10.1 Serial Processing 串行处理
最早没有 OS,用户直接和机器交互。没有调度,没有资源复用,准备时间很长。
特点:
- No OS
- 用户直接操作机器
- No scheduling
- Huge setup time
10.2 Simple Batch Systems 简单批处理
后来出现 monitor,把一批 job 放在一起执行。一个程序结束后回到 monitor,再运行下一个。
特点:
- 程序批量运行
- monitor 常驻内存
- 提高机器利用率
- 仍然是 uniprogramming
10.3 Multiprogrammed Batch Systems 多道批处理
当一个程序等待 I/O 时,CPU 可以切换到另一个程序执行。
这需要:
- 内存管理
- 调度
- 保存和恢复状态
它主要优化的是 throughput,也就是单位时间完成更多 job。
10.4 Time Sharing Systems 分时系统
分时系统让多个用户/进程按时间片共享计算机资源。目标是更好的响应时间。
特点:
- 多个用户/进程共享 CPU
- 每个进程获得 time slot
- 更适合交互式使用
- 资源消耗更高
10.5 其他 OS 类型
PPT 还提到:
- Real-time OS 实时操作系统:用于机器人、卫星、飞机等,需要满足 deadline。
- Distributed OS 分布式操作系统:可能建立在传统 OS 之上,常见模式包括 C/S 和 P2P。
- Microkernel 微内核:把驱动、文件系统等放到用户态,内核更小、更安全,但可能更慢。
- Hybrid kernel 混合内核:很多现代 OS 采用折中设计,例如 macOS。
10.6 OS 演化总结
OS 之所以不断变化,是因为它要适应:
- 新硬件:多核 CPU、GPU、NPU、NVM、RDMA
- 新负载:机器学习训练/推理、分布式程序、AR/VR
- 新需求:更快响应、更低功耗、更好易用性
PPT 最后强调:硬件越来越便宜,人越来越贵,所以 OS 会用一些效率换取易用性。
11. 计算机组成基础:OS 为什么离不开硬件?
OS 不是纯软件课,因为 OS 必须理解硬件暴露出来的接口。
11.1 基本硬件组件
一台机器可以粗略看成:
- CPU
- Memory
- Disk
- Input devices
- Output devices
11.2 CPU 的组成
CPU 里面包括:
- ALU:算术逻辑单元,负责计算
- CU:控制单元,负责控制取指和执行
- Registers:寄存器,CPU 内部最快的存储
- Cache:缓存
- 与 Memory 的交互接口
11.3 寄存器
x86-64 有通用寄存器,也有特殊寄存器,例如:
- IP/EIP/RIP:指向下一条要执行的指令
- RFLAGS:状态标志
- CS/SS/DS/ES/FS/GS:段寄存器
- CR0--CR15:控制寄存器
后面学用户态/内核态、分页、缺页异常、中断时,都会接触这些概念。
11.4 ISA:指令集架构
ISA 是 Instruction Set Architecture,指令集架构。
可以把 ISA 理解成硬件和软件之间的接口:
text
软件发出某条机器指令
CPU 按照 ISA 定义解释并执行它
例如一条指令通常包含:
text
opcode + operands
比如:
text
add R0 R1 R2
其中 add 是操作码,寄存器是操作数。
12. 一个 Hello World 程序的一生
一个简单的 C 程序从源码到运行结束,大致经历这些阶段。
12.1 写代码
程序员写出源代码:
c
#include <stdio.h>
int main() {
printf("Hello World\n");
return 0;
}
12.2 编译
编译器把高级语言转换成汇编/机器代码。常见工具有:
- GCC
- G++
- LLVM/Clang
12.3 链接
程序用到了 printf,但 printf 不是你自己写的。链接器需要把你的代码和库函数连接起来。
12.4 OS 加载程序到内存
OS 创建进程,建立虚拟地址空间,把代码段、数据段、堆、栈等放到合适位置。
12.5 OS 调度执行
OS 把进程放入就绪队列,调度器决定什么时候让它运行。CPU 从入口地址开始执行指令。
12.6 系统调用
当程序要输出到屏幕时,最终会通过系统调用请求 OS 服务。普通应用不能直接操作显示设备或终端。
12.7 程序结束,OS 回收资源
程序结束后,OS 回收内存、关闭文件描述符、释放内核数据结构,并记录退出状态。
总结:
text
源代码
↓ 编译
目标文件/汇编/机器码
↓ 链接
可执行文件
↓ OS 加载
进程
↓ OS 调度
CPU 执行
↓ syscall / I/O
和内核交互
↓ exit
OS 回收资源
13. Calling Convention:函数是怎么调用和返回的?
PPT 最后提出了一个问题:
c
void func_A() {
int a = 1 + 2;
int c = func_B(a);
print(c);
}
void func_B(int x) {
int y = x + 3;
return y;
}
问题包括:
func_A怎么跳到func_B?- 参数
x怎么传? func_B怎么返回?- 返回值
y放在哪里? - 局部变量存在什么地方?
这些由 calling convention 调用约定决定。
一般来说:
- 参数放在寄存器或栈里
call指令保存返回地址并跳转- 被调用函数建立自己的栈帧
- 返回值放在约定寄存器中
ret指令根据返回地址跳回调用者
这对后面理解线程栈、上下文切换、系统调用栈非常重要。
14. 第一讲核心考点总结
考点 1:OS 的定义
OS 是应用和硬件之间的软件层,负责管理 CPU、内存、磁盘、I/O 等资源,并向应用提供抽象接口。
考点 2:OS 的三个角色
| 角色 | 含义 | 例子 |
|---|---|---|
| Referee 裁判 | 分配资源、隔离程序、保证通信安全 | CPU 调度、内存保护、进程隔离 |
| Illusionist 魔术师 | 制造虚拟资源假象 | 虚拟 CPU、虚拟内存、虚拟磁盘 |
| Glue 胶水 | 提供公共服务,连接硬件和应用 | 文件读写、共享内存、消息传递、UI |
考点 3:CPU 虚拟化
OS 通过调度和上下文切换,让多个程序看起来像同时运行。
考点 4:内存虚拟化
每个进程都有自己的虚拟地址空间。相同虚拟地址可以映射到不同物理地址,因此进程之间互不干扰。
考点 5:OS vs kernel
Kernel 是 OS 的核心部分,负责底层资源管理和硬件交互。完整 OS 还包括系统库、shell、GUI、系统服务和工具。
考点 6:Hello World 生命周期
写代码 → 编译 → 链接 → OS 加载 → OS 调度执行 → 系统调用/I/O → 程序退出 → OS 回收资源。
考点 7:OS 为什么难
OS 难在复杂、直接操作硬件、并发 bug 多、指标冲突、抽象层多、历史包袱重。
15. 小测题及答案
题 1:什么是操作系统?
答案:
操作系统是硬件和应用/用户之间的软件层,负责管理硬件资源,例如 CPU、内存、磁盘、I/O 设备,并为应用程序提供安全、方便、高效的抽象接口。
题 2:OS as referee / illusionist / glue 分别是什么意思?
答案:
- Referee:操作系统作为裁判,负责资源分配、隔离和通信。
- Illusionist:操作系统作为魔术师,制造虚拟 CPU、虚拟内存等假象。
- Glue:操作系统作为胶水,提供文件、共享内存、消息传递、UI 等公共服务,把应用和硬件连接起来。
题 3:为什么多个程序可以看起来同时运行?
答案:
因为 OS 通过 CPU 调度和上下文切换,让不同程序轮流使用 CPU。每个程序都以为自己在运行,但实际上它们可能是在时间片之间快速切换。
题 4:为什么两个进程可以看到相同的虚拟地址,却不会互相影响?
答案:
因为每个进程都有自己的虚拟地址空间。相同的虚拟地址可以通过页表映射到不同物理地址。因此两个进程看到的 0x200000 可能对应完全不同的真实内存位置。
题 5:kernel 和完整 OS 有什么区别?
答案:
Kernel 是 OS 的核心部分,负责进程管理、内存管理、调度、设备驱动、中断处理、系统调用等。完整 OS 除了 kernel,还包括系统库、shell、GUI、系统服务、包管理器、默认应用等。
题 6:一个 Hello World 程序从源码到运行,大概经历什么?
答案:
text
写代码 → 编译 → 链接 → OS 加载到内存 → 创建进程 → 调度执行 → 通过系统调用输出 → 程序退出 → OS 回收资源
题 7:为什么 counter++ 在多线程环境中可能出错?
答案:
因为 counter++ 通常不是原子操作,而是包含读取、加一、写回多个步骤。两个线程交错执行时,可能都读到旧值,然后分别写回,导致更新丢失。
题 8:为什么 OS 需要硬件支持?
答案:
因为很多 OS 功能必须依赖硬件机制,例如用户态/内核态需要 CPU 特权级,虚拟内存需要 MMU,中断需要 CPU 支持,原子操作需要特殊硬件指令。
16. 常见 QA
Q1:OS 和普通应用程序最大的区别是什么?
普通应用运行在较低权限下,不能直接操作硬件和系统关键资源。OS,尤其是 kernel,拥有更高权限,可以管理 CPU、内存、设备和进程。
Q2:为什么应用程序不能直接读写磁盘?
因为这样既不安全也不方便。不同程序可能互相破坏数据,也需要各自适配不同磁盘硬件。OS 通过文件系统提供统一接口,例如 open/read/write,并负责权限检查和数据管理。
Q3:虚拟化是不是等于虚拟机?
不完全等于。虚拟化是一种思想,表示 OS 或系统软件制造某种资源假象。虚拟 CPU、虚拟内存都是虚拟化。虚拟机是更进一步,让整个 OS 都以为自己拥有完整硬件。
Q4:kernel 是不是就是 Linux?
严格说 Linux 是一个 kernel。Ubuntu、Debian、Fedora、Android 才是基于 Linux kernel 的完整操作系统或系统发行版。
Q5:Shell 是 kernel 吗?
不是。Shell 是用户态程序,比如 bash、zsh。它负责接收用户命令,然后通过系统调用请求 kernel 执行相关操作。
Q6:GUI 是 kernel 吗?
不是。桌面、窗口、文件管理器通常属于完整 OS 的用户态组件。kernel 提供底层支持,例如进程、内存、设备驱动和权限管理。
Q7:操作系统为什么要学习汇编和 CPU?
因为 OS 直接和硬件打交道。中断、上下文切换、系统调用、用户态/内核态切换、页表切换,都需要理解寄存器、指令、栈和 CPU 特权机制。
Q8:为什么 OS 课程后面会讲锁和并发?
因为 OS 本身管理大量并发任务,同时应用程序也会使用线程。多个线程共享数据时,如果没有同步机制,就可能出现竞态条件、死锁、数据不一致等问题。
17. 拓展理解
17.1 OS 的本质:抽象 + 资源管理 + 保护
可以把操作系统压缩成三个关键词:
text
Abstraction 抽象
Resource Management 资源管理
Protection 保护
抽象让程序员不用直接面对硬件;资源管理让有限硬件被多个程序共享;保护让程序之间互不破坏。
17.2 为什么"多一层间接层"很重要?
PPT 引用了 David Wheeler 的话:
We can solve any problem by introducing an extra level of indirection.
操作系统大量使用间接层:
- 文件名 → inode → 磁盘块
- 虚拟地址 → 页表 → 物理地址
- 系统调用 → kernel handler → 设备操作
- 进程 ID → PCB → 进程状态
多一层间接层的好处是灵活、安全、可控。代价是性能开销和复杂度增加。
17.3 第一讲和后续课程的联系
| 第一讲概念 | 后续对应内容 |
|---|---|
| CPU virtualization | 进程、线程、调度、上下文切换 |
| Memory virtualization | 地址翻译、页表、TLB、缺页异常 |
| OS as referee | 保护、权限、调度、同步 |
| OS as glue | 系统调用、文件系统、I/O |
| OS vs kernel | 用户态/内核态、syscall、interrupt |
| 并发难题 | 锁、条件变量、信号量、死锁 |
| Hello World 生命周期 | 编译链接、加载、进程创建、系统调用 |
18. 复习建议
复习第一讲时,不建议死背 PPT,而是抓住下面这条主线:
text
应用想用硬件
↓
直接用不安全、不方便、不公平
↓
OS 站在中间管理资源
↓
OS 同时扮演裁判、魔术师、胶水
↓
裁判:分配和保护
魔术师:虚拟 CPU 和虚拟内存
胶水:系统调用和公共服务
↓
后续课程就是解释这些机制如何实现
能够用自己的话讲清楚这条线,第一讲就基本掌握了。
19. 一句话收尾
操作系统不是一个"普通软件",而是所有应用和硬件之间的中间层。它一边向下管理复杂硬件,一边向上提供简单抽象;一边保证效率,一边保证安全;一边制造虚拟资源的假象,一边又必须在真实硬件限制下做出取舍。第一讲的意义,就是让我们先看清这门课的全局地图。