0
点赞
收藏
分享

微信扫一扫

保研考研面试-操作系统

王小沫 2022-01-28 阅读 66

保研上岸某中游985,准备的一些操作系统重要的基础知识,面试可能会问到:

1.进程的常见状态?以及各种状态之间的转换条件?

  • 就绪:进程已处于准备好运行的状态,即进程已分配到除CPU外的所有必要资源后,只要再获得CPU,便可立即执行。
  • 执行:进程已经获得CPU,程序正在执行状态。
  • 阻塞:正在执行的进程由于发生某事件(如I/O请求、申请缓冲区失败等)暂时无法继续执行的状态。

img

2.进程同步

进程同步的主要任务:是对多个相关进程在执行次序上进行协调,以使并发执行的诸进程之间能有效地共享资源和相互合作,从而使程序的执行具有可再现性。

同步机制遵循的原则:

(1)空闲让进;

(2)忙则等待(保证对临界区的互斥访问);

(3)有限等待(有限代表有限的时间,避免死等);

(4)让权等待,(当进程不能进入自己的临界区时,应该释放处理机,以免陷入忙等状态)。

进程的同步方法:互斥锁读写锁条件变量记录锁(record locking)信号量屏障

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

进程通信,是指进程之间的信息交换(信息量少则一个状态或数值,多者则是成千上万个字节)。因此,对于用信号量进行的进程间的互斥和同步,由于其所交换的信息量少而被归结为低级通信。

所谓高级进程通信指:用户可以利用操作系统所提供的一组通信命令传送大量数据的一种通信方式。操作系统隐藏了进程通信的实现细节。或者说,通信过程对用户是透明的。

高级通信机制可归结为三大类:

(1)共享存储器系统(存储器中划分的共享存储区);实际操作中对应的是“剪贴板”(剪贴板实际上是系统维护管理的一块内存区域)的通信方式,比如举例如下:word进程按下ctrl+c,在ppt进程按下ctrl+v,即完成了word进程和ppt进程之间的通信,复制时将数据放入到剪贴板,粘贴时从剪贴板中取出数据,然后显示在ppt窗口上。

