元某人也元某人也

操作系统

操作系统:进程调度、死锁、内存与磁盘管理复习笔记。

本文目录

第一章 引论

操作系统的主要功能

功能内容
处理机管理进程/线程调度、分配 CPU
存储器管理内存分配、虚拟存储、地址映射
设备管理I/O 分配、缓冲、驱动
文件管理文件存取、目录、权限
用户接口命令行、图形界面等(原文「窗口管理」多指用户接口层)

操作系统在计算机系统中处于硬件与用户/应用程序之间,是对硬件资源的抽象与管理者。

操作系统的特征

特征含义
并发两个或多个事件在同一时间间隔内发生(宏观同时、微观交替)
共享资源可供多个并发进程共同使用(互斥共享 / 同时访问)
虚拟把一个物理实体变为多个逻辑对应物(虚拟 CPU、虚拟内存等)
异步进程以不可预知的速度推进,需同步机制协调

操作系统的基本类型

类型特点
批处理多道程序并发,提高资源利用率,少交互
分时时间片轮转,用户可交互,响应及时
实时优先处理紧急事件,强调实时性与可靠性

第二章 进程的描述与控制

进程的概念

  • 定义:程序的一次动态执行过程(程序是静态的)。
  • 组成:PCB(进程控制块)+ 程序段(代码)+ 数据段(运行数据)。

进程的特征

动态性、并发性、独立性、异步性、结构性(由 PCB 描述)。

三级调度

调度作用
高级(作业)调度从外存后备队列选作业进入内存,建立进程,送入就绪队列
中级调度挂起/唤醒:内存紧张时把暂不运行进程换出;宽松时再换入
低级(进程)调度从就绪队列选进程,分配 CPU,进入运行态

三级调度关系

进程状态转换

进程状态转换

转换典型原因
运行 → 就绪时间片用完;被更高优先级进程抢占
运行 → 阻塞等待 I/O、等待资源、等待某事件发生
阻塞 → 就绪等待的事件发生(I/O 完成等)
就绪 → 运行被调度程序选中

进程通信(IPC)

方式说明
共享存储映射同一块内存区域
消息传递消息头 + 消息体,send/receive
管道半双工/全双工字节流(匿名管道、命名管道)

线程

对比进程线程
定位资源分配基本单位调度/执行基本单位
并发进程间可并发进程内线程也可并发
控制块PCBTCB(含线程 ID)
状态就绪、运行、阻塞同样三种基本状态

实现级别

类型说明
用户级线程线程库在用户空间调度,内核无感知
内核级线程内核参与调度;常见 1:1(一用户线程对应一内核线程)

第三章 处理机调度与死锁

调度方式

方式说明
非抢占进程占用 CPU 直到结束或主动放弃
抢占有更重要/更紧迫进程时,剥夺当前 CPU

调度评价指标

指标公式 / 含义
周转时间完成时间 − 到达时间
带权周转时间周转时间 ÷ 服务时间
等待时间周转时间 − 服务时间(或 在就绪队列中等待之和)
响应时间提交到首次响应(分时系统重要)
响应比(等待时间 + 服务时间)÷ 服务时间
CPU 利用率CPU 忙碌时间 ÷ 总时间
系统吞吐量完成作业数 ÷ 总时间

调度算法

1. 先来先服务(FCFS)

按到达顺序,非抢占。实现简单,短作业等待长作业时平均周转时间可能较大。

2. 短作业优先(SJF)

优先服务时间短的进程。

类型规则
非抢占 SJF当前进程运行完,在已到达进程中选服务时间最短
抢占 SJF(SRTN)新进程到达时,若其服务时间更短则抢占

SJF 示例

3. 优先级调度

按优先级高者优先;同优先级可按 FCFS。分抢占 / 非抢占。

4. 高响应比优先(HRRN)

非抢占,每次选择响应比最高的进程。

HRRN 示例

5. 时间片轮转(RR)

就绪队列 FCFS,每进程运行一个时间片,用完排到队尾。

优点缺点
公平、响应快,适合分时时间片难选;不区分紧急程度;上下文切换开销

6. 多级反馈队列(MLFQ)

  • 多级队列,优先级从高到低,时间片从小到大
  • 新进程进入最高级队列,FCFS + RR
  • 时间片用完未结束 → 降到下一级队尾
  • 已在最低级则仍在最低级队尾轮转

死锁

各进程互相等待对方持有的资源,导致都无法推进。

产生必要条件(四者同时成立)

  1. 互斥:资源只能互斥使用
  2. 占有并等待:持有资源的同时等待其他资源
  3. 不可剥夺:资源只能由持有者主动释放
  4. 循环等待:存在进程资源的环形等待链

