【Java开发岗面试】八股文—操作系统

声明:

  1. 背景:本人为24届双非硕校招生,已经完整经历了一次秋招,拿到了三个offer。
  2. 本专题旨在分享自己的一些Java开发岗面试经验(主要是校招),包括我自己总结的八股文、算法、项目、HR面和面试技巧等等,如有建议,可以友好指出,感谢,我也会不断完善。
  3. 想了解我个人情况的,可以关注我的B站账号:东瓜Lee

操作系统简介:

  1. 什么是操作系统?

    操作系统是一种运行在内核态的软件,它是应用程序和硬件之间的媒介,向应用程序提供硬件资源的访问、同时管理硬件资源。

    【Java开发岗面试】八股文—操作系统_第1张图片

  1. 操作系统主要有哪些功能?

    • 处理器管理:对CPU的管理和分配,主要指的是进程管理
    • 内存管理:内存的分配和管理,主要利用了虚拟内存的方式。
    • 外存管理:外存(磁盘)的分配和管理,将外存以文件的形式提供出去。
    • I/O管理:对输入/输出设备的统一管理。

  1. 操作系统的主要目的是什么?

    1. 管理计算机资源,包括 CPU、内存、磁盘、打印机等。
    2. 提供一种图形界面,提供了应用程序和计算机硬件之间的桥梁。
    3. 为其他软件提供服务,操作系统与软件进行交互,为其分配运行所需的任何必要资源。

  1. 什么是实时操作系统?

    实时操作系统对时间做出了严格的要求,分为两种:硬实时和软实时

    1. 硬实时:规定某个动作必须在规定的时刻内完成,要不然会有严重错误发生。比如一些生产车间配备的操作系统就是硬实时的,规定某个零件一定要在规定的时刻完成安装。
    2. 软实时:可以容忍偶然的超时错误,失败造成的后果并不严重,比如数字音频、多媒体、手机都是属于软实时操作系统。

  1. 什么是内核?

    可以这么说,内核是一个计算机程序,它是操作系统的核心,提供了操作系统最核心的能力,可以控制操作系统中所有的内容。


  1. 什么是用户态和内核态?

    首先要知道操作系统内核的意思,内核是操作系统的核心,具有很高的权限,可以控制 CPU、内存、硬盘等硬件资源,出于权限控制的考虑,因此大多数操作系统,把内存分成了两个区域

    • 用户空间,这个内存空间专门给应用程序使用,权限比较小;
    • 内核空间,这个内存空间只有内核程序可以访问,权限很大;

    当程序使用用户空间时,就说该程序在用户态执行,当程序使用内核空间时,程序就在内核态执行。


  1. 用户态和内核态是如何切换的?

    应用程序一般是运行在用户态的,如果要使用内核空间(也就是进入内核态),就需要通过系统调用来实现,具体来说就是:

    用户态的程序执行系统调用,就会产生一个中断,CPU会中断当前正在执行的应用程序,也就是开始执行内核程序,这样就进入了内核态,等内核程序处理完毕后,就会主动触发中断,把CPU执行权限交还给用户程序,到用户态继续执行。


  1. 中断的处理过程是什么?

    1. 保护现场:将当前执行程序的相关数据保存在寄存器中,然后入栈
    2. 开中断:以便执行中断时能响应较高级别的中断请求
    3. 中断处理过程
    4. 关中断:保证恢复现场时不会新的中断打扰
    5. 恢复现场:从栈中按序取出程序数据,恢复程序中断前的执行状态

  1. 中断和异常的区别是什么?

    中断是指CPU对系统发生某事件时的一种响应机制,即CPU暂停正在执行的程序,在保护现场后,自动的转去执行中断处理程序,执行完后,再返回到原程序的断点处继续执行。

    中断分为外中断和内中断

    1. 外中断就是一般指的中断,由于外部设备事件所引起的中断,如磁盘中断、打印机中断
    2. 内中断就是异常,是指由CPU内部事件所引起的中断,比如程序的非法指令或者地址越界


