(大二上)操作系统概念

1、操作系统
1、进程和线程的区别
1)进程是资源分配的最小单位,线程是程序执行的最小单位(资源调度的最小单位),一个进程可以有多个线程,同类的多个线程共享进程的堆和方法区资源,但每个线程有自己的程序计数器、虚拟机栈和本地方法栈。

2)进程有自己的独立地址空间,每启动一个进程,系统就会为它分配地址空间,建立数据表来维护代码段、堆栈段和数据段,这种操作非常昂贵。而线程是共享进程中的数据的,使用相同的地址空间,因此CPU切换一个线程的花费远比进程要小很多,同时创建一个线程的开销也比进程要小很多。
3)线程之间的通信更方便,同一进程下的线程共享全局变量、静态变量等数据,而进程之间的通信需要以通信的方式(IPC)进行。不过如何处理好同步与异步是编写多线程程序的难点。
4)但是多进程程序更健壮,多线程程序只要有一个线程死掉,整个进程也死掉了,而一个进程死掉并不会对另外一个进程造成影响,因为进程有自己独立的地址空间。
总结:
进程是对运行时程序的封装,是系统进行资源调度和分配的的基本单位,实现了操作系统的并发;
线程是进程的子任务,是CPU调度和分派的基本单位,用于保证程序的实时性,实现进程内部的并发;一个程序至少有一个进程,一个进程至少有一个线程,线程依赖于进程而存在;进程在执行过程中拥有独立的内存单元,而多个线程共享进程的内存。

2、进程间的通信的几种方式
进程间通信(IPC)除了共享内存,让协作进程还可通过进程间通信(IPC)工具来进行彼此间的通信。IPC是允许进程间不通过共享内存进行通信和同步的一种机制。IPC由消息传递系统(Message-Passing Systems)提供,它允许进程互相通信而不需要利用共享数据。IPC至少提供发送消息和接收消息两个操作。进程发送的消息可以是定长的或变长的。如果进程P和Q需要通信,必须先建立通信线路(communication link),然后互相发送消息和接收消息。
管道( pipe ):管道是一种半双工的通信方式,数据只能单向流动,而且只能在具有亲缘关系的进程间使用。进程的亲缘关系通常是指父子进程关系。
有名管道 (named pipe) : 有名管道也是半双工的通信方式,但是它允许无亲缘关系进程间的通信。
消息队列:消息队列是消息的链接表,存放在内核中并由消息队列标识符标识。它克服了上两种通信方式中信号量有限的缺点,具有写权限的进程可以按照一定得规则向消息队列中添加新信息;对消息队列有读权限得进程则可以从消息队列中读取信息。
高级管道(popen):将另一个程序当做一个新的进程在当前程序进程中启动,则它算是当前程序的子进程,这种方式我们称为高级管道方式。
信号量( semophore ) : 信号量是一个计数器,可以用来控制多个进程对共享资源的访问。它常作为一种锁机制,防止某进程正在访问共享资源时,其他进程也访问该资源。因此,主要作为进程间以及同一进程内不同线程之间的同步手段。
信号(signal):信号是一种比较复杂的通信方式,用于通知接收进程某个事件已经发生。
共享内存:可以说这是最有用的进程间通信方式。它使得多个进程可以访问同一块内存空间,不同进程可以及时看到对方进程中对共享内存中数据得更新。这种方式需要依靠某种同步操作,如互斥锁和信号量等;
套接字(socket):这是一种更为一般得进程间通信机制,它可用于网络中不同机器之间的进程间通信,应用非常广泛。

3、进程的状态
新建(new):进程正在创建中。运行(running):指令正在被执行。等待(waiting):进程等待某事件出现(如I/O完成或收到某个信号).。就绪(ready):进程等待被分配给处理器。终止(terminated):进程执行完毕。
状态的名称和数量随操作系统而异。任一时刻只能有一个进程处于运行状态,其它进程只能处于就绪或等待状态。

