1.操作系统的作用

  • 操作系统(OS)的核心作用是管理计算机的硬件和软件资源,提高计算机系统的效率,并为用户和应用程序提供一个方便、高效、安全的运行环境。

  • 核心功能(五大管理 + 一个接口)

    • 进程管理

    • 内存管理

    • 文件管理

    • 设备管理

    • 网络与通信

    • 用户接口

  • 管理硬件资源 这是最底层的作用。操作系统负责协调CPU、内存、硬盘、显卡等硬件,决定谁在什么时候使用哪项资源。例如:

    • CPU管理:让多个程序轮流使用CPU,看起来像同时在运行。

    • 内存管理:为每个程序分配独立的内存空间,互不干扰。

    • 设备管理:通过驱动程序,让键盘、打印机等硬件按统一的方式工作。

  • 提供用户接口 操作系统是用户与计算机硬件之间的“翻译”和中介,让你不用直接操作复杂的二进制代码。接口主要有两种:

    • 图形界面:通过窗口、图标、鼠标点击操作(如Windows、macOS、Android)。

    • 命令行:通过输入文字指令来操作(如Linux的终端)。

  • 作为应用程序的运行平台 操作系统为软件(如浏览器、Word、游戏)提供运行的基础环境。它定义了一套标准,让开发者不用关心底层硬件差异——只要软件遵循操作系统的规范,就能在该系统的任意电脑上运行。

  • 管理文件和数据 操作系统把硬盘上的数据组织成我们熟悉的文件和文件夹,并提供创建、复制、删除等操作功能。它负责将“D:\照片\旅行.jpg”这样的地址,翻译成硬盘上具体的物理位置。

  • 提供安全与保护 操作系统会隔离不同程序,阻止一个程序随意访问或破坏其他程序的数据。同时,它通过用户账户、密码权限等手段,防止未经授权的操作(比如普通用户不能删除系统文件)。

  • 一个简单的类比,把计算机比作一个大工厂:

    • 硬件(CPU、内存等)= 工人、机器、仓库

    • 应用程序(微信、游戏)= 需要生产任务的下单客户

    • 操作系统 = 工厂管理层

      • 它决定哪个客户的任务先做(进程调度)

      • 分配机器和工人(资源分配)

      • 防止不同客户的任务互相干扰(隔离保护)

      • 提供统一接单标准(系统调用接口)

      • 管理仓库里的原料和成品(文件管理)

2.进程管理(任务管理)

进程管理 = 创建/撤销进程 + 状态控制 + CPU调度 + 互斥同步 + 死锁处理 + 通信管理 —— 核心目标是让多个任务看似“同时运行”,且不互相干扰。

2.1进程的概念

  • 在操作系统中,进程管理是其最核心的功能之一。简单说,进程就是“正在运行的程序”。进程管理负责控制这些执行中的任务,确保它们公平、高效、安全地共享CPU等资源。

  • 进程由程序块、进程控制块(PCB)、和数据块三部分组成

  • 进程和程序的区别:

    • 进程是程序的一次执行过程,没有程序就没有进程

    • 程序是完成某个特定功能的一系列程序语句的集合,只要不被破坏,它就永远存在

    • 程序是一个静态的概念,而进程是一个动态的概念,它由创建而产生,完成任务后因撤销而消亡;进程是系统进行资源分配和调度的独立单位,而程序不是。

2.2进程的状态与转换

  • 典型的三态模型(基础):

    • 就绪态(Ready):具有运行条件,等待CPU分配。

    • 运行态(Running):占用CPU并执行指令。

    • 阻塞态(Blocked):又称等待态或睡眠态,正在等待某个事件的完成,不具备运行条件

  • 状态转换:

    • 就绪 → 运行:被调度器选中

    • 运行 → 就绪:时间片用完 或 被更高优先级抢占

    • 运行 → 阻塞:请求I/O或等待事件

    • 阻塞 → 就绪:等待的事件完成

  • 五态模型:

    • 活跃就绪、活跃阻塞、静止就绪、静止阻塞、运行

    • 挂起:将进程调出内存,保存到外存队列中,并释放资源

    • 激活:恢复挂起进程,重新调入内存

    • 目的:释放进程占用的资源以缓解资源不足

    • 原因:终端用户的请求,父进程的请求、OS的需要

2.3进程控制块(PCB)

操作系统为每个进程维护一个数据结构 PCB,它包含了进程的全部信息。PCB是进程存在的唯一标志。

PCB的主要内容:

  • 进程标识符:PID,唯一编号

  • 程序计数器:下一条指令的地址

  • CPU寄存器:上下文保存现场

  • 内存管理信息:基址、限长、页表等

  • 资源清单:打开的文件、使用的设备

  • 进程状态:就绪/运行/阻塞

  • 调度信息:优先级、时间片

