操作系统重点知识梳理&常见面试题整理

编程入门 行业动态 更新时间:2024-10-17 21:20:03
      操作系统一直以来都是自己的硬伤 , 在面试中一直在担心被问到操作系统 ,消除恐惧的最好方式就是直面恐惧,开始吧少年。

    多图警告!!!文中图片大部分来源于操作系统_清华大学(向勇、陈渝)课程

1 计算机体系结构和分层体系

    计算机硬件由CPU、存储器和IO设备构成,由总线连接。
    内存层次指CPU访问的指令或者数据所处的位置,CPU能访问CPU芯片内的寄存器和cache,OS无法管理,cache和寄存器速度快,但是容量小,主存容量较大,但掉电后数据或者指令丢失,磁盘容量最大,但速度最慢。

2 地址空间和地址生成

    物理地址空间 – 硬件支持的地址空间
    逻辑地址空间 – 在CPU运行的进程看到的地址

3 连续内存分配——内存碎片、动态分配

    在没有其他方式辅助的情况下,我们分配给一个进程的内存是连续的。在分配时候我们需要有动态分配与碎片处理。如何理解呢?就是每个进程需要一块内存,我们要选取合适的位置的内存分配给它。当有的进程先结束了内存还给操作系统,此时可能就会产生内存碎片,要对碎片进行处理。首先对一些概念进行解释。
     连续内存分配:给进程分配一块不小于指定大小的连续的物理内存区域。
     内存碎片:不能被利用的空闲内存,内存碎片又分为外部碎片和内部碎片。
    外部碎片:分配单元之间的未被利用的内存,比如两个进程之间的进程结束后的空间,如果后续请求的大小都大于这一部分空间,这部分空间就不能被利用,也就形成了外部碎片。
内部碎片:分配单元内部的未被使用的内存,这是由于分配时可能只能分配2的幂次方大小内存比如512字节,而实际使用了510字节,那么就有2字节的内部碎片。
动态分配:
    当程序加载执行时,需要分配给进程一个指定大小可变的分区,分区的地址是连续的。如图中右侧分给进程1到6内存空间。当进程3和进程5结束后它们所占有的位置重新变为空闲。操作系统要维护的数据结构就包含了内存中已分配区域与未分配区域。当有新的进程请求一定的内存空间时,则根据未分配空间进行一个动态分区分配。分配的策略是多种多样的。比如:
     最先分配,空闲分区列表按照地址顺序排序,遍历空闲分区,遇到的第一个大小满足需求的区域分配给进程。释放内存使,查看附近是否有临近的空闲区,有的话进行合并。优点是找和合并开销较小,算法简单,并且由于每次从小地址开始查找,可以在大地址处留有大块的空闲分区,可以分配给需要大内存的进程。缺点是会有外部碎片,因为切完剩下的可能有很多小块内存,也因此分配大内存时需要遍历到最后时间较长。
    最佳匹配,空闲分区列表按照大小排序,寻找空闲区域中大小大于需求大小中最小的分配给进程,具体实现时可以对空闲分区按大小排序从最小开始寻找第一个大于需求的内存区即可,如果不排序则需要整个遍历一遍。释放时,也是与邻近空闲区域合并。而合并时我们要找的是地址邻近的而不是大小邻近的,所以合并的开销会大一些。优点大部分分配的内存尺寸较小时效果很好,因为可以避免较大的内存被拆分,同时减小外部碎片的大小,同时相对来说比较简单。缺点是外部碎片还是较多,并且越小越无法被利用,容易产生很多无用的小碎片,此外如前所述释放分区较慢,合并时算法复杂。
    最差匹配,空闲分区列表按照大小排序,寻找空闲去榆中大小最大的区域从中划分出需要大小的内存分配给进程。释放时寻找邻近空闲分区合并。因此也存在最佳匹配的问题,释放内存时合并算法开销较大。优点是中等尺度内存分配较多时效果最好,可以避免产生太多小碎片。缺点是释放较慢,也会有外部碎片,容易破坏大的内存区域,因此后续无法分配大内存。
无论哪种算法都会存在空间碎片,所以可以采用压缩式与交换式碎片整理算法,但是碎片整理算法存在着不知何时压缩何时交换和开销问题,所以连续内存分配还是存在着很大的弊端。

3 非连续内存分配