处理策略

策略思路
预防破坏四条件之一(如按序分配资源)
避免分配前判断是否进入不安全状态(银行家算法)
检测允许发生,定期检测并恢复
解除剥夺资源、回滚、杀死进程等

安全状态 → 一定不会死锁;不安全状态 → 可能死锁。

银行家算法(避免死锁)

矩阵含义
Available可用资源向量
Max各进程最大需求
Allocation已分配
Need还需资源,Need = Max − Allocation

安全序列:若存在一种分配顺序使所有进程都能完成,则当前为安全状态。

银行家算法步骤 1

银行家算法步骤 2

死锁检测(资源分配图)

  • 方框:资源类;圆:进程
  • 资源 → 进程:已分配;进程 → 资源:正在请求
  • 资源耗尽 + 循环等待 是死锁关键特征

死锁检测图


第四章 进程同步

基本概念

概念说明
进程同步多进程按一定次序协作,保证可再现性
进程互斥访问临界资源时排他,同一时刻仅一进程进入临界区
临界资源一次仅允许一个进程使用的资源(打印机、共享变量等)

信号量机制

原语别名含义
wait(S)P申请资源,S--;若 S<0 则阻塞
signal(S)V释放资源,S++;若 S≤0 则唤醒等待者
用途初值用法
互斥S = 1进入临界区 P,离开 V
同步S = 0前驱操作后 V,后继操作前 P

经典问题

生产者—消费者

角色操作语义
生产者P(空缓冲区);生产;V(满缓冲区/产品)
消费者P(产品);消费;V(空缓冲区)

常用信号量:mutex=1(互斥访问缓冲区)、empty=n、full=0。

读者—写者

  • 多个读者可同时读
  • 写者互斥,且读写互斥
  • 用 readcount + mutex 保护计数;写者用 rw_mutex

第五章 存储器管理

目标

解决「程序逻辑地址空间 > 物理内存」:覆盖、交换、分页、分段、段页式。

连续分配

1. 单一连续分配

系统区(低地址)+ 用户区(用户进程)。简单,无碎片,利用率低。

单一连续分配

2. 固定分区

内存划分为固定大小分区,每区一道作业。有内部碎片。

固定分区

3. 动态分区

按进程需要动态划分,有外部碎片,需紧凑。

动态分区

动态分区分配算法

算法策略
首次适应 FF从头找第一个足够大的空闲区
最佳适应 BF选最小且够用的空闲区(易留小碎片)
最坏适应 WF选最大空闲区
邻近适应 NF从上次查找结束位置继续(首次适应的改进)

分页存储管理

逻辑地址 → 页号 + 页内偏移;物理地址 → 块号 + 块内偏移。

1
2
3
页号   = 逻辑地址 / 页面长度(整除)
页内偏移 = 逻辑地址 % 页面长度
物理地址 = 页表[页号].块号 × 页大小 + 页内偏移

分页地址变换

概念说明
页表页号 → 块号映射
TLB快表,加速地址变换
多级页表节省页表连续空间

第六章 虚拟存储器

在分页基础上,只把当前需要的页调入内存,其余在辅存;缺页时页面置换。

页面置换算法

算法规则特点
OPT淘汰未来最久不再访问的页理论最优,无法实现
FIFO淘汰最先进入内存的页简单,可能 Belady 异常
LRU淘汰最近最久未使用的页性能好,实现成本高
Clock环形队列 + 访问位LRU 近似,常用

原文「最近醉酒」为 LRU(Least Recently Used) 之笔误。
OPT 中「置换次数」= 发生缺页且需换出的次数(内存已满后的换页)。

工作集与抖动

  • 抖动(颠簸):频繁缺页,换页时间 > 执行时间
  • 缓解:增加物理块、局部置换、工作集算法

第七章 输入输出系统

磁盘调度(减少寻道时间)

假设当前磁头位置已知,请求队列给定。

算法规则
FCFS按请求到达顺序服务
SSTF每次选距磁头最近的柱面(可能饥饿)
SCAN(电梯)单向扫描到端点再反向;端点内只朝一个方向服务
C-SCAN循环扫描,只朝一个方向处理请求,到端点快速返回起点

磁盘调度 FCFS 示例

原文「按照要地址的顺序」多指 FCFS;「莫个方向」为 某个方向(C-SCAN)。

I/O 控制方式(补充)

方式说明
程序直接控制CPU 轮询
中断驱动I/O 完成中断通知
DMA块设备与内存直接传,少占 CPU
通道专用 I/O 处理器

考点速查