2.4进程调度(CPU调度)

  • 任务调度要解决的问题:

    • When:何时分配CPU

      • 任务调度的时机,5种情形

    • How:如何分配CPU

      • 任务调度方式,不可抢占,可抢占

    • What:按什么原则分配

      • 任务调度算法

      • 调度算法的性能指标

  • 调度用来确定多任务环境下任务执行的顺序和获得CPU资源后能够执行的时间长度

  • 操作系统通过一个调度程序来实现调度功能

    • 调度程序以函数的形式存在,用来实现操作系统的调度算法

    • 调度程序本身并不是一个任务,是一个函数调用,可在内核的各个部分进行调用

  • 调度程序:可以看做CPU的资源管理者。

    • 从就绪队列中选择一个任务去运行

    • 调度算法:调度程序在决策过程中所采用的算法,是在一个特定时刻用来确定将要运行的任务的一组规则

  • 任务调度的5种情况:

    • 当一个新的任务被创建时,需要做出一个调度决策,是立即执行这个新任务还是继续执行父任务

    • 当一个任务运行结束时,它不再占用CPU,这时调度器必须做出一个决策,从就绪队列中选择某个任务去运行

    • 当一个任务由于I/O操作、信号量或其他原因被阻塞时,也必须另选一个任务运行

    • 当一个I/O操作已经完成,而等待该I/O操作的任务将从阻塞状态变为就绪状态

    • 当一个时钟中断发生时,会唤醒一些延时任务或者可能会发现当前任务的时间片已经用完,从而把它变为就绪状态

  • 调度的方式:

    • 不可抢占式调度:当前进程一直运行,直到主动阻塞、主动让出(yield)或终止,系统才调度下一个进程。

    • 可抢占式调度:系统可以强制打断正在运行的进程,将 CPU 分配给其他进程。常见触发:时间片用完、高优先级任务就绪。

  • 调度算法的性能指标:

    • CPU的使用率

    • 响应时间:调度器为一个就绪任务进行上下文切换时所需的时间,以及任务在就绪队列中的等待时间

    • 周转时间:一个任务从提交到完成所经历的时间

    • 调度开销:调度器在做出调度决策时所需要的时间和空间开销

    • 公平性::大致相当的两个任务所得到的CPU时间应该大致相同。要防止饥饿,即一个任务始终得不到处理器去运行

    • 均衡性:尽可能使整个系统的各个部分(CPU、I/O)都忙起来,提高系统资源的使用效率

    • 吞吐量:单位时间内完成的任务数量

  • 常见调度算法:

    算法 思路 特点
    先来先服务 按到达顺序 公平,但短任务可能等很久(护航效应)
    最短作业优先 预期运行时间最短的先执行 平均等待时间最优,但无法预知时间,可能长任务饥饿
    时间片轮转调度 固定时间片,循环执行 响应快,适合分时系统,时间片选择关键
    优先级调度 优先级高的先执行 可能低优先级饥饿(解决:动态老化)
    多级反馈队列 多级队列,不同时间片,动态调整优先级 现代操作系统主流(如Linux CFS的变体)

    2.5进程同步与互斥

    • 互斥:同一时间只允许一个进程使用某个共享资源(临界资源),其他进程必须等待。(间接制约)

    • 同步:多个进程按预期的顺序执行,一个进程在某个点上必须等待另一个进程完成特定操作后才能继续。(直接制约)

    • 多个进程并发访问共享资源时可能出现混乱。

      • 临界资源:一次只允许一个进程使用的资源(如打印机、共享变量)。

      • 临界区:访问临界资源的代码段。

    • 信号量:信号量是一个非负整数变量 S,除初始化外,只能通过 P 和 V 操作访问。

      • P操作(荷兰语 Proberen,意为“尝试”):相当于 wait(S) → 申请资源

      • V操作(荷兰语 Verhogen,意为“增加”):相当于 signal(S) → 释放资源。

      • PV操作是操作系统利用信号量实现进程同步与互斥的一对原子操作

    • 经典同步问题:

      • 生产者-消费者(有界缓冲):有限缓冲区,生产者放数据,消费者取数据

      • 读者-写者:读者可同时读,写者独占。

      • 哲学家就餐:5个哲学家,两根筷子才能吃饭。。

    2.6死锁(Deadlock)

    • 两个或多个进程互相等待对方释放资源,导致永远阻塞。

    • 四个必要条件(缺一不可):

      • 互斥:资源不能被共享

      • 持有并等待:进程保持一个资源同时等待另一个

      • 不可剥夺:资源不能被强制抢走

      • 循环等待:形成环形等待链

    • 处理方法:

      • 预防:破坏四个条件之一(如资源一次性分配、可剥夺、按序申请)

      • 避免:银行家算法(安全性检查)、有序资源分配法

      • 检测与恢复:检测循环等待,杀死进程或回滚

      • 鸵鸟策略:忽略(很多系统如Windows、Linux默认如此)

    • 银行家算法:

      • 银行家算法是由 Dijkstra 提出的死锁避免算法,核心思想是:在每次分配资源前,模拟分配后系统是否仍处于安全状态,只有安全才真正分配。就像银行贷款前会评估客户能否最终偿还一样。

      • 分配资源的原则:

        • 当一个进程对资源的最大需求量不超过系统中的资源数时可以接纳该进程

        • 进程可以分期请求资源,但请求的总数不能超过最大需求量

        • 当系统现有的资源不能满足进程尚需资源数时,对进程的请求可以推迟分配,但总能使进程在有限的时间里得到资源

    2.7进程通信(IPC)

    • 任务间通信:任务之间为了协调工作,需要相互交换数据和控制信息

    • 任务之间的通信可以分为两种类型:

      • 低级通信:只能传递状态和整数值等控制信息,例如信号量机制、异步信号机制

      • 高级通信:能够传输任意数量的数据,主要有三类:共享内存、消息队列和管道

    方式 特点 典型例子
    管道 单向字节流,父子进程间常用 | 命令,匿名管道
    消息队列 消息块传递,支持多对多 POSIX消息队列
    共享内存 直接映射同一块物理内存 最快,但需同步(配合信号量)
    信号 异步通知事件 kill -9,SIGINT
    Socket 网络通信,也可本地跨机器 TCP/UDP,Unix域套接字

    2.7.1共享内存(Shared Memory)

    • 原理:将同一块物理内存映射到多个进程的虚拟地址空间,进程直接读写该内存区域,无需内核参与数据拷贝,是最快的 IPC。

    • 同步要求:必须配合信号量或互斥锁使用,否则会出现竞态条件。

    • 优点:速度极快(接近内存访问)。

    • 缺点:无内置同步机制;管理复杂(需要自己处理过期、大小变更等)。

    2.7.2消息队列(Message Queue)

    • 原理:内核中维护一个消息链表,每个消息带有类型和长度,进程可按类型读取。

    • 特点:

      • 有消息边界:

        • 每条消息独立收发,不像管道是字节流(发送 100 字节就要读 100 字节才能对齐)。

      • 支持多优先级:

        • 消息带有类型(整数),接收方可指定只读某类消息,以此实现优先级处理。

      • 异步通信:

        • 发送方发送后无需等待接收方;消息暂存在队列中,接收方可以在之后读取。

      • 内核持久:

        • 消息队列由内核管理,即使所有进程关闭,队列中的消息依然存在(除非显式删除)。

      • 双向通道:

        • 一个队列允许多个发送方和多个接收方,但通常配合多个队列实现双向。

    • 缺点:每个消息大小有限(如 8KB);仍有系统调用和拷贝开销。

    2.7.3管道(Pipe)

    • 原理:是 Unix/Linux 中最古老、最简单的进程间通信(IPC)方式,它提供单向、字节流的数据传输。管道分为匿名管道和命名管道(FIFO) 两种。

    • 匿名管道:

      • 特点:

        • 半双工:数据只能单向流动(一方写,一方读)。如需双向通信,需创建两个管道。

        • 亲缘关系:只能用于父子进程或兄弟进程(具有共同祖先的进程)。

        • 字节流:没有消息边界,读写类似于普通文件(read/write)。

        • 随进程消亡:当所有引用它的文件描述符关闭后,管道自动被内核销毁。

        • 阻塞/非阻塞:默认阻塞(读空管道会阻塞,写满管道会阻塞);可通过 fcntl 设为非阻塞。

    • 命名管道(FIFO):

      特性 匿名管道 命名管道 (FIFO)
      文件系统可见 是(有路径)
      适用范围 亲缘进程 任意进程
      生命周期 随最后一个引用关闭而销毁 文件存在,需手动删除
      打开阻塞 不适用(已打开) 是(默认阻塞直到两端都打开)
      创建方式 pipe() mkfifo() + open()
      通信方向 单向 单向
      消息边界 无(字节流)
      • 特点:

        • 有路径名:存在于文件系统中(使用 mkfifo 创建),不相关的进程可以通过文件路径打开同一个 FIFO。

        • 单向通信:仍然只能单向,但可以通过打开两个 FIFO 实现双向。

        • 持久性:FIFO 文件本身长期存在(直到被 unlink 删除),但数据不持久(内核缓冲区与匿名管道类似)。

        • 打开规则:以只读方式打开会阻塞,直到另一个进程以只写方式打开(反之亦然);可指定 O_NONBLOCK 避免阻塞。

    2.7.4信号量(Semaphore)

    • 说明:信号量是 同步机制(更准确说是进程/线程间同步与互斥的工具),用于控制对共享资源的访问或保证事件执行的顺序。它是一个非负整数,支持两个原子操作:P(wait)和 V(signal)。

    • 特点:

      • 同步/互斥:用于解决并发访问共享资源时的竞态条件,或实现生产者-消费者等顺序控制。

      • 可计数:可以表示可用资源数量(如 5 台打印机)。

      • 可阻塞:当 P 操作时若信号量为 0,进程会进入阻塞等待,直到被 V 唤醒。

      • 进程/线程均可使用:可以用于同一进程内的线程,也可以用于不同进程(需共享内存或命名信号量)。

    • 典型使用:

      • 互斥:二进制信号量(初值 1)保护临界区。

      • 同步:计数信号量(初值 0)实现前驱关系(如生产者-消费者中的 fullempty)。

    • API:POSIX sem_open / sem_wait / sem_post

    2.7.5信号(Signal)

    • 原理:软件中断,用于通知进程发生了某个事件(如用户按 Ctrl+C、非法内存访问)。信号可以携带很少的信息(通常只传递信号编号,少数信号可附带一个整数或指针)。

    • 特点:

      • 异步:信号可以在任何时候发送给进程,进程无需主动等待。

      • 轻量:只携带信号编号(少数实时信号可附带一个整数值或指针)。

      • 不可靠:传统信号可能丢失(多个相同信号只保留一个);实时信号支持排队。

      • 处理方式:进程可以忽略、捕获(执行自定义函数)或默认(终止、暂停等)。

    • 常用信号:SIGINTSIGTERMSIGKILLSIGSEGV 等。

      信号 编号 默认动作 常见触发场景
      SIGINT 2 终止进程 Ctrl+C
      SIGTERM 15 终止进程 kill <pid>
      SIGKILL 9 强制终止 kill -9(不能被捕获/忽略)
      SIGSEGV 11 产生 core 文件 段错误(非法内存访问)
      SIGCHLD 17 忽略 子进程状态改变(父进程常捕获它来回收子进程)
      • 典型使用

        • 用户按 Ctrl+C 终止前台进程。

        • 父进程通过 kill(pid, SIGTERM) 请求子进程退出。

        • 定时器到期发送 SIGALRM

      3.存储管理(内存管理)

      3.1存储管理概述

      • 说明:存储管理(通常称内存管理)是操作系统最核心的功能之一,负责内存的分配、回收、地址转换和保护,确保多道程序能高效、安全地共享有限的内存资源。

      • 存储管理的目标:

        • 内存分配与回收:记录内存的空闲/已用情况,为进程分配所需空间,进程结束时回收。

        • 地址转换:将程序使用的逻辑地址(虚拟地址)转换为物理内存的物理地址。

        • 内存保护:防止一个进程越界访问其他进程或 OS 的内存区域。

        • 内存共享:允许多个进程共享同一段内存(如共享库、进程间通信)。

        • 内存扩充(虚拟内存):利用辅存(如磁盘)模拟出比实际物理内存更大的地址空间。

      • 内存管理关键技术对比表

        技术 地址空间 分配单位 碎片 共享/保护 虚拟化支持
        固定分区 连续 整个分区 内碎片
        动态分区 连续 进程所需大小 外碎片
        分页 非连续 固定页框 内碎片 较易 是(请求分页)
        分段 非连续 可变段 外碎片 容易 是(请求分段)
        段页式 非连续 内碎片 容易

        3.2连续分配方式

        • 早期系统采用,进程被分配连续的物理内存块。

        3.2.1单一连续分配(Single Contiguous Allocation)

        • 是最简单的内存管理方式。在这种方案下,整个内存空间被划分为系统区和用户区两部分:系统区存放操作系统内核,用户区则全部分配给当前运行的唯一作业。、

        • 核心特点:

          • 内存中只能有一个用户程序运行

          • 用户程序独占整个用户区,不存在内存竞争

          • 实现简单,无需复杂的分配算法

          • CPU利用率低,内存浪费严重

        • 内存分为OS区和用户区,任何时候只有一道程序在用户区。

        • 简单,但利用率低,不适合多道程序。

        • 这种方案适用于早期的单道批处理系统。当作业大小 小于用户区时,剩余空间无法被其他作业使用,造成内部碎片;当作业大于用户区时,则无法装入运行。

        3.2.2固定分区分配(Fixed Partition Allocation)

        • 固定分区分配(Fixed Partition Allocation)是为了支持多道程序设计而提出的改进方案。操作系统在系统初始化时将内存划分为若干个大小固定(可相等或不等)的分区,每个分区可以装入一个作业。

        • 内存划分为若干固定大小的分区,每个分区可装入一道作业。

          • 等大小分区:所有分区大小相同,管理简单但灵活性差

          • 不等大小分区:根据常见作业大小划分,减少内部碎片

        • 当作业申请内存时,系统选择一个能容纳该作业的最小空闲分区进行分配。这种方案支持多道程序并发执行,提高了CPU和内存的利用率,但仍然存在内部碎片问题——即作业大小小于分区大小时,分区内的剩余空间被浪费。

        3.2.3可变分区分配

        • 与固定分区不同,它不会预先划分内存,而是根据进程的实际需求动态分配,既避免了内部碎片,又提高了内存利用率

        • 核心原理:

          • 动态划分:系统初始时内存是一个完整的空闲区。当进程申请内存时,根据进程大小从空闲区中划分出相应大小的分区分配给进程,剩余部分仍作为空闲区保留。

          • 分区回收:进程结束后,其占用的分区被释放。如果释放的分区与相邻的空闲区相邻,则会合并成一个更大的空闲区,以减少外部碎片。

          • 外部碎片:随着分配和回收的进行,内存中会产生许多小的空闲区(碎片)。虽然碎片总量可能很大,但由于不连续,无法满足大作业的内存需求。

        • 分配算法:当多个空闲分区都能满足进程需求时,操作系统需要选择合适的分配策略。以下是四种经典的分配算法:

          • 首次适应算法 (First Fit):

            • 从内存低地址开始查找,选择第一个能满足需求的空闲分区。实现简单,但会在低地址区产生大量碎片。

          • 下次适应算法 (Next Fit):

            • 从上次分配的位置继续查找,循环搜索。使内存分配更均匀,但可能将大分区撕裂。

          • 最佳适应算法 (Best Fit):

            • 选择能满足需求的最小空闲分区,保留大分区给大作业。但会产生大量难以利用的小碎片。

          • 最坏适应算法 (Worst Fit):

            • 选择最大的空闲分区进行分配,使剩余部分仍可能满足其他作业。但大分区会被快速消耗。

        • 外部碎片:分配和回收后产生许多难以利用的小空闲块(可通过紧凑(Compaction) 移动进程合并碎片,但代价高)。

        3.3非连续分配方式

        • 进程可分散在内存的不同位置,提高内存利用率。

        3.3.1分页式存储管理

        • 页式存储(Paging)是现代操作系统最核心的内存管理技术之一。它将进程的虚拟地址空间和物理内存都划分为固定大小的"页",通过页表建立映射关系,实现内存的非连续分配和高效管理。

        • 核心原理

          • 页:逻辑地址空间的基本单位,通常为4KB

          • 框:物理内存中与页大小相同的存储块

          • 表:记录虚拟页到物理页框映射的数据结构

          • 址:虚拟地址经转换得到物理地址

        • 地址结构:在页式存储中,逻辑地址被划分为两部分:页号(Page Number)和页内偏移(Offset)。页号用于在页表中查找对应的物理页框号,而页内偏移则直接拼接到物理地址中,保持不变。

          • 假设页面大小为4KB(2(12)),则页内偏移占12位,剩余高位作为页号。例如32位系统中,页号占20位,可寻址2(20) = 1M个页面。

        • 页式存储的优势

          • 消除外部碎片

            • 物理内存以固定大小的页框分配,不会产生无法利用的小碎片

          • 支持虚拟内存

            • 进程的逻辑地址空间可大于物理内存,通过页面置换实现

          • 简化内存管理

            • 分配和回收都以页为单位,算法简单高效

          • 便于共享和保护

            • 通过页表项的权限位实现内存保护和共享

        3.3.2分段式存储管理

        • 段式存储(Segmentation)是现代操作系统内存管理的核心技术之一。与页式存储按固定大小划分不同,段式存储根据程序的逻辑结构——如代码段、数据段、堆栈段——将内存划分为不同大小的段,每个段拥有独立的逻辑意义和访问权限。

        • 核心原理

          • 段:逻辑地址空间的基本单位

            • 按功能划分:代码、数据、堆栈

          • 表:段表记录映射关系

            • 段号+基址 + 段长 + 权限位

          • 在段式存储中,逻辑地址由两部分组成:段号(Segment Number)和段内偏移(Offset)。CPU通过段号查询段表,获得该段在物理内存中的起始地址(基址),再将段内偏移与基址相加,得到最终的物理地址。

            • 假设一个32位系统中,段号占16位,段内偏移占16位

            • 逻辑地址:0x00020026 对应 段号: 2, 偏移: 38

            • 按照段表,段号2对应的基址为0x3000,该段的最大容量为64字节

            • 对应物理地址:0x30000026

        • 段式存储的优势:

          • 逻辑独立性:每个段对应程序的一个逻辑单位(代码、数据、堆栈),便于模块化管理和保护。

          • 便于共享与保护:通过段表中的权限位,可以对不同段设置不同的访问权限(读、写、执行),实现代码段共享和数据段保护。

          • 动态扩展:堆栈段可以动态增长,数据段可以根据需要扩展,无需预先分配固定大小。

          • 无内部碎片:段的大小按需分配,不会产生页式存储中页面内部的浪费。

        • 段式存储VS页式存储

          特性 页式存储 段式存储
          划分依据 固定大小页面 逻辑功能模块
          大小 固定(如4KB) 可变
          碎片类型 内部碎片 外部碎片
          共享粒度 页面级 段级(更粗)
          逻辑意义 有(代码/数据/堆栈)

          3.3.3段页式存储管理

          • 说明:页与段的结合,内存管理的集大成者。 段页式存储管理(Segmentation-Paging)是现代操作系统内存管理的集大成者。它融合了段式存储的逻辑划分优势和页式存储的物理分配优势,通过两级地址映射实现高效、灵活的内存管理。

          • 核心思想:

            • 先分段,再分页

              • 程序按逻辑功能划分为段(代码段、数据段、堆栈段),每个段内部再按固定大小划分为页。这样既保留了段的逻辑独立性,又获得了页的物理分配灵活性。

            • 两级地址映射

              • 逻辑地址 → 段表 → 页表 → 物理地址。第一级通过段号查段表获得页表基址,第二级通过页号查页表获得物理页框号,最后拼接页内偏移。

          • 地址结构:

            • 逻辑地址被划分为三部分:

              • 段号决定访问哪个段,页号决定段内的哪一页,偏移决定页内的具体位置

            • 段表(每个进程一个):段号+页表长度+页表基址

              • 页表长度:该段所占的页数(即页表项的个数)

              • 页表基址:该段的页表在物理内存中的存放位置

            • 页表(每个段一个):页号+页框号

              • 页框号:该逻辑页所在的物理内存页框编号

          • 示例:

            • 假设系统配置

              • 逻辑地址空间:32位

              • 页面大小:4KB(2^12 = 4096字节)

              • 段号占8位,页号占12位,偏移占12位

            • 访问逻辑地址 0x00401050

              • 步骤1:分解地址0x00401050 = 0000 0000 0100 0000 0001 0000 0101 0000

                • 段号 = 0x00 = 0,页号 = 0x401 = 1025,偏移 = 0x050 = 80

              • 步骤2:查段表(每个进程一个段表)

                • 检查段号是否越界 8位

                • 段0的页表基址 = 0x10000(页表所在物理地址)

                • 段0的页表长度 LEN_A

              • 步骤3:查页表(每个段一个页表)

                • 检查页号是否越界 12位,1025是否小于LEN_A ,是否小于12位

                • 根据步骤2获得的页表基址,从0x10000处获取页表

                • 页表[1025] = 0x5000(假设该页映射到页框0x5000)

              • 步骤4:合成物理地址

                • 页框号0x5000,每个物理框4096个字节,页内偏移0x50

                • 物理地址 = 0x5000 * 4096 +0x50 = 0x5000050

          • 优势对比:段页式存储管理是现代操作系统(如Linux、Windows)广泛采用的内存管理方案。它既保留了段式存储在逻辑组织和权限控制上的优势,又继承了页式存储在物理分配和碎片控制上的优点。虽然地址转换需要两次查表会带来一定开销,但通过TLB(快表)缓存机制可以有效缓解这一问题。

            特性 段式存储 页式存储 段页式存储
            逻辑划分 ✓ 按功能 ✗ 固定大小 ✓ 先按功能分段
            碎片问题 外部碎片 内部碎片 内部碎片(可控)
            共享保护 ✓ 段级权限 ✗ 无逻辑边界 ✓ 段级权限+页级隔离
            地址转换 一次查表 一次查表 两次查表(有TLB加速)
            内存利用 中等

            3.4虚拟存储(Virtual Memory)

            • 说明:虚拟存储(Virtual Memory)是一种将辅存(如磁盘) 当作内存扩展的技术,它让每个进程认为自己拥有一个连续、完整的地址空间(通常远大于实际物理内存),而实际只将部分内容装入物理内存,其余保留在磁盘上,按需调入。

            • 核心思想:

              • 逻辑地址空间与物理地址空间分离:用户程序使用虚拟地址(也称逻辑地址),由操作系统和硬件(MMU)将其转换为物理地址。

              • 部分装入:一个进程不需要全部装入内存即可运行,只需装入当前必须的代码和数据(如正在执行的指令、即将访问的数据)。

              • 按需调页/调段:当程序访问的页(或段)不在内存中时,产生缺页中断,操作系统从磁盘将该页读入内存。

              • 透明性:对用户程序完全透明,仿佛拥有整个地址空间。

            • 虚拟存储的目的:

              • 内存扩充:允许运行比物理内存大的程序(例如在 4GB 内存的电脑上运行需要 10GB 内存的数据库)。

              • 提高内存利用率:只加载程序的实际工作集,节约物理内存。

              • 多道程序并发度提升:更多进程可同时驻留在内存中(虽然每进程只占部分页面)。

              • 简化编程:程序员无需担心内存大小限制,编译器生成逻辑地址即可。

            • 虚拟存储的实现方式

              • 请求分页(Demand Paging)—— 最常用

                • 结合分页技术,虚拟地址空间被划分为固定大小的页,物理内存划分为同样的页框。

                • 页表增加标志位:

                  • 有效位(存在位):该页是否在物理内存中。

                  • 修改位:该页是否被写过(决定换出时是否写回磁盘)。

                  • 访问位:用于页面置换算法。

                  • 保护位:读/写/执行权限。

                • 缺页处理:

                  • 检查页表:若有效位=0,产生缺页中断。

                  • 操作系统找到一个空闲页框(若无,则运行页面置换算法换出某页)。

                  • 从磁盘读取缺失的页到页框。

                  • 更新页表,有效位=1。

                  • 重新执行导致缺页的指令。

              • 请求分段(Demand Segmentation)

              • 请求段页式

            • 页面置换算法:当内存无空闲页框且需调入新页时,必须选择换出某个页面。

              • OPT 最佳置换算法(预知未来)

                • 置换未来最长时间不会被访问的页面。这是理论最优解,但实际无法实现——因为无法预知未来访问序列。主要用于评估其他算法的性能上限。

              • FIFO 先进先出置换算法

                • 按页面进入内存的先后顺序淘汰最早进入的页面。实现简单但性能较差,可能出现 Belady 异常——分配的物理页面增加,缺页次数反而上升。

              • LRU 最近最少未使用置换算法(统计过去推算未来)

                • 淘汰最长时间未被访问的页面。基于局部性原理——过去的行为预测未来。性能接近 OPT,但实现开销较大,需要维护访问时间记录。

                • 例如:一共3页,依次访问1-2-3-3-2-1-1-1 这时访问4,淘汰2

              • NRU 最近未使用置换算法(Clock 时钟算法,淘汰最先使用过的)

                • LRU 的近似实现,将页面组织成环形链表。每个页面有访问位,被访问时置 1。缺页时扫描链表,遇到访问位为 0 的页面即淘汰,为 1 则置 0 并继续扫描。

                • 例如:一共3页,依次访问1-2-3-3-2-1-1-1 这时访问4,淘汰1

            • 抖动 Thrashing

              • 当分配给进程的物理页面过少,工作集无法全部驻留内存时,频繁发生缺页中断,系统陷入"调入-置换"的恶性循环,CPU 利用率急剧下降。

            3.5磁盘

            • 磁盘是操作系统中最主要的外部存储设备(属于I/O设备),用于持久保存数据和程序。由于磁盘的读写速度远低于内存(差几个数量级),操作系统必须采用一系列管理技术来提升其效率和可靠性。

            3.5.1磁盘结构

            • 物理组成

              • 盘片:双面涂有磁性材料,通常多个盘片垂直堆叠。

              • 磁头:每面一个,读写数据,悬浮在盘面上方。

              • 磁道:每个盘面上的同心圆。

              • 扇区:磁道上最小的存储单位,通常为512字节或4KB。

              • 柱面:所有盘面上相同半径的磁道构成一个柱面。

              • 转速:如7200 RPM(每分钟转数),影响寻道延迟和旋转延迟。

            • 逻辑结构

              • 操作系统将磁盘抽象为一维的逻辑块数组(从0到N-1),每个块包含若干扇区。逻辑块到物理扇区的映射由磁盘控制器或文件系统完成。

            • 磁盘访问时间

              • 访问磁盘一个块的时间 = 寻道时间 + 旋转延迟 + 传输时间。

              • 寻道时间:磁头移动到目标磁道的时间(通常为几毫秒,占主导)。

              • 旋转延迟:目标扇区旋转到磁头下的时间(平均为转半圈的时间,例如7200 RPM下平均约4.17 ms)。

              • 传输时间:读取扇区数据的时间(很短,通常 < 1 ms)。

              • 因为寻道时间占比最大,操作系统通过磁盘调度算法减少平均寻道时间。

            • 磁盘容量

              • 非格式化容量:

              • 格式化容量:容量=柱面数×磁头数×扇区数/磁道×每扇区字节数

                • 柱面数(Cylinders):所有盘片上相同半径的磁道组成一个柱面。

                • 磁头数(Heads):即盘面数(每个盘面有一个读写磁头)。

                • 扇区数/磁道(Sectors per Track):每个磁道上划分的扇区数量,早期固定(如 17、63),现代磁盘使用区域位记录(ZBR),外圈扇区数多于内圈,因此公式变成近似值。

                • 每扇区字节数:几乎总是 512 字节(旧)或 4096 字节(4K 高级格式)。

            3.5.2磁盘调度算法

            • FCFS 先来先服务

              • 按请求到达顺序服务

              • 公平,但平均寻道时间长,性能差

            • SSTF 最短寻道时间优先

              • 选择离当前磁头最近的请求

              • 性能好,但可能导致饥饿(远处请求长期得不到服务)

            • SCAN 扫描算法

              • 磁头从一端向另一端移动,沿途服务请求,到达末端后折返(像电梯)

              • 避免饥饿,吞吐量稳定。又称电梯算法

            • C-SCAN 循环扫描算法

              • SCAN的改进:只单向服务,到达末端后快速返回起点(不服务返回路径)

              • 各位置等待时间更均匀

            4.文件管理

            • 文件管理是操作系统的重要功能之一,负责文件的存储、组织、访问和保护。它为用户和应用程序提供了一种便捷、统一的方式来管理持久化数据,而无需关心底层磁盘的物理细节。

            4.1文件与文件系统

            • 文件:是具有符号名的、存储在外部存储设备上的相关信息的集合。文件可以包含程序、文档、图片、音频等。

            • 文件系统:是操作系统中负责管理文件及其存储空间的软件模块。它定义了文件如何命名、存储、组织、以及如何访问。

            4.2文件的结构

            • 逻辑结构(用户视角)

              • 流式文件:无结构,视为字节序列。如 .txt, .bin

              • 记录式文件:由一组定长或变长的记录组成(如数据库文件)。常用于批处理系统。

              • 现代操作系统(如 Windows、Linux)主要支持流式文件。

            • 物理结构(文件在磁盘上的组织)

              • 固定结构

                • 文件数据连续存储在磁盘块中

                • 访问速度快,支持顺序/随机访问

                • 产生外部碎片,文件长度难扩展

              • 链接结构

                • 每个磁盘块有指针链接到下一块

                • 无外部碎片,适合顺序访问

                • 随机访问慢,指针占用空间,可靠性低(坏一块则后续丢失)

              • 索引结构

                • 为每个文件建立索引块,指向数据块

                • 支持高效随机访问,无外部碎片

                • 索引块需要额外空间,大文件需多级索引(如Unix的inode)

            4.3目录管理

            • 目录是一个特殊文件,记录文件名及其对应的文件控制信息(如inode号、位置、权限等)。

            • 目录结构层次:

              • 单级目录:所有文件在同一目录,易重名。

              • 两级目录:为每个用户建立独立目录,解决重名。

              • 树形目录(现代系统):允许子目录,支持层次化组织(如/home/user/docs/file.txt)。

              • 无环图目录:允许文件和目录的共享(多个路径指向同一文件),通过硬链接或符号链接实现。

            • 文件路径

              • 绝对路径:从根目录开始(如 /usr/bin/ls)。

              • 相对路径:从当前工作目录开始(如 ./doc/readme.txt)。

            4.4空闲存储空间的管理

            • 磁盘上的空闲块需要被管理,以分配新文件数据。常见方法:

              方法 描述 优点/缺点
              空闲块表 维护一个表记录连续空闲区 简单,但表大小限制
              空闲块链表 每个空闲块存下一块指针 简单,但链式访问效率低
              位示图 每个块对应一个bit,1表示已用,0表示空闲 简单、紧凑,易于找到连续空间(广泛使用,如ext2/3/4)
              成组链接 Unix早期方法,将空闲块分组,每组的第一块存下一组指针 适合大型文件系统
              • 位示图法:

                • 位示图是一块连续的内存区域,其中的每一位(bit)与磁盘上的一个存储块(逻辑块,如块大小 1KB、4KB 等)一一对应。

                • 状态含义:

                  • 0:对应的磁盘块空闲(未分配)。

                  • 1:对应的磁盘块已占用(已分配给文件或元数据)。

                • 位示图通常存放在内存中,以提高查询和更新速度;同时也会定期写回磁盘(或随文件系统元数据持久化),以防系统崩溃后丢失状态。

                • 设磁盘总块数为 N,则位示图需要的空间为 N / 8 字节。

                • 例子:一个 1TB 的磁盘,块大小为 4KB,则总块数为 1TB / 4KB = 2^28 块(约 2.68 亿块)。位示图大小 = 2^28 / 8 = 2^25 字节 = 32 MB。内存开销可接受。

                • 为了便于查找连续空闲块,位示图常按字(如 32 位或 64 位) 组织,可以一次性扫描一个字的 32 个位,提高速度。

                • 位示图法是管理磁盘空闲块的一种经典数据结构,以空间换时间(少内存占用量)的方式,支持快速判断单个块的占用状态,并能有效分配连续块。尽管扫描位图寻找连续空间有一定开销,但其简洁性、低内存开销以及易于与文件系统集成,使其成为主流文件系统(如 ext4、NTFS)的核心空闲空间管理手段。

              5.设备管理

              • 设备管理是操作系统的重要子系统,负责管理计算机系统中所有的输入/输出设备(如键盘、鼠标、显示器、磁盘、打印机等)。它的主要目标是屏蔽硬件差异、提供统一接口、提高I/O效率、保证数据安全。

              • 目标

                • 方便性:为用户和程序提供统一的、与设备无关的接口。

                • 效率:提高I/O速度,减少CPU等待时间,充分利用设备。

                • 可扩展性:增加新设备时无需修改上层应用程序。

              • 主要功能

                • 设备分配与回收:按一定策略将设备分配给进程,用完后回收。

                • 设备驱动:为每种设备实现驱动,负责与设备控制器通信。

                • 缓冲区管理:设立内存缓冲区,缓解CPU与设备速度不匹配问题。

                • 虚拟设备:通过SPOOLing技术将独占设备改造为共享设备。

                • 错误处理:检测I/O错误,尝试重试或报告。

              • SPOOLing技术(假脱机技术)

                • SPOOLing(Simultaneous Peripheral Operations On-Line)将独占设备(如打印机)改造为共享设备,提高设备利用率。

                • 工作原理:

                  • 当进程请求打印时,系统并不真正分配打印机,而是将该作业的输出写入磁盘上的输出井。

                  • 后台有一个守护进程(打印机守护程序) 不断从输出井取出数据,送往打印机。

                  • 对进程而言,它仿佛独占了一台快速打印机(实际是磁盘)。

                • 优点:

                  • 将独占设备虚拟为共享设备,避免进程直接等待物理设备。

                  • 实现了输入/输出与处理重叠。

                  • 典型应用:打印机、卡片阅读机、终端等。

                • 实现组件:

                  • 输入井 / 输出井:磁盘上一块区域存放输入/输出数据。

                  • 输入进程 / 输出进程:负责从输入设备读入井,或从井输出到设备。

                  • 井管理程序:分配井空间,协调读写。

              • 设备分类:

                • 独占设备:一次只能分配给一个进程(如打印机、磁带机)。

                • 共享设备:可同时分配给多个进程(如磁盘,通过I/O请求排队交替服务)。

                • 虚拟设备:通过SPOOLing将独占设备模拟为共享设备。

              • 设备分配策略:

                • 静态分配:进程运行前分配所需设备,运行中一直占用(浪费,但无死锁)。

                • 动态分配:进程运行中按需申请,用后立即释放(效率高,但可能死锁)。

              • 设备管理的核心任务

                • 控制I/O:选择合适的控制方式(中断、DMA),提高CPU效率。

                • 缓冲与虚拟:使用缓冲区和SPOOLing技术,缓解速度差异并共享独占设备。

                • 提供统一接口:实现设备独立性,上层应用无需关心具体硬件。

                • 分配与调度:按策略分配设备,避免死锁,优化性能(如磁盘电梯算法)。

              Logo

              openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构

              更多推荐