3.1 非连续内存分配

为什么要采用非连续内存分配?
    因为连续内存分配会产生内外碎片空间,内存的利用率很低,利用交换或压缩碎片整理算法的开销太大,又不好确定何时进行交换或者压缩,所以我们采用非连续内存分配法则。非连续内存分配法也不是没有缺点,他最大的缺点就是管理带来的开销(也就是说虚拟地址和物理地址之间的转换是有开销的)。
    非连续分配允许一个程序分散地装入到不相邻的内存分区中,根据分区的大小是否固定分为分页存储管理方式和分段存储管理方式。在分页存储管理方式中,如果不具备页面对换功能,则称为基本分页存储管理方式,或纯分页管理方式。
这个地方补上分页分段的知识点

4 虚拟内存

为什么要有虚拟内存?
    程序运行的过程中会发现内存越来越不够用,我们要想一些办法让更多的程序在有限的内存中跑起来。
在虚拟内存中出现之前存在覆盖技术和交换技术

    由上文可以看出覆盖技术和交换技术存在很大的问题,虚拟内存技术在一定程度上解决了这些问题。

    在程序执行的过程中,如果需要执行的指令或访问的数据不在内存当中,则由处理器或者操作系统将相应的页面或段导入到内存当中,如果内存有空闲则直接导入否则就需要页面置换算法进行页面置换。

    那虚拟内存技术是怎样实现的呢?下面以页式管理为基础看一看虚拟内存如何实现。

    丛上图可以看出,左侧是逻辑地址空间,右侧是物理地址空间。逻辑地址空间和物理地址空间是由页表来维护的。

    在页表中除了有逻辑地址和物理地址之间的对应关系信息以外,还保存了一些位信息,这些位信息会为虚拟内存技术提供支持。

5 页面置换算法

    在程序执行的过程中,如果需要执行的指令或访问的数据不在内存当中,则由处理器或者操作系统将相应的页面或段导入到内存当中,如果内存有空闲则直接导入否则就需要页面置换算法进行页面置换。

    1 最优页面置换算法
    2 先进先出
    3 LRU
    4 时钟页面置换算法
参考文献
    这里重点讲一讲时钟页面置换算法

6 先来先服务和短作业(进程)优先调度算法

1.先来先服务调度算法
    先来先服务(FCFS)调度算法是一种最简单的调度算法,该算法既可用于作业调度,也可用于进程调度。当在作业调度中采用该算法时,每次调度都是从后备作业队列中选择一个或多个最先进入该队列的作业,将它们调入内存,为它们分配资源、创建进程,然后放入就绪队列。在进程调度中采用FCFS算法时,则每次调度是从就绪队列中选择一个最先进入该队列的进程,为之分配处理机,使之投入运行。该进程一直运行到完成或发生某事件而阻塞后才放弃处理机。

2.短作业(进程)优先调度算法
    短作业(进程)优先调度算法SJ§F,是指对短作业或短进程优先调度的算法。它们可以分别用于作业调度和进程调度。短作业优先(SJF)的调度算法是从后备队列中选择一个或若干个估计运行时间最短的作业,将它们调入内存运行。而短进程优先(SPF)调度算法则是从就绪队列中选出一个估计运行时间最短的进程,将处理机分配给它,使它立即执行并一直执行到完成,或发生某事件而被阻塞放弃处理机时再重新调度。

二、高优先权优先调度算法
1.优先权调度算法的类型

    为了照顾紧迫型作业,使之在进入系统后便获得优先处理,引入了最高优先权优先(FPF)调度算法。此算法常被用于批处理系统中,作为作业调度算法,也作为多种操作系统中的进程调度算法,还可用于实时系统中。当把该算法用于作业调度时,系统将从后备队列中选择若干个优先权最高的作业装入内存。当用于进程调度时,该算法是把处理机分配给就绪队列中优先权最高的进程,这时,又可进一步把该算法分成如下两种。
1) 非抢占式优先权算法
    在这种方式下,系统一旦把处理机分配给就绪队列中优先权最高的进程后,该进程便一直执行下去,直至完成;或因发生某事件使该进程放弃处理机时,系统方可再将处理机重新分配给另一优先权最高的进程。这种调度算法主要用于批处理系统中;也可用于某些对实时性要求不严的实时系统中。