4、进程控制块PCB
每个进程在操作系统内拥有一个进程控制块PCB,它包含进程的许多信息:进程状态:包括新建、就绪、运行、等待、终止等。程序计数器:表示这个进程要执行的下一条指令的地址。CPU寄存器:累加器,索引寄存器、堆栈指针、通用寄存器等等。CPU调度信息:进程优先级、调度队列的指针和其他调度参数。内存管理信息:包括基址寄存器和界限寄存器的值(内存范围)、页表或者段表。记账信息:包括CPU时间、实际使用时间、时间界限、记账数量、进程数量等。I/O状态信息:包括分配给进程的I/O设备列表、打开文件的列表等。当然还有一个指针,用于进程调度。
上下文切换:将CPU切换到另一个进程时需要保存原有进程的状态(PCB),同时装入新进程的保存状态。上下文切换时系统不做其他工作,花费的时间是系统的额外开销,时间长短与硬件支持密切相关,通常为微秒级(1us-1000us)
5、调度程序
长期调度程序(作业调度):从存储设备的缓冲池中选择进程,并将它们装入内存以执行。(将作业加入作业队列,几秒到几分钟)长期调度程序选择进程的一个原则是维持系统稳定,即合理搭配系统中CPU为主的进程和I/O为主的进程。 如果I/O为主的进程太多,那么就绪等列几乎总为空,CPU调度程序则无事可做;如果CPU为主的进程太多,那么I/O等待队列几乎总为空,设备没有得到充分使用。系统会不平衡。
短期调度程序(CPU调度):从就绪可执行的进程中选择进程,并为其中之一分配CPU。(可能只需要几毫秒)
6、进程创建
进程树:进程在执行过程中,能通过系统调用创建多个新进程。创建进程称为父进程,新进程称为该进程的子进程。新进程也可进一步创建子进程,形成了进程树。
资源共享:1)父子进程共享所有资源;2)子进程共享父进程的部分资源,限制子进程只能使用父进程的资源子集能防止因创建过多的子进程使系统超载;3)父子进程不共享任何资源,子进程直接从操作系统那里获取资源。
执行:父进程和子进程并发执行;父进程等待,直到某个或全部子进程执行完毕。
7、进程终止
正常结束:当进程执行完最后一条语句后,使用系统调用exit请求操作系统删除它,进程结束。同时,通过系统调用wait,子进程将数据输出返回其父进程,操作系统释放进程的所有资源(物理内存,虚拟内存,文件,I/O缓冲)。
异常终止:父进程通过系统调用abort终止子进程。出现这种情况的原因很多:1)子进程使用了操作它所分配到的一些资源;2)分配给子进程的任务已不再需要;3)父进程退出,其所有子进程必须终止,即级联终止(cascading termination)。
8、多线程模型,用户线程和内核线程之间的对应关系
多对一模型。将多个用户线程映射到一个内核线程,线程管理在用户空间进行,因而效率较高。缺点:如果一个线程执行了阻塞系统调用,那么整个进程就会阻塞。任一时刻只能有一个线程访问内核,多个线程不能并行运行在多处理器上。
一对一模型。将每个用户线程映射到一个内核线程。优点是并发功能好。缺点:对系统支持的线程数量有所限制 。
多对多模型。多路复用许多用户级线程到同样数量或者更小数量的内核线程上,克服了多对一模型并发性差以及一对一模型线程数量受限的缺点。
9、线程池
尽管创建一个独立线程比创建一个独立进程的所需的资源要小很多,但是,无限制的线程仍会用尽系统资源(如CPU时间,内存),解决这个问题的方法之一是线程池(Thread Pools)。优点:通常处理现有线程的请求比等待创建新的线程要快;线程池限制了在任一时刻存在的线程的数量。
10、CPU调度
当CPU变为空闲时,操作系统就必须从就绪队列中选择一个进程来执行,进程的选择由短期调度程序(short-term scheduler,或CPU调度程序)执行。
当出现下面任何情形之一时,需要CPU调度:
(1)进程从运行状态转入等待状态(I/O请求); (必须调度一个新进程)
(2)进程从运行状态转入就绪状态(出现中断);
(对于非抢占式调度,不需要CPU调度);
(3)进程从等待状态转入就绪状态(I/O完成);
(对于非抢占式调度,不需要CPU调度);
(4)进程终止。
如果调度只发生在(1)和(4),则为非抢占式调度。
如果在(2)和(3)情形发生调度,则为抢占式调度。
11、操作系统中进程调度策略有哪几种?
调度准则:衡量调度算法优劣的标准
最优化调度准则:
1.CPU使用率——最大化。
2.吞吐量——最大化。
3.平均周转时间——最小化。
4.平均等待时间——最小化。
5.平均响应时间——最小化。
吞吐量:一个单位时间单元内所完成进程的数量。
周转时间:从进程提交到进程完成的时间段称为周转时间。
等待时间:等待时间为在就绪队列中等待所花费时间之和。
响应时间:从提交请求到产生第一响应的时间。
1)FCFS(先来先服务,队列实现,非抢占的):先请求CPU的进程先分配到CPU。
2)SJF(最短作业优先调度算法):SJF将每个进程与其下一个CPU区间长度相关联,当CPU可用时,它会赋给后面具有最短CPU区间的进程。
思想:
(1)非抢占式调度:当给一个进程分配CPU后,必须等待其执行完毕才能为新进程分配CPU。(2)抢占式调度:当一个进程分配CPU后,能被更短的新进程抢占CPU。
SJF算法是最佳的,但是它不能在短期CPU调度的层次上实现,因为没有办法知道下一个CPU请求的长度。也称最短剩余时间调度(SRTF)。
3)优先级调度算法(可以是抢占的,也可以是非抢占的):优先级越高越先分配到CPU,相同优先级先到先服务
存在的主要问题是:低优先级进程无穷等待CPU,会导致无穷阻塞或称为饥饿
解决方案:老化。
4)时间片轮转调度算法(可抢占的,RR):队列中没有进程被分配超过一个时间片的CPU时间,除非它是唯一可运行的进程。如果进程的CPU区间超过了一个时间片,那么该进程就被抢占并放回就绪队列。RR算法的性能很大程度上依赖于时间片的大小:如果时间片过大,那么RR算法与FCFS算法一样;如果时间片太小,那么进程切换过于频繁,增加系统的额外开销。
5)多级队列调度算法:将就绪队列分成多个独立的队列,每个队列都有自己的调度算法,其中,一个进程根据自身属性被永久地分配到一个队列中。队列之间也需调度,常用的调度算法有:1.固定优先级调度,可抢占式调度;2.在队列之间划分时间片,每个队列都有一定的CPU时间;例 如,80%的CPU时间分配给前台队列,而20%的CPU时间分配给后台队列。
6)多级反馈队列调度算法:与多级队列调度算法相比,其允许进程在队列之间移动:若进程使用过多CPU时间,那么它会被转移到更低的优先级队列;在较低优先级队列等待时间过长的进程会被转移到更高优先级队列,以防止饥饿发生。
12、进程同步
临界区问题:并发进程中可能改变共同变量、更新同一个表、写同一个文件的代码段。
进入区(上锁)、临界区、退出区(开锁)、剩余区。
解决临界区问题必须满足如下三项要求:

  1. 互斥:进程Pi在临界区内执行,其他进程不得进入临界区。
  2. 前进:如果没有进程在临界区执行,那么允许不在剩余区的进程计入临界区。
  3. 有限等待:从一个进程作出进入临界区的请求,直到该请求被允许为止,其他进程允许进入其临界区的次数有上限。
  4. 忙则等待;空则让进;等则有限;等则让权。
    进程同步的五种机制:
    1)信号量机制。一个信号量只能置一次初值,以后只能对之进行p操作或v操作。 由此也可以看到,信号量机制必须有公共内存,不能用于分布式操作系统,这是它最大的弱点。
    2)自旋锁。是指当一个线程在获取锁的时候,如果锁已经被其它线程获取,那么该线程将循环等待,然后不断的判断锁是否能够被成功获取,直到获取到锁才会退出循环。自旋锁是一种比较低级的保护数据结构和代码片段的原始方式,可能会引起死锁和过多地占用CPU资源。
    3)管程。信号量机制功能强大,但使用时对信号量的操作分散,而且难以控制,读写和维护都很困难。因此后来又提出了一种集中式同步进程——管程。其基本思想是将共享变量和对它们的操作集中在一个模块中,操作系统或并发程序就由这样的模块构成。这样模块之间联系清晰,便于维护和修改,易于保证正确性。
    4)会和。进程直接进行相互作用 。
    5)分布式系统。由于在分布式操作系统中没有公共内存,因此参数全为值参,而且不可为指针。
    13、硬件同步
    许多系统为解决临界区代码提供硬件支持,在修改共享变量时禁止中断,正在运行的指令不会被其它指令抢占CPU,适用于单处理器环境,通常为非抢占内核所使用。通常不适用于多处理器系统,禁止中断会降低系统效率,影响系统时钟。
    现代计算机系统提供特殊的原子指令,原子指令是指不能被中断的指令 ,检测和修改存储字的指令(TestAndSet()),交换两个字的内容的指令(Swap())。
    14、信号量
    硬件同步指令比较复杂,不便于程序员使用。为了解决这个困难,可以使用称为信号量(semaphore)的同步工具。信号量是一种不需要忙等的进程同步机制。Semaphore S–信号量S的定义,是一个整数变量,除了初始化外,只能通过两个标准的原子操作: S: wait() and signal()来访问。必须保证没有两个进程同时对相同的信号量执行wait()和signal()操作。解决临界区的问题实际上就是wait和signal代码处于临界区之前还是之后的问题。
    计数信号量 – 值域不受限制
    二进制信号量 – 值域只能是 0和1 ,也称为称为互斥锁
    15、自旋锁
    当一个进程位于其临界区时,其它任何试图进入临界区的进程都必须在其进入区的代码中连续循环。自旋锁的优势是不用阻塞进程,不必进行上下文切换。临界区的代码较短时,用自旋锁效率高。若临界区的代码较长,则需要取消忙等。
    自旋锁适合多处理器环境,因为:Wait()和signal()操作自身需要对同一信号量的互斥访问,单处理器可以通过简单的禁止中断保证Wait()和signal()的原子执行,因此不需要自旋锁。但是对于多处理器,禁止所有处理器的中断不仅困难,而且严重影响性能,这时适合用自旋锁保证各进程对同一信号量的互斥访问。
    16、同步和异步
    同步:多个并发进程进入临界区的顺序有明确的先后规则。用于表示同步关系的信号量的wait和signal操作是交叉出现在需要同步进程中的。
    互斥:是一种特殊的同步关系,并发进程进入临界区没有明确的先后关系。用于表示互斥关系的信号量的wait和signal操作是出现同一进程内部。