章节必记
特征并发、共享、虚拟、异步
调度FCFS、SJF/SRTN、RR、MLFQ、HRRN
指标周转、带权周转、响应比
死锁四条件;银行家=避免;安全序列
同步P/V;互斥 S=1;同步 S=0
存储FF/BF/WF/NF;页号/偏移公式
置换OPT、FIFO、LRU
磁盘SSTF、SCAN、C-SCAN
  flowchart TB
    subgraph 进程
        A[就绪] -->|调度| B[运行]
        B -->|I/O/等待| C[阻塞]
        C -->|事件完成| A
        B -->|时间片/抢占| A
    end

补充:考点速查

按考点组织,不按教材章节:进程与线程、同步与死锁、内存管理与页面置换。每一节都是能直接拿去答题的粒度。

操作系统的四大功能:进程控制,内存管理,设备管理,文件管理

进程控制涉及到对正在执行的程序实例的管理。操作系统负责创建、运行和终止进程,同时通过调度算法决定哪一个进程可以在何时获得处理器资源。这种管理不仅要保证多个进程能够并发执行,还需要确保它们之间能够有效地进行同步与互斥,以避免因资源冲突而造成的数据不一致性。

内存管理则关注于如何合理分配和回收计算机内存。操作系统需要为每个进程提供独立的地址空间,同时确保不同进程之间的内存隔离,以防止相互干扰。此外,通过引入虚拟内存的概念,操作系统能够扩展可用内存,提高系统的整体性能。

设备管理是操作系统另一个关键功能,它涉及对系统中各种输入输出设备的控制和协调。操作系统通过设备驱动程序为应用程序提供统一的接口,使得不同类型的硬件能够被高效地访问。同时,设备管理还包括对设备的调度与错误处理,以保证设备的高效利用和系统的稳定性。

文件管理是操作系统对数据文件的组织与维护。操作系统管理文件的创建、删除、读写等操作,并通过文件系统提供目录结构,使用户和程序能够方便地查找和访问文件。此外,文件管理还需要考虑数据的安全性和完整性,确保文件在存储和传输过程中的保护。

进程的定义:并发程序的执行,进程的同步与互斥

进程的定义进程可以被视为正在运行的程序的实例,它是操作系统进行资源管理和调度的基本单位。每个进程都有其独立的地址空间、代码、数据以及执行状态。

进程作为资源分配的基本单位,其管理的资源可分为 硬件资源 和 软件资源 两大类

并发程序的执行现代计算机系统通常需要同时处理多个进程,这种特性称为并发执行。并发使得多个进程能够在同一时间段内交替执行,尽管它们可能并不在物理上同时运行。这种机制充分利用了 CPU 的空闲时间,从而提高了系统的整体效率和响应能力,让用户能够流畅地使用多个应用程序。

进程的同步与互斥在多个进程共同访问共享资源时。为了确保这些进程能够安全有效地协作,进程之间必须进行同步。这意味着,某些进程在访问关键资源之前需要等待其他进程完成其操作,以避免数据的不一致性。例如,当两个进程同时尝试写入同一个文件时,若缺乏适当的控制,最终结果可能会出现混乱。因此,操作系统提供了多种同步机制,如信号量和互斥锁,以协调对共享资源的访问。

互斥确保同一时间只有一个进程能够访问特定的共享资源。通过互斥锁等机制,操作系统能够有效地防止多个进程同时修改资源,避免了竞态条件的发生,从而保护了数据的一致性和完整性。

进程的状态:创建,终止,就绪,运行,阻塞,挂起,激活以及相互转换关系

进程的生命周期从它被创建时开始。当系统接收到一个新的程序执行请求时,会为该程序创建一个新的进程,并为其分配必要的资源(如内存空间、文件描述符等)。此时,进程处于就绪态,意味着它已准备好执行,但尚未获得CPU时间片。

随着系统调度器的运行,它会从就绪队列中选择一个进程来执行。被选中的进程会从其就绪态转换为运行态,并开始占用CPU执行其程序代码。这是进程生命周期中最活跃的阶段,也是进程执行实际工作的阶段。

然而,在运行过程中,进程可能会遇到需要等待某个事件发生的情况(如等待I/O操作完成、等待信号量释放等)。此时,进程会主动调用阻塞原语,将自己从运行态转换为阻塞态,并释放CPU资源。在阻塞态下,进程暂停执行并等待所等待的事件发生。

一旦进程所等待的事件发生,操作系统会将其从阻塞态唤醒,并将其状态转换回就绪态。此时,进程再次具备了执行的条件,但需要等待CPU的调度。

随着进程的执行完毕或因为某种原因(如错误、资源不足等)而无法继续执行时,它会进入终止态。在终止态下,进程会释放其占用的所有资源,并从系统中消失。