2) 抢占式优先权调度算法
    在这种方式下,系统同样是把处理机分配给优先权最高的进程,使之执行。但在其执行期间,只要又出现了另一个其优先权更高的进程,进程调度程序就立即停止当前进程(原优先权最高的进程)的执行,重新将处理机分配给新到的优先权最高的进程。因此,在采用这种调度算法时,是每当系统中出现一个新的就绪进程i 时,就将其优先权Pi与正在执行的进程j 的优先权Pj进行比较。如果Pi≤Pj,原进程Pj便继续执行;但如果是Pi>Pj,则立即停止Pj的执行,做进程切换,使i 进程投入执行。显然,这种抢占式的优先权调度算法能更好地满足紧迫作业的要求,故而常用于要求比较严格的实时系统中,以及对性能要求较高的批处理和分时系统中。
2.高响应比优先调度算法
    在批处理系统中,短作业优先算法是一种比较好的算法,其主要的不足之处是长作业的运行得不到保证。如果我们能为每个作业引入前面所述的动态优先权,并使作业的优先级随着等待时间的增加而以速率a 提高,则长作业在等待一定的时间后,必然有机会分配到处理机。该优先权的变化规律可描述为:
操作系统
由于等待时间与服务时间之和就是系统对该作业的响应时间,故该优先权又相当于响应比RP。据此,又可表示为:
操作系统
由上式可以看出:
    (1) 如果作业的等待时间相同,则要求服务的时间愈短,其优先权愈高,因而该算法有利于短作业。
    (2) 当要求服务的时间相同时,作业的优先权决定于其等待时间,等待时间愈长,其优先权愈高,因而它实现的是先来先服务。
    (3) 对于长作业,作业的优先级可以随等待时间的增加而提高,当其等待时间足够长时,其优先级便可升到很高,从而也可获得处理机。简言之,该算法既照顾了短作业,又考虑了作业到达的先后次序,不会使长作业长期得不到服务。因此,该算法实现了一种较好的折衷。当然,在利用该算法时,每要进行调度之前,都须先做响应比的计算,这会增加系统开销。

三、基于时间片的轮转调度算法
1.时间片轮转法

  1. 基本原理
        在早期的时间片轮转法中,系统将所有的就绪进程按先来先服务的原则排成一个队列,每次调度时,把CPU 分配给队首进程,并令其执行一个时间片。时间片的大小从几ms 到几百ms。当执行的时间片用完时,由一个计时器发出时钟中断请求,调度程序便据此信号来停止该进程的执行,并将它送往就绪队列的末尾;然后,再把处理机分配给就绪队列中新的队首进程,同时也让它执行一个时间片。这样就可以保证就绪队列中的所有进程在一给定的时间内均能获得一时间片的处理机执行时间。换言之,系统能在给定的时间内响应所有用户的请求。
    2.多级反馈队列调度算法
        前面介绍的各种用作进程调度的算法都有一定的局限性。如短进程优先的调度算法,仅照顾了短进程而忽略了长进程,而且如果并未指明进程的长度,则短进程优先和基于进程长度的抢占式调度算法都将无法使用。而多级反馈队列调度算法则不必事先知道各种进程所需的执行时间,而且还可以满足各种类型进程的需要,因而它是目前被公认的一种较好的进程调度算法。在采用多级反馈队列调度算法的系统中,调度算法的实施过程如下所述。
        (1) 应设置多个就绪队列,并为各个队列赋予不同的优先级。第一个队列的优先级最高,第二个队列次之,其余各队列的优先权逐个降低。该算法赋予各个队列中进程执行时间片的大小也各不相同,在优先权愈高的队列中,为每个进程所规定的执行时间片就愈小。例如,第二个队列的时间片要比第一个队列的时间片长一倍,……,第i+1个队列的时间片要比第i个队列的时间片长一倍。
        (2) 当一个新进程进入内存后,首先将它放入第一队列的末尾,按FCFS原则排队等待调度。当轮到该进程执行时,如它能在该时间片内完成,便可准备撤离系统;如果它在一个时间片结束时尚未完成,调度程序便将该进程转入第二队列的末尾,再同样地按FCFS原则等待调度执行;如果它在第二队列中运行一个时间片后仍未完成,再依次将它放入第三队列,……,如此下去,当一个长作业(进程)从第一队列依次降到第n队列后,在第n 队列便采取按时间片轮转的方式运行。
        (3) 仅当第一队列空闲时,调度程序才调度第二队列中的进程运行;仅当第1~(i-1)队列均空时,才会调度第i队列中的进程运行。如果处理机正在第i队列中为某进程服务时,又有新进程进入优先权较高的队列(第1~(i-1)中的任何一个队列),则此时新进程将抢占正在运行进程的处理机,即由调度程序把正在运行的进程放回到第i队列的末尾,把处理机分配给新到的高优先权进程。

