北交 操作系统 课程笔记(一)

北交 操作系统 课程笔记(一)

根据王垠的博文,关于微内核的对话,可将 Linux 看作 C 语言的运行时系统。也有很多对这个观点的批评,让人分不清对错。让我们借着课程再思考一次吧!

概念

地位和目标

  • 计算机系统
    • 软件
      • 应用软件
      • 系统软件
        • 光盘刻录工具、汇编程序、编译器、数据库
        • 操作系统
    • 裸机(硬件和固件)

所谓系统软件,大概是指直接接触硬件的软件。光盘刻录工具需要接触光驱,汇编器、编译器需要和 CPU 接触,数据库和硬盘接触(据说 MySQL 团队希望绕过文件系统操作硬盘)。而应用软件可以利用操作系统提供的硬件交互功能。

  • 方便

    用户接口

  • 有效

    提高系统资源利用率

  • 可扩充

    适应计算机体系结构的发展

  • 开放

    兼容不同厂家的设备

作用

  • 用户与硬件系统之间的接口
    • 命令方式,通过 Shell
    • 系统调用,通过内核
  • 系统资源管理
    • 管理对象
      • 处理器
      • 存储器
      • 外设
    • 管理内容
      • 分配
      • 回收
      • 访问控制
      • 策略
  • 虚拟机

操作系统的作用有很多,但对用户来说只有计算和存储(不考虑网络)。Windows 让系统暴露给用户的部分基本完善,但暴露给开发者的部分仍然有待改进。

有一种观点认为,开发者就应该了解计算机系统的方方面面。这在计算机系统日益复杂,计算机行业分工逐渐细化的今天是不现实的。强迫前端开发人员了解后端内容,业务逻辑设计人员了解编程语言的解释器。把开发者想象成系统的一个模块,放在程序中都是接口设计的失败,放在人身上怎么就理所当然了呢?

计算机系统的组成及层次模型

  • 外壳
  • 系统调用
  • 核心
  • 硬件接口
  • 硬件

外壳是程序员使用的系统界面,设计初心是用简单的命令实现复杂的功能,但复杂程序难以用 shell 脚本表达。这推动 shell 脚本添加越来越多的特性,现在已经类似 C 的子集。添加特性背离了简单命令复杂功能的初心,让 shell 的学习成本越来越高。

我认为部分 Linux 发行版预装 python 就是个很好的想法。Python 作为一个成熟的高级语言,以语法简洁著称。用 python 代替 shell,功能上没有损失,也减轻了学习负担。

实例

操作系统是最基本的系统软件,是一组管理和控制计算机硬件和软件资源、对各类作业进行调度以组织和控制系统工作流程,并方便用户使用计算机的程序的集合。

  • 最基本的系统软件
  • 控制、调度系统
  • 方便用户使用计算机
  • MS DOS
  • Windows
  • Unix
  • Linux
  • Android

硬件基础

计算机系统的组成和体系结构

组成

处理器配合内存,通过总线指挥其他所有设备。如,网卡、硬盘。

内存系统由主存和高速缓存组成。主存是一个按字节编址的线性地址空间,搭配高速缓存(局部性原理),为大部分设备提供工作记忆。

体系结构

体系结构是指计算机系统的指令集,是系统识别的一套指令,且是唯一的一套。编译器要将高级语言翻译为机器指令。

指令集
  • 寄存器架构
  • 内存架构
  • 用户指令

权限与陷入

权限

C 语言可以利用指针直接修改内存,有可能利用这个特性修改内核,破坏设备。限制程序可以操作的内存可以组织恶意程序修改内核,但是内核自身仍需要指针操作,所以给不同的程序不同的特权级别。

陷入

也叫软中断,是程序失败时内核介入处理。和中断的相同点是都转而执行内核代码,不同点是陷入是程序内部时间触发的,中断是外部事件触发的,如 IO 操作。

硬件基础

体系结构是操作系统面对的硬件基础。体系结构中,

  • 寄存器架构

  • 内存管理模式

  • 中断与异常

    • 中断向量
    • 中断描述符表
    • 中断源
    • 异常源
  • 任务管理

  • 基本输入输出系统 BIOS

  • ……

