操作系统原理---面试知识点总结

1.进程与线程的区别

  • 根本区别:进程是操作系统资源分配的基本(最小)单位,而线程是任务调度和执行的基本(最小)单位。
  • 开销方面:每个进程都有独立的代码和数据空间,程序之间的切换会有较大的开销;对于线程,同一类线程共享代码和数据空间,每个线程都有自己独立的运行栈和程序计数器,线程之间切换的开销小。
  • 所处环境:在操作系统中能同时运行多个进程(程序);而在同一个进程中有多个线程同时执行(通过CPU调度,在每个时间片中只有一个线程执行)。
  • 内存分配方面:系统在运行的时候会为每个进程分配不同的内存空间;而对线程而言,除了CPU外,系统不会为线程分配内存(线程所使用的资源来自其所属进程的资源),线程组之间只能共享资源。
  • 包含关系:一个进程最少由一条线程组成。

2.进程的状态及其转换

进程的状态基本可以分为以下3类:

状态 说明
就绪态 进程已经具备运行条件,但是CPU还没有分配过来;
运行态 进程占用CPU,并在CPU上运行;
阻塞态 进程因等待某件事发生而暂时不能运行;

进程在一生中,都处于上述3种状态之一。

3种状态转换图:
操作系统原理---面试知识点总结
按照数学推理,上述三个状态如果可以互相转换的话,应该有6种情况,但是实际上只有4种,其余2种不可能发生。

首先介绍可以发生的4种转换情况,见下表。

状态转换 说明
就绪态---->运行态 运行的进程的时间片用完,调度就转到就绪队列中选择合适的进程分配给CPU。
运行态---->就绪态 这是由于调度引起的,当进程占用CPU的时间过长,会被转为就绪态。
运行态---->阻塞态 发生了I/O请求或等待某件事的发生。
阻塞态---->就绪态 进程所等待的事件发生,就进入就绪队列。

不可能发生的转换情况

状态转换 说明
阻塞态---->运行态 即使给阻塞进程分配CPU,也无法执行,操作系统載进行调度时不会載阻塞队列进行挑选,其调度的选择对象为就绪队列。
就绪态---->阻塞态 因为就绪态根本就没有被运行,何来进入阻塞态。

以上介绍的是进程的基本状态,但是在操作系统的具体实现中,细化为以下5种状态。见下表。

状态 说明
1.可运行态 运行态和就绪态的合并,表示进程正在运行或准备运行,Linux 中使用TASK_RUNNING 宏表示此状态。
2.浅度睡眠态 又名可中断睡眠状态。进程正在睡眠(被阻塞),等待资源到来时被唤醒,也可以通过其他进程信号或时钟中断唤醒。唤醒后进入就绪队列。Linux 使用TASK_INTERRUPTIBLE 宏表示此状态。
3.深度睡眠态 又名不可中断睡眠状态。其和浅度睡眠基本类似,但有一点就是不可被其它进程信号或时钟中断唤醒。该状态的进程只能用wake_up()函数唤醒。Linux 使用TASK_UNINTERRUPTIBLE 宏表示此状态。
4.暂停状态 进程暂停执行接受某种处理。如正在接受调试的进程处于这种状态。Linux 使用TASK_STOPPED 宏表示此状态。
5.僵死状态 进程已经结束但未释放PCB。Linux 使用TASK_ZOMBIE 宏表示此状态。

Linux进程间状态转换和内核调用图解:
操作系统原理---面试知识点总结

3.进程的同步与互斥

互斥:是指某一资源同时只允许一个访问者对其访问,具有唯一性和排他性。但互斥无法限制访问者对资源的访问顺序,即访问是无序的。

同步:是指在互斥的基础上(大多数情况),通过其他机制实现访问者对资源的有序访问。在大多数情况下,同步已经实现了互斥,特别是所有写入资源的情况必定是互斥的。少数情况是指可以允许多个访问者同时访问资源。

简单的说:同步体现的是一种协作性,呼哧体现的是一种排他性。

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

分类 说明
管道(匿名管道、命名管道) 管道的实质是一个内核缓冲区,管道的作用正如其名,需要通信的两个进程在管道的两端,进程利用管道传递信息。管道对于管道两端的进程而言,就是一个文件,但是这个文件比较特殊,它不属于文件系统并且只存在于内存中。
信号 信号是软件层次上对中断机制的一种模拟,是一种异步通信方式,进程不必通过任何操作来等待信号的到达。信号可以在用户空间进程和内核之间直接交互,内核可以利用信号来通知用户空间的进程发生了哪些系统事件。
信号量 信号量实质上就是一个标识可用资源数量的计数器,它的值总是非负整数。而只有0和1两种取值的信号量叫做二进制信号量(或二值信号量),可用用来标识某个资源是否可用。主要作为进程间以及同一进程内不同线程之间的同步手段。
消息队列 消息队列是消息的链表,具有特定的格,存放在内存中并由消息队列标识符标识,并且允许一个或多个进程向它写入与读取消息。消息队列克服了信号传递消息少,管道只能承载无格式字节流以及缓冲区大小受限等缺点。
共享内存 使得多个进程可以可以直接读写同一块内存空间,是针对其他通信机制运行效率较低而设计的。
套接字 套接字是更为基础的进程间通信机制,与其他方式不同的是,套接字可用于不同机器之间的进程间通信。