7 死锁相关

在另外一篇博客中 传送门

8 面试常见问题整理

什么是系统调用呢?
    根据进程访问资源的特点,我们可以把进程在系统上的运行分为两个级别:
    用户态(user mode) : 用户态运行的进程或可以直接读取用户程序的数据。
    系统态(kernel mode):可以简单的理解系统态运行的进程或程序几乎可以访问计算机的任何资源,不受限制。
说了用户态和系统态之后,那么什么是系统调用呢?

    我们运行的程序基本都是运行在用户态,如果我们调用操作系统提供的系统态级别的子功能咋办呢?那就需要系统调用了!

    也就是说在我们运行的用户程序中,凡是与系统态级别的资源有关的操作(如文件管理、进程控制、内存管理等),都必须通过系统调用方式向操作系统提出服务请求,并由操作系统代为完成。
进程和线程的区别。
进程:程序的动态执行过程 资源分配的基本单位
线程:一个进程可以包含一个或者多个线程,cpu调度的基本单位
    从上图可以看出:一个进程中可以有多个线程,多个线程共享进程的堆和方法区 (JDK1.8 之后的元空间)资源,但是每个线程有自己的程序计数器、虚拟机栈和 本地方法栈。

    总结:线程是进程划分成的更小的运行单位,一个进程在其执行的过程中可以产生多个线程。线程和进程最大的不同在于基本上各进程是独立的,而各线程则不一定,因为同一进程中的线程极有可能会相互影响。线程执行开销小,但不利于资源的管理和保护;而进程正相反。
进程有哪几种状态?
    创建状态(new) :进程正在被创建,尚未到就绪状态。
    就绪状态(ready) :进程已处于准备运行状态,即进程获得了除了处理器之外的一切所需资源,一旦得到处理器资源(处理器分配的时间片)即可运行。
    运行状态(running) :进程正在处理器上上运行(单核 CPU 下任意时刻只有一个进程处于运行状态)。
    阻塞状态(waiting) :又称为等待状态,进程正在等待某一事件而暂停运行如等待某资源为可用或等待 IO 操作完成。即使处理器空闲,该进程也不能运行。
    结束状态(terminated) :进程正在从系统中消失。可能是进程正常结束或其他原因中断退出运行。
进程间的通信方式
    (1)管道/匿名管道(Pipes) :用于具有亲缘关系的父子进程间或者兄弟进程之间的通信。
    (2)有名管道(Names Pipes) : 匿名管道由于没有名字,只能用于亲缘关系的进程间通信。为了克服这个缺点,提出了有名管道。有名管道严格遵循先进先出(first in first out)。有名管道以磁盘文件的方式存在,可以实现本机任意两个进程通信。
    (3)信号(Signal) :信号是一种比较复杂的通信方式,用于通知接收进程某个事件已经发生;
    (4)消息队列(Message Queuing) :消息队列是消息的链表,具有特定的格式,存放在内存中并由消息队列标识符标识。管道和消息队列的通信数据都是先进先出的原则。与管道(无名管道:只存在于内存中的文件;命名管道:存在于实际的磁盘介质或者文件系统)不同的是消息队列存放在内核中,只有在内核重启(即,操作系统重启)或者显示地删除一个消息队列时,该消息队列才会被真正的删除。消息队列可以实现消息的随机查询,消息不一定要以先进先出的次序读取,也可以按消息的类型读取.比 FIFO 更有优势。消息队列克服了信号承载信息量少,管道只能承载无格式字 节流以及缓冲区大小受限等缺。
    (5)信号量(Semaphores) :信号量是一个计数器,用于多进程对共享数据的访问,信号量的意图在于进程间同步。这种通信方式主要用于解决与同步相关的问题并避免竞争条件。
