面试操作系统常见问题
什么是操作系统
- 操作系统(Operating System, 简称OS)是管理计算机软件与硬件资源的程序,是计算机的基石。
- 操作系统本质上是一个运行在计算机上的软件程序,用于管理计算机硬件和软件资源。
- 操作系统屏蔽了硬件层的复杂性。
- 操作系统的内核(Kernel)是操作系统的核心部分,它负责系统的内存管理,硬件设备的管理,文件系统的管理以及应用程序的管理
Application
Kernel
Cpu Memory Devices
系统调用
用户态和系统态
- 用户态(user mode):用户态运行的进程可以直接读取用户程序的数据。
- 系统态(kernel mode):可以简单的理解系统态运行的进程或者程序几乎可以访问计算机的任何资源,不受限制。
如果程序需要进行系统态级别的资源有关操作(如文件管理、进程控制、内存管理),就必须通过系统调用的方式向操作系统提出服务请求,并由操作系统代为完成。
系统调用按功能大致可分为如下几类:
- 设备管理
- 文件管理
- 进程控制
- 进程通讯
- 内存管理
进程和线程的区别
下面的回答仅适用Java面试,不适用操作系统面试。
一个进程可以拥有多个线程,多个线程共享同一个进程的堆区和方法区资源,但是每个线程有自己的程序计数器、虚拟机栈和本地方法栈。
总结:线程是进程划分成的更小的运行单位,一个进程在其执行的过程中可以产生多个线程。线程和进程最大的不同在于基本上个进程是独立的,而各线程则不一定,同一个线程极有可能会相互影响。线程执行开销小,但不利于资源的管理和保护;而进程正相反。
进程间的通信方式
- 管道/匿名管道(Pipes):用于具有亲缘关系的父子进程间或者兄弟进程之间的通信。
- 有名管道(Names Pipes):有名管道严格遵循FIFO,以磁盘文件的方式存在,可以实现本机任意两个进程通信。
- 信号(Signal):信号是一种比较复杂的通信方式,用于接收进程某个事件已经发生。
- 消息队列(Message Queuing):消息队列遵循FIFO,但也可以实现消息的随机查询,比单纯的FIFO更有优势。消息队列只有在内核重启的时候才会被真正删除。
消息队列克服了信号承载信息量少,管道只能承载无格式字节流以及缓冲区大小受限等缺点。 - 信号量(Semaphores):信号量本质上是一个计数器,用于多个进程对共享数据的访问,它的意图在于进程间同步。这种通信方式主要用于解决同相关的问题并避免竞争条件。
- 共享内存(Shared Memory):使得多个进程可以访问同一块内存空间,不同进程可以及时看到对方进程中对共享内存中数据的更新。共享内存是一种公共资源,因此需要依靠某种同步操作,如互斥锁和信号量等。可以说这是最有用的进程间通信方式。
- 套接字(Sockets):此方法主要用于客户端和服务器之间通过网络进行通信。它是支持TCP/IP协议的网络通信的基本操作单元,可以看做是不同主机之间的进程进行双向通信的端点,简单的说就是通信双方的一种约定,通信双方都使用套接字中的相关函数来完成通信过程。
线程间的同步方式
- 互斥(Mutex):采用互斥对象机制,只有拥有互斥对象的线程才有访问公共资源的权限,因为互斥对象只有一个,所以任何时刻只有一个线程在访问该公共资源,以此保证公共资源不会被多个线程访问。Java中的synchronized关键字和各种lock都是这种机制。
- 信号量(Semaphores):它允许同一时刻多个线程访问同一资源,但是需要控制同一时刻访问此资源的最大线程数量。
- 事件(Event):Wait/Notify:通过通知操作的方式来保持多线程同步,还可以方便地实现多线程优先级的比较操作。
进程的调度算法
- 先到先服务(FCFS)
- 短作业优先
- 时间片轮转调度算法
- 优先级调度 (相同优先级以FCFS方式执行)
- 多级反馈队列调度算法(Multilevel Feedback Queue Scheduling):多级反馈队列调度算法既能使高优先级的作业得到响应,又能使短作业迅速完成
多级反馈队列原理简述:
- N个队列,每个队列对于cpu的优先级是不一样的。
- 优先级最低队列使用时间片轮转法;其他队列使用先到先服务,每一个进程分配一定的时间片,若时间片运行完时进程未结束,则进入下一优先级队列的末尾。
- 各个队列的时间片也是不一样的,它随优先级增加而减少。
内存管理
操作系统的内存管理
主要负责内存的分配与回收,并进行地址转换(逻辑地址->物理地址)。
内存管理机制
- 连续分配管理
块式管理 - 非连续分配管理
页式管理、段式管理、段页式管理
段页式管理机制:结合了段式管理和页式管理的优点。这种机制先分页再分段,段与段之间都是离散的。
快表和多级页表
分页内存管理中,最重要的两点是:
- 虚拟地址到物理地址的转换要快。
- 解决虚拟地址空间大,页表也会很大的问题。
快表是一种特殊的高速缓冲器(cache)中,其中的内容是页表的一部分或者全部内容。
使用快表之后的地址转换流程是这样的:
- 根据虚拟地址中的页号去快表中查询;
- 如果该页在快表中,直接从快表中读取相应的物理地址;
- 如果该页不在快表中,就访问内存中的页表,再从页表中得到物理地址,同时将页表中的该映射表添加到快表中;
- 当快表被填满后,又需要登记新页时,就按照一定的淘汰策略(LRU)淘汰掉快表中的一个页。
多级页表
引入多级页表的主要目的是为了避免把全部页表一直放在内存中占用过多空间,典型的时间换空间。
为了提高内存的空间性能,提出了多级页表的概念;但是提到空间性能是以浪费时间性能为基础的,因此为了补充损失的时间性能,提出了快表(即 TLB)的概念。 不论是快表还是多级页表实际上都利用到了程序的局部性原理,局部性原理在后面的虚拟内存这部分会介绍到。
分页机制和分段机制的共同点和区别
共同点:
- 分页机制和分段机制都是为了提高内存利用率,减少内存碎片。
- 页和段都是离散存储的,所以两者都是离散分配内存的方式。但是,每个页和段中的内存是连续的。
区别:
- 页的大小是固定的,由操作系统决定;而段的大小不固定,取决于我们当前运行的程序。
- 分页仅仅是为了满足操作系统内存管理的需求,而段是逻辑信息的单位,在程序中可以体现为代码段,数据段,能够更好满足用户的需要。
逻辑(虚拟)地址和物理地址
指针里面存储的数值即为内存里的一个地址,这个地址是逻辑地址,它是由操作系统决定的。物理地址真的是真实物理内存中的地址。
虚拟内存
虚拟内存是计算机系统管理内存的方式。
-
通过虚拟内存可以让程序拥有超过系统物理内存大小的可用内存空间。
-
另外,虚拟内存可以为每个进程提供一个一致的、私有的地址空间,这让每个进程产生了一种自己在独享主存的错觉(每一个进程拥有一片连续完整的内存空间)。
虚拟内存的意义是它定义了一个连续的虚拟地址空间,并且把内存扩展到硬盘空间。
局部性原理
程序执行时往往会呈现局部性原理,也就是说在某个较短的时间段内,程序执行局限于某一小部分,程序访问的存储空间也局限于某个区域。
局部性原理表现在以下两个方面:
- 时间局部性:如果程序中某条指令一旦执行,不久以后该指令可能再次执行;如果某数据被访问过,不久以后该数据可能再次被访问。时间局部性的典型原因,是由于在程序中存在着大量的循环操作。
- 空间局部性:一旦程序访问了某个存储单元,不久之后其附近的存储单元也将被访问,即程序在一段时间内所访问的地址,可能会集中在一定的范围之内,这是因为指令通常是顺序存放、顺序执行的,数据也是一般是以向量、数组、表等形式簇存储的。
时间局部性是通过将近来使用的指令和数据保存到高速缓存存储器中,并使用高速缓存的层次结构实现。空间局部性通常是使用较大的高速缓存,并将预取机制集成到高速缓存控制逻辑中实现。
虚拟内存技术实际上就是建立了 “内存一外存”的两级存储器的结构,利用局部性原理实现髙速缓存。
页面置换算法
地址映射过程中,若在页面中发现所要访问的页面不在内存中,则发生缺页中断。
缺页中断就是要访问的页不在主存,需要操作系统将其调入主存后再进行访问。在这个时候,被内存映射的文件实际上成了一个分页交换文件。
缺页中断发生时,当前内存中没有空闲的页面,操作系统就必须将内存中的一个页移出,这个时候就需要一种置换算法。
- OPT页面置换算法(最佳页面置换算法):
- FIFO(先进先出)
- LRU(最近未使用)
- LFU(最少使用)