虽然挂起和激活不是进程生命周期中的基本状态,但它们是进程管理中的重要概念。挂起是指将进程从内存中暂时移出并保存到外存中的过程,这通常是因为内存资源不足、系统需要优化性能或用户/操作系统的特定需求。挂起可以发生在进程的任何状态(除了终止态)下。激活则是挂起状态的逆过程,即将进程从外存中重新调入内存,并恢复其执行。

进程同步问题:生产者消费者模型,信号量机制

在生产者消费者模型中,有两个角色:生产者和消费者。生产者负责生成数据并将其放入缓冲区,而消费者则从缓冲区中取出数据进行处理。由于缓冲区的大小是有限的,因此必须确保生产者在缓冲区已满时等待,而消费者在缓冲区为空时也需要等待。这就引发了对进程同步的需求,以防止出现竞争条件,比如生产者尝试在满的缓冲区插入数据,或消费者尝试从空的缓冲区提取数据。

为了解决这个问题,信号量机制作为一种常用的同步工具被广泛应用。信号量是一种整型变量,用于控制对共享资源的访问。它可以分为两类:计数信号量和二进制信号量。计数信号量用于表示可用资源的数量,而二进制信号量则类似于互斥锁,只允许一个进程访问资源。

在生产者消费者模型中,可以使用两个信号量:一个用于表示缓冲区中可用的产品数量,另一个用于表示缓冲区中的空闲空间数量。当生产者生产一个产品时,它会减少空闲空间的信号量并增加可用产品的信号量;相反,消费者在消费一个产品时会减少可用产品的信号量并增加空闲空间的信号量。这样,通过适当的信号量操作,生产者和消费者能够有效地协调彼此的执行,从而保证缓冲区的正确使用和数据的一致性。

进程的调度与死锁,死锁条件

进程调度是操作系统管理和分配 CPU 资源的重要机制,其目的是决定哪一个进程在何时获得执行权,以实现高效的多任务处理。根据不同的调度策略,操作系统可以采用先来先服务、最短作业优先、轮转时间片等不同方法来优化系统性能和响应时间。有效的进程调度能确保系统资源得到合理利用,同时提升用户体验。

在多进程环境中,调度可能会导致进程之间的竞争,从而引发死锁问题。死锁是指两个或多个进程在执行过程中,因为相互等待对方释放资源而无法继续执行的状态。这通常发生在进程对共享资源的请求与占用之间存在循环依赖的情况下。

死锁发生的条件有四个,称为死锁的必要条件:

  1. 互斥条件:至少有一个资源必须处于非共享模式,即某个资源只能被一个进程占用。如果另一个进程请求该资源,它必须等待。
  2. 占有且等待条件:一个进程已经持有了至少一个资源,并且正在等待获取其他资源。
  3. 不剥夺条件:已经分配给一个进程的资源在此进程完成之前不能被强行剥夺,只有在该进程释放这些资源后,其他进程才能使用。
  4. 循环等待条件:存在一种进程资源的循环链,其中每个进程都在等待下一个进程所持有的资源。

当上述四个条件同时满足时,就可能发生死锁。因此,通过设计合理的调度策略和资源分配机制,操作系统可以尽量避免死锁的产生,比如通过资源分配图、银行家算法等方法进行死锁检测与预防。

如何避免死锁

为了避免死锁,可以采取以下几种策略:

  1. 破坏死锁条件:
    • 互斥条件:尽量减少使用互斥资源,或使用资源共享。
    • 占有且等待:要求进程在请求新资源时,必须首先释放当前持有的资源,或者在开始执行前一次性请求所有需要的资源。
    • 不剥夺条件:允许操作系统强制剥夺资源,即在必要时可以从正在运行的进程中收回资源。
    • 循环等待:对资源进行排序,确保进程按照一定的顺序请求资源,从而避免形成循环。
  2. 资源分配算法:采用如银行家算法等动态分配资源的方法,通过安全性检查,在分配资源之前确保不会导致死锁。
  3. 死锁检测与恢复:周期性地检测系统中是否存在死锁。如果检测到死锁,可以通过杀死某些进程或强制释放资源来恢复系统。
  4. 预防策略:在设计阶段,将死锁考虑在内,设计算法和软件系统以最大限度降低死锁发生的可能性。

通过上述措施,可以有效降低和预防进程死锁的发生,提高系统的稳定性和效率。

存储器管理:只读存储器,随机存储器,相对地址和绝对地址

在计算机系统中,存储器管理是确保各个程序高效运行的重要机制。存储器主要分为两种类型:只读存储器(ROM)和随机存储器(RAM)。