共享内存(Shared memory) :使得多个进程可以访问同一块内存空间,不同进程可以及时看到对方进程中对共享内存中数据的更新。这种方式需要依靠某种同步操作,如互斥锁和信号量等。可以说这是最有用的进程间通信方式。
    (6)套接字(Sockets) : 此方法主要用于在客户端和服务器之间通过网络进行通信。套接字是支持 TCP/IP 的网络通信的基本操作单元,可以看做是不同主机之间的进程进行双向通信的端点,简单的说就是通信的两方的一种约定,用套接字中的相关函数来完成通信过程。
线程间的同步的方式
    (1)互斥量(Mutex):采用互斥对象机制,只有拥有互斥对象的线程才有访问公共资源的权限。因为互斥对象只有一个,所以可以保证公共资源不会被多个线程同时访问。比如 Java 中的 synchronized 关键词和各种 Lock 都是这种机制。
    (2)信号量(Semphares) :它允许同一时刻多个线程访问同一资源,但是需要控制同一时刻访问此资源的最大线程数量
    (3)事件(Event) :Wait/Notify:通过通知操作的方式来保持多线程同步,还可以方便的实现多线程优先级的比较操
进程的调度算法
    (1)先到先服务(FCFS)调度算法 : 从就绪队列中选择一个最先进入该队列的进程为之分配资源,使它立即执行并一直执行到完成或发生某事件而被阻塞放弃占用 CPU 时再重新调度。
    (2)短作业优先(SJF)的调度算法 : 从就绪队列中选出一个估计运行时间最短的进程为之分配资源,使它立即执行并一直执行到完成或发生某事件而被阻塞放弃占用 CPU 时再重新调度。
    (3)时间片轮转调度算法 : 时间片轮转调度是一种最古老,最简单,最公平且使用最广的算法,又称 RR(Round robin)调度。每个进程被分配一个时间段,称作它的时间片,即该进程允许运行的时间。
多级反馈队列调度算法 :前面介绍的几种进程调度的算法都有一定的局限性。如短进程优先的调度算法,仅照顾了短进程而忽略了长进程 。多级反馈队列调度算法既能使高优先级的作业得到响应又能使短作业(进程)迅速完成。,因而它是目前被公认的一种较好的进程调度算法,UNIX 操作系统采取的便是这种调度算法。
    (4)优先级调度 : 为每个流程分配优先级,首先执行具有最高优先级的进程,依此类推。具有相同优先级的进程以 FCFS 方式执行。可以根据内存要求,时间要求或任何其他资源要求来确定优先级。
常见的几种内存管理机制
    简单分为连续分配管理方式和非连续分配管理方式这两种。连续分配管理方式是指为一个用户程序分配一个连续的内存空间,常见的如 块式管理。同样地,非连续分配管理方式允许一个程序使用的内存分布在离散或者说不相邻的内存中,常见的如页式管理、段式管理和段页式管理。
    (1)页式管理 :把主存分为大小相等且固定的一页一页的形式,页较小,相对相比于块式管理的划分力度更大,提高了内存利用率,减少了碎片。页式管理通过页表对应逻辑地址和物理地址。
    (2)段式管理 : 页式管理虽然提高了内存利用率,但是页式管理其中的页实际并无任何实际意义。 段式管理把主存分为一段段的,每一段的空间又要比一页的空间小很多 。但是,最重要的是段是有实际意义的,每个段定义了一组逻辑信息,例如,有主程序段 MAIN、子程序段 X、数据段 D 及栈段 S 等。 段式管理通过段表对应逻辑地址和物理地址。
    (3)段页式管理机制结合了段式管理和页式管理的优点。简单来说段页式管理机制就是把主存先分成若干段,每个段又分成若干页,也就是说 段页式管理机制 中段与段之间以及段的内部的都是离散的。
快表和多级页表
分页内存管理中,很重要的两点是:
    (1)虚拟地址到物理地址的转换要快。
    (2)解决虚拟地址空间大,页表也会很大的问题。