用户接口与系统调用

用户接口

  • 表现形式
    • 交互
      • 联机命令
      • 脱机命令
    • 程序
      • 系统调用
  • 使用者
    • 本地
    • 网络

我认为,python 在一定程度上统一了用户接口的表现形式,python 代码既有联机命令的简洁,又能作为脱机命令,还能进行系统调用。像jupyter这样的项目,也在一定程度上统一了本地与远程,对使用者来说只有 local host 和“非 local host ”的区别。

所以,现在看来仍有意义的是键盘终端处理程序的概念。其功能,

  • 接收用户从终端输入的字符
  • 管理字符缓冲
  • 字符屏幕显示
  • 屏幕编辑
  • 特殊字符处理

系统调用

系统调用与普通过程调用的区别
  • 运行在不同的系统状态

    • 软中断进入

    • 返回重新调度

我认为软中断与重调度在一定程度上从属于切换系统状态。

区别原因
运行在不同的系统状态为保护内核安全
软中断进入切换系统状态
返回重新调度优化 IO 相关操作

按我目前的理解,系统调用本应该仅仅是涉及操作系统服务的普通函数调用。将系统调用区别于普通过程调用的根本原因是保护内核的需求,而需要保护内核的原因是 C 语言指针操作内在的安全隐患。

软中断进入和返回重调度都不是需要特殊化系统调用的理由:

  • 软中断和普通调用对用户来说区别不大
  • 返回重调度难道不能作为操作系统的特性赋予涉及 IO 的“系统函数”吗?

综上,我认为特殊化系统调用是 C 语言的设计缺陷导致的。或者换句话说,操作系统根本不应该允许用户使用 C 语言这样的系统语言开发应用程序,而应该一律使用类似 JVM 的面向开发者的接口。

类型
  • 进程控制
    • 创建
    • 结束
    • 等待子进程结束
    • 进程信息设置与获取
    • 执行文件
  • 文件操纵
  • 进程通信
  • 系统信息维护
    • 时间设置与获取
    • 文件访问、权限设置

放在硬盘中的代码叫作业,作业加载到内存中成为进程。从机器的角度看,进程是一个操作序列;从人的角度看,进程是一组有顺序的函数调用。

进程通信的概念是怎么来的?站在某个函数的角度讲,本身所在进程的函数和其他进程的函数有什么区别?同进程的函数间有共享的内存。函数间需要共享内存的原因很多,主要还是为了节省内存空间。

为什么不把所有的内存都共享?因为我们希望给每个作业独占系统资源的错觉。既然希望独占,那为什么又要进程通信?我觉的其中原因是比较复杂的,试分析如下:

  • 别人编写的软件不是以函数库的形式,而是以机器代码的形式(可执行文件)出现在你的电脑里。这种情况下,你无法以函数传参的方式利用该软件的某项功能,因为可执行文件已经讲所有编程阶段可见的接口掩盖了。

    为了体会其间差别,你可以想象一下,如果所有的 python 库不是以函数库,而是以一组可执行文件的方式出现,那么利用这些第三方软件的唯一方式就是进程通信了。

  • 在目前的系统中,系统调用只能通过进程通信。由于系统允许直接执行第三方的机器码,理论上这些第三方代码与操作系统对计算机有同等的控制力。为防止恶意代码破坏系统,操作系统要让应用程序运行在一个较低的权限下,不能直接访问系统资源。这种情况下,应用程序也不能通过调用操作系统的函数实现系统调用,因为应用程序所在进程的权限根本无法执行操作系统的函数。

    这时只能通过(除直接函数调用之外的)某种方式将“参数”传给已经在运行的操作系统了,也就是进程通信。

实现
  • 设置系统调用号和参数
  • 用户态转为系统态
  • 进程切换(保护现场,中断/陷入向量表)

启动模块与自装入

引导