17、管程
管程的基本思想是:将共享变量以及对于共享变量所能执行的所有操作集中在一个模块中,一个复杂系统或者并发程序有若干个这样的模块构成,从而提高程序的可读性,便于修改和维护。
一个管程定义了一个数据结构和能为并发进程所执行(在该数据结构上)的一组操作,这组操作能同步进程和改变管程中的数据,这一点与面向对象中类的概念非常类似。管程本身就是互斥的,管程模块(包括共享的数据结构和操作)任一时刻只能被一个线程/进程访问。其它调用者必须等待。在linux操作系统中,利用信号量可以实现管程。
18、什么是死锁?死锁产生的条件?
死锁的概念:在两个或者多个并发进程中,如果每个进程持有某种资源而又等待其它进程释放它或它们现在保持着的资源,在未改变这种状态之前都不能向前推进,称这一组进程产生了死锁。通俗的讲,就是两个或多个进程无限期的阻塞、相互等待的一种状态。
死锁产生的四个必要条件:1)互斥:至少有一个资源必须属于非共享模式,即一次只能被一个进程使用;若其他申请使用该资源,那么申请进程必须等到该资源被释放为止;2)占有并等待:一个进程必须占有至少一个资源,并等待另一个资源,而该资源为其他进程所占有;3)非抢占:进程不能被抢占,即资源只能被进程在完成任务后自愿释放;4)循环等待:若干进程之间形成一种头尾相接的环形等待资源关系
死锁的处理基本策略和常用方法:解决死锁的基本方法主要有预防死锁、避免死锁、检测死锁、解除死锁 、鸵鸟策略 等。
1) 死锁预防。死锁预防的基本思想是只要确保死锁发生的四个必要条件中至少有一个不成立,就能预防死锁的发生,具体方法包括:
a.打破互斥条件:允许进程同时访问某些资源。但是,有些资源是不能被多个进程所共享的,这是由资源本身属性所决定的,因此,这种办法通常并无实用价值。
b.打破占有并等待条件:可以实行资源预先分配策略(进程在运行前一次性向系统申请它所需要的全部资源,若所需全部资源得不到满足,则不分配任何资源,此进程暂不运行;只有当系统能满足当前进程所需的全部资源时,才一次性将所申请资源全部分配给该线程)或者只允许进程在没有占用资源时才可以申请资源(一个进程可申请一些资源并使用它们,但是在当前进程申请更多资源之前,它必须全部释放当前所占有的资源)。但是这种策略也存在一些缺点:在很多情况下,无法预知一个进程执行前所需的全部资源,因为进程是动态执行的,不可预知的;同时,会降低资源利用率,导致降低了进程的并发性,还可能发生饥饿。
c.打破非抢占条件:允许进程强行从占有者哪里夺取某些资源。也就是说,当一个进程占有了一部分资源,在其申请新的资源且得不到满足时,它必须释放所有占有的资源以便让其它线程使用。这种预防死锁的方式实现起来困难,会降低系统性能。
d.打破循环等待条件:实行资源有序分配策略。对所有资源排序编号,所有进程对资源的请求必须严格按资源序号递增的顺序提出,即只有占用了小号资源才能申请大号资源,这样就不回产生环路,预防死锁的发生。

