文章目录
- 1. 进程的有哪几种状态,状态转换图,及导致转换的事件。
- 2. 进程与线程的区别。
- 3. 进程通信的几种方式
- 4. 临界区及在临界区实现互斥的方案
- 5. 线程的实现方式. (也就是用户线程与内核线程的区别)
- 6. 用户态和核心态的区别
- 7. 死锁的概念,导致死锁的原因,饥饿与活锁
- 8. 导致死锁的四个必要条件。
- 9. 处理死锁的四个方式
- 进程调度的两种方式
- 10. 进程调度的多种算法:
- 11. Windows内存管理的方式(块式、页式、段式、段页式).
- 12. 常见的页面置换算法
- 13. 常见的内存分配与空闲内存管理算法
- 14. 虚拟内存的定义及实现方式:
- 15. 外存分配(文件存储)的几种方式,及各种优劣。
- 16. DMA。
- 17. 启动计算机的过程
- 18.多道程序设计技术
- 19.软连接和硬链接的区别:
- 20.文件系统备份
- 21.I/O设备的三种工作方式
- 22.磁盘格式化与磁盘臂调度算法
1. 进程的有哪几种状态,状态转换图,及导致转换的事件。
- 运行态:进程占用CPU,并在CPU上运行;
- 就绪态:进程已经具备运行条件,但是CPU还没有分配过来;
- 阻塞态:进程因等待某件事发生而暂时不能运行;
当然理论上上述三种状态之间转换分为六种情况;
运行——>就绪:1,主要是进程占用CPU的时间过长,而系统分配给该进程占用CPU的时间是有限的;
2,在采用抢先式优先级调度算法的系统中,当有更高优先级的进程要运行时,该进程就被迫让出CPU,
该进程便由执行状态转变为就绪状态。
就绪——>运行:运行的进程的时间片用完,调度就转到就绪队列中选择合适的进程分配CPU
运行——>阻塞:正在执行的进程因发生某等待事件而无法执行,则进程由执行状态变为阻塞状态,如发生了I/O请求
阻塞——>就绪:进程所等待的事件已经发生,就进入就绪队列
以下两种状态是不可能发生的:
阻塞——>运行:即使给阻塞进程分配CPU,也无法执行,操作系统在进行调度时不会从阻塞队列进行挑选,而是从就绪队列中选取
就绪——>阻塞:就绪态根本就没有执行,谈不上进入阻塞态。
2. 进程与线程的区别。
进程是资源(CPU、内存等)分配的基本单位,它是程序执行时的一个实例。程序运行时系统就会创建一个进程,并为它分配资源,然后把该进程放入进程就绪队列,进程调度器选中它的时候就会为它分配CPU时间,程序开始真正运行。
线程是程序执行时的最小单位,它是进程的一个执行流,是CPU调度和分派的基本单位,一个进程可以由很多个线程组成,线程间共享进程的所有资源,每个线程有自己的堆栈和局部变量。线程由CPU独立调度执行,在多CPU环境下就允许多个线程同时运行。同样多线程也可以实现并发操作,每个请求分配一个线程来处理。
进程有自己的独立地址空间,每启动一个进程,系统就会为它分配地址空间,建立数据表来维护代码段、堆栈段和数据段,这种操作非常昂贵。而线程是共享进程中的数据的,使用相同的地址空间,因此CPU切换一个线程的花费远比进程要小很多,同时创建一个线程的开销也比进程要小很多。
线程之间的通信更方便,同一进程下的线程共享全局变量、静态变量等数据,而进程之间的通信需要以通信的方式(IPC)进行。不过如何处理好同步与互斥是编写多线程程序的难点。
但是多进程程序更健壮,多线程程序只要有一个线程死掉,整个进程也死掉了,而一个进程死掉并不会对另外一个进程造成影响,因为进程有自己独立的地址空间。
进程是资源分配的最小单位,线程是程序执行的最小单位。
3. 进程通信的几种方式
- 管道( pipe):管道是一种半双工的通信方式,数据只能单向流动,而且只能在具有亲缘关系的进程间使用。进程的亲缘关系通常是指父子进程关系。
- 有名管道 (named pipe):有名管道也是半双工的通信方式,但是它允许无亲缘关系进程间的通信。
- 信号量( semophore ):信号量是一个计数器,可以用来控制多个进程对共享资源的访问。它常作为一种锁机制,防止某进程正在访问共享资源时,其他进程也访问该资源。因此,主要作为进程间以及同一进程内不同线程之间的同步手段。
- 消息队列( message queue):消息队列是由消息的链表,存放在内核中并由消息队列标识符标识。消息队列克服了信号传递信息少、管道只能承载无格式字节流以及缓冲区大小受限等缺点。
- 信号 ( signal ):信号是一种比较复杂的通信方式,用于通知接收进程某个事件已经发生。
- 共享内存( shared memory ):共享内存就是映射一段能被其他进程所访问的内存,这段共享内存由一个进程创建,但多个进程都可以访问。共享内存是最快的
IPC方式,它是针对其他进程间通信方式运行效率低而专门设计的。它往往与其他通信机制,如信号量,配合使用,来实现进程间的同步和通信。 - 套接字( socket ):套解字也是一种进程间通信机制,与其他通信机制不同的是,它可用于不同及其间的进程通信。
4. 临界区及在临界区实现互斥的方案
临界区:指的是一个访问共用资源(例如:共用设备或是共用存储器)的程序片段,而这些共用资源又无法同时被多个线程访问的特性。
竞争条件:两个或者多个进程读写某些共享数据,而最后的结果取决于进程运行的精确时序,这称为竞争条件。
2.实现互斥的方案
在这些方案中,当一个进程在临界区更新内存时,其他进程将不会进入临界区,也不会带来任何麻烦。
(1)屏蔽中断
每个进程进入临界区之后屏蔽所有中断,并在离开之前打开中断。这不是一个好方案,中断对系统来说很重要。而且如果系统是多核处理器,那屏蔽中断只能对一个核生效,另一个核依然可以干扰临界区。
屏蔽中断对操作系统本身而言是一项有用的技术,但对于用户进程则不是一种合适的通用互斥机制。
(2)锁变量
维护一个变量,如果是0则可以进入临界区然后把他设置为1,否则不能进入,退出时重新设置为0。但是也会存在竞争条件,在某进程将其设置为1的时刻有个进程刚好读到0,那GG。
(3)严格轮换法
用一个变量turn来记录轮到哪个进程进入临界区。每个进程不停地查阅这个变量,直到对应自己的值出现为止,这个过程(连续的测试一个变量直到某个值出现为止,称为忙等待),由于这种方法浪费CPU时间,通常需要避免。用于忙等待的锁称为:自旋锁。
(4)Peterson’s 解法
通过将锁变量与警告变量相结合,最早提出了一个不需要一个严格轮换的软件互斥方法。
While语句代表自旋锁,一直在这里查询interest数组
两个进程同时申请的时候,后写入的turn(1)将会生效,那么他在while循环中进行等待,而0号进程进入临界区。
(5)硬件方案:TSL指令(测试并加锁)
3.睡眠与唤醒
④⑤两种方案都具有忙等待的缺点,这些算法都是,当某个进程想进入临界区时,先检查能否允许进入,如果不允许就原地等待,直到允许为止。
防止忙等待的方法:使用sleep与wakeup原语,当今称无法进入临界区时,他们将阻塞,而不是忙等待。
4.信号量
是用来控制临界区不被并发调用的一种设施,用一个整型变量来累计唤醒次数,供以后使用。具有down和up两种原子操作(要么完全执行,要么都不执行)。
Down:检查是否大于0,若是则减一并继续。如果是0则进程将睡眠。
Up:对信号量加一,如果多个进程在等着这个资源进行down,那么系统随机选择一个允许他down。
5.互斥量
如果不需要信号量的计数能力,可以使用一个简化版本——互斥量。
互斥量是一种特殊的信号量,它只有两种状态: unlocked (0) 或 locked (1)。
(6)管程
为了更易于编写正确的程序,提出了管程这样一种高级同步原语。一个管程是一个由过程、变量及数据结构等组成的一个集合,类似于一个类。任意时刻管程中,只能有一个活跃进程,因此管程可以有效的完成互斥。
管程中的 wait 和 signal 与信号量中的 P V 操作相似;
一个进程执行 P 操作后,该进程未必会被阻塞,但是一个进程执行 wait 操作后,它一定被阻塞;
一个进程执行 V 操作后,要么一个被阻塞的进程被唤醒,要么信号量的值加1;但是,一个进程执行 signal 操作后,若没有进程在该变量被阻塞则没有任何动作。
(7)条件变量
虽然管程提供了一种互斥的简便途径,但是还需要一种方法使得进程在无法继续运行时被阻塞。引入条件变量,以及相关的两个操作:wait和signal,当一个管程过程发现他无法继续运行时,他会在某个条件变量(比如full)上执行wait操作,该操作导致调用进程自身阻塞,还将在管程外等待的一个进程拉进来。如果此时有个消费者消费了,那么她执行在full上执行signal操作,然后将挂起的进程唤醒,在消费者执行完之后,由被唤醒进程运行。
5. 线程的实现方式. (也就是用户线程与内核线程的区别)
用户级线程指不需要内核支持而在用户程序中实现的线程,其不依赖于操作系统核心,应用进程利用线程库提供创建、同步、调度和管理线程的函数来控制用户线程。不需要用户态/核心态切换,速度快,操作系统内核不知道多线程的存在,因此一个线程阻塞将使得整个进程(包括它的所有线程)阻塞。由于这里的处理器时间片分配是以进程为基本单位,所以每个线程执行的时间相对减少。
优点:
- 线程切换不需要转换到内核空间,节省了宝贵的内核空间;
- 调度算法可以是进程专用,由用户程序进行指定;
- 用户级线程实现和操作系统无关;
缺点:
- 系统调用阻塞,同一进程中一个线程阻塞和整个进程都阻塞了。
- 一个进程只能在一个cpu上获得执行。
内核级线程:由操作系统内核创建和撤销。内核维护进程及线程的上下文信息以及线程切换。一个内核线程由于I/O操作而阻塞,不会影响其它线程的运行。
优点:
- 在多处理器上,内核可以调用同一进程中的多个线程同时工作;
- 如果一个进程中的一个线程阻塞了,其他线程仍然可以得到运行;
缺点:
对于用户线程的切换代价太大,在同一个线程中,从一个线程切换到另一个线程时,
需要从用户态,进入到内核态并且由内核切换。因为线程调度和管理在内核实现。
混合实现:内核只感知到内核线程,且只调度内核级别的线程,而用户级别的线程则交给进程自己调度。
两者的区别:
1)内核级线程是OS内核可感知的,而用户级线程是OS内核不可感知的。
2)用户级线程的创建、撤消和调度不需要OS内核的支持,是在语言(如Java)这一级处理的;而内核支持线程的创建、撤消和调度都需OS内核提供支持,而且与进程的创建、撤消和调度大体是相同的。
3)用户级线程执行系统调用指令时将导致其所属进程被中断,而内核支持线程执行系统调用指令时,只导致该线程被中断。
4)在只有用户级线程的系统内,CPU调度还是以进程为单位,处于运行状态的进程中的多个线程,由用户程序控制线程的轮换运行;在有内核支持线程的系统内,CPU调度则以线程为单位,由OS的线程调度程序负责线程的调度。
5)用户级线程的程序实体是运行在用户态下的程序,而内核支持线程的程序实体则是可以运行在任何状态下的程序。
6. 用户态和核心态的区别
当一个任务(进程)执行系统调用而陷入内核代码中执行时,我们就称进程处于内核运行态(或简称为内核态)。此时处理器处于特权级最高的(0级)内核代码中执行。当进程处于内核态时,执行的内核代码会使用当前进程的内核栈。每个进程都有自己的内核栈。当进程在执行用户自己的代码时,则称其处于用户运行态(用户态)。即此时处理器在特权级最低的(3级)用户代码中运行。当正在执行用户程序而突然被中断程序中断时,此时用户程序也可以象征性地称为处于进程的内核态。因为中断处理程序将使用当前进程的内核栈。这与处于内核态的进程的状态有些类似。
用户态切换到内核态的3种方式:系统调用、异常、外围设备中断。
7. 死锁的概念,导致死锁的原因,饥饿与活锁
死锁是指两个或两个以上的进程在执行过程中,由于竞争资源或者由于彼此通信而造成的一种阻塞的现象,若无外力作用,它们都将无法推进下去。此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等待的进程称为死锁进程
1)因为系统资源不足。
2)进程运行推进的顺序不合适。
3)资源分配不当等
饥饿:没有阻塞但是拿不到执行权
活锁:
礼貌的进程可能导致活锁;某个进程意识到它不能获取所需要的下一个锁的时候,就胡一场是礼貌的释放已经获得的锁,如果另一个进程在相同的时刻做了相同的动作,那么两个人都无法正常前进,无限制的推后。
8. 导致死锁的四个必要条件。
1、互斥。一次只有一个进程可以使用一个资源。其他进程不能访问已分配给其他进程的资源。
2、占有且等待。当一个进程等待其他进程时,继续占有已经分配的资源。
3、不可抢占。不能强行抢占进程已占有的资源。
4、循环等待。存在一个封闭的进程链,使得每个进程至少占有此链中下一个进程所需要的一个资源。
任何一个条件不满足,死锁都不会发生。
9. 处理死锁的四个方式
1)忽略该问题。例如鸵鸟算法,该算法可以应用在极少发生死锁的的情况下。为什么叫鸵鸟算法呢,(鸵鸟策略)
2)检测死锁并且恢复。(检测与解除策略)
(1)利用抢占恢复
从某些进程中拿走资源并分配给另外的进程;
(2)利用回滚恢复
周期性地对检查点进行检查;若发现死锁则将进程恢复到一个更早的状态;
(3)通过杀死进程恢复
简单暴力的方式;
将环中的某个进程杀死并释放其资源;
其他进程过得资源得以运行;
一般选择杀死那些可以从头开始的进程;
3)仔细地对资源进行动态分配,以避免死锁。(避免策略)
确保系统不会进入不安全的状态。系统动态分析每一个资源请求,确保系统总是进入安全状态,仔细对资源进行分配,动态地避免死锁
(1)资源轨迹图
(2)安全状态和不安全状态
① 安全状态
一个状态是安全的,如果存在某种调度顺序是的每个进程都可以结束即使所有进程都请求
其所需的全部资源;
② 二者的区别
在一个安全状态,系统可以保证所有进程都能结束。
在一个不安全状态,系统不保证所有进程都能结束。
③ 银行家算法
4)通过破除死锁四个必要条件之一,来防止死锁产生。(预防策略)
确保死锁发生的条件(四个条件)无法满足。
(1)破坏互斥条件
如果资源不被一个进程独占,那么死锁肯定不会发生,使用假脱机技术, CPU将多个进程丢给守护进程,自己不再进行管理。
避免分配那些不是绝对必须的资源,尽量做到尽可能少的进程可以真正请求资源。
(2)破坏占有并等待条件
要求进程在执行前获取所有的资源,否则他不获得任何资源,进行等待。
(i)很多进程运行时才知道需要多少资源
(ii)资源利用率不高
当一个进程请求资源时,先暂时释放其当前占用的所有资源,然后在尝试一次获得所需的全部资源。
(3)破坏不可抢占条件。
若一个进程占有一些资源,同时请求另外的无法分配给它的资源,那么该进程将释放其所占有的
所有资源;
这个方法可以应用于可重启的资源,如内存,先保存,然后恢复。不适用于打印机等,打印到一半
被抢了那全打的是错的。
(4)破坏环路等待条件
保证任何一个进程在任何时刻只能占用一个资源,如果要请求其他资源,必须放弃他手上的第一个资源
(这样导致在资源分配图中与该进程连接的永远只有一条边,不会发生回路)
给资源编号,进程请求的资源必须按照资源编号的升序提出。
进程调度的两种方式
两种方式:非抢占式调度和抢占式调度
(1)非抢占调度方式
在这种调度方式中,OS一旦把处理机分配给某个就绪状态的进程后,就让该进程一直执行下去,直至该进程完成或由于该进程等待某事件发生而被阻塞时,才把处理机分配给其他进程。
(2)抢占调度方式
在这种调度方式中,进程调度程序可根据某种原则停止正在执行的进程,将已分配给当前进程的处理机收回,重新分配给另一个处于就绪状态的进程。
10. 进程调度的多种算法:
-
批处理系统中的调度
(1)先来先服务
(2)最短作业优先SJF(shortest job first)很难预知进程需要的CPU用时。
给定一个进程集合,SJF能够获得最优的平均最小等待时间。
(3)最短剩余时间优先 -
交互式系统中的调度–满足响应时间要求
(1)轮转调度
如果等待队列中有 n个进程,那么每个进程将获得 1/n 的CPU用时,且每个进程的等待时间不会超过 (n-1)q单位时间。
① 特性:
当q 增大时,算法将转化为 FIFO(q太大相当于要把真个程序运行完才结束)当q 减小时,算法将产生较大比例的开销(频繁的上下文切换),因此,q 应当设的合适。
一个进程运行结束直接走人,不需要等到时间片结束。
周转时间比SJF长,但是响应速度快——毕竟交互式系统就是要靠这个吃饭
(2)优先级调度
每个进程一个优先级,SJF就是一个特例(以运行时间为优先级)
问题:低优先级的进程可能会发生饥饿现象。
解决方案: 引入老化技术 – 等待的进程的优先级会随着时间推移而增大。
(3)多级队列
级别高的先运行,但是时间片比较短,每次一个进程用完分配的时间片之后,就会被移到下一个优先级类,该类的时间片是上个类的两倍。也就是随着优先级不断降低,拥有的时间片逐渐增多。
(4)最短进程优先
首先运行最短的作业会使得响应时间最短,唯一的问题是如何从当前可运行进程中找出最短的哪一个进程。一种方法是根据过去的行为进行推测,并执行估计运行时间最短的那个。
老化:通过当前测量值和先前估计值进行加权平均而得到的下一个估计值的技术。
(5)保证调度
向用户做出明确的性能保证,然后去实现它。为了实现所做的保证,系统必须跟踪各个进程自创建以来已经使用了多少时间和他们还因该获得多少时间。比例为0.5说明只获得了一半,2说明超时了,算法转向比率最低的进程。
(6)彩票调度
可以给优先级高的进程多一些彩票,如果出售了100张,一个进程拥有20张,那么长此以往他大概会占据20%的CPU时间。
彩票调度反应十分迅速。协作进程之间还可以交换彩票,简单。
(7)公平分享调度
这里不再考虑进程,而是考虑用户数目,无论一个用户的进城有多少,CPU运行时间按照人数来均分。
11. Windows内存管理的方式(块式、页式、段式、段页式).
当程序运行时需要从内存中读出这段程序的代码。代码的位置必须在物理内存中才能被运行,由于现在的操作系统中有非常多的程序运行着,内存中不能够完全放下,所以引出了虚拟内存的概念。把哪些不常用的程序片断就放入虚拟内存,当需要用到它的时候在load入主存(物理内存)中。这个就是内存管理所要做的事。内存管理还有另外一件事需要做:计算程序片段在主存中的物理位置,以便CPU调度。内存管理有块式管理,页式管理,段式和段页式管理。现在常用段页式管理。
- 块式管理:把主存分为一大块、一大块的,当所需的程序片断不在主存时就分配一块主存空间,把程序片断load入主存,就算所需的程序片度只有几个字节也只能把这一块分配给它。这样会造成很大的浪费,平均浪费了50%的内存空间,但是易于管理。
- 页式管理:把主存分为一页一页的,每一页的空间要比一块一块的空间小很多,显然这种方法的空间利用率要比块式管理高很多。
- 段式管理:把主存分为一段一段的,每一段的空间又要比一页一页的空间小很多,这种方法在空间利用率上又比页式管理高很多,但是也有另外一个缺点。一个程序片断可能会被分为几十段,这样很多时间就会被浪费在计算每一段的物理地址上(计算机最耗时间的大家都知道是I/O吧)。
段页式管理:结合了段式管理和页式管理的优点。把主存分为若干页,每一页又分为若干段。
————————————————
分页与分段的主要区别:
12. 常见的页面置换算法
-
最优页面置换算法:置换出之后可能使用最少的,比如一个页面可能要到100条指令后会被访问,也有页面在1000条指令后才会被访问,那就删除1000的,但是你怎么知道这个具体的时间?只能靠猜
-
最近未使用页面置换算法(NRU):
频繁访问未修改>少访问已修改,
Class 1未访问,显然是之前被修改但是隔了很久没有访问所以访问位置0。所以他很少访问,应该拿走,优先级低于经常访问的。
主要是想减少磁盘IO。
-
先进先出页面置换算法:总是丢弃最老的页面
-
第二次机会页面置换算法:总是检查最老的页面,如果既老,又没有被使用,那么可以立即置换。如果R是0,就置换掉,如果R=1把他R置为0并放到链表头部
-
时钟页面置换算法:与第二次机会算法类似,但是这里是一个循环链表,如果是R=0就把新页表插入。。。。。。。经常要在链表中移动页面,既降低了效率又不是很有必要。
-
最近最少使用页面置换算法LRU:
置换未使用时间最长的页面、
完全体:维护一个所有页面的链表,用的最多的放在表头,每次访问内存都必须更新整个链表。
给一个64位计数器,每条指令执行完之后+1,每次访问内存后c值保存到对应页表项,缺页中断时OS找c值最小的,也是最近最少使用的。
-
软件模拟ARU: NFU:最不频繁使用
R:0or1,累加的R值大致反映了页面被访问的频繁程度
-
工作集模型:显然页面置换算法是请求调页,而工作集模型是属于预先调入。
没有有效的方法可以迅速地计算出工作集,有几个近似的方法
思想:考察最近访问的页面,将不在工作集中的页面置换出去。也就是过去的 τ 虚拟时间内访问的页面集 (虚拟时间为该进程使用CPU的时间)来近似一个进程的工作集。
-
工作集时钟页面置换算法
(i)R=1的项不适合删除,R置为0,检查下一个表项。
(ii)R=0且生存时间大于τ且页面干净,可以申请替换。
(iii)如果M=1(被操作过),不能立即申请,为了避免磁盘操作,指针继续向前。
转了一圈返回起点:如果调度过写操作,那么就选一个写完干净的。如果没有写回过,就随机置换一个干净的。
算法总结;
13. 常见的内存分配与空闲内存管理算法
连续分配方式,是指为一个用户程序分配一个连续的内存空间。它主要包括单一连续分配、固定分区分配和动态分区分配。
-
单一连续分配: 即不使用存储器抽象,直接使用物理内存。内存在此方式下分为系统区和用户区,系统区仅提供给操作系统使用,通常在低地址部分;用户区是为用户提供的、除系统区之外的内存空间。这种方式无需进行内存保护。
这种方式的优点是简单、无外部碎片,可以釆用覆盖技术,不需要额外的技术支持。缺点是只能用于单用户、单任务的操作系统中,有内部碎片,存储器的利用率极低。 -
固定分区分配:固定分区分配是最简单的一种多道程序存储管理方式,它将用户内存空间划分为若干个固定大小的区域,每个分区只装入一道作业。当有空闲分区时,便可以再从外存的后备作业队列中,选择适当大小的作业装入该分区,如此循环。
固定分区分配在划分分区时,有两种不同的方法,如下图所示。
分区大小相等:用于利用一台计算机去控制多个相同对象的场合,缺乏灵活性。
分区大小不等:划分为含有多个较小的分区、适量的中等分区及少量的大分区。
- 动态分区分配:动态分区分配又称为可变分区分配,是一种动态划分内存的分区方法。这种分区方法不预先将内存划分,而是在进程装入内存时,根据进程的大小动态地建立分区,并使分区的大小正好适合进程的需要。因此系统中分区的大小和数目是可变的。
- 动态分区在开始分配时是很好的,但是之后会导致内存中出现许多小的内存块。随着时间的推移,内存中会产生越来越多的外部碎片(还没有分配出去,但是由于太小而无法分配给申请空间的新进程的内存空间空闲块)。
- 克服外部碎片可以通过紧凑(Compaction)技术来解决,就是操作系统不时地对进程进行移动和整理。但是这需要动态重定位寄存器的支持,且相对费时。紧凑的过程实际上类似于Windows系统中的磁盘整理程序,只不过后者是对外存空间的紧凑。
常见动态内存分配算法及优缺点如下:
(1)首次适应算法。使用该算法进行内存分配时,从空闲分区链首开始查找,直至找到一个能满足其大小要求的空闲分区为止。然后再按照作业的大小,从该分区中划出一块内存分配给请求者,余下的空闲分区仍留在空闲分区链中。
该算法倾向于使用内存中低地址部分的空闲分区,在高地址部分的空闲分区很少被利用,从而保留了高地址部分的大空闲区。显然为以后到达的大作业分配大的内存空间创造了条件。缺点在于低址部分不断被划分,留下许多难以利用、很小的空闲区,而每次查找又都从低址部分开始,这无疑会增加查找的开销。
(2)循环首次适应算法。该算法是由首次适应算法演变而成的。在为进程分配内存空间时,不再每次从链首开始查找,而是从上次找到的空闲分区开始查找,直至找到一个能满足要求的空闲分区,并从中划出一块来分给作业。该算法能使空闲中的内存分区分布得更加均匀,但将会缺乏大的空闲分区。
(3)最佳适应算法。该算法总是把既能满足要求,又是最小的空闲分区分配给作业。
为了加速查找,该算法要求将所有的空闲区按其大小排序后,以递增顺序形成一个空白链。这样每次找到的第一个满足要求的空闲区,必然是最优的。孤立地看,该算法似乎是最优的,但事实上并不一定。因为每次分配后剩余的空间一定是最小的,在存储器中将留下许多难以利用的小空闲区。同时每次分配后必须重新排序, 这也带来了一定的开销。
(4)最差适应算法。最差适应算法中,该算法按大小递减的顺序形成空闲区链,分配时直接从空闲区链的第一个空闲分区中分配(不能满足需要则不分配)。很显然,如果第一个空闲分区不能满足,那么再没有空闲分区能满足需要。这种分配方法初看起来不太合理,但它也有很强的直观 吸引力:在大空闲区中放入程序后,剩下的空闲区常常也很大,于是还能装下一个较大的新程序。
最坏适应算法与最佳适应算法的排序正好相反,它的队列指针总是指向最大的空闲区,在进行分配时,总是从最大的空闲区开始查寻。
该算法克服了最佳适应算法留下的许多小的碎片的不足,但保留大的空闲区的可能性减小了,而且空闲区回收也和最佳适应算法一样复杂。
空
闲
内
存
管
理
空闲内存管理
空闲内存管理
① 使用位图的存储管理
内存被划分成分配单元,每个分配单元对应一位,0:空闲,1:占用。
分配单元越小位图越大,内存与分配单元的大小决定了位图的大小。
查找位图中指定长度的连续0串是十分耗时的操作.
② 使用链表的存储管理.
维护一个记录已经分配内存段和空闲内存段的链表。链表中的节点,或者是一个进程或者是两个进程之间的一块空闲区
链表中的每个节点都包含以下域:空闲区(H)或者进程(P),起始地址,长度和指向下一个结点的指针。
注意分配内存的查找算法。
14. 虚拟内存的定义及实现方式:
基于局部性原理,在程序装入时,可以将程序的一部分装入内存,而将其余部分留在外存,就可以启动程序执行。在程序执行过程中,当所访问的信息不在内存时,由操作系统将所需要的部分调入内存,然后继续执行程序。另一方面,操作系统将内存中暂时不使用的内容换出到外存上,从而腾出空间存放将要调入内存的信息。这样,系统好像为用户提供了一个比实际内存大得多的存储器,称为虚拟存储器。
之所以将其称为虚拟存储器,是因为这种存储器实际上并不存在,只是由于系统提供了部分装入、请求调入和置换功能后(对用户完全透明),给用户的感觉是好像存在一个比实际物理内存大得多的存储器。虚拟存储器的大小由计算机的地址结构决定,并非是内存和外存的简单相加。虚拟存储器有以下三个主要特征:
多次性,是指无需在作业运行时一次性地全部装入内存,而是允许被分成多次调入内存运行。
· 对换性,是指无需在作业运行时一直常驻内存,而是允许在作业的运行过程中,进行换进和换出。
· 虚拟性,是指从逻辑上扩充内存的容量,使用户所看到的内存容量,远大于实际的内存容量。
虚拟内存技术的实现
虚拟内存中,允许将一个作业分多次调入内存。釆用连续分配方式时,会使相当一部分内存空间都处于暂时或“永久”的空闲状态,造成内存资源的严重浪费,而且也无法从逻辑上扩大内存容量。因此,虚拟内存的实现需要建立在离散分配的内存管理方式的基础上。虚拟内存的实现有以下三种方式:
· 请求分页存储管理。
· 请求分段存储管理。
· 请求段页式存储管理。
15. 外存分配(文件存储)的几种方式,及各种优劣。
文件存储实现的关键问题,是记录各个文件分别用到哪些磁盘块,主要有以下几种方式
- 连续分配:每个文件作为一连串连续的数据块存储。
① 优势
实现方式简单;
读数据的性能好;
② 缺点
产生磁盘碎片;
需要预先知道文件的大小; - 链表分配:为每个文件构造磁盘块链表,每个块的第一个字作为指向下一个块的指针,块的其他部分存放数据。
① 优势
充分利用磁盘空间,很少会产生磁盘碎片。
目录项只需要记录链头的指针即可。
② 缺点
链表的随机访问困难,读操作很慢
指针的存在使得每个物理块中存储的数据不是2的整数幂次方,大多数操作系统是以2的整数幂次方来读取数据,因此这样效率就低了。 - 采用内存中的表进行链表分配(文件分配表FAT:file allocation table)
类比进程的进程分配表PCB
将链表分配的每个磁盘块的指针字放在内存中的一个表中(每个块对应一个指针,一个表项)。
- I节点
i节点记录了文件的属性以及文件内容的存储地址。
给每个文件赋予一个i节点(n字节),其中列出文件属性和文件块的磁盘地址
打开文件时,其i节点才在内存,最多打开k个文件,则内存最多需要kn个字节
但文件大小超出i节点能容纳的数目时,最后的盘块采用指针块地址,类似于二层也表一样,指针块里又可以放很多的指针。
16. DMA。
直接内存访问(DirectMemory Access,DMA)
直接内存访问是一种内存访问技术。它允许计算机内部的某些硬件子系统(外设),可以独立地直接的读写系统内存,不需要CPU的介入处理。在同等程度的处理器负担下,DMA是一种快速的数据传送方式。很多硬件的系统会使用DMA,包含硬件控制器、绘图显卡、网卡和声卡。
DMA允许不同速度的硬件设备来沟通,不需要CPU的大量中断负载。CPU初始化传输动作,但传输动作本身是由DMA控制器完成的。在DMA传输过程中,不需要CPU的参与,CPU则可以进行其他的工作。DMA传输对于高性能嵌入式系统算法和网络是很重要的。
注:如果不用DMA,内存和磁盘的数据交互则需要通过CPU,CPU需要将每一片数据从来源中读出复制到寄存器,然后再把它们写回到新的地方。
17. 启动计算机的过程
每台计算机有一个双亲板(母板),在该板上有一个基本输入输出系统BIOS(basic input output stream),BIOS里面有底层的I/O软件,包括读键盘,写屏幕,进行磁盘I/O以及其他操作。
打开电源,启动电源。
计算机启动时,BIOS开始运行,检查其他设备是否已安装并正常响应。
BIOS扫描总线并找出连接在上面的设备。
BIOS通过尝试存储在CMOS中存储区的设备清单决定启动设备,加载操作系统。
操作系统询问BIOS,以获得配置信息;
将所有的驱动程序调入内核,初始化有关表格,创建需要的任何背景进程,并在每个终端上启动登录程序和GUI。
18.多道程序设计技术
多道程序设计技术是指在内存同时放若干道程序,使它们在系统中并发执行,共享系统中的各种资源。 当一道程序暂停执行时,CPU立即转去执行另一道程序。 [特点]:多道、宏观上并行(不同的作业分别在CPU和外设上执行)、微观上串行(在单CPU上交叉运行)。
19.软连接和硬链接的区别:
软链接实际上只是一段文字,里面包含着它所指向的文件的名字,系统看到软链接后自动跳到对应的文件位置处进行处理;相反,硬链接为文件开设一个新的目录项,硬链接与文件原有的名字是平权的,在Linux看来它们是等价的。 由于这个原因,硬链接不能连接两个不同文件系统上的文件
20.文件系统备份
增量转储:周期性的进行全面转储,而每天只对从上次一全面转储起发生变化的数据做备份。稍微好一点的做法只备份自最近一次转储以来更改过的文件。
(1)物理转储
从磁盘的第0块开始,全部按序输出到磁带上,直到最后一块复制完毕。
(2)逻辑转储
从一个或几个指定的目录开始,递归地转储其自给定基准日期后所更改的全部文件和目录.
21.I/O设备的三种工作方式
- 程序控制I/O
但是需要轮询或者忙等待, - 中断驱动I/O
将CPU从繁忙等待中解脱出来
(1)CPU初始化IO并启动第一次IO操作;
(2)CPU去忙别的活;
(3)当IO完成时,CPU将被中断;(I/O完成时才会发出中断)
(4)CPU处理中断;
(5)CPU恢复被中断的程序;
有个明显缺点是中断发生在每个字符,太频繁 - 使用DMA的I/O
让DMA控制器一次给打印机提供一个字符而不需要打扰CPU,将中断的次数从打印每个字符减少到打印每个缓冲区一次。
22.磁盘格式化与磁盘臂调度算法
磁盘能够使用之前,每个盘片必须经手软件完成的低级格式化,该格式包含一系列同心的磁道,每个磁道包含若干数目的扇区。格式化容量通常比非格式化容量低20%。
(1)柱面斜进-低级格式化内容之一
每个磁道上第0扇区的位置与前一个磁道存在偏移,防止读取的数据不在一个磁道上,如果不斜进一点,那么换道完成时磁头已经超过了预期位置,需要再转一圈。类似的也存在磁头斜进,但是通常小于一个扇区的时间。
(2)磁盘交错编号-低级格式化的操作之一
问题:要读取两个连续的扇区,读完第一个需要写会内存,这段时间里已经从第二个扇区通过了,回来的时候需要重转一圈才能回到目的扇区。
磁盘臂调度算法
(1)先来先服务
(2)最短寻道优先,速度快但是可能有人饿死。
(3)电梯算法:保持在一个方向移动知道这个方向没有请求,然后改变方向。移动次数上界:柱面数的两倍
参考blogs:
https://blog.csdn.net/leechow007/article/details/76284274
https://blog.csdn.net/liuqiyao_01/article/details/39156651
https://www.jianshu.com/p/f9c2cd85e2f6