进程管理:

  1. 并行和并发有什么区别?

    可以分为单核CPU、多核CPU来讨论

    单核CPU:因为一个核心执行一个任务,所以不管在哪一时刻,都只能有一个任务在被CPU执行,但是因为 CPU时间片的轮转很快,也就是任务的切换速度很快,所以在某一段时间来看,多个任务是同时执行的,这就是并发。

    多核CPU:因为有多个CPU核心,那么同一时刻就能有多个任务被执行,这样就是并行,但是一般来讲任务数量肯定是大于CPU核心数量的,所以多核CPU也是并行和并发同时存在的。


  1. 进程和线程的区别和联系

    1. 进程就是运行中的程序,一个进程可以包含一个或多个线程,一个线程其实就是一个指令流,然后将一条条的指令交给CPU执行。
    2. 一个进程对应到一个内存空间,一个进程内的多个线程可以共享这个内存空间
    3. 进程的上下文切换速度没有线程快
    4. 根本上的区别就是,进程是 操作系统资源分配 的基本单位,线程是 操作系统调度的 基本单位

    协程:微线程,是一种用户态的轻量级线程,一个线程可以有多个协程,协程需要线程来承载运行。


  1. 程序和进程的区别

    程序是静态的,是存放在外存中的;

    进程是是运行中的程序,是动态的,具备生命周期,而且是在内存层面执行的。


  1. 什么是进程上下文切换?

    进程的上下文切换就是 将 CPU 资源从一个进程分配给另一个进程。

    从用户角度看,计算机能够同时运行多个进程,这恰恰是操作系统通过快速上下文切换造成的结果。在切换的过程中,操作系统需要先存储当前进程的状态,再读入下一个进程的状态,然后执行。


  1. 线程上下文切换了解吗?

    这还得看线程是不是属于同⼀个进程:

    • 当两个线程不是属于同一个进程,则切换的过程就跟进程上下文切换⼀样;
    • 当两个线程是属于同一个进程,因为内存是共享的,所以在切换时,这些资源就保持不动,只需要切换线程不共享的数据;

    所以整体来说,线程的上下文切换要比进程开销小很多。


  1. 进程有哪些状态?

    os中:

    1. 新建态:进程被创建的时候
    2. 就绪态:可运行态,但是此时还没有被CPU分配执行
    3. 运行态:可运行态,被CPU分配执行了
    4. 阻塞态:进程正在等待某一事件的发生(比如等待输入输出完毕),而暂时停止运行
    5. 终止态:进程执行完毕后

    java中:

    1. 新建态(NEW):新建态(创建线程对象)
    2. 可执行态(RUNNABLE):新建态调用start(),就变成了可执行状态(有执行资格,如果被执行了就是运行态,没有被执行就是就绪态)
    3. 阻塞态(BLOCKED):运行态(可执行状态)的线程没有获得锁就会变成阻塞态,拿到了锁就会变成就绪态(可执行状态)
    4. 等待态(WAITING):主动让运行态的线程调用wait(),就会变成等待状态,调用notify()唤醒线程,就会变成就绪态(可执行状态)
    5. 计时等待态(TIMED_WAITING):主动让运行态的线程调用sleep(),就会变成时间等待状态,等时间一过,就会变成就绪态(可执行状态)
    6. 终止态(TERMINATED):(线程终止)

  1. 什么是僵尸进程?

    僵尸进程是进程已执行完成且处于终止状态,但在进程表中却仍然存在。

  2. 什么是孤儿进程?
    一个父进程退出,而它的子进程还在运行,那么这些进程就是孤儿进程。


  1. 进程 有哪些调度算法?

    1. 先来先服务FIFO

      非抢占式的调度算法,按照请求的顺序进行调度。有利于长作业,但不利于短作业,因为短作业必须一直等待前面的长作业执行完毕才能执行,而长作业又需要执行很长时间,造成了短作业等待时间过长。

    2. 短作业优先SJF

      非抢占式的调度算法,按照估计的运行时间最少的顺序进行调度。长作业有可能会饿死,处于一直等待短作业执行完毕的状态。因为如果一直有短作业到来,那么长作业永远得不到调度。

    3. 最短剩余时间优先

      最短作业优先的抢占式版本,按照剩余运行时间的顺序进行调度。 当一个新的作业到达时,其整个运行时间与当前进程的剩余时间作比较。如果新的进程需要的时间更少,则挂起当前进程,运行新的进程。否则新的进程等待。

    4. 优先级调度

      为每个进程分配一个优先级,按优先级进行调度。为了防止低优先级的进程永远等不到调度,可以随着时间的推移增加等待进程的优先级。

    5. 时间片轮转

      将所有就绪进程先按 先来先服务的原则排成一个队列,每次调度时,把 CPU 时间分配给队首进程,该进程可以执行一个时间片。当时间片用完时,由计时器发出时钟中断,调度程序便停止该进程的执行,并将它送往就绪队列的末尾,同时继续把 CPU 时间分配给队首的进程。

      (时间片轮转算法的效率和时间片的大小有很大关系:因为进程切换都要保存进程的信息并且载入新进程的信息,如果时间片太小,会导致进程切换得太频繁,在进程切换上就会花过多时间。 而如果时间片过长,那么实时性就不能得到保证。)


  1. 进程间 通信有哪些方式?

    1. 套接字Socket
    2. 管道Pipe
    3. 信号量Signal
    4. 共享内存
    5. 消息队列

  1. 线程间 通信有哪些方式?(在Java中)

    Java中的线程通信是指在多线程开发中,不同线程之间进行信息交流和数据共享的过程

    1. 使用volatile、synchronized关键字
    2. 等待/通知机制:wait()、notify()、notifyAll()方法
    3. 管道的输入输出流:一个线程可以将数据写入管道输出流,而另一个线程可以从管道输入流中读取数据(PipedInputStream、PipedOutputStream)
    4. 使用Thread.join()方法:使得线程可以按序执行
    5. 使用ThreadLocal:使得线程对于共享变量的访问的安全性

  1. 线程 有哪些实现方式?

    1. 内核态线程实现:在内核空间实现的线程,由内核直接管理线程。

    2. 用户态线程实现:在用户空间实现线程,不需要内核的参与,内核对线程无感知。

    3. 混合线程实现:现代操作系统基本都是将两种方式结合起来使用。

      用户态的执行系统负责进程内部线程在非阻塞时的切换;内核态负责阻塞线程的切换。即我们同时实现内核态和用户态线程管理。每个内核态线程可以服务一个或多个用户态线程。


  1. 线程 间如何同步?

    同一个进程内有多个线程,为了避免多个线程同时访问数据造成的混乱,就需要有线程同步机制。所谓同步,就是要使得线程 协同步调,按照预定的先后顺序访问共享资源。

    主要有6种 线程同步机制

    1. 互斥锁、自旋锁、读写锁
    2. 条件变量
    3. 信号量
    4. 屏障

  1. 死锁产生有哪些条件?

    四个必要条件:

    1. 资源互斥
    2. 不可抢夺
    3. 请求与保持
    4. 循环等待

  1. 如何预防死锁呢?

    预防死锁产生的四个必要条件之一就可以了

    1. 资源互斥:不能实现
    2. 请求与保持:一次性分配所需资源,这样在进程运行期间不会在提出资源请求。
    3. 不可抢夺:当某进程获得了部分资源,但得不到其它资源,则释放已占有的资源。这意味着某一进程已经占有的资源,在运行过程中会被暂时地释放掉,也可认为是被抢夺了。
    4. 循环等待:系统给每类资源赋予一个编号,每一个进程严格按照编号递增的顺序请求资源。

  1. 如何避免死锁呢?

    避免死锁并不需要事先采取各种限制措施去破坏四个必要条件,而是在资源动态分配过程中,防止系统进入不安全状态,来避免死锁的发生。

    典型的避免死锁的算法是银行家算法

    1. 核心思想是:进程动态地申请资源,每次申请资源时 系统都执行安全状态检查算法 判断本次申请是否会造成系统处于不安全状态,如果会出现不安全状态 则阻塞进程;如果是安全状态,则完成资源的分配。
    2. 安全状态检查算法的思想是找到一个安全序列,使所有进程都能执行完毕。如果找到安全序列,则处于安全状态,否则为不安全状态。

  1. 死锁的检测、解除

    死锁检测与解除是指当死锁发生时,系统能够检测到死锁发生的位置和原因,并能通过外力破坏死锁发生的必要条件,从而使得并发进程从死锁状态中恢复出来。

    死锁检测方法:银行家算法中判断系统是否安全的算法

    当利用死锁检测算法检测出系统已经出现了死锁,那么,此时就需要对系统采取相应的措施。常用的解除死锁的方法有

    • 剥夺资源:从其它进程剥夺足够数量的资源给死锁进程,以解除死锁状态;
    • 终止或撤消进程:可以直接撤消死锁进程。