只读存储器是一种特殊的存储设备,通常用于存放固件,比如计算机开机时所需的启动程序。这种存储器在制造时就被写入了数据,正常情况下无法再进行修改或只能有限度地修改。因此,它的数据在断电后依然能保持完好,这使得它非常适合用于保存关键的系统信息和指令。

与此相对的是随机存储器,它是一种能够在使用过程中不断读写的内存。随机存储器分为动态随机存取存储器(DRAM)和静态随机存取存储器(SRAM),它们都是易失性的存储器,也就是说,一旦电源断开,里面的数据将会消失。随机存储器的速度较快,适合用来存储正在处理的数据和程序代码,因而在计算机运行时起着至关重要的作用。

在计算机进行数据访问时,涉及到两种地址概念:绝对地址和相对地址。绝对地址是指计算机内存中特定位置的唯一标识符,能直接用于访问某一块内存。它就像是每个房间都有自己的门牌号,明确指向一个确切的地方。而相对地址则是以某个基准点为参考,表示与该基准点的距离。这种方式更灵活,可以适应程序在不同内存位置加载时的需求,使得程序的设计更加高效、便捷。

速度问题:CPU>寄存器>缓存>主存>磁盘缓存>硬盘

不同存储层次之间存在显著的速度差异,这主要与它们的物理特性、技术实现和设计目的有关

  1. CPU:作为计算机的核心处理单元,CPU 是执行所有指令的地方。其速度非常快,通常在纳秒级(10^-9秒),这是因为 CPU 内部的电路和逻辑门能迅速进行运算和控制操作。CPU 的设计是为了优化执行效率,能够快速响应各种计算任务。
  2. 寄存器:寄存器是 CPU 内部的高速存储单元,其访问速度极快,因为它们位于处理器内部,与处理器的其他组件对接紧密。这种直接连接消除了数据传输过程中可能出现的延迟,因此寄存器用于存放当前正在处理的数据和指令。
  3. 缓存:缓存(Cache)是一种较小但速度非常快的存储空间,位于 CPU 和主存之间。缓存的访问速度快于主存(RAM),因为它使用更高级的电路设计和更少的访问延迟。缓存存储常用的数据和指令,以减少 CPU 访问主存的次数,从而提高整体性能。由于缓存容量有限,其设计侧重于存储最近使用或将要使用的数据,这种局部性原理(时间局部性和空间局部性)大幅提升了数据读取速度。
  4. 主存(RAM):主存属于易失性存储器,虽然其速度比硬盘快,但毕竟需要通过一定的总线和接口与 CPU 通信。主存的访问时间通常在微秒级(10^-6秒),慢于寄存器和缓存,主要是因为其存储介质(如 DRAM)需要时间来充电和放电,同时涉及更多的电气路径和控制逻辑。
  5. 磁盘缓存:磁盘缓存是在硬盘和主存之间设置的一块高速缓存区域,旨在加速对硬盘数据的访问。其访问速度比硬盘快得多,通常在微秒级。这种速度差异源于磁盘缓存使用的是 RAM 技术,而不是硬盘的机械读取机制。磁盘缓存会存储从硬盘中读取的数据,以便 CPU 可以更快速地访问。
  6. 硬盘:硬盘是计算机的持久存储设备,用于长期保存数据。其访问速度最慢,通常在毫秒级(10^-3秒)。这主要是由于硬盘是机械装置,读写头必须移动到正确的位置以访问数据,且存取速度受到旋转速度、寻道时间等因素的影响。此外,硬盘采用的磁性存储介质也使得读取和写入操作比较耗时。

各种存储层次因其物理特性、技术实现和设计目的的不同,导致了显著的速度差异。操作系统利用这些差异,通过有效管理和调度来优化数据访问和提高整体系统性能。

程序的装入和链接(动态装入,静态装入,重定位)

静态装入:在程序编译时将全部代码和数据装入内存,执行效率高,但缺乏灵活性。动态装入:在程序运行时根据需要装入部分代码和数据,节省内存空间,灵活性强,但可能增加性能开销。重定位:将程序地址转换为实际内存地址,支持程序在不同内存位置的加载,简化了开发和管理过程。

1. 静态装入静态装入是在程序编译时将所有必要的代码和数据直接加载到内存中的一种方式。在这一过程中,可执行文件被完整地加载到特定的内存地址,操作系统在程序开始执行之前已经完成了所有的链接和装入工作。这种方法的优点是执行效率高,因为程序在运行时不需要进行额外的链接或加载。然而,它的缺点是缺乏灵活性,如果程序需要修改或更新,就需要重新编译和装入整个程序。

2. 动态装入