2)死锁避免的基本思想
通过限制资源申请来预防死锁,缺点是设备使用率低和系统吞吐量低。
死锁避免要求系统提供一些关于如何申请资源的附加信息:1.要求进程说明可能需要的每种资源类型的最大需求。2.死锁避免算法动态检测资源分配状态以确保循环条件不可能成立。3.资源分配状态由可用资源和分配资源及进程最大需求决定。
死锁避免的基本思想是动态地检测资源分配状态,以确保循环等待条件不成立,从而确保系统处于安全状态。所谓安全状态是指:如果系统能按某个顺序为每个进程分配资源(不超过其最大值),那么系统状态是安全的,换句话说就是,如果存在一个安全序列,那么系统处于安全状态。
资源分配图算法和银行家算法是两种经典的死锁避免的算法,其可以确保系统始终处于安全状态。其中,资源分配图算法应用场景为每种资源类型只有一个实例(申请边,分配边,需求边,不形成环才允许分配),而银行家算法应用于每种资源类型可以有多个实例的场景。
3)死锁检测
如果系统既不采用死锁预防,也不采用死锁避免算法,那么系统可以进入不安全状态,可能导致死锁。此时,系统应提供死锁检测算法:检测系统状态,确定系统是否出现了死锁。
恢复机制:从死锁状态中恢复的算法。
4)死锁解除
  死锁解除的常用两种方法为进程终止和资源抢占。