内存管理:

  1. 什么是虚拟内存?

    如果只有一个程序or进程,那么就可以直接访问实际物理内存,但是如果有多个进程,同时访问同一块物理内存就会产生冲突,但是现在肯定都是多线程并发执行的,所以就引出了虚拟内存的概念。

    操作系统不让进程直接去访问物理地址,它为每个进程都分配一套独立的虚拟地址,也提供了一种机制可以让进程的虚拟地址映射到实际的物理地址。这样进程访问虚拟地址的时候,就由操作系统转换到不同的物理地址(通过CPU芯片中的内存管理单元MMU的映射关系),这样就不会发生冲突。

    于是,这里就引出了两种地址的概念:

    1. 程序直接使用的内存地址叫做 虚拟内存地址
    2. 真正存在在硬件里面的内存地址叫 物理内存地址

    操作系统是如何管理虚拟地址和物理地址之间的关系的呢?在内存分段和分页下,有不同的方式


  1. 什么是内存分段?

    内存分段是从程序的逻辑角度来看,分成了栈段、堆段、数据段、代码段等,这样可以分离出不同属性的段。

    在内存分段机制下,虚拟地址和物理地址是怎么映射的?

    1. 虚拟地址由两部分组成:段选择因子(包括了段号)、段内偏移量

    2. 通过段表 将虚拟地址和物理地址映射起来

      【Java开发岗面试】八股文—操作系统_第2张图片

    分段机制的缺陷

    1. 内存碎片

    2. 内存交换的效率低

      (为了解决这两个问题,所以才有的内存分页)

  2. 什么是内存分页?

    分页是把整个虚拟和物理内存空间 划分成一些的固定大小的空间,这样一个连续并且固定大小的内存空间,就叫做页,在 Linux 下,每一个页的大小为 4KB(Linux用的就是内存分页)

    在内存分页机制下,虚拟地址和物理地址是怎么映射的?

    1. 虚拟地址由两部分组成:(虚拟)页号、页内偏移量
    2. 通过页表 将虚拟地址和物理地址映射起来(根据虚拟页号找到物理页号,再加上偏移量)
    【Java开发岗面试】八股文—操作系统_第3张图片

  1. 多级页表知道吗?

    操作系统中可能会有非常多的进程,如果只是简单的使用分页,可能会导致页表变得非常大,所以,就引入了多级页表。

    多级页表

    就是在原来的单级页表的基础上 再次分页,这里利用了局部性原理

    局部性原理

    1. 时间局部性:认为 最近被访问的页,在不久的将来还会被访问
    2. 空间局部性:认为 被访问的页面,周围的页面也会被访问

  1. 什么是快表?

    利用了局部性原理,即在某一段时间内,程序的执行可能仅限于程序中的某一部分(比如说对某个代码块执行循环操作),相应地,所访问的内存空间也局限于某个区域。

    利用这一特性,把最常访问的几个页表项 存储到访问速度更快的硬件中,于是在 CPU 芯片中,加入了一个专门存放 程序最常访问的页表项 的 Cache,这个 Cache 就是 TLB,通常称为页表缓存、快表。


  1. 分页和分段有什么区别?

    1. 段是信息的逻辑单位,是根据用户的需要划分的,对用户是可见的;

      页是信息的物理单位,是为了方便管理内存而划分的,对用户是不可见的。

    2. 段向用户提供二维地址空间;

      页向用户提供的是一维地址空间。

    3. 段的大小不固定,由它所完成的功能决定;

      页的大小固定,比如Linux中一个页是4KB。


  1. 页面置换算法有哪些?

    进程运行时若其访问的页面不在内存中,便会产生一个缺页中断,请求操作系统将缺页从磁盘中调入内存,但是如果内存已无空闲内存空间,就需要调出内存中的一些页面 放回磁盘中,选择调出页面的算法就是页面置换算法

    常见的页面置换算法

    1. 最佳页面置换算法(OPT)(无法实现)

      最佳页面置换算法是一个理想的算法,思路:置换在未来最长时间不访问的页面

      该算法的实现需要计算内存中每个逻辑页面的下一次访问时间,然后比较 选择未来最长时间不访问的页面。但这个算法是无法实现的,因为当缺页中断发生时,操作系统无法知道页面下一次将在什么时候被访问。

    2. 先进先出置换算法(FIFO)

      思路:选择在内存中停留时间最长的页面

      FIFO的实现机制是使用链表将所有在内存的页面按照进入时间的早晚链接起来,然后每次置换链表头节点上的页面就行了。

    3. 最近最久未使用置换算法(LRU)

      思路:选择最近最久没有使用的页面进行置换(当前时间 - 上次被访问的时间 最大的值),最近很久没有使用了,就认为该页面用的少,就置换出去

      开销比较大,实际用的少

    4. 最近最少使用置换算法(LFU)

      思路:选择最近最少使用的页面进行置换出去(统计页面的使用次数 最小的值),最近用的很少,就置换出去

    5. 时钟页面置换算法(Lock)

      思路:把所有的页都保存在⼀个类似钟表的环形链表中,⼀个表针指向最老的页面。

      当发生缺页中断时,算法首先检查表针指向的页面:

      ​ 如果它的访问位是 0 就淘汰该页面,并把新的页面插入到这个位置,然后把表针前移⼀个位置;

      ​ 如果访问位是 1 就清除访问位,并把表针前移⼀个位置,重复这个过程直到找到了一个访问 位为 0 的页面为至;