快表
    为了解决虚拟地址到物理地址的转换速度,操作系统在 页表方案基础之上引入了 快表 来加速虚拟地址到物理地址的转换。我们可以把块表理解为一种特殊的高速缓冲存储器(Cache),其中的内容是页表的一部分或者全部内容。作为页表的 Cache,它的作用与页表相似,但是提高了访问速率。由于采用页表做地址转换,读写内存数据时 CPU 要访问两次主存。有了快表,有时只要访问一次高速缓冲存储器,一次主存,这样可加速查找并提高指令执行速度。
    (1)使用快表之后的地址转换流程是这样的:
    (2)根据虚拟地址中的页号查快表;
    (3)如果该页在快表中,直接从快表中读取相应的物理地址;
    (4)如果该页不在快表中,就访问内存中的页表,再从页表中得到物理地址,同时将页表中的该映射表项添加到快表中;
    (5)当快表填满后,又要登记新页时,就按照一定的淘汰策略淘汰掉快表中的一个页。

    看完了之后你会发现快表和我们平时经常在我们开发的系统使用的缓存(比如 Redis)很像,的确是这样的,操作系统中的很多思想、很多经典的算法,你都可以在我们日常开发使用的各种工具或者框架中找到它们的影子。
多级页表
    引入多级页表的主要目的是为了避免把全部页表一直放在内存中占用过多空间,特别是那些根本就不需要的页表就不需要保留在内存中。
总结:
    为了提高内存的空间性能,提出了多级页表的概念;但是提到空间性能是以浪费时间性能为基础的,因此为了补充损失的时间性能,提出了快表(即 TLB)的概念。 不论是快表还是多级页表实际上都利用到了程序的局部性原理,局部性原理在后面的虚拟内存这部分会介绍到。
分页机制和分段机制的共同点和区别
共同点 :
    (1)分页机制和分段机制都是为了提高内存利用率,较少内存碎片。
    (2)页和段都是离散存储的,所以两者都是离散分配内存的方式。但是,每个页和段中的内存是连续的。
区别 :
    (1)页的大小是固定的,由操作系统决定;而段的大小不固定,取决于我们当前运行的程序。
    (2)分页仅仅是为了满足操作系统内存管理的需求,而段是逻辑信息的单位,在程序中可以体现为代码段,数据段,能够更好满足用户的需要。
逻辑(虚拟)地址和物理地址
    我们编程一般只有可能和逻辑地址打交道,比如在 C 语言中,指针里面存储的数值就可以理解成为内存里的一个地址,这个地址也就是我们说的逻辑地址,逻辑地址由操作系统决定。物理地址指的是真实物理内存中地址,更具体一点来说就是内存地址寄存器中的地址。物理地址是内存单元真正的地址。
CPU 寻址了解吗?为什么需要虚拟地址空间?
现代处理器使用的是一种称为 虚拟寻址(Virtual Addressing)的寻址方式。使用虚拟寻址,CPU 需要将虚拟地址翻译成物理地址,这样才能访问到真实的物理内存。 实际上完成虚拟地址转换为物理地址转换的硬件是 CPU 中含有一个被称为 内存管理单元(Memory Management Unit, MMU) 的硬件。
为什么需要虚拟地址空间?
    先从没有虚拟地址空间的时候说起吧!没有虚拟地址空间的时候,程序都是直接访问和操作的都是物理内存。但是这样有什么问题呢?
    (1)用户程序可以访问任意内存,寻址内存的每个字节,这样就很容易(有意或者无意)破坏操作系统,造成操作系统崩溃。
    (2)想要同时运行多个程序特别困难,比如你想同时运行一个微信和一个 QQ 音乐都不行。为什么呢?举个简单的例子:微信在运行的时候给内存地址 1xxx 赋值后,QQ 音乐也同样给内存地址 1xxx 赋值,那么 QQ 音乐对内存的赋值就会覆盖微信之前所赋的值,这就造成了微信这个程序就会崩溃。
    总结来说:如果直接把物理地址暴露出来的话会带来严重问题,比如可能对操作系统造成伤害以及给同时运行多个程序造成困难。
通过虚拟地址访问内存有以下优势:

    (1)程序可以使用一系列相邻的虚拟地址来访问物理内存中不相邻的大内存缓冲区。
    (2)程序可以使用一系列虚拟地址来访问大于可用物理内存的内存缓冲区。当物理内存的供应量变小时,内存管理器会将物理内存页(通常大小为 4 KB)保存到磁盘文件。数据或代码页会根据需要在物理内存与磁盘之间移动。
    (3)不同进程使用的虚拟地址彼此隔离。一个进程中的代码无法更改正在由另一进程或操作系统使用的物理内存。
