Introduction and Examples

目标

  1. 理解操作系统的设计和实现. 设计是指整体的系统结构, 实现是指具体的代码设计
  2. 了解操作系统工作原理, 动手实现OS, 并通过操作系统的接口, 编写系统软件.

操作系统本身的目标

  1. 抽象硬件. 硬件本身是较低层次的资源, 操作系统实现了高层次的接口和抽象, 像进程(Process),文件系统(file System)等, 为其他硬件提供了一个基本的环境, 也提供了更好的移植性.
  2. 其次是使得多个的应用之间能够共享计算机底层的硬件资源. 我们能够在计算机上同时运行多个应用而他们之间不会相互影响, 这叫多路复用 (multiplex).
  3. 在多路复用下我们要保证这些程序不会相互影响, 需要隔离(Isolation).
  4. 但是我们也需要一些有用的影响, 我们需要能够共享(Sharing). 例如像数据交互, 进程通信等.
  5. 用户想要能够自主控制是否共享, 我们需要一个权限系统(Security / Access Control System).
  6. 在确保操作系统自身服务正常运行的情况下, 能为应用提供高性能(Performance), 且OS不能阻碍应用获取高的性能, 甚至需要帮助应用获得高性能.
  7. 一个操作系统需要能够满足不同用户的不同需求, 支持很多不同类型的应用. 可以打游戏, 写文档, 还能运行数据库服务.

操作系统结构

应用 编译器 Shell DB
文件系统 进程管理 内存分配 访问控制
CPU 内存 硬盘 网络接口

底层是计算机硬件. 整个计算机共用这些硬件资源

中间是内核服务, 用来管理控制计算机的资源, 同时管理用户进程, 操作系统的核心.

顶层是用户的应用.

操作系统主要研究系统的内核, 连接内核和应用之间的接口, 内核服务的架构.

Kernel API

类似于程序的函数调用, 是向内核发起系统调用, 使得应用能够访问内核中的服务.

与函数调用不同的是, 系统调用会跳到内核中进行.

内核是在计算机启动时第一个运行的, 且始终在运行着. 内核拥有操作硬件的权限, 执行系统调用就能跳到内核中操作硬件, 而程序中的函数调用做不到这点.

困难与乐趣并存

矛盾点

在设计操作系统时会遇到许多矛盾点.

  1. 我们希望操作系统是高效且易用的.
    • 高效意味着我们需要在设计上更贴近硬件底层一些
    • 易用则需要OS为应用提供可移植的抽象接口.
    • 需要在两者中达成一个平衡.
  2. 而在给其他人在你的OS上开发时, 你希望能够给其他程序员更简单易用的API来调取内核服务.
    • 接口不能太多太复杂.
    • 接口要有强大的功能 (我理解为很实用的, 功能齐全的)
    • 我们需要提供出简单但是又强大的接口
  3. 最后一个矛盾是, 想要OS能给应用更多的灵活性, 同时要保证安全性.
    • 应用不能跳过内核直接访问到硬件影响其他应用, 或是影响操作系统.
高效 抽象
强大 简单
灵活 安全

这是在系统设计上的三个矛盾点.

交互

OS提供了许多特性和大量的服务, 他们之间趋向于交互, 有时候是奇怪的交互…

两个功能, open 和 fork

使用open打开文件, 内核会返回文件的描述符 (fd).

使用fork新建当前进程的副本, 内核会返回新进程的进程号(pid).

但是在一个进程中先open一个文件, 再fork这个进程, 新的进程能否访问到之前的fd呢? Yes

这就是奇怪的交互

其他的点

OS还必须要适应硬件的飞快发展, 以及各种不同的用途