动态装入是在程序运行时根据需要将代码和数据加载到内存中的一种方式。在这种情况下,只有程序执行所需的部分代码会被加载,而不是整个程序。这使得程序可以节省内存空间,并允许多个程序共享相同的库。此外,动态装入支持模块化编程,可以根据需求动态链接库或模块,从而提高了灵活性和可扩展性。然而,动态装入可能导致一定的性能开销,因为在运行过程中会有额外的链接和加载操作。

3. 重定位

重定位是一个与装入相关的过程,涉及将程序中指定的地址(如变量和函数地址)转换为实际内存地址。静态重定位是在编译时确定内存地址,而动态重定位则在程序运行时由操作系统负责调整地址。重定位允许程序在不同的内存位置加载,这样可以有效利用内存,提高程序的灵活性。当使用重定位时,程序员不必关心其代码在内存中的确切位置,这大大简化了软件开发和管理。

这三者共同作用于操作系统的内存管理,使得程序能够高效、灵活地运行。

内存空间划分算法:首次适应;最佳适应;最坏适应

内存空间划分算法是一种用于动态分配内存的方法。首次适应算法从内存的开始位置出发,寻找第一个足够大的空闲区块来满足进程的内存需求。这种方法简单且高效,因为它能迅速找到合适的内存区域。然而,频繁的内存分配和释放可能导致碎片化。

最佳适应算法会遍历所有空闲区块,选取最小的那个能够满足请求的区域。这种方式旨在最大限度地减少剩余空间,从而降低内存碎片的产生。虽然这种算法在理论上有助于提高内存利用率,但由于查找过程需要遍历整个列表,因此效率较低。

最坏适应算法选择最大的空闲区块进行分配,期望剩余的内存块依然足够大,以便满足后续的需求。这种方法的目的是避免大块内存的迅速消耗,尽管从实际效果来看,它并不能有效减少内存碎片,并且同样面临查找时间长的问题。

段式存储和页式存储,以及段页式存储的优缺点,原理

段式存储段式存储是一种将程序和数据按照逻辑结构划分为多个段的内存管理方式。在这种方式中,每个段代表程序中的一个功能模块,例如一个函数或数组。每个段都有一个基地址和长度,CPU通过段号和段内偏移量来访问具体的内存位置。这种方法的优点在于它与程序的逻辑结构相符,非常自然和易于理解。在段式存储中,可以实现不同进程之间的代码共享,同时保护各自的数据和代码。然而,由于段的大小不固定,可能导致外部碎片的产生。此外,维护段表也需要占用一定的存储空间,这增加了系统的开销。

页式存储页式存储是另一种内存管理方式,它将物理内存和逻辑地址空间都划分为固定大小的单元,称为页和页框。逻辑地址由页号和页内偏移组成,操作系统使用页表来实现逻辑页到物理页框的映射。这种方法的一个显著优点是消除了外部碎片的问题,因为所有的页都是固定大小的,只会存在少量的内部碎片。此外,页式存储允许灵活的内存分配和释放,使得系统能够高效地利用可用内存。然而,页式存储的缺点在于,为每个进程维护页表会占用额外的内存,并且随着程序规模的增大,管理页表的复杂性也随之增加。

段页式存储段页式存储结合了段式存储和页式存储的优点,采用分层结构对内存进行管理。在这种模式下,逻辑地址空间被划分为多个段,每个段又可以进一步划分成多个固定大小的页。这样做不仅保留了段式存储的逻辑组织优势,还利用页式存储消除了外部碎片的问题,同时减少了内部碎片的影响。段页式存储支持模块化编程,便于代码共享和资源保护,但其实现的复杂性明显增加。系统需要同时维护段表和页表,这会带来更大的内存开销。因此,虽然段页式存储在很多方面表现出色,但在性能和管理上也提出了更高的要求。

页面置换算法(LRU,LFU,FIFO这些)

**LRU(Least Recently Used,最近最少使用)**LRU算法基于一个假设,即如果某个页面最近被访问过,那么它在不久的将来可能会再次被访问。因此,LRU选择那些最长时间未被访问的页面进行替换。这通常通过维护一个页面访问的时间戳或引用计数来实现。LRU能够较好地适应实际工作负载,但其实现较为复杂,因为需要频繁更新页面的使用状态。

**LFU(Least Frequently Used,最不常用)**LFU算法则是基于页面被访问的频率进行置换。它认为,如果某个页面在过去一段时间内被访问的次数最少,那么它在未来被访问的概率也低。因此,LFU会选择那些访问次数最少的页面进行替换。LFU可以有效地处理一些特定模式的访问,但在频繁变化的访问模式下可能表现不佳,并且同样存在实现复杂度高的问题。

