操作系统面试题总结
文章目录
操作系统引论
- 并发:同一段时间内多个程序执行
- 共享:系统中的资源可以被内存中多个并发执行的进线程共同使用
- 虚拟:通过时分复用以及空分复用(如虚拟内存),把一个物理实体虚拟为多个
- 异步:系统中的进程是以走走停停的方式执行的,且以一种不可预知的速度推进
-
进程管理
进程控制,进程同步,进程通信和进程调度
-
内存管理
内存分配,内存保护,地址映射,内存扩充
-
设备管理
管理所有外围设备,包括完成用户IO请求,为用户进程分配IO设备,提高IO设备利用率,提高IO速度,方便IO使用
-
文件管理
管理用户文件和系统文件,方便使用的同时保证安全性。包括磁盘存储空间管理,目录管理,文件读写管理以及文件共享及保护
-
提供用户接口
程序接口(如API)和用户接口(如GUI)
- 批处理操作系统:成批处理、系统吞吐量高、资源利用率高、用户不能敢于作业的执行
- 分时操作系统:多路性、独立性、及时性、交互性
- 实时操作系统:及时响应、快速处理、高可靠性和安全性、不要求系统资源利用率
操作系统的主要组成部分:进程和线程的管理、存储管理、设备管理、文件管理
静态链接库是.lib
格式的文件,一般在工程的设置界面加入工程中。程序编译时,会把lib文件代码加入到程序中,因此会增加代码大小。不能手动移除lib代码。
动态链接库是程序运行时动态装入内存的模块,格式为.dll
,在程序运行是可以随意加载和移除,节省内存空间。
进程与线程
- 进程是具有一定独立功能的程序关于某个数据集合上的一次运行活动,是系统进行资源分配和调度的一个独立单位
- 线程是进程的一个实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位
- 一个进程可以有多个线程,多个线程可以并发运行
- 线程基本不拥有系统资源,只拥有一些在运行中必不可少的资源,比如程序计数器、寄存器和栈
- 但线程可以与其他线程共享进程所拥有的全部资源
- 线程可以创建和撤销另一个线程
线程:抢占式调度
协程:协同式调度,避免了无意义的调度,可以提高性能,但程序员必须要自己承担调度的责任。协程也失去了标准线程使用多CPU的能力。
运行在用户态下的程序,只能受限地访问内存,不允许访问外围设备。占用CPU的能力被剥夺,CPU资源可以被其他程序获取。
运行在内核态下的程序,可以访问内存所有数据,包括外围设备。
用户态切换到内核态的三种方式:
- 系统调用:用户态进程主动要求切换到内核态的一种方式。用户态进程通过系统调用,申请使用操作系统提供的服务程序,以完成工作。
- 异常:当CPU在执行运行在用户态下的程序时,发生了某些事先不可知的异常,会触发由当前运行进程切换到处理此异常的内核相关程序中。因此也就转到了内核态,比如缺页异常。
- 外围设备终端:外围设备完成用户请求的操作后,会像CPU发送相应的中断信号。此时,CPU会暂停执行下一条即将要执行的指令,转而执行与中断信号对应的处理程序。如果先前执行的指令是用户态的程序,那么转换的过程自然就发生了由用户态到内核态的转换。
- 程序是一个静态概念,进程是一个动态概念
- 程序没有并行特征,而进程有并行特征
- 程序不会竞争计算机系统资源,而进程是竞争计算机系统资源的基本单位
- 不同的进程可以包含同一程序,只要该程序所对应的数据集不同
- 进程代码段
- 进程的公有数据
- 进程打开的文件描述符
- 信号的处理器
- 进程的当前目录
- 进程用户ID与进程组ID
-
信号量
允许统一时刻多个线程访问同一个资源,但需要控制统一时刻访问此资源的最大线程数量
-
互斥量
实际上是信号量的一种特殊情况,允许统一时刻只有一个线程访问同一个资源
-
信号,也叫事件
通过通知操作的方式来保证多线程同步,还可以方便实现多线程优先级的比较操作
-
互斥锁
保护临界区,确保同一时间,只有一个线程访问数据。
如果互斥量已经上锁,调用线程会阻塞,直到互斥量被解锁
-
自旋锁
在获取到锁之前,一直处于循环检测保持者是否已经释放了锁。
与互斥锁的区别是,在申请自旋锁时,线程处于忙等状态,而非挂起状态
-
信号量
一个计数器,用来控制多个进程对共享资源的访问。
互斥锁为信号量的一个特殊情况。
-
读写锁
高级别锁,区分读和写,符合条件时,允许多个线程访问对象。
处于读锁时,允许其他线程和本线程的读锁,但不允许写锁。
处于写锁时,任何锁操作都会睡眠等待
-
递归锁
递归锁是互斥锁的一个特殊情况。同样地,只能由一个线程访问该对象,但允许同一个线程在未释放其拥有的锁时,反复对锁进行加锁操作
在两个或者多个并发进程中,如果每个进程持有某种资源,又等待其他进程释放它目前持有的资源,在未改变这种状态之前,都不能向前推进。这一情况被称作死锁。
死锁产生的四个条件:
- 互斥条件:一个资源一次只能被一个进程使用
- 请求与保持条件:一个进程因请求资源而阻塞时,对其自身拥有的资源保持不放
- 不可剥夺条件:进程获得的资源,在未完全使用完之前,不能强行剥夺
- 循环等待条件:若干进程之前形成一种头尾相接的环形等待资源关系
解决死锁的基本方法:预防死锁,避免死锁,检测死锁,解决死锁
-
预防死锁:确保死锁发生的四个必要条件中,至少有一个不成立
-
避免死锁:动态检测资源分配状态,确保循环等待条件不成立,使系统处于安全状态
-
解决死锁:包括进程终止和资源抢占
- 选择一个牺牲品
- 回滚
- 饥饿(使回滚得越多的,越不可能继续作为牺牲品)
-
管道
分为三种:普通管道PIPE、命名管道NAME_PIPE、流管道S_PIPE
普通管道为半双工,只能单向传输,只能在父子进程间使用
流管道去除了第一种限制,可以双向传输
命名管道去除了第二种限制,可以在许多并不相关的进程之间进行通讯
-
系统IPC(包括消息队列、信号量、共享内存)
信号量是一个计数器,用来控制多个进程对资源的访问,通常作为一种锁机制
消息队列是消息的链表,存放在内核中并由消息队列标识符标识
信号(也叫事件)是一种比较复杂的通信方式,用于通知接受进程某个事件已经发生
共享内存是映射一段能被其他进程访问的内存,这段共享内存由一个进程创建,但是多个进程可以访问。共享内存是最快的IPC方式
-
SOCKET
套接口也是一种进程间通信机制,它可用于不同主机间的进程通信
- 就绪状态:进程已经获得了除处理机以外的所需资源,正在等待分配处理机资源
- 运行状态:占用处理机资源运行,处于此状态的进程数小于CPU数
- 阻塞状态:进程等待某种条件,在条件满足之前无法执行
进程的状态转换有四种:
- 就绪—运行,如:当前运行进程阻塞,调度程序选一个优先级最高的进程占有处理机
- 运行—就绪,如:当前运行进程时间片用完
- 运行—阻塞,如:当前运行进程等待键盘输入
- 阻塞—就绪,如:I/O操作完成,被中断处理程序唤醒
状态 | 含义 |
---|---|
创建 | 还未开始的线程,处于此状态 |
就绪 | 正在Java虚拟机里面执行的线程,处于此状态 |
阻塞 | 该线程阻塞于锁 |
等待 | 进入该状态的线程需要等待其他线程做出一些特定动作,比如通知或中断 |
超时等待 | 该状态不同于等待,在该状态的线程,只会在一个特定时间内等待其他线程执行特定动作。若其他线程一直不执行,它可自行返回 |
终止 | 已经结束的线程,处于此状态 |
先来先服务、短进程优先、优先级、时间片轮转、多级反馈
-
信号量机制
对信号量使用P和V操作,P将信号量值减一,V将信号量值加一。
当信号量值S大于0时,表示当前可用资源的数量,当S小于0时,表示当前正在等待该资源的进程数
使用PV操作实现进程互斥时,要注意:
- 每个程序中,用户实现互斥的PV操作必须成对出现。先做P操作,进临界区,后做V操作,出临界区
- PV操作应分别紧靠临界区的头尾部,临界区的代码应该尽可能短,不能有死循环
- 互斥信号量的初值一般为1
使用PV操作实现进程同步时,要注意:
- 先分析进程间的制约关系,确定信号量种类。
- 在保证进程间有正确的同步关系情况下,哪个进程先执行,哪个 进程后执行,彼此间通过什么资源(信号量)进行协调,从而明确要设置哪些信号量
- 信号量的初值与相应资源的数量有关,也与PV操作在程序代码中出现的位置有关
- 同一信号量的PV操作要成对出现,但它们分别在不同的进程代码中
-
自旋锁管程
-
会合
-
分布式系统
每个进程中,访问临界资源的那段程序块被称为临界区。每次只准许一个进程进入临界区,进入后不允许其他进程进入。
- 若有若干进程要求进入空闲临界区,一次仅允许一个进程进入
- 若已有进程进入临界区,其他进程必须等待
- 进入临界区的进程必须在有限时间内退出
- 如果进程不能进入临界区,则必须让出CPU
中断指的是,在计算机执行期间,系统内发生任何非寻常或非预期的急需处理时间,使得CPU中断当前正在执行的程序,而转去执行相应的事件处理程序。处理完毕后,处理器又返回原来被中断的地方,继续执行或调度新的进程。
轮询指的是,系统定时对各种设备轮流询问一遍是否有处理要求。有要求的,则加以处理。轮询占据了CPU相当一部分处理时间,是一种效率较低的 方式。
中断:容易遗漏一些问题,CPU 利用率高
轮询:效率低,等待时间长,CPU利用率低
存储管理
Windows 提供了 3 种方法进行内存管理,分别为:
- 虚拟内存,适用于管理大型对象或者结构数组
- 内存映射文件,适用于管理大型数据流以及在单个计算机上运行多个进程之间的共享数据
- 内存堆栈,适用于管理大量小对象
Windows 操纵内存可分为两个层面,分别为:
- 物理内存
- 虚拟内存
-
首次适应算法
空闲分区以地址递增次序链接,分配内存时顺序查找,找到大小能满足要求的第一个空闲分区
-
最佳适应算法
空闲分区按容量递增的次序链接,找到第一个能满足要求的空闲分区
-
最坏适应算法
空闲分区以容量递减的次序链接,找到第一个能满足要求的空闲分区,也就是挑选最大的分区
段式存储管理是一种符合用户视角的内存分配管理方案。在段式存储管理中,将程序的地址空间划分为若干段,如代码段、数据段、堆栈段。每个进程有一个二维地址空间,相互独立,互不打扰。
段式存储管理的优点是:没有内碎片,因为段大小可变,可以通过改变段的大小而消除内碎片。但会产生外碎片,比如4K的段换5K的段,会产生1K的外碎片
页式存储管理是一种用户视角内存与物理内存相分离的内存分配管理方案。在页式存储管理中,将程序的逻辑地址划分为固定大小的页,而物理内存划分为同样大小的帧。程序加载时,可将任意一页放入内存中任意一个帧,这些帧不必连续,从而实现了离散分离。
页式存储管理的优点是:没有外碎片,因为页的大小固定,但会产生内碎片,因为一个页可能填充不满
两者的不同点:目大地信内
- 目的不同:分页是由于系统管理的需要,是信息的物理单位。分段是由于用户的需要,是信息的逻辑单位。
- 大小不同:页的大小固定,由系统决定。段的大小不固定,由其完成的功能决定
- 地址空间不同:页向用户提供一维地址空间,段向用户提供二维地址空间
- 信息共享:页的保护和共享收到限制,段利于存储保护和信息共享
- 内存碎片:分页没有外碎片,但有内碎片;分段没有内碎片,但有外碎片
页表用于记录逻辑地址和实际存储地址之间的映射关系,以实现从页号到物理块号的映射。
访问分页系统中内存数据需要两次的内存访问。
- 从内存中访问页表,找到指定的物理块号,加上页内偏移,得到实际物理地址
- 根据第一次访问得到的物理地址,访问内存,存取数据
分段内存管理中,地址是二维的,其中一维为段号,另一维是段内地址。每个段的长度不一样,每个段内部都从0开始编址。
段内部为连续内存分配,但段与段之间离散分配,因此有了段表机制,以从一个逻辑地址映射到一个物理地址。
缓冲区溢出指的是,计算机向缓冲区填充数据时,超出了缓冲区本身的容量,溢出的数据覆盖在了合法的数据上。其危害有:
- 程序崩溃,导致拒绝服务
- 跳转并且执行一段恶意代码
造成缓冲区溢出的主要原因是因为程序中没有仔细检查用户输入。
虚拟内存允许执行进程不必完全在内存中。
每个进程拥有独立的地址空间,这个空间被分为大小相等的多个块,称为页。每个页都是一段连续的地址。这些页被映射到物理内存,但并不是所有页都在内存里才能运行程序。
当程序引用到一部分在物理内存中的地址空间时,由硬件进行必要的映射。当程序引用到一部分不在物理内存中的地址空间时,操作系统负责将缺失的部分装入物理内存,并重新执行失败的指令。
虚拟内存的应用与优点
- 在内存中可以保留多个进程,系统并发度提高
- 解除了用户与内存之间的紧密约束,进程可以比内存的全部空间还大
访问虚拟内存时,会访问到 MMU(Memory Management Unit),去匹配对应的物理地址。如果内存已满,还会调用页面置换算法。
- FIFO,先进先出
- LRU,last recently used,最近最少使用,根据使用时间到现在的长短来判断
- LFU,last frequently used,最近使用次数算法,根据使用次数来判断
- OPT,optimal replacement,最优置换算法,保证置换出去的是不再被使用的页,或在实际内存中最晚使用
程序的内存分配
- 堆:由程序员分配释放,若程序员不释放,程序结束时可能由操作系统回收
- 栈:由编译器自动分配释放,存放函数的参数值、局部变量的值等等
- 全局区/静态区
- 全局变量和静态变量是放在一起的
- 初始化的全局变量和静态变量放在一个区域
- 未初始化的全局变量和静态变量放在另一个区域
- 程序结束时由系统释放
- 文字常量区:常量字符串的存放位置,由操作系统在程序结束后释放
- 程序代码区:存放函数体的二进制代码
#include<iostream>
using namespace std;
int a = 0;//全局初始化区
char *p1;//全局未初始化区
int main()
{
int b;//栈
char s[] = "abc";//栈
char *p2;//栈
char *p3 = "123456";//p3在栈,“123456”在常量区
static int c = 0;//全局初始化区
p1 = (char *)malloc(10);
p2 = (char *)malloc(20);
//分配得来的10和20字节在堆区
strcpy(p1, "123456");
//“123456”在常量区,编译器可能会将它与p3所指向的“123456”优化成一个地方
}
输入与输出
- FCFS:先进先出
- SSTF:Shortest Seek Time First,最短寻道时间优先。可能会出现饥饿现象
- Elevator:向一个方向寻道,寻完后再向另一个方向寻道
RAID 磁盘阵列技术 Redundant Arrays of Independent Disks
-
RAID 0
- 需要两张以上的硬盘,可提高整个硬盘的性能和吞吐量
- 无冗余或错误修复能力,若一张硬盘丢失,则所有数据丢失
-
RAID 1
- 镜像,在主硬盘上存放数据时,也在镜像硬盘上写一样的数据。一张硬盘坏了,还有另外一张可以代替。
- RAID 1 数据安全性最好,但磁盘利用率最低
-
RAID 2
- 至少需要三台磁盘驱动器。以汉明码方式将数据编码后分区为独立的比特,将数据分别写入硬盘中。
- 加入了错误修正码ECC,数据整体容量会比原始数据大一些
-
RAID 3
- 采用数据交错存储技术。
-
RAID 4
- 块交织技术
-
RAID 5
- 硬盘分区,储存性能、数据安全与村塾成本兼顾
- 需要至少三块硬盘,将数据和相对应的奇偶校验信息存储在组成RAID 5的各个磁盘上,并且奇偶校验信息和相对应的数据分别存储于不同磁盘上。
- 允许一块硬盘损坏。
-
RAID 6
- 增加了第二个独立的奇偶校验信息块,数据可靠性非常高。
- 允许两块磁盘同时失效
- 至少需要四块硬盘
Linux
操作 | 举例 |
---|---|
显示文件目录ls | ls |
改变当前目录cd | cd /home |
建立子目录mkdir | mkdir xiong |
删除子目录rmdir | rmdir /mnt/cdrom |
删除文件rm | rm /ucdos/fox |
复制文件 | cp /ucdos/fox |
获取帮助信息man | man ls |
显示文件内容 less | less mwm.lx |
重定向与管道type | type readme>>direct(将readme的内容追加到direct文件中去) |
文件类型 | 属主权限 | 属组权限 | 其他用户权限 |
---|---|---|---|
d代表目录,-代表文件,l代表链接文档,b代表可随机存取装置,c代表串行端口设备(一次性读取装置,如键盘、鼠标) | rwx,代表可读可写可执行,若没有某权限则使用-表示 | rwx,代表可读可写可执行,若没有某权限则使用-表示 | rwx,代表可读可写可执行,若没有某权限则使用-表示 |
举例:dr-xr-xr-x
d 此为目录文件
r-x 属主拥有读和执行权限,没有写权限
r-x 属组拥有读和执行权限,没有写权限
r-x 其他用户拥有读和执行权限,没有写权限