系统加电后,基本输入输出系统 BIOS 会执行磁盘特定位置的机器码。在这个位置放上引导程序,把整个操作系统从硬盘加载到内存中。引导程序必须长512字节,准确占据一个磁盘扇区,最后两个字节为55AA。这个磁盘中特殊的位置就是启动盘引导扇区(0:0:1)。

发展

单道批处理

一批作业在监督程序的控制下顺序执行,内存中始终只有一道作业。

  • 自动
  • 顺序
  • 单道

多道批处理

特点
  • 多道。内存驻留多道程序,允许并发
  • 无序。先开始不一定先结束
  • 调度
需求
  • 处理器分配与回收
  • 内存分配、回收、保护
  • IO 设备共享
  • 文件管理

这个阶段的内存管理问题应该还是相对简单的,因为没有进程通信的需求,只要禁止程序访问别人的内存空间就可以了。

功能及特征

处理器管理

  • 作业调度
  • 进程调度
    • 就绪进程队列
    • 处理机分配
    • 运行现场
  • 调度算法
    • 先来先服务
    • 优先级
进程控制
  • 主要任务
    • 创建
    • 撤销
    • 状态转换(开始、暂停)
  • 机制
    • 原语,类似数据库中的事务
    • 进程、线程
进程同步
  • 主要任务
    • 并发协调
    • 临界资源
  • 机制
    • 信号量
进程通信
  • 共享存储器
  • 管道
  • 消息传递
    • 消息缓冲队列
    • 邮箱

内存管理

主要任务
  • 提高内存利用率
  • 进程互不干扰,保护内核安全
  • 逻辑地址转换为物理地址
  • 逻辑上扩充内存容量
机制
  • 内存管理数据结构

    • 连续/离散
    • 静态/动态
  • 回收

  • 越界检查

    • 上下界寄存器
    • 定长页、段
    • 特权分级
  • 页表

  • 虚拟内存

操作系统的内存管理和 JVM 的内存管理有何不同?最明显的不同是操作系统以页或段为单位管理内存,要时刻提防越界行为。而 Java 程序只能通过引用访问内存中的对象,以对象(数据结构)为单位管理内存。

设备管理

任务
  • 设备分配
  • 缓冲管理
  • 设备通信
机制
  • 虚拟设备
  • 单/双/多缓冲
  • 字符缓冲
  • 公用缓冲池
  • IO 指令(合法性检查)
  • 中断

文件管理

任务
  • 外存管理(分配、回收)
    • 防止未经核准的用户存取文件
    • 防止冒名顶替存取文件
    • 防止以不正确的方式使用文件
  • 文件按名存取
  • 快速查找
  • 共享与保护
机制
  • 文件控制块
  • 索引结点
  • 目录结构

特征

  • 并发

    为了充分利用计算资源。

  • 共享

    和数据库类似。

  • 虚拟

    JVM 广受欢迎,虚拟机应用越来越多,说明虚拟是一项重要特征。

  • 异步

    进程执行顺序与执行时间不确定,和 Internet “尽力而为”的服务有点像。

结构设计

设计原则

  • 可维护性
  • 可靠性
  • 可理解性
  • 可用性
  • 性能

模块化

分层原则
分层
用户接口
策略
……
时钟管理、进程调度
资源管理公用模块。如队列、堆栈、信号量操作等

这一课学完,我对王垠的观点更加赞同了。大量的复杂性是允许计算机直接运行第三方机器码带来的,比如

  • 第三方机器码可能直接修改内核,所以需要保护,需要区分内核空间和用户空间,需要区分系统调用和普通函数调用。
  • 第三方机器码可能滥用系统资源,产生内存泄漏、文件句柄泄漏。所以第三方代码的内存(以及文件)操作需要操作系统的监督。
  • 第三方机器码可能设计各种各样的接口,所以需要输入输出重定向,带来很多字符流解析错误(这甚至引起安全漏洞,参见模拟 SQL 注入攻击)。

而这些问题都可以通过增加一层抽象,即虚拟机(如 JVM),来一举消灭。鉴于 chez scheme 拥有接近于 C 的速度,我认为这并不是天方夜谭。

  • 1
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值