(2)消息传递系统(进程间的数据交换以消息(message)为单位,当今最流行的微内核操作系统中,微内核与服务器之间的通信,无一例外地都采用了消息传递机制。

(3)管道通信系统(管道即:连接读写进程以实现他们之间通信的共享文件(pipe文件,类似先进先出的队列,由一个进程写,另一进程读))。

  • 管道:**管道是单向的、先进先出的、无结构的、固定大小的字节流,它把一个进程的标准输出和另一个进程的标准输入连接在一起。**写进程在管道的尾端写入数据,读进程在管道的道端读出数据。数据读出后将从管道中移走,其它读进程都不能再读到这些数据。管道提供了简单的流控制机制。进程试图读空管道时,在有数据写入管道前,进程将一直阻塞。同样地,管道已经满时,进程再试图写管道,在其它进程从管道中移走数据之前,写进程将一直阻塞。

  • 信号量信号量是一个计数器,可以用来控制多个进程对共享资源的访问。它常作为一种锁机制,防止某进程正在访问共享资源时,其它进程也访问该资源。因此,主要作为进程间以及同一进程内不同线程之间的同步手段。

  • 消息队列是一个在系统内核中用来保存消 息的队列,它在系统内核中是以消息链表的形式出现的。消息队列克服了信号传递信息少、管道只能承载无格式字节流以及缓冲区大小受限等缺点

  • 共享内存:共享内存允许两个或多个进程访问同一个逻辑内存。这一段内存可以被两个或两个以上的进程映射至自身的地址空间中,一个进程写入共享内存的信息,可以被其他使用这个共享内存的进程,通过一个简单的内存读取读出,从而实现了进程间的通信**。如果某个进程向共享内存写入数据,所做的改动将立即影响到可以访问同一段共享内存的任何其他进程

  • 套接字:套接字也是一种进程间通信机制,与其它通信机制不同的是,它可用于不同机器间的进程通信。

💯4.上下文切换

上下文:执行活动的全过程的静态描述,也就是当前进程的寄存器内容以及内存也表的详细信息等。

对于单核单线程CPU而言,在某一时刻只能执行一条CPU指令。上下文切换(Context Switch)是一种将CPU资源从一个进程分配给另一个进程的机制。从用户角度看,计算机能够并行运行多个进程,这恰恰是操作系统通过快速上下文切换造成的结果。在切换的过程中,操作系统需要先存储当前进程的状态(包括内存空间的指针,当前执行完的指令等等),再读入下一个进程的状态,然后执行此进程。

5.进程与线程的区别和联系?

  • 进程是具有一定独立功能的程序关于某个数据集合上的一次运行活动,进程是系统进行资源分配和调度的一个独立单位。
  • 线程是进程的一个实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位。

进程和线程的关系

(1)一个线程只能属于一个进程,而一个进程可以有多个线程,但至少有一个线程。线程是操作系统可识别的最小执行和调度单位。

(2)资源分配给进程,同一进程的所有线程共享该进程的所有资源。 同一进程中的多个线程共享代码段(代码和常量),数据段(全局变量和静态变量),扩展段(堆存储)。但是每个线程拥有自己的栈段,栈段又叫运行时段,用来存放所有局部变量和临时变量。

(3)线程在执行过程中,需要协作同步。不同进程的线程间要利用消息通信的办法实现同步。

进程与线程的区别?

(1)进程有自己的独立地址空间,线程没有

(2)进程是资源分配的最小单位,线程是CPU调度的最小单位

(3)进程和线程通信方式不同(线程之间的通信比较方便。同一进程下的线程共享数据(比如全局变量,静态变量),通过这些数据来通信不仅快捷而且方便,当然如何处理好这些访问的同步与互斥正是编写多线程程序的难点。而进程之间的通信只能通过进程通信的方式进行。)

(4)进程上下文切换开销大,线程开销小

(5)一个进程挂掉了不会影响其他进程,而线程挂掉了会影响其他线程

(6)对进程进程操作一般开销都比较大,对线程开销就小了

为什么进程上下文切换比线程上下文切换代价高?

进程切换分两步:

1.切换页目录以使用新的地址空间

2.切换内核栈和硬件上下文

对于linux来说,线程和进程的最大区别就在于地址空间,对于线程切换,第1步是不需要做的,第2是进程和线程切换都要做的。

进程恢复执行前必须装入寄存器的那一组数据成为硬件上下文。

切换的性能消耗:

线程上下文切换和进程上下问切换一个最主要的区别是线程的切换虚拟内存空间依然是相同的,但是进程切换是不同的。这两种上下文切换的处理都是通过操作系统内核来完成的。内核的这种切换过程伴随的最显著的性能损耗是将寄存器中的内容切换出。

链接:https://www.zhihu.com/question/25532384/answer/81152571

进程和线程都是一个时间段的描述,是CPU工作时间段的描述。

  • 进程(process)与线程(thread)最大的区别是进程拥有自己的地址空间,某进程内的线程对于其他进程不可见,即进程A不能通过传地址的方式直接读写进程B的存储区域。进程之间的通信需要通过进程间通信(Inter-process communication,IPC)。与之相对的,同一进程的各线程间之间可以直接通过传递地址或全局变量的方式传递信息
  • **进程作为操作系统中拥有资源和独立调度的基本单位,可以拥有多个线程。**通常操作系统中运行的一个程序就对应一个进程。在同一进程中,线程的切换不会引起进程切换。在不同进程中进行线程切换,如从一个进程内的线程切换到另一个进程中的线程时,会引起进程切换。相比进程切换,线程切换的开销要小很多。线程于进程相互结合能够提高系统的运行效率。

线程可以分为两类:

  • 用户级线程(user level thread):。用户级线程的好处是非常高效,不需要进入内核空间,但并发效率不高。
  • 内核级线程(kernel level thread):内核可以将不同线程更好地分配到不同的CPU,以实现真正的并行计算。

事实上,在现代操作系统中,往往使用组合方式实现多线程,即线程创建完全在用户空间中完成,并且一个应用程序中的多个用户级线程被映射到一些内核级线程上,相当于是一种折中方案。

6.进程调度

调度种类

  • 高级调度:(High-Level Scheduling)又称为作业调度,它根据某种算法决定将外存上处于后备队列中哪几个作业调入内存,并为他们创建进程,分配必要的资源,并将他们放入就绪队列。
  • 低级调度:(Low-Level Scheduling)又称为进程调度,它决定把就绪队列的某进程获得CPU;
  • 中级调度:(Intermediate-Level Scheduling)又称为在虚拟存储器中引入,在内、外存对换区进行进程对换。

非抢占式调度与抢占式调度

  • 非抢占式:分派程序一旦把处理机分配给某进程后便让它一直运行下去,直到进程完成或发生进程调度进程调度某事件而阻塞时,才把处理机分配给另一个进程。
  • 抢占式:操作系统将正在运行的进程强行暂停,由调度程序将CPU分配给其他就绪进程的调度方式。

调度策略的设计

  • 响应时间: 从用户输入到产生反应的时间
  • 周转时间: 从任务开始到任务结束的时间

CPU任务可以分为交互式任务批处理任务,调度最终的目标是合理的使用CPU,使得交互式任务的响应时间尽可能短,用户不至于感到延迟,同时使得批处理任务的周转时间尽可能短,减少用户等待的时间。

调度算法:

FIFO或First Come, First Served (FCFS)先来先服务

  • 调度的顺序就是任务到达就绪队列的顺序。
  • 公平、简单(FIFO队列)、非抢占、不适合交互式。
  • 未考虑任务特性,平均等待时间可以缩短。

Shortest Job First (SJF)

  • 最短的作业(CPU区间长度最小)最先调度。
  • SJF可以保证最小的平均等待时间。

Shortest Remaining Job First (SRJF)

  • SJF的可抢占版本,比SJF更有优势。
  • SJF(SRJF): 如何知道下一CPU区间大小?根据历史进行预测: 指数平均法。

优先权调度

  • 每个任务关联一个优先权,调度优先权最高的任务。
  • 注意:优先权太低的任务一直就绪,得不到运行,出现“饥饿”现象。

Round-Robin(RR)轮转调度算法

  • 设置一个时间片,按时间片来轮转调度(“轮叫”算法)
  • 优点: 定时有响应,等待时间较短;缺点: 上下文切换次数较多;
  • 时间片太大,响应时间太长;吞吐量变小,周转时间变长;当时间片过长时,退化为FCFS。

多级队列调度

  • 按照一定的规则建立多个进程队列
  • 不同的队列有固定的优先级(高优先级有抢占权)
  • 不同的队列可以给不同的时间片和采用不同的调度方法
  • 存在问题1:没法区分I/O bound和CPU bound;
  • 存在问题2:也存在一定程度的“饥饿”现象;

多级反馈队列

  • 在多级队列的基础上,任务可以在队列之间移动,更细致的区分任务。
  • 可以根据“享用”CPU时间多少来移动队列,阻止“饥饿”。
  • 最通用的调度算法,多数OS都使用该方法或其变形,如UNIX、Windows等。

多级反馈队列调度算法描述:

  • 进程在进入待调度的队列等待时,首先进入优先级最高的Q1等待。
  • **首先调度优先级高的队列中的进程。若高优先级中队列中已没有调度的进程,则调度次优先级队列中的进程。**例如:Q1,Q2,Q3三个队列,只有在Q1中没有进程等待时才去调度Q2,同理,只有Q1,Q2都为空时才会去调度Q3。
  • **对于同一个队列中的各个进程,按照时间片轮转法调度。**比如Q1队列的时间片为N,那么Q1中的作业在经历了N个时间片后若还没有完成,则进入Q2队列等待,若Q2的时间片用完后作业还不能完成,一直进入下一级队列,直至完成。
  • 在低优先级的队列中的进程在运行时,又有新到达的作业,那么在运行完这个时间片后,CPU马上分配给新到达的作业(抢占式)。

7.死锁的条件?以及如何处理死锁问题?

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

产生死锁的必要条件:

  • 互斥条件(Mutual exclusion):资源不能被共享,只能由一个进程使用。
  • 请求与保持条件(Hold and wait):已经得到资源的进程可以再次申请新的资源。
  • 非抢占条件(No pre-emption):已经分配的资源不能从相应的进程中被强制地剥夺。
  • 循环等待条件(Circular wait):系统中若干进程组成环路,该环路中每个进程都在等待相邻进程正占用的资源。

如何处理死锁问题:

死锁预防:设置协议

死锁避免:仔细地对资源进行动态分配,使系统始终处于安全状态,可利用银行家算法

死锁的检测与解除:资源分配图、抢占资源、终止进程

💯 8.临界资源

  • 在操作系统中,进程是占有资源的最小单位(线程可以访问其所在进程内的所有资源,但线程本身并不占有资源或仅仅占有一点必须资源)。但对于某些资源来说,其在同一时间只能被一个进程所占用。这些一次只能被一个进程所占用的资源就是所谓的临界资源。典型的临界资源比如物理上的打印机,或是存在硬盘或内存中被多个进程所共享的一些变量和数据等(如果这类资源不被看成临界资源加以保护,那么很有可能造成丢数据的问题)。
  • **对于临界资源的访问,必须是互斥进行。**也就是当临界资源被占用时,另一个申请临界资源的进程会被阻塞,直到其所申请的临界资源被释放。而进程内访问临界资源的代码被成为临界区。

💯 9.一个程序从开始运行到结束的完整过程(四个过程)

1、预处理:条件编译,头文件包含,宏替换的处理,生成.i文件。

2、编译:将预处理后的文件转换成汇编语言,生成.s文件

3、汇编:汇编变为目标代码(机器代码)生成.o的文件

4、链接:连接目标代码,生成可执行程序

链接

10.内存池、进程池、线程池

线程池:线程池的原理很简单,类似于操作系统中的缓冲区的概念,它的流程如下:先启动若干数量的线程,并让这些线程都处于睡眠状态,当需要一个开辟一个线程去做具体的工作时,就会唤醒线程池中的某一个睡眠线程,让它去做具体工作,当工作完成后,线程又处于睡眠状态,而不是将线程销毁。

进程池与线程池同理。

内存池:**内存池是指程序预先从操作系统申请一块足够大内存,此后,当程序中需要申请内存的时候,不是直接向操作系统申请,而是直接从内存池中获取;同理,当程序释放内存的时候,并不真正将内存返回给操作系统,而是返回内存池。**当程序退出(或者特定时间)时,内存池才将之前申请的内存真正释放。

🅰️ 11.动态链接库与静态链接库的区别

静态库

  • 静态库是一个外部函数与变量的集合体。静态库的文件内容,通常包含一堆程序员自定的变量与函数,其内容不像动态链接库那么复杂,在编译期间由编译器与链接器将它集成至应用程序内,并制作成目标文件以及可以独立运作的可执行文件。而这个可执行文件与编译可执行文件的程序,都是一种程序的静态创建(static build)。

动态库

  • 静态库很方便,但是如果我们只是想用库中的某一个函数,却仍然得把所有的内容都链接进去。一个更现代的方法则是使用共享库,避免了在文件中静态库的大量重复。
  • 动态链接可以在首次载入的时候执行(load-time linking),这是 Linux 的标准做法,会由动态链接器ld-linux.so 完成,比方标准 C 库(libc.so) 通常就是动态链接的,这样所有的程序可以共享同一个库,而不用分别进行封装。
  • 动态链接也可以在程序开始执行的时候完成(run-time linking),在 Linux 中使用 dlopen()接口来完成(会使用函数指针),通常用于分布式软件,高性能服务器上。而且共享库也可以在多个进程间共享。
  • 链接使得我们可以用多个对象文件构造我们的程序。可以在程序的不同阶段进行(编译、载入、运行期间均可),理解链接可以帮助我们避免遇到奇怪的错误

区别:

  1. 使用静态库的时候,静态链接库要参与编译,在生成执行文件之前的链接过程中,要将静态链接库的全部指令直接链接入可执行文件中。而动态库提供了一种方法,使进程可以调用不属于其可执行代码的函数。函数的可执行代码位于一个.dll文件中,该dll包含一个或多个已被编译,链接并与使用它们的进程分开储存的函数。
  2. 静态库中不能再包含其他动态库或静态库,而在动态库中还可以再包含其他动态或者静态库。
  3. 静态库在编译的时候,就将库函数装在到程序中去了,而动态库函数必须在运行的时候才被装载,所以使用静态库速度快一些。

链接

💯 12.虚拟内存?优缺点?

定义:具有请求调入功能和置换功能,能从逻辑上对内存容量加以扩充得一种存储器系统。其逻辑容量由内存之和和外存之和决定。

与传统存储器比较虚拟存储器有以下三个主要特征:

  • 多次性,是指无需在作业运行时一次性地全部装入内存,而是允许被分成多次调入内存运行。
  • 对换性,是指无需在作业运行时一直常驻内存,而是允许在作业的运行过程中,进行换进和换出。
  • 虚拟性,是指从逻辑上扩充内存的容量,使用户所看到的内存容量,远大于实际的内存容量。

虚拟内存的实现有以下两种方式:

  • 请求分页存储管理。
  • 请求分段存储管理。

13.页面置换算法

操作系统将内存按照页面进行管理,在需要的时候才把进程相应的部分调入内存。当产生缺页中断时,需要选择一个页面写入。如果要换出的页面在内存中被修改过,变成了“脏”页面,那就需要先写会到磁盘。页面置换算法,就是要选出最合适的一个页面,使得置换的效率最高。页面置换算法有很多,简单介绍几个,重点介绍比较重要的LRU及其实现算法。

一、最优页面置换算法

最理想的状态下,我们给页面做个标记,挑选一个最远才会被再次用到的页面调出。当然,这样的算法不可能实现,因为不确定一个页面在何时会被用到。

二、先进先出页面置换算法(FIFO)及其改进

这种算法的思想和队列是一样的,该算法总是淘汰最先进入内存的页面,即选择在内存中驻留时间最久的页面予淘汰。实现:把一个进程已调入内存的页面按先后次序链接成一个队列,并且设置一个指针总是指向最老的页面。缺点:对于有些经常被访问的页面如含有全局变量、常用函数、例程等的页面,不能保证这些不被淘汰。

三、最近最少使用页面置换算法LRU(Least Recently Used)

根据页面调入内存后的使用情况做出决策。LRU置换算法是选择最近最久未使用的页面进行淘汰。

1.为每个在内存中的页面配置一个移位寄存器。(P165)定时信号将每隔一段时间将寄存器右移一位。最小数值的寄存器对应页面就是最久未使用页面。

2.利用一个特殊的栈保存当前使用的各个页面的页面号。每当进程访问某页面时,便将该页面的页面号从栈中移出,将它压入栈顶。因此,栈顶永远是最新被访问的页面号,栈底是最近最久未被访问的页面号。

链接:分页内存管理(把虚拟内存空间和物理内存空间均划分为大小相同的页面等内容)

链接:分段内存管理

14.中断与系统调用

**所谓的中断就是在计算机执行程序的过程中,由于出现了某些特殊事情,使得CPU暂停对程序的执行,转而去执行处理这一事件的程序。等这些特殊事情处理完之后再回去执行之前的程序。**中断一般分为三类:

  • 由计算机硬件异常或故障引起的中断,称为内部异常中断
  • 由程序中执行了引起中断的指令而造成的中断,称为软中断(这也是和我们将要说明的系统调用相关的中断);
  • 由外部设备请求引起的中断,称为外部中断。简单来说,对中断的理解就是对一些特殊事情的处理。

与中断紧密相连的一个概念就是中断处理程序了。当中断发生的时候,系统需要去对中断进行处理,对这些中断的处理是由操作系统内核中的特定函数进行的,这些处理中断的特定的函数就是我们所说的中断处理程序了。

另一个与中断紧密相连的概念就是中断的优先级。中断的优先级说明的是当一个中断正在被处理的时候,处理器能接受的中断的级别。中断的优先级也表明了中断需要被处理的紧急程度。**每个中断都有一个对应的优先级,当处理器在处理某一中断的时候,只有比这个中断优先级高的中断可以被处理器接受并且被处理。**优先级比这个当前正在被处理的中断优先级要低的中断将会被忽略。

典型的中断优先级如下所示:

  • 机器错误 > 时钟 > 磁盘 > 网络设备 > 终端 > 软件中断

在讲系统调用之前,先说下进程的执行在系统上的两个级别:用户级和核心级,也称为用户态和系统态(user mode and kernel mode)

用户空间就是用户进程所在的内存区域,相对的,系统空间就是操作系统占据的内存区域。用户进程和系统进程的所有数据都在内存中。处于用户态的程序只能访问用户空间,而处于内核态的程序可以访问用户空间和内核空间。

用户态切换到内核态的方式如下:

  • 系统调用:程序的执行一般是在用户态下执行的,但当程序需要使用操作系统提供的服务时,比如说打开某一设备、创建文件、读写文件(这些均属于系统调用)等,就需要向操作系统发出调用服务的请求,这就是系统调用。
  • 异常:当CPU在执行运行在用户态下的程序时,发生了某些事先不可知的异常,这时会触发由当前运行进程切换到处理此异常的内核相关程序中,也就转到了内核态,比如缺页异常。
  • **外围设备的中断:**当外围设备完成用户请求的操作后,会向CPU发出相应的中断信号,这时CPU会暂停执行下一条即将要执行的指令转而去执行与中断信号对应的处理程序,如果先前执行的指令是用户态下的程序,那么这个转换的过程自然也就发生了由用户态到内核态的切换。比如硬盘读写操作完成,系统会切换到硬盘读写的中断处理程序中执行后续操作等。

用户态和核心态(内核态)之间的区别是什么呢?

权限不一样。

  • 用户态的进程能存取它们自己的指令和数据,但不能存取内核指令和数据(或其他进程的指令和数据)
  • **核心态下的进程能够存取内核和用户地址某些机器指令是特权指令,在用户态下执行特权指令会引起错误。**在系统中内核并不是作为一个与用户进程平行的估计的进程的集合。

15.C++多线程,互斥,同步

同步和互斥

当有多个线程的时候,经常需要去**同步(注:同步不是同时刻)**这些线程以访问同一个数据或资源。

所谓同步,是指在不同进程之间的若干程序片断,它们的运行必须严格按照规定的某种先后次序来运行,这种先后次序依赖于要完成的特定的任务。如果用对资源的访问来定义的话,**同步是指在互斥的基础上(大多数情况),通过其它机制实现访问者对资源的有序访问。**在大多数情况下,同步已经实现了互斥,特别是所有写入资源的情况必定是互斥的。少数情况是指可以允许多个访问者同时访问资源。

所谓互斥,是指散布在不同进程之间的若干程序片断,当某个进程运行其中一个程序片段时,其它进程就不能运行它们之中的任一程序片段,只能等到该进程运行完这个程序片段后才可以运行。如果用对资源的访问来定义的话,互斥某一资源同时只允许一个访问者对其进行访问,具有唯一性和排它性。但互斥无法限制访问者对资源的访问顺序,即访问是无序的。

多线程同步和互斥有几种实现方法

线程间的同步方法大体可分为两类:用户模式和内核模式。顾名思义,内核模式就是指利用系统内核对象的单一性来进行同步,使用时需要切换内核态与用户态,而用户模式就是不需要切换到内核态,只在用户态完成操作。

用户模式下的方法有:原子操作(例如一个单一的全局变量),临界区。

内核模式下的方法有:事件,信号量,互斥量。

1、临界区: 通过对多线程的串行化来访问公共资源或一段代码,速度快,适合控制数据访问。
2、互斥量: 为协调共同对一个共享资源的单独访问而设计的。
3、信号量: 为控制一个具有有限数量用户资源而设计。
4、事 件: 用来通知线程有一些事件已发生,从而启动后继任务的开始。

16.逻辑地址 VS 物理地址 VS 虚拟内存

  • **所谓的逻辑地址,是指计算机用户(例如程序开发者),看到的地址。**例如,当创建一个长度为100的整型数组时,操作系统返回一个逻辑上的连续空间:指针指向数组第一个元素的内存地址。由于整型元素的大小为4个字节,故第二个元素的地址时起始地址加4,以此类推。事实上,逻辑地址并不一定是元素存储的真实地址,即数组元素的物理地址(在内存条中所处的位置),并非是连续的,只是操作系统通过地址映射,将逻辑地址映射成连续的,这样更符合人们的直观思维
  • 另一个重要概念是虚拟内存。操作系统读写内存的速度可以比读写磁盘的速度快几个量级。但是,内存价格也相对较高,不能大规模扩展。于是,操作系统可以通过将部分不太常用的数据移出内存,“存放到价格相对较低的磁盘缓存,以实现内存扩展。操作系统还可以通过算法预测哪部分存储到磁盘缓存的数据需要进行读写,提前把这部分数据读回内存。虚拟内存空间相对磁盘而言要小很多,因此,即使搜索虚拟内存空间也比直接搜索磁盘要快。唯一慢于磁盘的可能是,内存、虚拟内存中都没有所需要的数据,最终还需要从硬盘中直接读取。这就是为什么内存和虚拟内存中需要存储会被重复读写的数据,否则就失去了缓存的意义。现代计算机中有一个专门的转译缓冲区(Translation Lookaside Buffer,TLB),用来实现虚拟地址到物理地址的快速转换。

与内存/虚拟内存相关的还有如下两个概念:

参考链接:https://blog.csdn.net/newcong0123/article/details/52792070

💯17.内部碎片与外部碎片

在内存管理中,内部碎片是已经被分配出去的的内存空间大于请求所需的内存空间。

外部碎片是指还没有分配出去,但是由于大小太小而无法分配给申请空间的新进程的内存空间空闲块。

固定分区存在内部碎片,可变式分区分配会存在外部碎片;

页式虚拟存储系统存在内部碎片段式虚拟存储系统,存在外部碎片

为了有效的利用内存,使内存产生更少的碎片,要对内存分页,内存以页为单位来使用,最后一页往往装不满,于是形成了内部碎片。

为了共享要分段,在段的换入换出时形成外部碎片,比如5K的段换出后,有一个4k的段进来放到原来5k的地方,于是形成1k的外部碎片。

💯18.同步和互斥的区别

​ 当有多个线程的时候,经常需要去同步这些线程以访问同一个数据或资源。例如,假设有一个程序,其中一个线程用于把文件读到内存,而另一个线程用于统计文件中的字符数。当然,在把整个文件调入内存之前,统计它的计数是没有意义的。但是,由于每个操作都有自己的线程,操作系统会把两个线程当作是互不相干的任务分别执行,这样就可能在没有把整个文件装入内存时统计字数。为解决此问题,你必须使两个线程同步工作。

所谓同步,是指散步在不同进程之间的若干程序片断,它们的运行必须严格按照规定的某种先后次序来运行,这种先后次序依赖于要完成的特定的任务。如果用对资源的访问来定义的话,同步是指在互斥的基础上(大多数情况),通过其它机制实现访问者对资源的有序访问。在大多数情况下,同步已经实现了互斥,特别是所有写入资源的情况必定是互斥的。少数情况是指可以允许多个访问者同时访问资源。

所谓互斥,是指散布在不同进程之间的若干程序片断,当某个进程运行其中一个程序片段时,其它进程就不能运行它们之中的任一程序片段,只能等到该进程运行完这个程序片段后才可以运行。如果用对资源的访问来定义的话,互斥某一资源同时只允许一个访问者对其进行访问,具有唯一性和排它性。但互斥无法限制访问者对资源的访问顺序,即访问是无序的。

19.什么是线程安全

如果多线程的程序运行结果是可预期的,而且与单线程的程序运行结果一样,那么说明是“线程安全”的。

💯20.同步与异步

同步:

  • 同步的定义:是指一个进程在执行某个请求的时候,若该请求需要一段时间才能返回信息,那么,这个进程将会一直等待下去,直到收到返回信息才继续执行下去。
  • 特点:
  1. 同步是阻塞模式;
  2. 同步是按顺序执行,执行完一个再执行下一个,需要等待,协调运行;

异步:

  • 是指进程不需要一直等下去,而是继续执行下面的操作,不管其他进程的状态。当有消息返回时系统会通知进程进行处理,这样可以提高执行的效率。
  • 特点:
  1. 异步是非阻塞模式,无需等待;
  2. 异步是彼此独立,在等待某事件的过程中,继续做自己的事,不需要等待这一事件完成后再工作。线程是异步实现的一个方式。

💯同步与异步的优缺点:

  • 同步可以避免出现死锁,读脏数据的发生。一般共享某一资源的时候,如果每个人都有修改权限,同时修改一个文件,有可能使一个读取另一个人已经删除了内容,就会出错,同步就不会出错。但,同步需要等待资源访问结束,浪费时间,效率低。
  • 异步可以提高效率,但,安全性较低。

21.系统调用与库函数的区别

  • **系统调用(System call)是程序向系统内核请求服务的方式。**可以包括硬件相关的服务(例如,访问硬盘等),或者创建新进程,调度其他进程等。系统调用是程序和操作系统之间的重要接口。
  • 库函数:把一些常用的函数编写完放到一个文件里,编写应用程序时调用,这是由第三方提供的,发生在用户地址空间
  • 移植性方面,不同操作系统的系统调用一般是不同的,移植性差;而在所有的ANSI C编译器版本中,C库函数是相同的。
  • 调用开销方面,系统调用需要在用户空间和内核环境间切换,开销较大;而库函数调用属于“过程调用”,开销较小。

22.守护、僵尸、孤儿进程的概念

  • 守护进程:运行在后台的一种特殊进程,独立于控制终端并周期性地执行某些任务
  • 僵尸进程:一个进程 fork 子进程,子进程退出,而父进程没有wait/waitpid子进程,那么子进程的进程描述符仍保存在系统中,这样的进程称为僵尸进程。
  • 孤儿进程:一个父进程退出,而它的一个或多个子进程还在运行,这些子进程称为孤儿进程。(孤儿进程将由 init 进程收养并对它们完成状态收集工作)

23.Semaphore(信号量) Vs Mutex(互斥锁)

  • 当用户创立多个线程/进程时,如果不同线程/进程同时读写相同的内容,则可能造成读写错误,或者数据不一致。此时,需要通过加锁的方式,控制临界区(critical section)的访问权限。**对于semaphore而言,在初始化变量的时候可以控制允许多少个线程/进程同时访问一个临界区,**其他的线程/进程会被堵塞,直到有人解锁。
  • Mutex相当于**只允许一个线程/进程访问的semaphore。**此外,根据实际需要,人们还实现了一种读写锁(read-write lock),它允许同时存在多个阅读者(reader),但任何时候至多只有一个写者(writer),且不能于读者共存。

💯24.IO多路复用

服务器必须响应两个相互独立的I/O事件如何处理的问题

IO多路复用是指内核一旦发现进程指定的一个或者多个IO条件准备读取,它就通知该进程。IO多路复用适用如下场合:

  • 当客户处理多个描述字时(一般是交互式输入和网络套接口),必须使用I/O复用。
  • 当一个客户同时处理多个套接口时,而这种情况是可能的,但很少出现。
  • 如果一个TCP服务器既要处理监听套接口,又要处理已连接套接口,一般也要用到I/O复用。
  • 如果一个服务器即要处理TCP,又要处理UDP,一般要使用I/O复用。
  • 如果一个服务器要处理多个服务或多个协议,一般要使用I/O复用。
  • 与多进程和多线程技术相比,I/O多路复用技术的最大优势是系统开销小,系统不必创建进程/线程,也不必维护这些进程/线程,从而大大减小了系统的开销。

🅰️25.线程安全

如果你的代码所在的进程中有多个线程在同时运行,而这些线程可能会同时运行这段代码。如果每次运行结果和单线程运行的结果是一样的,而且其他的变量的值也和预期的是一样的,就是线程安全的。或者说:一个类或者程序所提供的接口对于线程来说是原子操作或者多个线程之间的切换不会导致该接口的执行结果存在二义性,也就是说我们不用考虑同步的问题。

线程安全问题都是由全局变量及静态变量引起的。

若每个线程中对全局变量、静态变量只有读操作,而无写操作,一般来说,这个全局变量是线程安全的;若有多个线程同时执行写操作,一般都需要考虑线程同步,否则的话就可能影响线程安全。

补充:

1. 什么是内核态和用户态?如何实现内核态和用户态的切换?

用户程序执行时的两种状态,内核可以执行特权指令等一切指令,一切存储空间,而用户态只能访问用户地址空间

切换,除了系统调用(软中断)意外,还有:异常,外部中断

🅰️2.进程通信

低级的数据通信:共享数据结构,比如生产者消费者的有界缓冲区

高级的:共享存储区域

管道通信系统:共享文件,写进程,读进程,字符流

消息传递系统:通过原语通信;通过中间实体,比如邮箱通信

3.进程调度的时机,不能调度时机

当前进程执行完毕,被阻塞,时间片被用完,发生系统调用后返回进程,抢占调度优先级更高的进程

不能:终端处理程序执行时候、在内核程序临界区内等

💯 虚拟内存

在逻辑上对内存进行拓展,以虚拟分页存储管理为例,他将主存以及辅存分成页大小相同的若干份,以页为单位进行页面的换入换出,一个进程有若干页组成,CPU要访问的数据的逻辑地址通过地址变换机构得到物理地址,通过物理地址可以从内存或者外存中找到该数据。(具体在内存还是外存,看是否在内存,牵连到页面调入工作)

对于用户看来,既有接近主存的速度,又有接近辅存的容量。

🅰️LRU、LFU 实现机制

LRU:

硬件的支持:用栈或者寄存器

利用一个特殊的栈保存当前使用的各个页面的序号:

访问某页面时候,将页面号从栈里移出放到栈顶。栈底就是最近时间内最久未使用的。

LFU:

最近时间内最少未使用的

每个页面设置一个移位寄存器,每次访问某页时,便将该移位寄存器的最高位置置为1,再每隔一定时间右移一次。

段式与页式的优缺点:

优点:没有外碎片,每个内碎片不超过页的大小。

缺点:程序全部装入内存,要求有相应的硬件支持,如地址变换机构缺页中断的产生和选择淘汰页面等都要求有相应的硬件支持。增加了机器成本和系统开销。

段式:

优点:可以分别编写和编译,可以针对不同类型的段采取不同的保护,可以按段为单位来进行共享,包括通过动态链接进行代码共享

可以将一个进程放在同一个段内,便于进行 操作“共享等

缺点:会产生外部碎片。

举报

相关推荐

0 条评论