Appearance
6.1810 2024 第1讲:操作系统概述
什么是操作系统?
一个操作系统(O/S)是介于硬件和用户应用程序之间的软件层。
- 硬件 (h/w): CPU、内存 (RAM)、磁盘、网络接口 (net) 等。
- 用户应用程序:
sh(shell),cc(编译器), 数据库 (DB) 等。 - 内核服务: 文件系统 (FS), 进程管理, 内存管理, 网络协议栈等。
- 系统调用: 应用程序请求内核服务的接口。
操作系统的目的
- 多路复用 (Multiplex): 在多个应用程序之间共享硬件资源。
- 隔离 (Isolate): 隔离应用程序以确保安全并控制 bug 的影响范围。
- 共享 (Share): 在相互协作的应用程序之间共享数据。
- 抽象 (Abstract): 为上层应用提供硬件的抽象,以实现可移植性和便利性。
设计中的权衡
操作系统设计充满了挑战性的权衡:
- 效率 vs. 抽象/可移植/通用性
- 强大的接口 vs. 简单的接口
- 灵活性 vs. 安全性
- 可移植性 vs. 利用新硬件和新接口
课程结构
在线信息:
- 网站: https://pdos.csail.mit.edu/6.1810/ (包含课程表、作业、实验)
- Piazza: 用于发布公告、讨论和实验求助。
讲座:
- 操作系统思想
- 以 xv6(一个小巧的操作系统)为例,通过代码和书籍进行案例研究。
- 实验背景知识
- 操作系统相关论文
- 要求: 每节课前提交一个关于阅读材料的问题。
实验 (Labs):
- 目的: 获得动手实践经验。
- 大部分实验为期一周。
- 类型:
- 系统编程: (例如第一个实验)
- 操作系统原语: (例如,线程切换)
- xv6 内核扩展: (例如,网络驱动)
- 寻求帮助:
- 在 Piazza 上提问和回答问题。
- 参加助教的 Office Hours。
- 注意: 鼓励讨论,但请不要查看他人的解决方案!
评分:
- 50% 实验 (基于你本地运行的相同测试)。
- 30% 考试 (期中、期末)。
- 15% 实验检查会议 (我们会随机抽查实验并提问)。
- 5% 家庭作业问题。
- 重点: 实验占分很高,请尽早开始!
UNIX 系统调用简介
应用程序通过“系统调用”与操作系统交互。你将在实验中大量使用、扩展和改进它们。
xv6 简介
- xv6 是我们为本课程专门创建的一个操作系统,它模仿 UNIX,但简单得多。
- 为什么是 UNIX? 它是许多现代操作系统(如 Linux, MacOS)的祖先。学习 xv6 有助于理解其他操作系统。
- 你将能够完全理解 xv6 的每一部分——没有秘密。
- xv6 在课程中有两个角色:
- 核心机制的示例。
- 大部分实验的起点。
- xv6 运行在 RISC-V CPU 上,你将在 QEMU 模拟器中运行它。
系统调用示例
read()和write()(ex1.c: 复制输入到输出)read()和write()是系统调用,它们看起来像函数调用,但实际上会以一种保持用户/内核隔离的方式跳转到内核中。- 文件描述符 (File Descriptor, FD): 第一个参数是一个小整数,告诉内核要操作哪个“打开的文件”。
- UNIX 约定: FD
0是标准输入,1是标准输出。 read()的第二个参数是要读入数据的内存地址,第三个参数是最大字节数。
open()(ex2.c: 创建文件)open()创建或打开一个文件,并返回一个新的文件描述符。- 每个进程都有自己独立的文件描述符空间。
fork()(ex3.c: 创建新进程)fork()创建一个调用进程的副本(子进程)。- 子进程拥有父进程内存、寄存器和文件描述符的副本。
- 返回值: 在父进程中返回子进程的 PID,在子进程中返回
0。
exec()(ex4.c: 执行一个程序)exec()用一个可执行文件中的内容替换当前进程的内存。- 它会加载新的指令和数据,但保留文件描述符。
- 如果成功,
exec()不会返回。
wait()(ex5.c: fork + exec)- Shell 不能直接调用
exec(),否则它自己就退出了。 - 标准流程: Shell
fork()一个子进程,子进程调用exec(),父进程调用wait()等待子进程结束。 wait()允许父进程获取子进程的退出状态。
- Shell 不能直接调用
I/O 重定向 (ex6.c)
- Shell 如何实现
echo hello > out? - 子进程在调用
exec()之前,先close(1)关闭标准输出,然后open("out", ...)。因为open会返回最小的可用 FD,所以新的文件会获得 FD1。 exec会保留文件描述符,所以echo的标准输出就自然地被重定向到了文件out。
- Shell 如何实现
管道 (Pipes) (ex7.c, ex8.c)
- Shell 如何实现
ls | grep x? pipe()系统调用创建一对相连的文件描述符。- 写入其中一个 FD 的数据可以从另一个 FD 读出。
- Shell 创建一个管道,然后
fork()两次,设置好子进程的输入输出,再分别exec()对应的命令。
- Shell 如何实现