进程终止是指简单地终止一个或多个进程以打破循环等待,包括两种方式:终止所有死锁进程和一次只终止一个进程直到取消死锁循环为止,代价很大。
资源抢占是指从一个或多个死锁进程那里抢占一个或多个资源,此时必须考虑三个问题:
  a. 选择一个牺牲品
  b. 回滚:回滚到安全状态
  c. 饥饿(在代价因素中加上回滚次数,回滚的越多则越不可能继续被作为牺牲品,避免一个进程总是被回滚)
19、线程有几种状态?
在 Java虚拟机中,线程从最初的创建到最终的消亡,要经历若干个状态:创建(new)、就绪(runnable/start)、运行(running)、阻塞(blocked)、等待(waiting)、时间等待(time waiting) 和 消亡(dead/terminated)。在给定的时间点上,一个线程只能处于一种状态,各状态的含义如下图所示:

20、线程同步的方式
线程同步:即当有一个线程在对内存进行操作时,其他线程都不可以对这个内存地址进行操作,直到该线程完成操作, 其他线程才能对该内存地址进行操作,而其他线程又处于等待状态。
互斥量 Synchronized/Lock:采用互斥对象机制,只有拥有互斥对象的线程才有访问公共资源的权限。因为互斥对象只有一个,所以可以保证公共资源不会被多个线程同时访问。
信号量 Semphare:它允许同一时刻多个线程访问同一资源,但是需要控制同一时刻访问此资源的最大线程数量。
事件(信号),Wait/Notify:通过通知操作的方式来保持多线程同步,还可以方便的实现多线程优先级的比较操作。
21、逻辑地址空间和物理地址空间
逻辑地址:由CPU产生,通常也称为虚拟地址。(进程的内部地址,0到MAX)。
物理地址:内存单元的实际地址,即加载到内存地址寄存器中的地址。
由程序所生产的所有逻辑地址的集合称为逻辑地址空间,与这些逻辑地址对应的所有物理地址的集合称为物理地址空间。
编译和加载时的地址绑定方法生成相同的逻辑地址和物理地址。执行时的地址绑定方案导致不同的逻辑地址和物理地址。
22、内存管理单元(MMU)
运行时将逻辑地址映射到物理地址的硬件设备称为内存管理单元。内存管理单元的设计有许多方法:如连续内存分配、分页、分段、带有分页的分段等等。
用户程序只处理逻辑地址,只有在指令和数据的加载和存储时,才将逻辑地址映射成物理地址。
23、交换
处理内存超载的方法:交换和虚拟内存。进程可以暂时从内存中交换出来到备份存储上,当需要执行时再调回内存。
备用存储:快速磁盘,需容纳所有用户程序的内存映像拷贝,同时也必须提供对这些内存映像的直接访问。(速度快、容量大、直接访问)
交换的问题:采用连续内存分配方案,换出进程必须处于完全空闲(等待I/O的进程不能换出)。换入进程的地址空间。交换的时间很长,执行的时间很少。只有进程过多,内存吃紧时,启动交换。