5.作业(进程)的调度算法有哪些?

  1. **先来先服务(FCFS,First-Come-Frist-Served):**此算法的原则是按照作业到达后备作业队列(或进程进入就绪队列)的先后次序来选择作业(或进程)。
  2. **短作业优先(SJF,Shortest Process Next):**这种调度算法主要用于作业调度,它从作业后备队列中挑选所需运行时间(估计值)最短的作业进入主存运行。
  3. **时间片轮转调度算法(RR,Round-Robin):**当某个进程执行的时间片用完时,调度程序便停止该进程的执行,并将它送入就绪队列的末尾,等待分配下一时间片再执行。然后把处理机分配给就绪队列中新的队首进程,同时也让它执行一个时间片。这样就可以保证就绪队列中的所有进程,在一给定的时间内,均能获得时间片处理机执行时间。
  4. **高响应比优先(HRRN,Highest Response Ratio Next):**按照高响应比((已等待时间+要求运行时间)/ 要求运行时间)优先的原则,在每次选择作业投入运行时,先计算此时后备作业队列中每个作业的响应比RP然后选择其值最大的作业投入运行。
  5. 优先权(Priority)调度算法: 按照进程的优先权大小来调度,使高优先权进程得到优先处理的调度策略称为优先权调度算法。注意:优先数越多,优先权越小。
  6. **多级队列调度算法:**多队列调度是根据作业的性质和类型的不同,将就绪队列再分为若干个子队列,所有的作业(或进程)按其性质排入相应的队列中,而不同的就绪队列采用不同的调度算法。

6.什么是死锁?死锁产生的原因?产生死锁的必要条件?如何预防死锁?如何避免死锁?如何解除死锁?

什么是死锁:在2个或多个并发进程中,如果每个进程持有某有资源而又都等待别的进程释放它们现在保持的资源,在未改变这种状态之前都不能向前推进,称这一组进程产生了死锁。通俗地讲,就是2个或多个进程被无限期地阻塞、相互等待的一种状态。

死锁产生的原因:系统资源不足;进程推进顺序非法。

产生死锁的必要条件:(以下4个条件有一个不成立,就不会产生死锁)

  • 互斥:某种资源一次只允许一个进程访问,即该资源一旦分配给某个进程,其他进程就不能再访问,直到该进程访问结束。
  • 不可剥夺:一个进程所获得的资源在未使用完毕之前,不能被其它进程强行剥夺,而只能由获得该资源的进程资源释放。
  • 占有且等待:一个进程本身已占有部分资源(一种或多种),但是还有资源未得到满足,就会等待其它进程释放该资源。
  • 循环等待:存在一个进程链,使得每一个进程都占有下一个进程所需的至少一种资源。

如何预防死锁(静态策略):破坏产生死锁的四个必要条件之一即可。

如何避免死锁(动态策略):它不限制进程有关申请资源的命令,而是对进程所发出的每一个申请资源命令加以动态地检查,并根据检查结果决定是否进行资源分配。就是说,在资源分配过程中若预测有发生死锁的可能性,则加以避免。这种方法的关键是确定资源分配的安全性。

采用的常用方法:

  1. 安全序列。安全序列{P1,P2,…,Pn}是这样组成的:若对于每一个进程Pi,它需要的附加资源可以被系统中当前可用资源加上所有进程Pj当前占有资源之和所满足,则{P1,P2,…,Pn}为一个安全序列,这时系统处于安全状态,不会进入死锁状态。
  2. 银行家算法。银行家算法允许死锁必要条件中的互斥条件、不可剥夺、占有且等待条件的存在。该方法允许进程动态地申请资源,系统在进行资源分配之前,先计算资源分配的安全性。若此次分配不会导致系统从安全状态向不安全状态转换,便可将资源分配给进程;否则不分配资源,进程必须阻塞等待。从而避免发生死锁。

如何解除死锁

  1. 强制性地从系统中撤销一个或多个死锁的进程以断开循环等待链,并收回分配给终止进程的全部资源功剩下的进程使用。
  2. 使用一个有效的挂起和解除机构来挂起一些死锁的进程,其实质是从被挂起的进程那里抢占资源以解除死锁。