**FIFO(First-In-First-Out,先进先出)**FIFO算法是一种简单的页面置换策略,它按照页面进入内存的顺序进行替换。当需要替换页面时,FIFO选择最早进入内存的页面进行替换。这种方法实现简单,但并不总能保证性能,因为它无法根据页面的使用情况做出智能决策。某些情况下,FIFO可能会导致"Belady’s anomaly",即增加内存页数反而导致缺页率上升。

进程与线程的区别和联系

进程和线程是操作系统中用于实现并发和多任务处理的基本概念,二者有着重要的区别和联系。

区别

  1. 定义:进程是系统分配资源的基本单位,是程序在执行过程中所创建的一个实例,具有独立的地址空间;而线程是进程内的一个执行单元,同一进程内的多个线程共享进程的资源,如内存和文件句柄。
  2. 资源占用:进程拥有自己的内存空间、数据段和系统资源。线程则不拥有独立的内存空间,多个线程可以共享同一进程的内存和资源,这使得线程之间的通信更为高效。
  3. 调度与开销:进程切换需要保存和加载完整的进程上下文,开销相对较大;而线程切换只需保存和加载线程相关的状态,开销较小,因此线程的创建和销毁比进程更快。
  4. 并发性:进程间通信(IPC)相对复杂,因为它们拥有独立的地址空间;而同一进程中的线程可以通过共享内存等方式进行快速通信,但也需要考虑同步问题以避免竞争条件。

联系

  1. 组成关系:线程是进程的一个组成部分,一个进程至少有一个线程(主线程),而可以包含多个线程。进程为线程提供了运行的环境。
  2. 协同工作:进程和线程都是为了实现多任务和并发执行,进程通过内部的多个线程来提高应用程序的响应能力和处理性能。

进程是资源分配的基本单位,而线程是进程内部的执行单位。两者在实现并行计算时各有优势,能够根据具体需求选择使用。

多线程编程安全性

多线程编程安全性是指在多个线程并发执行时,确保数据完整性和系统稳定性的能力。随着线程的并发运行,可能会出现以下问题:

  • 数据竞争:多个线程同时访问和修改共享数据,导致数据不一致。
  • 死锁:两个或多个线程互相等待对方释放资源,造成所有相关线程无法继续执行。
  • 活锁:线程持续响应彼此的状态变化,但无法推进进度,导致效率低下。

为确保多线程程序的安全性,可以采取一些策略,包括使用互斥锁、信号量和条件变量来同步线程访问共享资源。此外,设计时应考虑资源申请顺序及避免过度锁定,以减少死锁风险。合理管理线程之间的交互可以提升程序性能,确保数据的一致性和安全性。

线程池,线程的创建,同步,安全问题

线程池

线程池是一种管理和复用多个线程的机制。它预先创建一定数量的线程,并将这些线程放入一个池中,以便在需要时快速分配和重用。这样可以减少频繁创建和销毁线程的开销,提高系统性能。线程池能够有效控制并发的线程数,避免线程过多导致的资源竞争和上下文切换。

线程的创建

在线程编程中,可以通过不同的方式创建线程,常见的方法包括:

  • 继承线程类:通过创建一个继承自线程类的子类,并重写其 run() 方法。
  • 实现 Runnable 接口:定义一个实现了 Runnable 接口的类,并将其实例传递给线程对象来创建线程。

创建线程时,需要注意合理使用线程资源,避免过多的线程造成系统负担。

同步

在多线程环境中,同步是确保多个线程安全地访问共享资源的手段。常见的同步方法包括:

  • 互斥锁(Mutex):确保在某一时刻只有一个线程能访问共享资源。
  • 信号量(Semaphore):控制同时访问某个特定资源的线程数量。
  • 条件变量:允许线程在特定条件下等待或通知其他线程。

通过这些同步机制,可以有效避免数据竞争等问题。

安全问题

在多线程编程中,常见的安全问题包括:

  1. 数据竞争:多个线程同时修改共享数据,可能导致不一致的结果。
  2. 死锁:两个或多个线程互相等待对方释放资源,导致程序停滞。
  3. 活锁:线程在不断尝试执行却无法取得进展的问题。
  4. 饥饿:某些线程长时间无法获取资源,导致无法执行。

为解决这些问题,开发者需要谨慎设计线程间的交互、合理使用同步机制,并遵循最佳实践以提升程序的安全性和稳定性。

信号量机制

信号量是一种用于控制对共享资源访问的同步机制,主要通过一个计数器来管理并发访问。它允许多个线程或进程之间进行协调,确保安全地使用有限的资源。

在信号量的工作机制中,当一个线程希望访问某个资源时,它会执行 P 操作。如果信号量的计数器大于0,线程就可以继续执行并将计数器减1;如果计数器为0,线程则会进入等待状态,直到有其他线程释放资源。相应地,当线程完成对资源的使用后,会执行 V 操作,将计数器加1,并可能唤醒等待该资源的其他线程。