24、连续内存分配
内存通常分为两个区域:一个用于驻留操作系统,另一个用于用户进程。内存保护:保护用户进程之间互不影响,以及保护操作系统不受用户进程的影响。通过采用重定位寄存器和界限寄存器可以实现内存保护。重定位寄存器(基址寄存器)含有进程所在的最小物理地址;界限寄存器含有逻辑地址的值。每个逻辑地址必须小于界限寄存器。
内存管理单元(MMU)动态地将逻辑地址加上重定位寄存器的值后映射成物理地址,再根据物理地址送交内存单元 。

多分区方法:固定分区(MFT),可变分区(MVT)
可变分区中有孔(hole):可用的内存块。一开始整个内存是一个孔,随着进程的进入和中止,整个内存将遍布着许多大小不同的孔。操作系统有一个表用于记录那些内存可用(孔)和那些内存已用。当进程需要内存时,为该进程查找足够大的孔。如果找到,则为其分配所需的内存,未分配的作为一个新的孔下次再用。

如何查找合适的孔?1.首次适应:查找孔集合,分配第一个足够大的孔;2.最佳适应:分配最小的足够大的孔;3.最差使用:分配最大的孔;首次适应和最佳适应在执行时间和利用空间方面都好于最差适应。首次适应比最佳适应要快。
碎片:碎片是指因太小而无法分配给任何进程的孔。
1)外部碎片:所有小孔的内存之和满足请求,但不连续,形成外部碎片。上述三种分配算法都存在外部碎片的问题。
2)内部碎片:内存以固定大小的块为单位分配(固定分区方法),进程所分配的内存可能比实际需要的要大,形成内部碎片。(分配了但不用)
解决外部碎片问题的方法之一是紧缩:移动内存内容,将所有空闲空间合并成一整块。紧缩的缺点是有条件限制(要求重定位是动态的)、开销大。
解决外部碎片问题的另一种方法是允许物理地址空间为非连续的,这样只要有足够的内存就可为进程分配,这种方案的实现技术有分页和分段。
25、分页
分页内存管理方案允许进程的物理地址空间是非连续的。将物理内存分为固定大小的块,称为帧(frame)。大小为2的幂(512B-8M)。逻辑内存也分为固定大小的块,称为页(page)。页的大小与帧相同。内存的分配信息保存在称为帧表(frame table)的数据结构中。如果一个进程需要n页,则在内存在寻找n个空闲帧,如果有,则分配。为进程分配内存时建立一个页表,用于将逻辑地址转换成物理地址。采用分页技术不会产生外部碎片,但是会有内部碎片。
总结:物理内存块为帧,帧表表示内存分配信息。逻辑内存块为页,页表用于将逻辑地址转化成物理地址。
地址转换机制 :逻辑地址高m-n位为§页表索引,低n位(d)为页偏移 。

页表的硬件实现:
操作系统为每个进程分配一个页表,页表保存在内存中,页表的指针与其他信息一起存入进程控制块。
页表基寄存器(PTBR)指向页表,切换页表只需改变PTBR的值即可。
页表长度寄存器(PTLB)表示页表的长度。
页表机制存在的问题:访问内存中的一个字节需要两次内存访问,一次是根据页码查找页表,另一次是访问字节,因而内存访问速度减半。
解决上述问题的标准方案是采用较小但专用的快速硬件缓冲,称为关联内存或者翻译后被缓冲器(TLB)。
有些TLB在每个TLB条目中还保存地址空间标识符(ASID)。ASID可用来惟一地标识进程,为进程提供地址空间保护。
TLB是关联的快速内存,每个TLB条目包含键(标签)和值。

