基于王道OS
1.0版本是 北航软院OS课程笔记
2.0版本是 保研复习笔记
计算机系统:硬件、操作系统、应用程序、用户
操作系统是指控制和管理整个计算机系统的硬件和软件资源,合理地组织、调度计算机的工作与资源分配,进而为用户和其他软件提供方便的接口与环境的程序集合。操作系统是计算机系统中最基本的系统软件。
并发是指两个或多个事件在同一时间间隔内发生。操作系统的并发性是指计算机系统中同时存在多个运行的程序。
操作系统中引入进程的目的就是为了实现并发。
宏观上,多个程序是同时执行的。微观上,每个时刻只有一个程序执行。即操作系统的并发性是通过分时实现的。
并发和并行的区别
系统资源可供内存中多个并发执行的进程共同使用。
互斥共享方式:虽然可供多个进程使用,但规定一段时间内只允许一个进程访问该资源。
同时访问方式:允许一段时间内同时由多个进程访问。(指宏观意义上的同时)
并发与共享互为条件
将物理实体抽象为逻辑对应。即将物理上的硬件变为逻辑上用户感觉到的事物。
例子:
虚拟处理器技术,是将一个物理上的CPU虚拟为多个逻辑上的CPU,使其能同时为多个用户服务;
虚拟内存,将一台机器上的物理存储器变为虚拟存储器,从而从逻辑上扩充存储器容量;
虚拟外设,将一台物理I/O设备虚拟为多台逻辑I/O设备,使每个用户能够占用一台。
操作系统的虚拟技术可以分为时分复用技术(虚拟处理器)、空分复用技术(虚拟存储器)。
多个程序并发执行时,由于资源有限,他们并不是一贯到底的,而是走走停停的,它以不可预知的速度向前推进,这就是操作系统的异步性。
处理机管理:即对进程的管理,进程控制、进程同步、进程通信、死锁处理、处理机调度
存储器管理:内存分配与回收、地址映射、内存保护与共享、内存扩充等
文件管理:即对文件系统的管理,包括文件存储空间的管理、目录管理、文件读写管理和保护等
设备管理:完成用户I/O请求,方便用户使用各种设备,并提高设备利用率;包括缓冲管理、设备分配、设备处理和虚拟设备等
命令接口(用户通过这些命令来组织和控制作业执行)
联机命令接口(用户和操作系统之间的交互性)、脱机命令接口(用户提供Mission List,系统依次完成)
程序接口(即系统调用)
图形接口(即GUI,图形用户界面)
将裸机改造成功能更强、更方便使用的机器。
手工操作阶段
批处理阶段(用户只能事先编写作业控制说明书,作业执行时用户无法干预;单道批处理、多道批处理)
分时操作系统(按时间片划分CPU资源分给各作业使用,并进行时间片轮转,如果一个作业在这一个时间片内没有执行完,它需要让出CPU资源等待下一次调度。由于计算机速度很快,作业运行轮转得也快,因此给每个用户的感觉就像是自己独占一台计算机)
实时操作系统(紧急任务不需排队。及时性,可靠性)
网络操作系统(把网络中各台计算机连接起来,共享资源,数据传送)
分布式计算机系统(各台计算机地位平等)
个人计算机操作系统(Windows、Linux)
嵌入式操作系统、服务器操作系统、智能手机操作系统
CPU执行的程序有两种:内核程序和用户程序。内核程序可以执行一些特权指令,如I/O指令、置中断指令等,而出于安全考虑,用户程序不能。
具体实现方式是将CPU划分为用户态和内核态两个状态。当CPU处于内核态时才能执行内核程序的特权指令,否则不能。
层次式结构的操作系统:最底层是与硬件关联紧密的模块,如时钟管理、中断处理、设备驱动等;其次是运行频率较高的程序,如进程管理、存储器管理和设备管理。这两部分内容构成了操作系统的内核。
操作系统内核大致包含以下四部分内容:
按照层级结构设计的操作系统,其底层必然是一些可被调用的公用小程序,它们各自完成一个操作。
相当于有特定功能的原子性的小工具函数。将这些函数称为原语。
定义原语的方法:关闭中断,让其所有动作不可分割地完成之后再打开中断。
进程管理
存储器管理
设备管理
CPU从用户态进入内核态的唯一方式是通过中断或异常。
指来自CPU执行指令以外的事件发生,如设备发出的I/O结束中断,表示设备输入/输出已完成;时钟中断,表示一个固定时间已到,让处理机处理计时、启动定时运行的任务等。外中断是强迫中断。
指源自CPU执行指令内部的事件,如程序的非法操作码、地址越界、算术溢出、缺页中断(强迫中断)及专门的陷入指令(自愿中断)等引起的事件。
有些异常,如非法指令、除数为零等异常,无法通过异常处理程序恢复故障,因此不能回到原断点执行,必须终止进程。
其中1—3是由硬件自动完成的(中断隐指令),4—9是由操作系统的中断处理程序完成的。
系统调用的处理由操作系统内核态来完成,用户可以执行陷入指令来发起系统调用,请求操作系统提供服务。用户执行陷入指令,相当于把CPU的使用权主动交给操作系统内核程序(CPU会从用户态进入内核态),随后操作系统对系统调用请求做出处理,处理完成后将CPU使用权再还给用户。
引入系统调用的目的是:用户不能直接执行对系统有很大影响的命令,必须通过系统调用这一接口来完成,这样可以保证系统运行的稳定性和安全性。
系统调用是操作系统内核提供给用户的接口,它发生在用户态;而系统调用的处理函数是对系统有较大影响的操作,是操作系统内核预设的操作,发生在内核态
所以外部中断、缺页、系统调用、陷入指令都发生在用户态;而其处理函数发生在内核态。(所以trap指令不是特权指令)
系统调用的执行顺序:① 传递系统调用参数 ② 执行陷入指令 ③ 执行相应的服务程序 ④ 返回用户态
引入进程的目的:更好地描述和控制程序的并发执行,实现操作系统的并发性和共享性。
进程控制块PCB(Process Control Block)
进程是系统进行资源分配和调度的一个独立单位
动态性
进程与程序是截然不同的两个概念,进程是程序的一次执行过程,包括创建、活动、暂停、终止等,是动态的。而程序只是静态的代码。
并发性
多个进程存在于内存中可以并发执行
独立性
指进程是一个能独立运行、独立获得资源和独立接受调度的基本单位。
异步性
由于进程之间的相互制约,使得进程具有独立执行的间断性。即进程不可预知的速度向前推进,这会导致执行结果的不可再现性,为此操作系统必须配置相应的同步机制。
结构性
每个进程都配置一个PCB对其进行描述。从结构上看,进程实体是由程序段、数据段和进程控制块三部分组成的。
区别就绪态和阻塞态,就绪态是指进程已经得到了除处理机外的所有资源,一旦得到处理机,就能立即执行。而阻塞态(等待态)是指由于正在等待某一事件而暂停运行。就绪态是已得到资源,等待处理机;而阻塞态是等待资源。
img进程状态转换
系统由运行态进入阻塞态是主动的行为,是由于进程主动请求某一资源失败导致的;而由阻塞态进入就绪态是被动的行为,一定是由于其他进程对资源的占用状态发生了变化而引起的。
线程请求资源失败进入阻塞态,线程被高优先级线程抢占进入就绪态。
子进程继承父进程的资源,子进程退出时要将其使用的资源归还给父进程,父进程退出时必须退出所有子进程。
进程创建原语:
进程终止原因:① 正常结束;② 异常结束:进程发生异常事件而结束 ③ 外界干预:进程应外界请求而终止运行,如父进程请求、父进程终止、操作员或操作系统干预等。
进程终止/退出/撤销原语:
进程的阻塞指正在执行的进程由于请求系统资源失败、等待某种操作、新数据尚未到达等,由系统自动执行阻塞原语,使自己由运行态转为阻塞态。进程的阻塞是进程主动的动作。
阻塞原语:
唤醒原语:
调度和切换:调度是指决定资源分配给哪个进程,是一种决策行为;切换是指实际的分配行为,是执行行为。先有资源的调度,后有进程的切换。
PCB是进程存在的唯一标志。
进程描述信息:进程标识符PID、用户标识符UID
进程控制和管理信息:进程当前状态、进程优先级、代码运行入口地址、程序的外存地址、进入内存时间、CPU占用时间、信号量
资源分配清单:代码段指针、数据段指针、堆栈段指针、文件描述符、键盘、鼠标
CPU相关信息:通用寄存器值、地址寄存器值、控制寄存器值、标志寄存器值、状态字
进程PCB表通常包括链接方式和索引方式两种。将不同状态的进程放在不同的队列或索引表中。
程序段就是能被进程调度程序调度到CPU执行的程序代码段。程序可被多个进程共享。
一个进程的数据段可以是进程对应的程序加工处理的原始数据,也可以是程序执行时产生的中间或最终结果。
低级通信方式:PV操作。
高级通信方式能够高效传输大量数据。
多个进程可以共享某一块区域,都可以对其进行读写操作。但是需要通过同步互斥工具(PV操作等)进行控制。
低级:基于结构体的共享
高级:基于存储区的共享
进程间数据以格式化的消息为单位传递,通过发送消息和接收消息的原语进行数据交换。
直接通信
间接通信
管道是指用于连接读进程和写进程以实现它们之间的通信的一个共享文件,又名pipe文件。向管道提供写进程,以字符流的形式将大量数据送入写管道,读进程从管道中读数据。
为了协调双方通信,管道必须提供同步、互斥和确定对方存在三个功能。
半双工通信。
引入线程的目的:减小程序在并发执行时所付出的时间和空间开销,提高操作系统的并发性能。
线程不拥有资源,但与同一进程中的其他线程共享资源。进程是资源分配的最小单位,线程是调度的最小单位。
线程实现的方式:用户级线程、内核级线程、组合方式。
用户级线程中线程的管理和调度由应用程序在用户空间完成,内核意识不到线程的存在(即对内核来说仍然是一整个进程)。
内核级线程中线程的管理和调度在内核空间中完成,用户空间只有相应接口。
多线程模型
多对一模型
将多个用户级线程映射到一个内核级线程,线程的管理在用户空间中完成。效率高,但并发能力欠缺。
一对一模型
将每个用户级线程映射到一个内核级线程。并发能力强,但开销大。
多对多模型
将m个用户级线程映射到n个内核级线程。m<=n
作业调度:从外存中选取后备作业,为其分配内存、设备等
内存调度:将暂时不能运行的进程调至外存等待,此时进程状态为挂起态。内存调度的作用是提高内存利用率和系统吞吐量。
进程调度:从进程就绪队列中选取一个进程运行
不能进行进程调度的情况:
应当进行进程调度的情况:
请求调度事件 -> 进程调度程序 -> 调度新的就绪程序 -> 进程切换
会导致饥饿现象
按照优先级调度,有抢占和不抢占两种
系统进程 > 用户进程;交互型进程 > 非交互型进程;I/O型进程 > 计算型进程;
相应比Rp = (等待时间 + 要求服务时间)/(要求服务时间)
按照先后顺序调度作业,但每次调度只能运行一个时间片。
如果时间片很大,那么时间片轮转就变成了先来先服务。
如果时间片很小,系统会在进程切换中耗费很大的开销,降低效率。
一次仅允许一个进程使用的资源称为临界资源,如打印机等。对临界资源的访问必须互斥地进行,访问临界资源的那段代码称为临界区。
进入区
在进入区检查是否可以进入,如果能,则应设置正在访问临界区的标志,以阻止其他进程同时进入临界区
临界区
进程中访问临界资源的那段代码,又称临界段
退出区
将正在访问临界区的标志清除
剩余区
代码中的其余部分
也称直接制约关系,是指为完成某个任务建立的两个或多个进程,这些进程因为需要在某些位置上协调他们的工作次序而等待、传递信息所产生的制约关系。
也称间接制约关系,当一个进程进入临界区使用临界资源时,另一个进程必须等待。
为禁止两个进程同时进入临界区,同步机制应遵循以下原则:
软件:单标志法;双标志法先检查;双标志法后检查;Peterson’s Algorithm;
硬件:中断屏蔽方法;硬件指令方法。
信号量可以用来解决同步和互斥的问题,它只有两个原语:wait(P操作)和signal(V操作)。
wait操作/P操作表示请求一个资源,signal操作/V操作,表示释放一个资源
整型信号量(忙等的实现方式):请求不到资源就重复请求,直到请求到为止
记录型信号量(非忙等的实现方式):请求不到资源就将线程加在资源的等待队列中,资源闲置后唤醒等待队列中的进程
semaphore S = 0; // 初始化为0
// 同步:P1、P2需要按次序执行
P1(){
...
V(S); // 在P1末尾给S加一
}
P2(){
P(S); // S一开始为0,P2无法执行,必须等P1执行完在末尾加上1后,P2才能执行
...
}
信号量的初始值代表资源个数
semaphore S = 1;
P1(){
P(S); // P1、P2都在程序起始处尝试获取资源,因为S初始值为1,只能有一个进程获取到
// P1临界区内容
V(S);
}
P2(){
P(S);
// P2临界区内容
V(S);
}
前驱关系与同步一样,只是这里涉及的顺序更复杂一些而已,因此每一个前驱关系设置一个信号量,并将他们都初始化为0,在前面的进程末尾执行V操作,在后面的进程起始处执行P操作
管程类似一个类,将对共享资源的操作都封装起来,其中包括共享数据结构S、对S的初始化函数init_code()、申请资源函数take_away()、归还资源函数give_back()等。
条件变量,每个条件变量有一个等待队列,实现了排队等待功能
与信号量的区别是:信号量是有值的,其值反应了共享资源剩余个数,而条件变量仅实现了将等待资源的进程加入等待队列中。
如果没有条件变量,当一个进程进入管程后被阻塞,但进程没有释放管程,此时其他进程无法再进入管程
monitor Demo{// 设置一个名为Demo的管程
共享数据结构S;
condition x; // 条件变量x
init_code(){
S=3;
}
take_away(){
if(S <= 0)
x.wait(); // 如果资源不够,将进程加入x的等待队列中,即将进程阻塞在条件变量x上
...; // 如果资源足够,分配资源,执行操作
}
give_back(){
...; // 归还资源,做一系列操作
if(有进程在等待)
x.signal(); // 唤醒一个等待进程
}
}
生产者-消费者问题
设置互斥信号量mutex,full表示缓冲池中满缓冲区数,empty表示缓冲池中空缓冲区数。
mutex = 1;
full = 0; // 是缓冲区中生产出的物品总量
empty = n; // 是缓冲区中空闲的位置总量
producer(){
while(1){
produce an item;
P(empty); // 占用一个空缓冲区,消耗什么P什么
P(mutex); // 互斥信号量
add nextp to buffer;
V(mutex); // 互斥信号量
V(full); // 满缓冲区加一,提供什么V什么
}
}
consumer(){
while(1){
P(full); // 消耗什么P什么
P(mutex);
remove an item from buffer;
V(mutex);
V(empty);
consume the item;
}
}
复杂的生产者-消费者问题
plate = 1;
apple = 0;
orange = 0;
dad(){
while(1){
prepare an apple;
P(plate); // 爸爸和妈妈对盘子的访问是互斥的
put the apple on the plate;
V(apple);
}
}
mother(){
while(1){
prepare an orange;
P(plate); // 爸爸和妈妈对盘子的访问是互斥的
put the orange on the plate;
V(orange);
}
}
son(){
while(1){
P(orange);
take the orange from the table;
V(plate);
eat the orange;
}
}
daughter(){
while(1){
P(apple);
take the apple from the plate;
V(plate);
eat the apple;
}
}
读者-写者问题
死锁即因为多个进程互相等待资源而造成的僵局。
使死锁的四个条件中的某一个不会达成(四种方法都不太好)
系统安全状态
系统分配资源前先计算资源分配的安全性,如果安全允许分配,否则不允许
银行家算法
死锁解除:
资源剥夺法
撤销进程法
进程回退法
内存管理:操作系统对内存的划分和动态分配
功能:
创建进程首先要将程序和数据装入内存,步骤是:
编译:由编译程序将用户源代码编译成若干目标模块
链接:链接库函数,形成一个完整的装入模块
装入:由装入程序将装入模块装入内存运行
程序链接的三种方式:静态链接、装入时动态链接、运行时动态链接
装入模块在装入内存时的三种方式:绝对装入、可重定位装入、动态运行时装入
内存保护
保护操作系统不受用户进程的影响,且用户进程之间不会互相影响
单一连续分配:
系统区在低地址部分,供操作系统使用;用户区在高地址部分,供用户使用。
优点:简单、无外部碎片
缺点:只能供单用户、单任务的操作系统使用。
固定分区分配:
将内存划分为若干固定大小的区域,每一个区域只装入一道作业。分区大小相等或分区大小不等(提前划分为多个个小分区、适量中等分区和少量大分区,与动态分区并不相同)。
优点:无外部碎片
缺点:某程序可能因为太大而不能装进任何一个分区中;程序如果比较小会存在内部碎片。
动态分区分配:
不预先划分内存,而是在进程装入时根据进程大小动态建立分区,并使分区大小正好适合进程需要
使用一段时间后会导致内存中存在很多小的碎片,可以使用紧凑技术来解决。
将内存和进程都按照块划分,进程中的块称为页Page,内存中的块称为页框Page Frame,外存也以同样的单位划分,称为块Block。进程执行时申请主存空间,即为每个页分配主存中的可用页框。
每页大小4KB。
页面太小:会导致进程需要大量页面,页表占用大量内存空间,同时增加硬件地址转换开销,降低页面换入换出的效率
页面太大:会导致内部碎片,降低内存利用率
逻辑地址结构:页号(20位)+页内偏移量(12位)
页号:地址空间最多允许220页
页内偏移量:4KB = 4 × 1024B = 1012B
页表:存放页号到物理块号的映射关系
页表寄存器PTR:存放页表位置,即页表在内存中的起始地址F和页表长度M。
设页面大小为L,则逻辑地址到物理地址的变换过程:
① 计算页号P和页内偏移量W
② 比较P和页表长度M,如果P>=M,产生缺页中断
③ F+P×L得页表中物理块号的存放地址,读出物理块号b
④ b×L+W即得物理地址
快表TLB
具有并行查找能力的高速缓存器,将常用的页表项放在快表中,快表查询不到再去慢表查,提升页表查询速度。
由于局部性原理,快表命中率可达90%以上
两级页表
一级页号+二级页号+页内偏移量
顶级页表只有一个页面,能存放4KB/4B=1024个页表项,因此一级页号占用10位
由于页内偏移需要12位,因此二级页号占用10位,这样就可以将二级页表控制在一页范围内,提高页表查询效率
先分段再分页
逻辑地址:段号 + 页号 + 页内偏移量
首先,在段表中根据段号找到该段的页表始址
然后,在页表中根据页号找到该页的起始地址
最后,该页起始地址+页内偏移量即指定地址
局部性原理:
虚拟内存原理:
程序装入时,只将程序的一部分装入内存,而将其余部分留在外存,就可以启动程序执行。程序执行过程中,如果访问的信息不在内存,操作系统通过缺页中断处理程序将其调入内存,然后继续执行程序。另一方面,操作系统将暂时不用的内容换出到外存上,以腾出内存空间。
这样,系统好像为用户提供了一个比实际内存空间大得多的存储空间,称之为虚拟内存。
虚拟内存必须在离散分配的内存管理系统中才能实现。
请求分页系统页表需包含以下内容:
页号 + 物理块号 + 状态位P + 访问字段A + 修改位M + 外存地址
状态位P:指示该页是否已调入内存
访问字段A:记录本页在一段时间内被访问的次数
修改位M:标识该页调入内存后是否被修改过
外存地址:指出该页在外存中的地址,通常是物理块号
当所需页不在内存中时,就会产生缺页中断,缺页中断是内中断(异常)。
处理流程如下:程序因缺页中断而被阻塞,操作系统进行缺页中断的处理。如果内存中有空闲块,就分配一个块,将外存中的一个页装入该块中。如果内存中没有空闲块,就将内存中的一个块换出腾出空间,再将需要的块调入内存。完成后将缺页的进程唤醒。
内存没有空间的时候决定换出哪一个页的算法
淘汰以后永远不适用的页面,或在最长时间内不会被访问的页面(未来)
无法实现,但是可以用来评价其他算法
优先淘汰进入内存最早的页面
可能出现Belady异常
选择最近最长时间未被访问过的页面淘汰,应用局部性原理,认为过去一段时间内未访问过的页面,在最近的未来也不会访问
实现:为每个页面设置一个访问字段,记录自上次访问以来经过的时钟周期数
设置使用位u用以标记页面是否被访问过,设置修改位m用以标记页面是否被修改过
换出时搜索内存中所有页面,选择顺序如下:
TODO
频繁发生缺页中断
文件是以计算机硬盘为载体的存储在计算机上的信息集合。
在计算机资源调度和分配中,计算机以进程为基本单位;在用户输入、输出中,计算机以文件为基本单位。
名称
标识符:标识文件系统内文件的唯一标签
类型
位置
大小
保护
时间、日期和用户标识
所有文件信息都保存在目录结构中,而目录结构保存在外存中。文件信息在需要时才调入内存。
创建文件:在文件系统中为文件找到空间;在目录中为新文件创建目录条目。
写文件:执行一个系统调用,指明文件名称和要写入的内容。系统通过搜索目录中的文件名称获得文件的起始位置,系统会为文件设置一个写指针,初始化为文件起始位置,每次写入操作从写指针开始,并在写入时更新写指针。
读文件:执行一个系统调用,指明文件名称和要读入文件块的内存位置。同样,系统搜索目录中的文件名称获得文件位置等信息,系统为文件设置一个读指针
文件重定位:按某条件搜索目录,将当前文件位置设置为指定位置
删除文件:先在目录项中找到文件的目录项,删除目录项,然后回收空间。
截断文件:文件所有属性不变,但删除其内容,即将文件长度设为0
文件的读、写、重定位、删除等都涉及搜索给定文件的目录项的操作,因此将其抽象为系统调用open。
系统调用open的功能是,将指定文件的属性从外存复制到内存中的打开文件表中,并返回一个指向打开文件表对应条目的指针。
操作系统在第一次使用文件时调用open系统调用,系统再次使用文件时只需根据指针在打开文件表中获得指定文件的索引,而不需要重复在目录中搜索文件。
当进程不再需要使用文件时,操作系统将文件从打开目录表中删除,进程完成关闭文件的操作。
另外,文件还需保存的信息有:
第一位文件类型:-表示文件,d表示目录
文件权限标识:顺序为rwx,另外还可以将其有无对应权限表示为二进制的1和0,并用数字代表权限,例如777表示rwx
没有结构,数据按顺序组织成记录
顺序文件:文件中记录一个接一个的排列,有顺序存储、链表存储两种方式,顺序文件的顺序有关键字顺序和时间顺序两种。
索引文件:对于每条记录定长的文件,可以通过直接计算得到第i条数据的位置,但对于记录不定长的文件,顺序文件只能遍历前i-1条数据,效率较低。因此我们可以引入索引文件,记录记录序号和对应指针。
索引顺序文件:将顺序文件的所有记录分为若干组,每组第一条记录的关键字值作为该组在索引表中的关键字值,并对应每组第一条记录的位置。类似于词典中将所有单词按照首字母分为26组,每组在索引表中对应一条索引,组与组之间按顺序排列。
查找某记录时先确定其分组,根据分组索引表找到组起始位置,然后在组中顺序查找对应记录位置。
散列文件或直接文件:根据文件关键字,通过散列函数计算出应存储的物理地址
目录中存储的每一个文件的条目是一个文件控制块(FCB),其中包含下列信息:
UNIX系统中,将除文件名之外的其他描述信息放在索引结点中,目录中存放的是文件名和索引结点编号。这样,在检索目录时,不需要将大量其他文件的文件描述信息随目录一起调入内存,只需要将最轻量的文件名和索引结点编号调入内存并检索即可。当找到指定文件目录项时,才根据索引结点编号将对应索引结点调入内存。
每一个文件都有一个唯一的索引结点存在在磁盘中,称为磁盘索引结点,当需要使用这个文件时,将磁盘索引结点复制到内存中。
单级目录结构:整个文件系统只有一张目录表,文件名不能重复
两级目录结构:分为主文件目录和用户文件目录,主文件目录记录所有用户文件目录所在位置,用户文件目录记录该用户的所有文件的信息
多级目录结构(树形):用.
表示当前目录
无环图目录结构:
对于文件F,其所有者为用户A,当用户B要共享该文件时,只需在用户B的目录中添加一个目录项,指向文件F的索引结点
对于文件F,其所有者为用户A,当用户B要共享该文件时,需要在系统中创建一个LINK型的文件L,用户B的目录中添加一个目录项指向L,L中的内容是文件F的路径名。
对于硬链接,当其中一个用户需要删除文件时,不能将文件直接删除,否则其他共享该文件的用户其目录项中的文件指针会悬空。其删除操作是,将文件的链接计数器count的值减1,然后删除自己目录中的目录项。
对于软链接,当文件拥有者要删除文件时,可以将文件直接在磁盘中删除,当文件共享者要访问文件时,他们仍然能访问到自己的LINK文件,只是这个LINK文件中存放的路径对应的文件不存在了,当访问时会出现访问失败,此时只需要将LINK文件删除即可。
为每个文件和目录设置一个访问控制列表(ACL),以规定用户的访问权限。常见的ACL设置三个用户域,即所有者、组、其他用户。
用户操作一个文件系统时,从上到下操作的层次分别为:
用户—>用户调用接口—>文件目录系统—>存取控制验证模块—>逻辑文件系统与文件信息缓冲区—>物理文件系统—>辅助分配模块与设备管理程序模块
文件系统为用户操作文件系统提供的若干系统调用,包括新建文件、打开文件、读写文件等,这一模块使得控制转入文件目录系统
功能是管理文件目录,当控制在这一模块完成工作后,将转入存取控制验证模块
将用户访问要求与FCB中的访问控制权限进行比较,通过存取控制验证后将进入逻辑文件系统
根据文件的逻辑结构将用户要读写的逻辑记录转换为文件中的相应块号,得到块号后将进入物理文件系统
将逻辑文件系统所得块号转换为物理地址
负责分配和回收辅存空间
分配设备、分配设备缓冲区、处理设备中断、释放设备和缓冲区等
每条目录项(包括文件名和索引结点编号)顺序排列组成线性表
哈希表是根据文件名得到哈希函数的值
每个文件在磁盘上占有一组连续的块
访问第n条记录只需访问磁盘1次
目录项中存放文件名、相关信息,并添加文件首块的地址。
隐式链接分配:在每个物理块末尾存放下一个块的指针
显式链接分配:将每个物理块块号及末尾指针提出来放在一张表中(文件分配表,FAT)
-1表示没有下一块,-2表示文件块闲置
访问第n条记录需访问磁盘n次
每个文件有一个块用于存放索引表,索引表中记录了该文件用的所有块号。
对于某条记录,如果其在第m级,则需访问磁盘m+1次
记录磁盘空闲盘块的方法:
空闲表法:对于每一组空闲盘块,记录第一个空闲的盘块号和空闲盘块数量
空闲链表法:将所有空闲盘块按照链表的形式组织起来
位示图法:用0代表空闲,1代表已分配,记录每一个盘块的分配情况
成组链表法:UNIX系统中使用,结合了空闲表法和空闲链表法,
径向可以划分为各个磁道,各磁道又可以划分为各个扇区
磁盘读写操作的时间包括磁盘寻道时间、旋转延迟时间和传输时间
先来先服务
最短寻找时间优先算法:选择离当前磁道最近的磁道作为下一次服务对象
扫描算法:当前移动方向上最近的请求作为下一次服务的对象,又称电梯调度算法
循环扫描算法:规定磁头单向移动,回返时快速移动到起点而不处理任何请求
磁盘初始化:
打印机、鼠标、显示器、键盘等
磁盘、磁带、光盘等
网络接口、调制解调器等
例如一个读操作的步骤为:
CPU向I/O设备下达读指令—>I/O设备进行准备,将数据放在自己的数据寄存器中等待CPU读—>CPU检查I/O设备的状态,状态可读—>CPU从I/O设备的数据寄存器中读数据—>CPU向存储器中写入数据—>完成
程序直接控制的方式中,CPU独立控制I/O设备。由于CPU无法确定I/O设备准备是否完成,因此需要对I/O设备的状态进行循环检查,直到确认该字已经在I/O设备的数据寄存器中才能开始读,类似于忙等。
由于CPU的高速性和I/O设备的低速性,CPU资源会被极大浪费。
中断驱动的方式中,允许I/O设备主动打断CPU的运行并请求服务。这种方式下,CPU向I/O设备下达读命令后可以去做其他事情,直到I/O设备通过中断通知CPU其状态准备已完成。
虽然中断驱动的方式使得CPU不必参与I/O设备状态准备的阶段,但是CPU仍然需要亲自参与读阶段,因为I/O设备到内存需要经过CPU的寄存器才能完成。而DMA方式相当于在I/O设备和内存之间开辟了一条通道,使得读操作不必经过CPU,更大地解放了CPU。
此时读操作的步骤为:
CPU向I/O设备下达读操作—>I/O设备进行状态准备—>I/O设备通过DMA将数据直接读入内存—>读操作完成,DMA向CPU发送中断
DMA中存在下列四种寄存器
命令/状态寄存器(CR):用于接收从CPU发来的I/O命令或相关控制信息,或I/O设备的状态
内存地址寄存器(MAR):读操作中,MAR用于存放读入的数据在内存中的起始目标地址。写操作中,MAR用于存放需要写入的数据在内存中的起始源地址。
数据寄存器(DR):用于暂存需要从设备到内存或从内存到设备的数据。
数据计数器(DC):用于存放本次要传输的字节数
通道方式是DMA方式的发展。即将对一个数据块的读/写为单位改为对一组数据块的读/写为单位。
从数据量来看,中断控制方式是每个数据中断一次CPU,DMA方式是每次一个数据块,而通道方式每次可以读或写一组数据块。
中断方式:
DMA方式:
实现I/O与用户交互的接口
又称设备无关性软件。其功能是将物理设备抽象成逻辑设备,便于进行统一的分配、回收等操作,并向用户层提供统一的接口。
负责具体实现系统对设备发出的操作指令,驱动I/O设备工作。
负责保存被中断处理的CPU环境,转入相应处理程序,并在处理完后恢复现场
I/O设备
磁盘高速缓存Disk Cache:
将内存中的空闲盘块作为磁盘的高速缓冲区,暂存从磁盘中读出的一系列盘块中的信息。逻辑上属于磁盘,物理上其实是内存中的盘块。
缓冲区Buffer:
在高速设备与低速设备之间,用于存放从高速设备传给低速设备的(或相反)的数据。
当缓冲区中有数据时,不能冲入,只能读出。只有当缓冲区为空时才能冲入数据。
独占式
分时式
SPOOLing方式
设备控制表(DCT):一个设备对应一个DCT,用于存放设备各属性,例如类型、状态、标识符等
控制器控制表(COCT):控制器控制表中的每个表项必定对应一个通道
通道控制表(CHCT):而一个通道可以供多个设备控制器使用
系统设备表(SDT):整个系统只有一个SDT,用于存储所有外接设备,每个设备占一个条目。
整个系统中只有一个逻辑设备表(LUT),用于将逻辑设备映射到物理设备。