赞
踩
Meltdown和Spectre(熔断和幽灵)
冯诺依曼结构(普林斯顿结构)
哈佛结构(不考
批处理系统
加载在计算机上的一个系统软件,在它的控制下,计算机能够自动地、成批地处理一个或多个用户的作业(这作业包括程序、数据和命令)。
联机批处理系统
作业的输入输出由CPU处理
脱机批处理系统
作业的输入输出脱离主机控制
多道程序系统
同时把多个程序放入内存中(前提是内存放的下),并允许它们交替在CPU中运行,它们共享系统中的各种硬、软件资源。当一道程序因I/O请求而暂停运行时,CPU便立即转去运行另一道程序。
特点:
- 多道
- 宏观并行
- 微观串行
多道批处理系统
特点:多道、成批
优点:系统吞吐量达、资源利用率高
缺点:平均周转时间长、不能提供交互能力
分时系统
将CPU处理时间分割为多个时间片,将时间片分给不同程序,达到多个程序“同时”运行的效果
现代操作系统基本特征
并发执行、资源共享、虚拟化管理、异步性
gcc工具
ELF文件部分含义
链接的过程
重定位链接地址计算
程序入口点
_start 函数 ,
程序的装载与运行
执行过程:
shell调用fork()系统调用
创建一个子程序
子程序调用execve()加载program (装载)
程序的装载细节
存储管理的基本机制:抽象
基本概念:地址空间、逻辑地址、物理地址
地址空间:一个进程所能够用于访问内存的地址集合。
逻辑地址:又称虚拟地址,程序所使用的地址。
物理地址:物理内存中数据存储的地址
存储管理的基石:
存储管理的功能
存储分配和回收:存储管理的主要内容。讨论其算法和相应的数据结构。
地址变换:可执行文件生成中的链接技术、程序加载时的重定位技术,进程运行时硬件和软件的地址变换技术和机构。
存储共享和保护:代码和数据共享,对地址空间的访问权限(读、写、执行)。
存储器扩充:涉及存储器的逻辑组织和物理组织;
由应用程序控制:覆盖;
由OS控制:交换(整个进程空间),请求调入和预调入(部分进程空间)
单道程序内存管理
特点:
在单道程序环境下,整个内存里只有两个程序:一个用户程序和操作系统。
操作系统所占的空间是固定的。
因此可以将用户程序永远加载到同一个地址,即用户程序永远从同一个地方开始运行。
用户程序的地址在运行之前可以计算。
方法:
分析:
优点:执行过程中无需地址翻译,程序运行速度快。
缺点:比物理内存大的程序无法加载,因而无法运行;造成资源浪费(小程序会造成空间浪费;I/O时间长会造成计算资源浪费)。
多道程序的内存管理
特点:分区式分配
方法:
固定式分区分析:
把内存划分为若干个固定大小的连续分区
优点:易于实现,开销小。
缺点:内碎片造成浪费,分区总数固定,限制了并发执行的程序数目。
采用的数据结构:分区表--记录分区的大小和使用情况。
分配方式
单一队列
多队列
可变式分区分析:
可变式分区:分区的边界可以移动,即分区的大小可变。
优点:没有内碎片。
缺点:有外碎片。
闲置空间的管理
位图表示法:
链表表示法:
基于顺序搜索的4种分配算法
基于索引搜索的分配算法
基于顺序搜索的动态分区分配算法一般只是适合于较小的系统,如果系统的分区很多,空闲分区表(链)可能很大(很长) ,检索速度会比较慢。为了提高搜索空闲分区的速度,大中型系统采用了基于索引搜索的动态分区分配算法。
系统中碎片
内部碎片:分配给作业的存储空间内未被利用的部分。只有作业完成后才能被释放。
外部碎片:分区与分区间无法利用的分区。
消除外部碎片的方法:紧凑技术(Compaction)
多重分区分配
多重分区分配:为了支持结构化程序设计,操作系统往往把一道作业分成若干片段(如子程序、主程序、数据组等)。这样,片段之间就不需要连续了。只要增加一些重定位寄存器,就可以有效地控制一道作业片段之间的调用。
分区的存储保护
存储保护是为了防止一个作业有意或无意地破坏操作系统或其它作业。常用的存储保护方法有
界限寄存器方法:
存储保护键方法:
覆盖:把一个程序划分为一系列功能相对独立的程序段,让执行时不要求同时装入内存的程序段组成一组(称为覆盖段),共享主存的同一个区域,这种内存扩充技术就是覆盖。
交换:把暂时不用的某个(或某些)程序及其数据的部分或全部从主存移到辅存中去,以便腾出存储空间;接着把指定程序或数据从辅存读到相应的主存中,并将控制转给它,让其在系统上运行。
交换技术的几个问题
覆盖与交换技术的区别
基本概念
页面大小辨析
关于页表
页表存放在内存中,属于进程的现场信息。
用途:
记录进程的内存分配情况
实现进程运行时的动态重定位。
访问一个数据需访问内存2 次(页表一次,内存一次)。
页表的基址及长度由页表寄存器给出。
二级页表
一级页表存在问题:逻辑地址大,页表大,占用存储空间(要求连续)大。
将页表再进行分页,离散地将各个页表页面存放在不同的物理块中,同时也再建立一个外层页表用以记录页表页面对应的物理块号。
正在运行的进程先把外层页表(页表的页表)调入内存,而后动态调入内层页表。只将当前所需的一些内层页表装入内存,其余部分根据需要再陆续调入。
练习题:
存在的问题: 内存访问效率降低
快表TLB
有效内存访问时间计算(一级页表)
TLB查询时间 ε \varepsilon ε 单次内存访问时间 τ \tau τ TLB命中率 α \alpha α
有效内存访问时间EAT=(τ+ε)α + (2τ+ε)(1-α) = 2τ + ε - τα
例题:
哈希页表(Hashed Page Table)
反置页表(Inverted Page Table)
段式存储管理的主要动机
**方便编程:**通常一个作业是由多个程序段和数据段组成的,用户一般按逻辑关系对作业分段,并能根据名字来访问程序段和数据段。
**信息共享:**共享是以信息的逻辑单位为基础的。页是存储信息的物理单位,段是信息的逻辑单位。页式管理中地址空间是一维的,主程序、子程序都顺序排列,共享公用子程序比较困难,一个共享过程可能需要几十个页面。
**信息保护:**页式管理中,一个页面中可能装有2 个不同的子程序段的指令代码,不能通过页面共享实现一个逻辑上完整的子程序或数据块的共享。段式管理中,可以使用信息的逻辑单位进行保护。
**动态增长:**实际应用中,某些段(数据段)会不断增长,前面的存储管理方法均难以实现。
**动态链接:**动态链接在程序运行时才把主程序和要用到的目标程序(程序段)链接起来。
基本思想
地址变换
段表记录了段与内存位置的对应关系。
段表保存在内存中。
段表的基址及长度由段表寄存器给出。
访问一个字节的数据/指令需访问内存两次(段表一次,内存一次)。
逻辑地址由段和段内地址组成。
地址变换过程
将逻辑地址中的段号S 与段表长度TL 进行比较。
若S>TL,表示访问越界,产生越界中断。
(Reentrant Code)
又称为“纯代码”(Pure Code)
,是指在多次并发调用时能够安全运行的代码。要求:不能使用全局/静态变量;代码不能修改代码本身;不能调用其他的不可重入代码。分段管理优缺点
分页与分段的比较
分页的作业的地址空间是单一的线性地址空间(注:页式管理所用的一维的虚拟地址也称为线性地址),分段作业的地址空间是二维的。
“页”是信息的“物理”单位,大小固定。“段”是信息的逻辑单位,即它是一组有意义的信息,其长度不定。
分页对用户是透明的,是系统对于主存的管理。分段是用户可见的(分段可以在用户编程时确定,也可以在编译程序对源程序编译时根据信息的性质来划分)。
实现原理
基本思想:用分段方法来分配和管理虚拟存储器,而用分页方法来分配和管理物理存储器。
段页式存储管理:分段和分页原理的结合,即先将用户程序分成若干个段(段式) ,并为每一个段赋一个段名,再把每个段分成若干个页(页式) 。
地址结构由段号、段内页号、及页内位移三部分所组成。
系统中设段表和页表,均存放于内存中。读一次指令或数据须访问内存三次。为提高速度可增设高速缓存。
每个进程一张段表,每个段一张页表。
段表含段号、页表始址和页表长度;页表包含页号和页框号。
程序的局部性
程序在执行时,大部分是顺序执行的指令,少部分是转移和过程调用指令。(空间局部性)
过程调用的嵌套深度有限,因此执行的范围不超过这组嵌套的过程。(空间局部性)
程序中存在很多对特定数据结构的操作,如数组操作,往往局限在较小范围内。(空间局部性)
程序中存在很多循环结构,它们由少量指令组成,而被多次执行。(时间局部性)
局部性原理
指程序在执行过程中的一段较短时间内,所执行的指令地址和指令的操作数地址分别局限于一定区域。具体表现为:
时间局部性:即一条指令的一次执行和下次执行,一个数据的一次访问和下次访问都集中在一段较短时间内;
空间局部性:即当前指令和邻近的几条指令,当前访问的数据和邻近的数据都集中在一个较小区域内。
虚拟存储
目标**(与覆盖和交换的关系)**:
原理:
特征:
离散性: 物理内存分配的不连续,虚拟地址空间使用的不连续(数据段和栈段之间的空闲空间,共享段和动态链接库占用的空间)
多次性: *作业被分成多次调入内存运行。*正是由于多次性,虚拟存储器才具备了逻辑上扩大内存的功能。多次性是虚拟存储器最重要的特征,其它任何存储器不具备这个特征。
**对换性:**允许在作业运行过程中进行换进、换出。换进、换出可提高内存利用率。
**虚拟性:**允许程序从逻辑的角度访问存储器,而不考虑物理内存上可用的空间容量。
虚拟性以多次性和对换性为基础,
多次性和对换性必须以离散分配为基础。
优缺点:
优点:
**小内存大程序:**可在较小的可用(物理)内存中执行较大的用户程序;
**支持更多并发:**可在(物理)内存中容纳更多程序并发执行;
不必影响编程时的程序结构(与覆盖技术比较)
**虚拟内存通常远大于物理内存:**提供给用户可用的虚拟内存空间通常大于物理内存
代价:虚拟存储量的扩大是以牺牲CPU 处理时间以及内外存交换时间为代价。
限制:虚拟内存的最大容量主要由计算机的地址结构决定。例如: 32 位机器的虚拟存储器的最大容量就是4GB。
与Cache异同:
相同点:
出发点相同:二者都是为了提高存储系统的性能价格比而构造的分层存储体系,都力图使存储系统的性能接近高速存储器,而价格和容量接近低速存储器。
原理相同:都是利用了程序运行时的局部性原理把最近常用的信息块从相对慢速而大容量的存储器调入相对高速而小容量的存储器。
不同点:
侧重点不同:cache主要解决主存与CPU的速度差异问题;虚存主要解决存储容量问题,另外还包括存储管理、主存分配和存储保护等。
数据通路不同:CPU与cache和主存之间均有直接访问通路,cache不命中时可直接访问主存;而虚存所依赖的辅存与CPU之间不存在直接的数据通路,当主存不命中时只能通过调页解决,CPU最终还是要访问主存。
透明性不同:cache的管理完全由硬件完成,对系统程序员和应用程序员均透明;而虚存管理由软件(OS)和硬件共同完成,由于软件的介入,虚存对实现存储管理的系统程序员不透明,而只对应用程序员透明(段式和段页式管理对应用程序员“半透明”)。
未命中时的损失不同:由于主存的存取时间是cache的存取时间的5~10倍,而主存的存取速度通常比辅存的存取速度快上千倍,故主存未命中时系统的性能损失要远大于cache未命中时的损失。
请求分页(段)系统
请求分页与请求分段系统的比较:
虚存机制要解决的关键问题:
请求分页式管理
基本概念:
地址映射问题
进程空间到虚存空间的映射(进程的虚存分配)
在程序装入时,由装载器(Loader)完成。
分配是以段为单位(需页对齐)进行的。
事实上,在每个进程创建加载时,内核只是为进程“创建”了虚拟内存的布局,同时建立好虚拟内存和磁盘文件之间的映射(即存储器映射) 。实际上,并不立即就把虚拟内存对应位置的程序数据和代码(比如.text .data段)拷贝到物理内存中,等到运行对应的程序时,才会通过缺页异常,来拷贝数据。
用户可执行文件(如Hello World可执行文件)及共享库(如HelloWorld中调用的库文件中的printf函数)都是以文件的形式存储在磁盘中,初始时其在页表中的类型为file backed,地址为相应文件的位置。
堆(heap)和栈(stack)在磁盘上没有对应的文件,页表中的类型为anonymous,地址为空。
未分配部分没有对应的页表项,只有在申请时(如使用malloc( )申请内存或用mmap( )将文件映射到用户空间)才建立相应的页表项。
请求式分页管理的页表
页面调入问题
页面面调入策略:按需调页
页面调入策略-预调页
缺页错误处理过程
当进程执行中需访问的页面不在物理内存中时,会引发发生缺页中断(也称缺页异常),进行所需页面换入,步骤如下:
- 陷入内核态,保存必要的信息(OS及用户进程状态相关的信息)。(现场保护)
- 查找出发生缺页中断的虚拟页面(进程地址空间中的页面)。这个虚拟页面的信息通常会保存在一个硬件寄存器中,如果没有的话,操作系统必须检索程序计数器,取出这条指令,用软件分析该指令,通过分析找出发生页面中断的虚拟页面。(页面定位)
- 检查虚拟地址的有效性及安全保护位。如果发生保护错误,则杀死该进程。(权限检查)
- 查找一个空闲的页框(物理内存中的页面),如果没有空闲页框则需要通过页面置换算法找到一个需要换出的页框。(新页面调入 1 ^1 1)
- 如果找的页框中的内容被修改了,则需要将修改的内容保存到磁盘上¹。(注:此时需要将页框置为忙状态,以防页框被其它进程抢占掉)(旧页面写回)
- 页框“干净”后,操作系统将保持在磁盘上的页面内容复制到该页框中²。(新页面调入 2 ^2 2)
- 当磁盘中的页面内容全部装入页框后,向CPU发送一个中断。操作系统更新内存中的页表项,将虚拟页面映射的页框号更新为写入的页框,并将页框标记为正常状态。(更新页表)
- 恢复缺页中断发生前的状态,将程序指针重新指向引起缺页中断的指令。(恢复现场)
- 程序重新执行引发缺页中断的指令,进行存储访问。(继续执行)
缺页处理过程涉及了用户态和内核态之间的切换,虚拟地址和物理地址之间的转换(这个转换过程需要使用MMU和TLB)
¹,² :此时会引起一个写磁盘调用,发生上下文切换(在等待磁盘写的过程中让其它进程运行)。
最优置换(OPT算法)
所有页置换算法中页错误率最低,但它需要引用串(即页面访问序列)的先验知识,因此无法实现。
算法将内存中的页P置换掉,页P满足:从现在开始到未来某刻再次需要页P,这段时间最长。也就是OPT 算法会置换掉未来最久不被使用的页。
OPT 算法通常用于比较性研究,衡量其他页置换算法的效果。
先进先出(First-in, First-out)
最简单的页置换算法,系统记录每个页被调入内存的时间,当必需置换掉某页时,选择最旧的页换出。具体实现如下:
性能较差。较早调入的页往往是经常被访问的页,这些页在FIFO算法下被反复调入和调出。可能出现Belady异常现象。
Belady异常现象 :在使用FIFO算法作为缺页置换算法时,随着分配的页框增
多,缺页率反而提高
注意:虽然这种现象说明的场景是缺页置换,但在运用FIFO算法作为缓存替换算法时,同样也会遇到,即增加缓存容量,但缓存命中率反而会下降的情况。
改进的FIFO算法—Second Chance
每个页面会增加一个访问标志位,用于标识此数据装入内存后是否被再次访问过。
A是FIFO队列中最旧的页面,且其放入队列后没有被再次访问,则A被立刻淘汰;否则,如果放入队列后被访问过,则将A移到FIFO队列尾部,并且将访问标志位清除。
如果所有页面都被访问过,则经过一次循环后就按FIFO原则淘汰。
改进的FIFO算法— Clock
FIFO类算法对比:
工作集与驻留集管理
工作集(working set):进程运行正在使用的页面集合。
进程的驻留集(Resident Set):虚拟存储系统中,每个进程驻留在内存的页面集合,或进程分到的物理页框集合。
引入工作集的目的是依据进程在过去的一段时间内访问的页面来调整驻留集大小。
工作集的动态变化
工作集算法
进程驻留集管理主要解决的问题:系统应当为每个活动进程分配多少个页框。
影响页框分配的主要因素:
页面分配策略
固定分配策略:为每个活动进程分配固定数量的页框。即每个进程的驻留集大小在运行期间固定不变。
可变分配策略:为每个活动进程分配的页框数在其生命周期内是可变的。即系统首先给进程分配一定数量的页框,运行期间可以增/减页框。
可根据进程的缺页率调整进程的驻留集。当缺页率很高时,驻留集太小,需增加页框;当缺页率一段时间内都保持很低时,可以在不会明显增加进程缺页率的前提下,回收其一部分页框,减小进程的驻留集。
页面置换策略
内存块初始分配方法
等分法:为每个进程分配存储块的最简单的办法是平分,即若有m块、n个进程,则每个进程分m/n块(其值向下取整)。
比例法:分给进程的块数=(进程地址空间大小/全部进程的总地址空间)*可用块总数
优先权法:为加速高优先级进程的执行,可以给高优先级进程分较多内存。如使用比例分配法时,分给进程的块数不仅取决于程序的相对大小,而且也取决于优先级的高低。
抖动问题(thrashing)
定义:
随着驻留内存的进程数目增加,即进程并发程度的提高,处理器利用率先上升,然后下降。
这里处理器利用率下降的原因通常称为虚拟存储器发生“抖动”,也就是:每个进程的驻留集不断减小,当驻留集小于工作集后,缺页率急剧上升,频繁调页使得调页开销增大。
因此,OS要选择一个适当的进程数目,以在并发水平和缺页率之间达到一个平衡。
抖动的消除与预防
局部置换策略:如果一个进程出现抖动,它不能从另外的进程那里夺取内存块,从而不会引发其他进程出现抖动,使抖动局限于一个小的范围内。然而这种方法并未消除抖动的发生。(微观层面)
引入工作集算法(微观)
预留部分页面(微观或宏观)
挂起若干进程:当出现CPU利用率、而磁盘I/O非常频繁的情况时,就可能因为多道程序度太高而造成抖动。为此,可挂起一个或几个进程,以便腾出内存空间供抖动进程使用,从而消除抖动现象。(宏观)
负载控制
多道程序系统允许多个进程同时驻留内存,以提高系统吞吐量和资源利用率。
如果同时驻留的进程数量太多,每个进程都竞争各自需要的资源,反而会降低系统效率。将导致每个进程的驻留集太小,发生缺页中断的概率很大,系统发生抖动的可能性就会很大。
如果在内存中活动进程太少,则所有活动进程同时处于阻塞状态的可能性就会很大,从而降低处理机利用率。
负载控制主要解决系统应当保持多少个活动进程驻留在内存的问题,即控制多道程序系统的度。当内存中的活动进程数太少时,负载控制将增加新进程或激活一些挂起进程进入内存;反之,当内存中的进程数太多时,负载控制将暂时挂起一些进程,减少内存中的活动进程数。
系统负载的判断
L = S准则:通过调整多道程序的度,使发生两次缺页之间的平均时间(L)等于处理一次缺页所需要的平均时间(S)。即平均地,一次缺页处理完毕,再发生下一次缺页。此时,处理机的利用率将达到最大。
50%准则:当分页单元的利用率保持在50%左右时,处理机的利用率将达到最大。如果系统使用基于CLOCK置换算法的全局置换策略,可通过监视扫描指针的移动速率来调整系统负载。如果移动速率低于某个给定的阀值,则意味着近期页面失败的次数较少,此时可以增加驻留内存的活动进程数。如果超出阀值,则近期页面失败的次数较多,此时,系统应当减少驻留内存的活动进程数。
页面清除策略
页面缓冲算法(page buffering)
改善时间性能的途径
写时复制技术(copy-on-write)
内存映射文件(Mem-Mapped File)
多级页表
多级页表的动机
节省页表所占用的内存空间
动态调入页表: 只将当前需用的部分页表项调入内存,其余的需用时再调入。
PS:
页目录
页目录自映射
关键点
构建方法
给定一个页表基址$PT_{base} $,该基址需4M对齐,即:
P
T
b
a
s
e
=
((
P
T
b
a
s
e
)
>
>
22
)
<
<
22
;
PT_{base} =(( PT_{base})>> 22)<< 22;
PTbase=((PTbase)>>22)<<22;
不难看出,
P
T
b
a
s
e
PT_{base}
PTbase的低22位全为0。
页目录表基址
P
D
b
a
s
e
PD_{base}
PDbase在哪里?
P
D
b
a
s
e
=
P
T
b
a
s
e
∣
(
P
T
b
a
s
e
)
>
>
10
PD_{base} = PT_{base} |(PT_{base})>>10
PDbase=PTbase∣(PTbase)>>10
自映射目录表项
P
D
E
s
e
l
f
−
m
a
p
p
i
n
g
PDE_{self-mapping}
PDEself−mapping在哪里?
P
D
E
s
e
l
f
−
m
a
p
p
i
n
g
=
P
T
b
a
s
e
∣
(
P
T
b
a
s
e
)
>
>
10
∣
(
P
T
b
a
s
e
)
>
>
20
PDE_{self-mapping} = PT_{base} |(PT_{base})>>10| (PT_{base})>>20
PDEself−mapping=PTbase∣(PTbase)>>10∣(PTbase)>>20
是不是一定要4M对齐?
特别强调
只要给定4M对齐的页表基址(虚拟地址),就可以得到所有页表项对应的地址,也就包括页目录表基址和自映射页目录项在页目录表中的位置。因此页目录表基址和自映射页目录项在虚空间中是计算出来的。
页表主要供OS使用的,因此页表和页目录表通常放置在OS空间中(如Win的高2G空间);
“页目录自映射”的含义是页目录包含在页表当中,是我们采用的映射(或组织)方法的一个特征,是虚拟地址空间内的映射,与虚拟地址到物理地址的映射无关!
支持“页目录自映射”可节省4K(虚拟地址)空间
多级页表情况
小结
两个基本概念:并发与并行
程序顺序执行时的特征
程序并发执行时的特征
并发性的确定-Bernstein条件
定义:
R(Si):Si的读子集, 其值在Si中被引用的变量的集合
W(Si):Si的写子集, 其值在Si中被改变的变量的集合
两个进程S1和S2可并发,当且仅当下列条件同时成立:
判断程序并发执行结果是否可再现的充分条件。
进程的定义和特征
进程是程序的一次执行;
进程是可以和别的计算并发执行的计算;
进程可定义为一个数据结构,及能在其上进行操作的一个程序;
进程是一个程序及其数据在处理机上顺序执行时所发生的活动;
进程是程序在一个数据集合上运行的过程,它是系统进行资源分配和调度的一个独立单位。
进程的特征
一个进程应该包括
进程与程序的区别
原语
Fork()函数
进程状态及其演变
就绪状态:进程已获得除处理机外的所需资源,等待分配处理机资源;只要分配CPU就可执行。
执行状态:占用处理机资源;处于此状态的进程的数目小于等于CPU的数目。在没有其他进程可以执行时(如所有进程都在阻塞状态),通常会自动执行系统的idle进程(相当于空操作)。
阻塞状态:正在执行的进程,由于发生某种事件而暂时无法执行,便放弃处理机处于暂停状态。
转换时刻:
就绪–> 运行
运行–> 就绪
运行进程用完了时间片
运行进程被中断,因为一高优先级进程处于就绪状态
运行–> 阻塞
阻塞–> 就绪
进程控制块PCB
作用:
进程控制块是进程管理和控制的最重要的数据结构,每一个进程均有一个PCB,在创建进程时,建立PCB,伴随进程运行的全过程,直到进程撤消而撤消。
内容
进程标识符:每个进程都必须有一个唯一的标识符,可以是字符串,也可以是一个数字。Linux系统中就是一个整型数。在进程创建时由系统赋予。
程序和数据地址:把PCB与其程序和数据联系起来。
当前状态:为了管理的方便,系统设计时会将相同的状态的进程组成一个队列,如就绪进程队,等待进程则要根据等待的事件组成多个等待队列,如等待打印机队列、等待磁盘I/O完成队列等等。
现场保护区: 当进程因某种原因不能继续占用CPU时(等待打印机),释放CPU,这时就要将CPU的各种状态信息保护起来,为将来再次得到处理机恢复CPU的各种状态,继续运行。
同步与同步机制: 用于实现进程间互斥、同步和通信所需的信号量等。
优先级: 进程的优先级反映进程的紧迫程度,通常由用户指定和系统设置。Linux系统采用用户设置和系统计算相结合的方式确定进程的优先级。
资源清单: 列出所拥有的除CPU外的资源记录,如拥有的I/O设备、打开的文件列表等。
链接字: 根据进程所处的执行状态,进程相应的PCB加入到不同队列中。PCB链接字指出该进程所在队列中下一个进程PCB的首地址。
其他信息: 如进程记账信息,进程占用CPU的时间等。
在linux 中每一个进程都由task_struct 数据结构来定义,task_struct就是我们通常所说的PCB。
PCB组织方式
辨析:进程上下文切换vs 陷入内核
线程(thread)的提出
进程的不足:
需要提出一种新的实体,满足以下特性:
进程与线程区别
调度:现代操作系统将资源拥有者称为进程(process,task),将可执行单元称为线程(Thread)。
线程:将资源与计算分离,提高并发效率。
并发性
多进程:多个程序可以并发执行,改善资源使用率,提高系统效率
多线程:并发粒度更细(任务级并行)、并发性更好
线程可提高进程内的并发程度
拥有资源
线程间可以共享资源
系统开销
线程占用资源少
小结
引入线程的优势:线程很轻量,容易创建、撤销
进程v.s. 线程
用户级线程:User level threads(ULT)
内核级线程:Kernel level threads (KLT)
用户级线程和内核级线程的比较
内核级线程是OS内核可感知的,而用户级线程是OS内核不可感知的。
用户级线程的创建、撤消和调度不需要OS内核的支持,是在语言或用户库这一级处理的;而内核级线程的创建、撤消和调度都需OS内核提供支持,而且与进程的创建、撤消和调度大体是相同的。
用户级线程执行系统调用指令时将导致其所属进程的执行被暂停,而内核级线程执行系统调用指令时,只导致该线程被暂停。
用户级线程和内核级线程的总结
在只有用户级线程的系统内,CPU调度还是以进程为单位,处于运行状态的进程中的多个线程,由用户程序控制线程的轮换运行;在有内核级线程的系统内,CPU调度则以线程为单位,由OS的线程调度程序负责线程的调度。
用户级线程的程序实体是运行在用户态下的程序,而内核级线程的程序实体则是可以运行在任何状态下的程序。
混合实现方式
线程模型
有些系统同时支持用户线程和内核线程,由此产生了不同的多线程模型,即实现用户级线程和内核级线程的不同连接方式。
1. Many-to-One Model<img src="https://gitee.com/fuoct/myblog/raw/master/img/image-20240602005720284.png" alt="image-20240602005720284" style="zoom:20%;" /> - 将多个用户级线程映射到一个内核级线程,线程管理在用户空间完成。此模式中,用户级线程对操作系统不可见(即透明)。 - 优点:线程管理是在用户空间进行的,因而效率比较高。 - 缺点:当一个线程在使用内核服务时被阻塞,那么整个进程都会被阻塞;多个线程不能并行地运行在多处理机上。 2. One-to-one Model<img src="https://gitee.com/fuoct/myblog/raw/master/img/image-20240602005801408.png" alt="image-20240602005801408" style="zoom:20%;" /> - 将每个用户级线程映射到一个内核级线程。 - 优点:当一个线程被阻塞后,允许另一个线程继续执行,所以并发能力较强。 - 缺点:每创建一个用户级线程都需要创建一个内核级线程与其对应,这样创建线程的开销比较大,会影响到应用程序的性能。 3. Many-to-Many Model<img src="https://gitee.com/fuoct/myblog/raw/master/img/image-20240602005819497.png" alt="image-20240602005819497" style="zoom:20%;" /> - 将n 个用户级线程映射到m 个内核级线程上,要求m <= n。 - 特点:在多对一模型和一对一模型中取了个折中,克服了多对一模型的并发度不高的缺点,又克服了一对一模型的一个用户进程占用太多内核级线程,开销太大的缺点。又拥有多对一模型和一对一模型各自的优点,可谓集两者之所长。
补充:
Linux并不确切区分进程与线程,而将线程定义为“执行上下文”,它实际只是同一个进程的另外一个执行上下文而已。对于调度,仍然可以使用进程的调度程序。Linux的内核进程,使用kernel_thread创建,一般被称作线程。
有两个系统调用可用以建立新的进程:fork与clone。fork一般用以创建普通进程,而clone 可用以创建线程,kernel_thread便是通过sys_clone来创建新的内核进程。fork与clone都调用do_fork函数执行创建进程的操作。fork并不指定克隆标志,而clone可由用户指定克隆标志。克隆标志有CLONE_VM、CLONE_FS 、CLONE_FILES 、CLONE_SIGHAND 与CLONE_PID等,这些克隆标志分别对应相应的进程共享机制。而fork创建普通进程则使用SIGCHLD标志。
fork:创建普通进程
clone:创建线程
kernel_thread:创建内核进程什么情况下不适合用多线程?
大量计算的情况,同时计算过程不可拆分的情况(计算密集型)
程序的并发执行
进程的同步与互斥
进程互斥(间接制约关系):
进程同步(直接制约关系):
同步与互斥的区别与联系:
互斥:某一资源同时只允许一个访问者对其进行访问,具有唯一性和排它性。互斥无法限制访问者对资源的访问顺序,即访问是无序访问。
同步:是指在互斥的基础上,通过其它机制实现访问者对资源的有序访问。在大多数情况下,同步已经实现了互斥,特别是所有对资源的写入的情况必定是互斥的。少数情况是指可以允许多个访问者同时访问资源。
临界区应当满足的四个条件:
没有进程在临界区时,想进入临界区的进程可进入。
任何两个进程都不能同时进入临界区(MutualExclusion);
任何一个进程进入临界区的请求应该在有限时间内得到满足(Bounded Waiting)。
当一个进程运行在临界区外面时,不能妨碍其他的进程进入临界区(Progress);
死等、忙等、有限等待、让权等待 解释:
机制设计上应遵循的准则
软件方法
Dekker算法:第一个不需要严格轮换的互斥算法
Peterson算法:第一个不需要轮换的互斥算法
Bakery Algorithm(面包店算法):支持任意数量进程
硬件方法
中断屏蔽:使用“开/关中断”指令。
执行“关中断”指令,进入临界区操作;
退出临界区之前,执行“开中断”指令。
优缺点:
简单
不适用于多CPU系统;
往往会带来很大的性能损失:很多日常任务都是靠中
断机制触发的,比如时钟,如果屏蔽中断,会影响时
钟和系统效率;
用户进程的使用可能很危险,例如:关中断之后,不
再打开中断,会导致整个系统无法继续运行;
使用范围:内核进程(少量使用)。
使用test and set指令
TS(test-and-set )是一种不可中断的基本原语(指令)。它会把“1”写到某个内存位置并传回其旧值。在多进程可同时访问内存的情况下,如果一个进程正在执行TS指令,在它执行完成前,其它的进程不可以执行TS指令。
TestAndSet(boolean_ref lock) {
boolean initial = lock;
lock = true;
return initial;
}
自旋锁Spinlocks
利用test_and_set硬件原语提供互斥支持
通过对总线的锁定实现对某个内存位置的原子读与更新
acquire(lock) {
while(test_and_set(lock) == 1)
/* do nothing */;
}
release(lock) {
lock = 0;
}
几个算法的共性问题
无论是软件解法(如Peterson)还是硬件(如TSL或XCHG)解法都是正确的,它们都有一个共同特点:当一个进程想进入临界区时,先检查是否允许进入,若不允许,则该进程将原地等待,直到允许为止。
如果采用用户级线程实现多线程,是否会发生优先级反转(指同一个进程的多个线程)?为什么?
- 优先级反转发生是由于低优先级进程运行在临界区时由于高优先级进程就绪而被切换。如果高优先级进程使用忙等的策略尝试进入临界区,就会一直忙等,使得低优先级进程没有机会离开临界区。
- 如果使用用户级线程,低优先级线程不会被高优先级线程抢占(进入临界区一般需要系统调用,其他线程也同时会被阻塞),因为抢占发生在进程级别。但是对于内核级线程的实现,这个是可能发生的。
同步实现的基本思路
同步中,进程经常需要等待某个条件的发生,如果使用忙等待的解决方案,势必浪费大量CPU时间。
解决方法:将忙等变为阻塞,可使用两条进程间的通信原语:Sleep和Wakeup
信号量
信号量: 一个确定的二元组(s, q),其中s是一个具有非负初值的整型变量,q是一个初始状态为空的队列. 当发出P操作时:
s为正,则该值等于可立即执行的进程的数量;s <= 0,那么发出P操作后的进程被阻塞,│s │是被阻塞的进程数。
q是一个初始状态为空的队列,当有进程被阻塞时就会进入此队列。
信号量的分类
二元信号量机制
通常使用二元信号量的PV操作实现两个进程的互斥。
应用时应注意:
每个进程中用于实现互斥的P、V操作必须成对出现,先做P操作,进临界区,后做V操作,出临界区。
P、V操作应分别紧靠临界区的头尾部,临界区的代码应尽可能短,不能有死循环。
互斥信号量的初值一般为1。
P(S) :while S<=0 do skip;
S:=S-1;
V(S) :S:=S+1;
一般信号量的结构
信号量的操作
信号量在并发中的典型应用
一种低级通信原语:屏障Barriers
“信号量集”机制
P.V操作的优缺点
管程的定义和组成:管程是在程序设计语言当中引入的一种高级同步机制。
Hoare管程
两个队列
Hoare管程的条件变量
Hoare管程的同步原语
Hoare管程:信号量定义
每个管程必须提供一个用于互斥的信号量mutex(初值为1)。
进程调用管程中的任何过程时,应执行P(mutex);进程退出管程时应执行V(mutex)开放管程,以便让其他调用者进入。
为了使进程在等待资源期间,其他进程能进入管程,故在wait操作中也必须执行V(mutex),否则会妨碍其他进程进入管程,导致无法释放资源。
对每个管程,引入信号量next(初值为0),凡发出signal操作的进程应该用P(next)挂起自己,直到被释放进程退出管程或产生其他等待条件。
进程在退出管程的过程前,须检查是否有别的进程在信号量next上等待,若有,则用V(next)唤醒它。next-count(初值为0),用来记录在next上等待的进程个数。
引入信号量x-sem(初值为0),申请资源得不到满足时,执行P(x-sem)挂起。由于释放资源时,需要知道是否有别的进程在等待资源,用计数器x-count(初值为0)记录等待资源的进程数。
执行signal操作时,应让等待资源的诸进程中的某个进程立即恢复运行,而不让其他进程抢先进入管程,这可以用V(x-sem)来实现
进程间通信(Inter-Process-Comm)IPC
无名管道(Pipe)
无名管道应用的一个重大限制是它没有名字,因此,只能用于具有亲缘关系的进程间通信,在有名管道提出后,该限制得到了克服。
FIFO不同于无名管道之处在于它提供一个路径名与之关联,以FIFO的文件形式存在于文件系统中。这样,即使与FIFO的创建进程不存在亲缘关系的进程,只要可以访问该路径,就能够彼此通过FIFO相互通信(能够访问该路径的进程以及FIFO的创建进程之间),因此,通过FIFO不相关的进程也能交换数据。
需注意的是,FIFO严格遵循先进先出(first in firstout),对管道及FIFO的读总是从开始处返回数据,对它们的写则把数据添加到末尾。
共享内存
生产者-消费者问题(the producer-consumer problem)
描述:问题描述:若干进程通过有限的共享缓冲区交换数据。其中,“生产者”进程不断写入,而“消费者”进程不断读出;共享缓冲区共有N个;任何时刻只能有一个进程可对共享缓冲区进行操作。
分析:
解决方法
用PV操作解决生产者/消费者问题
采用Sleep和Wakeup原语的方法
用管程解决生产者消费者问题
拓展:
如果缓冲区大小为无限大
- 是否还需要互斥?
- 是否还有同步?
- 影响生产者,还是消费者?
- 需要,因为缓冲区是共享资源。
- 需要。
- 对消费者没有影响,对生产者有影响(无需等待empty)。
读者-写者问题(the readers-writers problem)
问题描述:对共享资源的读写操作,任一时刻“写者”最多只允许一个,而“读者”则允许多个。即:“读-写”互斥,“写-写”互斥,“读-读”允许。
问题分析
读进程的行为:
系统中会有多个读进程同时访问共享数据。
可分为三类:第一个进入的读进程(占有资源),最后一个离开的读进程(释放资源)和其他读进程。
需要设置一个计数器readcount来记录读进程的数目。
写进程的行为:排他性地使用资源。
确定同步与互斥关系:
确定临界资源:Data, readcount
解决
哲学家进餐问题(the dining philosophers problem)
其他问题
闸机问题
理发师问题
生产者消费者扩展1,2
构建水分子问题
吸烟者问题
读写者-灯开关模式
- 什么是CPU调度?
CPU 调度的任务是控制、协调多个进程对CPU 的竞争。也就是按照一定的策略(调度算法),从就绪队列中选择一个进程,并把CPU 的控制权交给所选中的进程。- CPU调度的场景
- N 个进程就绪,等待CPU
- M个CPU,M≥1
- OS需要决策,给哪个进程分配哪个CPU 。
何时进行调度(When)
CPU切换过程(How)
调度的类型
高级调度:又称为“宏观调度”、“作业调度”。从用户角度,一次提交若干个作业,对每个作业进行调度。时间上通常是分钟、小时或天。
中级调度:又称为“内外存交换”,指令和数据必须在内存里才能被CPU直接访问。从存储器资源管理的角度,将进程的部分或全部换出到外存上,将当前所需部分换入到内存。
低级调度:又称为“微观调度”、“进程或线程调度”。从CPU资源管理的角度,执行的单位。时间上通常是毫秒。因为执行频繁,要求在实现时达到高效率。
调度性能准则
面向用户的调度性能准则
周转时间:作业从提交到完成(得到结果)所经历的时间。包括:在收容队列中等待,CPU上执行,就绪队列和阻塞队列中等待,结果输出等待--批处理系统
响应时间:用户输入一个请求(如击键)到系统给出首次响应(如屏幕显示)的时间--分时系统
面向系统的调度性能准则
吞吐量、平均等待时间和平均周转时间公式
(Turnover Time)
=完成时刻- 提交时刻四种调度算法
最简单的调度算法,按先后顺序调度。
按照作业提交或进程变为就绪状态的先后次序,分派CPU;
当前作业或进程占用CPU,直到执行完或阻塞,才让出CPU(非抢占方式)。
在作业或进程唤醒后(如I/O完成),并不立即恢复执行,通常等到当前作业或进程让出CPU。
FCFS的特点
比较有利于长作业,而不利于短作业。
有利于CPU繁忙的作业,不利于I/O繁忙的作业。
短作业优先SJF
又称为“短进程优先”SPN(Shortest Process Next);这是对FCFS算法的改进,其目标是减少平均周转时间。
优点:
比FCFS改善平均周转时间和平均带权周转时间,缩短作业的等待时间;
提高系统的吞吐量;
缺点:
对长作业非常不利,可能长时间得不到执行;
未能依据作业的紧迫程度来划分执行的优先级;
难以准确估计作业(进程)的执行时间,从而影响调度性能。
最短剩余时间优先SRTN
最高响应比优先HRRN
时间片轮转(RR:Round Robin)
本算法主要用于微观调度,设计目标是提高资源利用率。其基本思路是通过时间片轮转,提高进程并发性和响应时间特性,从而提高资源利用率;
步骤
将系统中所有的就绪进程按照FCFS原则,排成一个队列。
每次调度时将CPU分派给队首进程,让其执行一个时间片。时间片的长度从几个ms到几百ms。
在一个时间片结束时,发生时钟中断。
调度程序据此暂停当前进程的执行,将其送到就绪队列的末尾,并通过上下文切换执行当前的队首进程。
进程可以未使用完一个时间片,就让出CPU(如阻塞)。
多级队列(MQ:Multi-level Queue)
多级反馈队列(MFQ: Multi-level Feedback Queue )
多级反馈队列算法是时间片轮转算法和优先级
算法的综合和发展。优点:
几点说明
优先级反转(倒置)的解决方法
P31
P42
一组进程中,每个进程都无限等待组内其他进程所占有的资源,在无外力介入的条件下,将因永远分配不到资源而无法运行的现象。
死锁发生原因
死锁发生的四个必要条件
活锁和饥饿
活锁(livelock):是指任务或者执行者没有被阻塞,由于某些条件没有满足,导致一直重复尝试,失败,尝试,失败。
饥饿(starvation):某些进程可能由于资源分配策略的不公平导致长时间等待。当等待时间给进程推进和响应带来明显影响时,称发生了进程饥饿,当饥饿到一定程度的进程所赋予的任务即使完成也不再具有实际意义时称该进程被饿死(starve to death)
处理死锁方法
死锁预防
打破互斥条件:即允许进程同时访问某些资源。但是,有的资源是不允许被同时访问的,像打印机等等,这是资源本身的属性。
打破请求且保持的条件:可以实行资源预先分配策略。只有当系统能够满足当前进程的全部资源需求时,才一次性地将所申请的资源全部分配给该进程,否则不分配任何资源。由于运行的进程已占有了它所需的全部资源,所以不会发生占有资源又申请资源的现象,因此不会发生死锁。
但是,这种策略也有如下缺点:
1. 在许多情况下,由于进程在执行时是动态的,不可预测的,因此不可能知道它所需要的全部资源。
2. 资源利用率低。无论资源何时用到,一个进程只有在占有所需的全部资源后才能执行。即使有些资源最后才被用到一次,但该进程在生存期间却一直占有。这显然是一种极大的资源浪费;
3. 降低进程的并发性。因为资源有限,又加上存在浪费,能分配到所需全部资源的进程个数就必然少了。
死锁避免
死锁预防是排除死锁的静态策略,它使产生死锁的四个必要条件不能同时具备,从而对进程申请资源的活动加以限制,以保证死锁不会发生。
死锁的避免是排除死锁的动态策略,它不限制进程有关资源的申请,而是对进程所发出的每一个申请资源命令加以动态地检查,并根据检查结果决定是否进行资源分配。即分配资源时判断是否会出现死锁,有则加以避免。如不会死锁,则分配资源。
死锁避免不那么严格限制产生死锁的四个必要条件(区别于死锁预防)
银行家算法
银行家算法(Dijkstra, 1965)一个银行家把他的固定资金(capital)贷给若干顾客。只要不出现一个顾客借走所有资金后还不够,银行家的资金应是安全的。银行家需一个算法保证借出去的资金在有限时间内可收回。
为了保证资金的安全,银行家规定:
假定顾客借款分成若干次进行;并在第一次借款时,能说明他的最大借款额。具体算法:
银行家算法特点
检测死锁:保存资源的请求和分配信息,利用某种算法对这些信息加以检查,以判断是否存在死锁。死锁检测算法主要是检查是否有循环等待。
死锁解除
设备的管理的目的和功能
I/O管理示意(软件角度)
用户进程在运行过程中,提出I/O 请求, 一旦请求被操作系统接受,操作系统则负责完成该请求。
我们把硬件设备抽象为控制器。控制器中包含控制寄存器、状态寄存器,以及一些数据寄存器。从操作系统角度,是通过对这些寄存器进行相应的控制,达到控制设备的目的。
在OS中,I/O 设备管理可直接从应用程序或文件系统得到请求,并负责完成这个请求。它具体包括:
逻辑I/O :完成设备无关的操作,如设备分配,设备回收
数据准备等;
设备驱动程序:负责对设备控制器进行控制(通过读写其中的寄存器)。
中断服务程序:设备工作结束后负责向CPU 发中断信号,中断服务程序完成相应处理。
I/O管理的特点
设备控制器
I/O端口地址
内存映射I/O的特点
优点:
不需要特殊的保护机制来阻止用户进程进行相应的I/O 操作。操作系统要避免把包含了控制寄存器的那部分地址空间放入用户的虚拟地址空间中。
可以引用内存的每一条指令都可以适用于引用控制寄存器。
缺点:
I/O独立编址的特点
优点:
外设不占用内存的地址空间
编程时,易于区分是对内存操作还是对I/O操作
缺点:
P31
程序控制I/O,也称轮询或查询方式I/O,它由CPU代表进程向I/O模块发出指令, 然后进入忙等状态, 直到操作完成之后进程才能够继续执行。
中断驱动, 当I/O操作结束后由设备控制器主动地来通知设备驱动程序, 而不是依靠设备驱动程序不断地去轮询看看设备的状态。
DMA,直接存储器访问方式, 是由一个专门的控制器来完成数据从内存到设备或者是从设备到内存的传输工作。
通道与DMA的原理几乎是一样的,通道是一个特殊功能的处理器,它有自己的指令和程序专门负责数据输入输出的传输控制。CPU将“传输控制”的功能下放给通道后只负责“数据处理”功能。这样,通道与CPU分时使用内存,实现了CPU内部运算与I/O设备的并行工作。
单缓冲(single buffer)
每当用户进程发出一个I/O请求时,操作系统便在主存中为之分配一个缓冲区,T、M,C的定义见下图。由于T和C是可以并行的,当T>C时,系统对每一块数据的处理时间为M+T,反之,为M+C,系统对每一块数据的处理时间为Max(C,T) + M。
双缓冲(double buffer)
两个缓冲区,CPU和外设都可以连续处理而无需等待对方。要求CPU的处理速度和外设速度相近。在双缓冲时,系统处理一块数据的时间可以粗略地认为是Max(C,T),如果C<T,可使块设备连续输入,如果C>T,则可使CPU不必等待设备输入。
环形缓冲(circular buffer)
若CPU和外设的处理速度差较大,双缓冲效果不够理想,因此引入了多缓冲机制,可将多个缓冲组织成循环缓冲形式。对于用作输入的循环缓冲,通常是提供给输入进程或计算进程使用,输入进程不断向空缓冲去输入数据,而计算进程则从中提取数据进行计算。
循环缓冲区的组成如下
多个缓冲区,在循环缓冲区中包括多个缓冲区,每个缓冲区的大小相同,作为输入的多缓冲区可分为三种类型,用于装输入数据的空缓冲区R、已装满数据的缓冲区G以及计算进程正在使用的工作缓冲区C。
多个指针,作为输入的缓冲区可设置三个指针,用于指示计算进程下一个可用缓冲区G的指针Nextg、指示输入进程下次可用的空缓冲区R的指针Nexti、以及用于指示计算进程正在使用的缓冲区C的指针Current。
缓冲池
P70
基本概念
扇区(sector):盘片被分成许多扇形的区域
磁道(track): 盘片上以盘片中心为圆心,不同半径的同心圆。
柱面(cylinder):硬盘中,不同盘片相同半径的磁道所组成的圆柱。
每个磁盘有两个面,每个面都有一个磁头(head)。
- 距离轴心最远的柱面/磁道编号为0
- 外道数据访问速度更快
磁盘的组织
读一个扇区需要“柱面/磁头/扇区”三个参数
现代磁盘驱动器可以看做一个一维的逻辑块的数组,逻辑块是最小的传输单位
一维逻辑块数组按顺序映射到磁盘的扇区。
扇区0是最外面柱面的第一个磁头(磁道)第一个扇区。
该映射是先按磁道内扇区顺序,再按柱面内磁道顺序,再按从外到内的柱面顺序来排序的。
Flash Disk
Flash Disk的特征是低功耗、大容量、数据访问速度高。
Flash Disk执行一次数据读写的周期比硬盘短。
问题:容量、价格、寿命(P/E)、可靠性、读写不对称(读快、写慢)。
Flash Disk两种技术:NAND / NOR
CHS模式: Cylinder, Header, Sector
8.46GB问题:CHS模式
第2至第4字节是该分区起始地址。其中第2字节为起始磁头号(面号);第3字节的低6位为起始扇区号,高2位则为起始柱面号的高2位;第4字节为起始柱面号的低8位。
柱面号最大值为2^10 = 1024(0~1023)
扇区号不会超过2^6 - 1 = 63(0~63)
磁头号不会超过2^8 = 256(0~255)
这个扇区之前的所有物理扇区所包含的字节数为:
磁盘空间的管理
P16
磁盘访问时间
四种磁盘调度算法
先来先服务算法(FCFS)
最短寻道时间优先算法(SSTF)
扫描算法(SCAN)电梯调度:反复来回
循环扫描算法(C-SCAN):单向
算法思想:
按照所要访问的柱面位置的次序去选择访问者。
移动臂到达最后一个柱面后,立即带动读写磁头快速返回到0号柱面。
返回时不为任何的等待访问者服务。
返回后可再次进行扫描。
由于SCAN算法偏向于处理那些接近中间磁道的访问请求,所以使用改进型的C-SCAN算法可避免这个问题
“磁臂粘着”现象:有一个或几个进程对某一磁道有较高的访问频率, 即这个(些)进程反复请求对某一磁道的I/O操作,从而垄断了整个磁盘设备。
P29
RAID
RAID分级
P33
文件控制块
文件逻辑结构和物理结构
物理结构的三种结构
连续结构
优点:
缺点:
文件长度一经固定便不易改变,容易出现磁盘碎片;
不利于文件的动态增加和修改;
适合于变化不大的文件
串联结构
什么是串联结构
串联文件结构是按顺序由串联的块组成的,即文件的信息按存储介质的物理特性存于若干块中。
每个物理块的最末一个字(或第一个字)作为链接字,它指向后继块的物理地址。链首指针存放在该文件目录中。文件的结尾块的指针为“∧”,表示文件至本块结束。
对于记录式文件,一块中可包含一个逻辑记录或多个逻辑记录,也可以若干物理块包含一个逻辑记录。
优点:
缺点:
索引结构
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。