当关联内存根据给定值(页号)查找时,它会同时与所有键进行比较,如果找到条目,就得到相应的值域(帧号)。
TLB只包括页表中的一小部分条目,当CPU产生逻辑地址后,其页号提交给TLB。如果找到页号,则取得帧号,从而可以访问内存;否则,从页表中取得帧号,同时将页号和帧号增加的TLB中。
详情看实验6 —— MMU算法

内存保护:在分页环境中,内存保护是通过与每个帧相关联的保护位来实现的。这些位保存在页表中,如定义每一页是可读、可写或只读。页表中通常还有一个位:有效-无效位。操作系统通过对该位的设置可以允许或者不允许对某页的访问。
该位有效:表示相关的页在进程的逻辑地址空间内,是合法(有效)的页。
该位无效:表示相关的页不在进程的逻辑地址空间内,是非法(无效)的页。

共享页:分页的优点之一是可以共享共同代码:共享代码:多个进程之间可以共享同一只读代码(重入代码)段的拷贝:在所有进程中,共享代码的逻辑地址必须是相同的。
私有代码和数据:每个进程保留着独占的代码和数据;私有代码和数据所在的页可以在逻辑地址空间的任何地方。
组织页表的常见技术:层次化页表、哈希页表、反向页表
26、分段
用户通常认为内存是一组不同长度的段的集合,而不是一个线性的字节数组,段之间没有一定的顺序。分段正是基于这种观点的内存管理方法。分段是指将逻辑地址空间划分成一组段,每个段都有名称和长度。地址指定了段名和段内偏移。因此用户可通过两个量来指定地址段名和偏移。

逻辑地址由两个元素组成:<段号s,段内偏移d>
段表:将二维的用户定义地址映射为一维物理地址。段表的每个条目都包含:基地址:包含段的起始地址;界限:指定段的长度
段表基地址寄存器(STBR)指向内存中的段表所在的物理地址;
段表界限寄存器(STLR)指示程序所用的段的个数
段号S小于STLR的时候才是有效的。

27、分页和分段有什么区别(内存管理)?
段式存储管理是一种符合用户视角的内存分配管理方案。在段式存储管理中,将程序的地址空间划分为若干段(segment),如代码段,数据段,堆栈段;这样每个进程有一个二维地址空间,相互独立,互不干扰。段式管理的优点是:没有内碎片(因为段大小可变,改变段大小来消除内碎片)。但段换入换出时,会产生外碎片(比如4k的段换5k的段,会产生1k的外碎片)
  页式存储管理方案是一种用户视角内存与物理内存相分离的内存分配管理方案。在页式存储管理中,将程序的逻辑地址划分为固定大小的页(page),而物理内存划分为同样大小的帧,程序加载时,可以将任意一页放入内存中任意一个帧,这些帧不必连续,从而实现了离散分离。页式存储管理的优点是:没有外碎片(因为页的大小固定),但会产生内碎片(一个页可能填充不满)。
两者的不同点:
1)目的不同:分页是由于系统管理的需要而不是用户的需要,它是信息的物理单位;分段的目的是为了能更好地满足用户的需要,它是信息的逻辑单位,它含有一组其意义相对完整的信息
2)大小不同:页的大小固定且由系统决定,而段的长度却不固定,由其所完成的功能决定;
3)地址空间不同: 段向用户提供二维地址空间;页向用户提供的是一维地址空间;
4)信息共享:段是信息的逻辑单位,便于存储保护和信息的共享,页的保护和共享受到限制;
5)内存碎片:页式存储管理的优点是没有外碎片(因为页的大小固定),但会产生内碎片(一个页可能填充不满);而段式管理的优点是没有内碎片(因为段大小可变,改变段大小来消除内碎片)。但段换入换出时,会产生外碎片(比如4k的段换5k的段,会产生1k的外碎片)。
28、虚拟内存
虚拟内存:虚拟内存允许执行进程不必完全在内存中。虚拟内存的基本思想是:每个进程拥有独立的地址空间,这个空间被分为大小相等的多个块,称为页(Page),每个页都是一段连续的地址。这些页被映射到物理内存,但并不是所有的页都必须在内存中才能运行程序。当程序引用到一部分在物理内存中的地址空间时,由硬件立刻进行必要的映射;当程序引用到一部分不在物理内存中的地址空间时,由操作系统负责将缺失的部分装入物理内存并重新执行失败的命令。这样,对于进程而言,逻辑上似乎有很大的内存空间,实际上其中一部分对应物理内存上的一块(称为帧,通常页和帧大小相等),还有一些没加载在内存中的对应在硬盘上。注意,请求分页系统、请求分段系统和请求段页式系统都是针对虚拟内存的,通过请求实现内存与外存的信息置换。