信号量特别适合限制并发访问,如在数据库连接池中控制最大并发连接数,同时也能用于线程间的协作与通信。通过有效管理线程的访问,信号量能够减少数据竞争和死锁的发生。然而,使用信号量时需要小心设计操作的顺序,以避免潜在的死锁和资源饥饿问题。总之,信号量是多线程编程中一种重要的同步工具。

虚拟内存

定义:虚拟内存是操作系统提供的抽象内存管理机制,将物理内存、磁盘交换文件和其他资源统一为连续的虚拟地址空间。

核心功能:内存隔离:每个进程拥有独立的虚拟地址空间,防止越界访问。分页机制:将内存分为固定大小的页(如4KB),按需加载到物理内存。扩展可用内存:通过磁盘交换文件支持超过物理内存大小的内存需求。

操作系统如何实现内存管理的

第一步:虚拟内存 —— 创造“内存幻觉”当进程启动时,操作系统通过虚拟内存技术为它分配一个连续的、独立的虚拟地址空间(例如0x0000到0xFFFF),让进程误以为自己独占了完整的物理内存。• 关键作用: • 进程无需关心物理内存的实际分配,避免内存碎片问题。 • 隔离不同进程的内存空间,防止越界访问(如进程A无法直接读写进程B的数据)。

第二步:分页机制 —— 虚实地址映射的“翻译官”操作系统将虚拟内存和物理内存都划分为固定大小的页(如4KB),通过页表这一多层数据结构记录虚拟页到物理页帧的映射关系。• 运作过程:

  1. 进程访问虚拟地址0x1234时,CPU的内存管理单元(MMU)自动将地址拆解为页号(Page Number)和页内偏移(Offset)。
  2. 查询页表,找到页号对应的物理页帧(如页表项显示虚拟页2映射到物理页帧5)。
  3. 将物理页帧号与偏移组合,得到实际物理地址0x5000 + 0x034 = 0x5034。

• 优化手段: • 多级页表(如x86-64使用四级页表)压缩页表空间占用。 • TLB快表缓存常用页表项,加速地址转换。

第三步:缺页中断 —— 动态加载的“调度员”若MMU发现目标虚拟页在页表中标记为未加载(即物理页帧为空或指向磁盘),会触发缺页中断,CPU切换到内核态处理:

  1. 操作系统检查该页是否合法(如进程是否有访问权限)。
  2. 从磁盘的 **交换区(Swap)**或文件(如内存映射文件)中加载缺失的页到物理内存。
  3. 更新页表,建立虚拟页到新物理页帧的映射。
  4. 重新执行被中断的指令,此时虚拟地址已可正常访问。

• 场景示例: • 进程首次访问代码段、动态分配的堆内存,或长时间未使用的缓存页时,均可能触发缺页中断。

第四步:页面置换 —— 内存不足的“淘汰策略”当物理内存不足时,操作系统通过页面置换算法选择牺牲页换出到磁盘,腾出空间加载新页:

  1. 选择目标页:根据算法(如LRU最近最少使用、FIFO先进先出)筛选最不活跃的页。
  2. 写回数据:若页已被修改(脏页),先将其内容写回磁盘。
  3. 更新状态:在页表中标记该虚拟页为“未加载”,物理页帧释放给新页使用。

• 设计权衡: • LRU精准但实现复杂(需硬件记录访问时间),FIFO简单但可能误删常用页。 • 现代系统采用近似LRU(如Clock算法)平衡效率与精度。

第五步:内存保护 —— 安全隔离的“守卫者”通过页表项中的权限位,操作系统严格控制进程的内存访问行为:• 权限类型: • 读(R)、写(W)、执行(X)、用户/内核模式(U/K)。• 违规处理: • 若进程试图越权操作(如写只读页、访问内核页),触发段错误(Segmentation Fault),操作系统终止进程。

• 扩展应用: • 可执行代码标记为“不可写”(防止代码注入攻击)。 • 数据页标记为“不可执行”(防御缓冲区溢出攻击)。

全流程示例:进程访问内存的完整旅程

  1. 进程请求读取虚拟地址0x1234。
  2. MMU查询页表,发现该页未加载(触发缺页中断)。
  3. 操作系统选择置换物理页帧5,将其内容写回磁盘(若为脏页)。
  4. 从磁盘加载目标页到物理页帧5,更新页表映射。
  5. MMU重新翻译地址,检查权限(如该页是否可读)。
  6. 进程最终从物理地址0x5034读取数据,全程无需感知物理内存的分配细节。
仅用于交流学习,记录学习心得