虚拟内存的技术实现
    虚拟内存的实现需要建立在离散分配的内存管理方式的基础上。 虚拟内存的实现有以下三种方式:

    请求分页存储管理 :建立在分页管理之上,为了支持虚拟存储器功能而增加了请求调页功能和页面置换功能。请求分页是目前最常用的一种实现虚拟存储器的方法。请求分页存储管理系统中,在作业开始运行之前,仅装入当前要执行的部分段即可运行。假如在作业运行的过程中发现要访问的页面不在内存,则由处理器通知操作系统按照对应的页面置换算法将相应的页面调入到主存,同时操作系统也可以将暂时不用的页面置换到外存中。
    请求分段存储管理 :建立在分段存储管理之上,增加了请求调段功能、分段置换功能。请求分段储存管理方式就如同请求分页储存管理方式一样,在作业开始运行之前,仅装入当前要执行的部分段即可运行;在执行过程中,可使用请求调入中断动态装入要访问但又不在内存的程序段;当内存空间已满,而又需要装入新的段时,根据置换功能适当调出某个段,以便腾出空间而装入新的段。
    请求段页式存储管理

9、虚拟内存和物理内存

如果只使用物理内存会存在如下的问题:
    (1)因为我的物理内存时有限的,当有多个进程要执行的时候,都要给4G内存,很显然你内存小一点,这很快就分配完了,于是没有得到分配资源的进程就只能等待。当一个进程执行完了以后,再将等待的进程装入内存。这种频繁的装入内存的操作是很没效率的
    (2)由于指令都是直接访问物理内存的,那么我这个进程就可以修改其他进程的数据,甚至会修改内核地址空间的数据,这是我们不想看到的
    (3)因为内存时随机分配的,所以程序运行的地址也是不正确的。
于是针对上面会出现的各种问题,虚拟内存就出来了。进程得到的这虚拟内存是一个连续的地址空间(这也只是进程认为),而实际上,它通常是被分隔成多个物理内存碎片,还有一部分存储在外部磁盘存储器上,在需要时进行数据交换。

进程开始要访问一个地址,它可能会经历下面的过程

    (1)每次我要访问地址空间上的某一个地址,都需要把地址翻译为实际物理内存地址
    (2)所有进程共享这整一块物理内存,每个进程只把自己目前需要的虚拟地址空间映射到物理内存上
    (3)进程需要知道哪些地址空间上的数据在物理内存上,哪些不在(可能这部分存储在磁盘上),还有在物理内存上的哪里,这就需要通过页表来记录
页表的每一个表项分两部分,第一部分记录此页是否在物理内存上,第二部分记录物理内存页的地址(如果在的话)
    (4)当进程访问某个虚拟地址的时候,就会先去看页表,如果发现对应的数据不在物理内存上,就会发生缺页异常
    (5)缺页异常的处理过程,操作系统立即阻塞该进程,并将硬盘里对应的页换入内存,然后使该进程就绪,如果内存已经满了,没有空地方了,那就找一个页覆盖,至于具体覆盖的哪个页,就需要看操作系统的页面置换算法是怎么设计的了。

页表的工作原理如下图

    (1)我们的cpu想访问虚拟地址所在的虚拟页(VP3),根据页表,找出页表中第三条的值.判断有效位。 如果有效位为1,DRMA缓存命中,根据物理页号,找到物理页当中的内容,返回。
    (2)若有效位为0,参数缺页异常,调用内核缺页异常处理程序。内核通过页面置换算法选择一个页面作为被覆盖的页面,将该页的内容刷新到磁盘空间当中。然后把VP3映射的磁盘文件缓存到该物理页上面。然后页表中第三条,有效位变成1,第二部分存储上了可以对应物理内存页的地址的内容。
    (3)缺页异常处理完毕后,返回中断前的指令,重新执行,此时缓存命中,执行1。
    (4)将找到的内容映射到告诉缓存当中,CPU从告诉缓存中获取该值,结束。

10、Linux常见命令和一些常识

ps
    在Linux中,ps(Process Status)用于列出系统中当前运行的进程(process)的状态,ps命令列出的是当前那些进程的快照。如果要动态的显示进程信息,需要使用top命令。使用ps命令可以确定当前有哪些进程正在运行中与运行的状态、进程是否结束、进程是否僵死、哪些进程占用过多资源等。