由图可以看出,虚拟内存实际上可以比物理内存大。当访问虚拟内存时,会访问MMU(内存管理单元)去匹配对应的物理地址(比如图5的0,1,2)。如果虚拟内存的页并不存在于物理内存中(如图的3,4),会产生缺页中断,从磁盘中取得缺的页放入内存,如果内存已满,还会根据某种算法将磁盘中的页换出。
虚拟内存有两种实现方案:1. 按需页面调度。2. 按需分段调度:段是不定长的,因而段置换算法比页置换算法复杂许多。
按需页面调度:进程驻留在辅助存储器上(硬盘),当执行进程时,按需将它换入内存。按需页面调度类似于分页系统+交换,和交换不同的是,它并不将整个进程换入内存,而只是调入某些需要的页,这种交换称为懒惰交换(lazy swapper)。对进程的页进行的交换操作称为调页程序(pager)
当需要某个页时,就参考其页表(页号-帧号)的有效位:(为了硬件保护)
该位有效:说明相关的页合法,且已在内存中。
该位无效:表明该页无效(不在进程的逻辑地址空间内,设置为i),或者有效但在磁盘上(虚拟内存中,设置为页所在的磁盘地址)。
页错误:进程试图访问尚未调入内存的页时,(即访问标记为无效的页),将产生页错误陷阱。
处理错误页的步骤: 1)参考页表(与PCB一起保存)、确定引用是否合法。2)如果引用非法,中断进程;如果合法,但页在磁盘中,则将其调入。3)在物理内存中找到一个空闲帧(查找空闲帧链表)。4)将所需的页调入空闲帧,修改页表。5)重启因陷阱而中断的指令,进程可以访问所需页。
有效访问时间=(1-p)内存访问时间+p页错误处理时间。 页错误处理时间主要包括:处理页错误中断,页交换时间,重新启动进程;
页面置换:过度分配帧,当一个用户进程执行出现页错误时,操作系统确定所需页在磁盘上的位置,但却发现空闲帧链表为空(没有空闲帧:所有帧都被使用) 解决过度分配帧问题的方法是采用页面置换。
页面置换的基本方法:查找所需页在磁盘上的位置。查找空闲帧,如果有空闲帧,那么就使用它;如果没有空闲帧,就使用页面置换算法选择一个“牺牲”帧。将“牺牲”帧的内容写到磁盘上,修改页表和帧表。将所需的页读入空闲帧,修改页表和帧表。重启进程。
页面置换算法:
1)FIFO先进先出算法:在操作系统中经常被用到,比如作业调度(主要实现简单,很容易想到)。
2)LRU(Least recently use)最近最少使用算法:根据使用时间到现在的长短来判断;
3)LFU(Least frequently use)最少使用次数算法:根据使用次数来判断;
4)OPT(Optimal replacement)最优置换算法:理论的最优,理论;就是要保证置换出去的是不再被使用的页,或者是在实际内存中最晚使用的算法。
29、虚拟内存的应用与优点
虚拟内存很适合在多道程序设计系统中使用,许多程序的片段同时保存在内存中。当一个程序等待它的一部分读入内存时,可以把CPU交给另一个进程使用。虚拟内存的使用可以带来以下好处:在内存中可以保留多个进程,系统并发度提高。解除了用户与内存之间的紧密约束,进程可以比内存的全部空间还大。
30、颠簸
颠簸本质上是指频繁的页调度行为,具体来讲,进程发生缺页中断,这时,必须置换某一页。然而,其他所有的页都在使用,它置换一个页,但又立刻再次需要这个页。因此,会不断产生缺页中断,导致整个系统的效率急剧下降,这种现象称为颠簸(抖动)。
内存颠簸的解决策略包括:1)如果是因为页面替换策略失误,可以修改替换算法来解决这个问题;2)如果是因为运行的程序太多,造成程序无法同时将所有频繁访问的页面调入内存,则要降低多道程序的数量;3)否则,还剩下两个办法:终止该进程或增加物理内存容量。
31、局部性原理
时间上的局部性:最近被访问的页在不久的将来还会被访问;
空间上的局部性:内存中被访问的页周围的页也很可能被访问。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值