外存管理(文件系统):

  1. 访问速度和容量对比

    img

  1. 硬链接和软链接有什么区别?

    硬链接等同于文件本身,软链接就是快捷方式

    硬链接就是在目录下创建一个条目,记录着文件名与 inode 编号,这个 inode 就是源文件的 inode。删除任意一个条目,文件还是存在,只要引用数量不为 0。但是硬链接有限制,它不能跨越文件系统,也不能对目录进行链接。

    【Java开发岗面试】八股文—操作系统_第4张图片

    软链接相当于重新创建一个文件,这个文件有独立的inode,但是这个文件的内容是另外一个文件的路径,所以访问软链接的时候,实际上相当于访问到了另外一个文件,所以软链接是可以跨文件系统的,甚至目标文件被删除了,链接文件还是在的,只不过打不开指向的文件了而已。

    【Java开发岗面试】八股文—操作系统_第5张图片
  2. 磁盘调度算法有哪些?

    在计算机系统中,各个进程可能会不断提出磁盘读写的操作请求,由于这些进程发送请求的速度 可能比磁盘响应的速度快,因为有必要为每个磁盘设备 建立一个等待队列

    磁盘调度算法通过优化磁盘的访问请求顺序来提高磁盘的访问性能,寻道时间是磁盘访问最耗时的部分,如果请求顺序优化得当,必然可以节省一些不必要的寻道时间,从而提高磁盘的访问性能。


常见的磁盘调度算法有6种

  1. 先来先服务
  2. 最短寻找时间优先
  3. 扫描算法
  4. 循环扫描算法

I/O设备

  1. 零拷贝了解吗?

    零拷贝是指计算机在执行I/O操作时,CPU不需要将数据 从一个存储区域复制到另一个存储区域,从而减少上下文切换以及数据拷贝的时间。

    零拷贝是一种I/O操作优化技术,它并不是真的没有数据拷贝,而是广义上讲的减少和避免不必要的数据拷贝。

    以读取一个文件并通过socket发送文件数据为例,一般需要read和write两个系统调用,这种传统的I/O读写流程,需要4次用户态和内核态的上下文切换和4次数据拷贝,这些额外的上下文切换和数据拷贝,会消耗大量的CPU资源和内存带宽,降低数据传输的效率。零拷贝减少了上下文切换和内存拷贝的次数。

  2. 讲一讲I/O多路复用?【待学习】

【后续继续补充,敬请期待】

你可能感兴趣的:(---Java开发岗面试---,java,面试,操作系统,秋招,春招,校招,八股文)