netstat
    netstat是一款命令行工具,可用于列出系统上所有的网络套接字连接情况,包括tcp、udp以及unix套接字,另外他还能列出处于监听状态(即等待接入)的套接字。如果想确认系统上的web服务有没有起来,可以使用netstat查看。
top
    经常用来监听linux的系统状况,是常用的性能分析工具,能够实时显示系统中各个进程的资源占用情况。
awk
    AWK:是一种处理文本文件的语言,是一个强大的文本分析工具
相比较屏幕处理的优点,在处理庞大文件时不会出现内存溢出或是处理缓慢的问题,通常用来格式化文本信息。
cat a.txt 一次性显示整个文件内容
tail -f b.txt 实时刷新文件尾部,用于观察程序运行情况
show
例如:show date 、show cal
就是用来显示时间、显示日历
vi vim 实现文本的编辑
vi和vim都是Linux中的编辑器,不同的是vim比较高级,可以视为vi的升级版本。
vi使用于文本编辑,但是vim更适用于coding

HTTP状态码
    这部分其实是计算机网络中的内容,但是跟指令的记忆方式相同,所以放在了这里。

200 - 请求成功
301 - 资源(网页等)被永久转移到其它URL
404 - 请求的资源(网页等)不存在
500 - 内部服务器错误

分类 分类描述
1** 信息,服务器收到请求,需要请求者继续执行操作
2** 成功,操作被成功接收并处理
3** 重定向,需要进一步的操作以完成请求
4** 客户端错误,请求包含语法错误或无法完成请求
5** 服务器错误,服务器在处理请求的过程中发生了错误

11、中断、异常和系统调用

本节操作的系统主要讲系统内核如何与外部设备和应用程序打交道的,这也是操作系统的主要功能:基于硬件设备之运行,为上层的应用程序提供系统服务。

通过本节的例子就可以很清楚地理解操作系统是如何在这两者之中运行。下面我就围绕这个图来讲解本部分的知识。

(一)从宏观上把握关键部分

在宏观上主要是包括三个部分的内容:

第一个是操作系统内核,是整个内容的核心;

第二个是外部设备,包括了输入输出设备,存储设备等。

第三个是应用程序,主要是由用户运用的程序。

(二)处理过程:主要是讨论双方之间的关系

1、操作系统与外部设备之间:主要通过中断机制来实现。

例如,在键盘在输出的时候,首先会把数据写到一个特定的缓冲区,这个缓冲区是有大小限制,如果数据超过其限制大小,先前数入的内容就会被冲掉,所以外部设备会通过中断机制,向内核发出指令,然后内核通过调用设备驱动程序,及时把缓冲区的内容读写到内核中。这样就达成了一个操作系统内核与外部设备进行数据交互的过程。

2、操作系统与上层应用程序:主要通过异常与系统调用两个机制来实现。

这里面可以分为两种情况来讨论,一种是应用程序异常运行程序的情况,另一种是应用程序正常运行的情况。

(1)异常的处理机制:例如在应用程序有一个程序片段,是一个除以零的代码,这显然是不合法的。在内核处理过程中,就会通过“异常服务例程"进行处理,捕获到异常的代码,然后抛出异常来即时处理,并返回异常处理结果。

(2)程序正常处理机制:这种情况是出现最多。当程序运行时,调用相关的函数库来获取系统调用接口,通过相关接口向存储设备或输入输出设备请求数据,然后在内核中处理应用程序,最后并把结果输出给用户或保存回存储设备。这个过程主要是依靠系统调用机制来实现。举个例子,银行储存着用户的钱,但是在用户取钱的时候,又不允许用户直接拿钥匙去开保险柜,所以需要对外提供一个服务的窗口。当用户需要拿钱的时候,就需要到柜台办理取钱业务,然后由柜台人员把钱取出来交给用户,此时的柜台人员就相当于系统调用接口,充当两者交流中心或处理中心的的中介作用。
  系统调用:操作系统的接口是连接应用软件与操作系统的中间桥梁。接口在程序设计中表现的形式就是:函数。操作系统提供的函数就被称为系统调用(system call)

更多推荐

操作系统重点知识梳理&常见面试题整理

本文发布于:2023-06-14 07:44:00,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1452799.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:面试题   操作系统   常见   重点   知识

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!