【36】C++岗位求职面试八股文第三十六篇(操作系统)

系列文章目录

第一篇:语言基础

第二篇:设计模式

第三篇:数据库

第四篇:计算机网络

第五篇:操作系统

第六篇:LInux

第七篇:数据结构

第八篇:智力题

[121]管程

信号量提供了一种方便且有效的进程同步机制,但是它们的使用错误可能导致难以检测的时序错误,因为这些错误只有在特定执行顺序时才会出现,而这些顺序并不总是出现。

为了处理这种错误,研究人员开发了一些高级语言工具,一种重要的、高级的同步工具,即管程(monitor)。管程中包含了面向对象的思想,它将表征共享资源的数据结构及其对数据结构操作的一组过程,包括同步机制,都集中并封装在一个对象内部,隐藏了实现细节。封装于管程内部的数据结构仅能被封装于管程内部的过程所访问,任何管程外的过程都不能访问它;反之,封装于管程内部的过程也仅能访问管程内的数据结构。所有进程要访问临界资源时,都只能通过管程间接访问,而管程每次只准许一个进程进入管程,执行管程内的过程,从而实现了进程互斥。

[122]死锁产生的条件,如何解决前提是进程或者线程死锁: 是指多个进程在执行过程中,因争夺资源而造成了互相等待。此时系统产生了死锁。

产生的条件:死锁发生有四个必要条件:(1)互斥条件:进程对所分配到的资源不允许其他进程访问,若其他进程访问,只能等待,直到进程使用完成后释放该资源;(2)请求保持条件:进程获得一定资源后,又对其他资源发出请求,但该资源被其他进程占有,此时请求阻塞,而且该进程不会释放自己已经占有的资源;(3)不可剥夺条件:进程已获得的资源,只能自己释放,不可剥夺;(4)环路等待条件:若干进程之间形成一种头尾相接的循环等待资源关系。

如何解决:(1)资源一次性分配,从而解决请求保持的问题(2)可剥夺资源:当进程新的资源未得到满足时,释放已有的资源;(3)资源有序分配:资源按序号递增,进程请求按递增请求,释放则相反。(破坏环路等待条件)

[123]有了进程,为什么还要有线程?1原因

进程在早期的多任务操作系统中是基本的执行单元。每次进程切换,都要先保存进程资源然后再恢复,这称为上下文切换。但是进程频繁切换将引起额外开销,从而严重影响系统的性能。为了减少进程切换的开销,人们把两个任务放到一个进程中,每个任务用一个更小粒度的执行单元来实现并发执行,这就是线程。

2线程与进程对比(1)进程间的信息难以共享。由于除去只读代码段外,父子进程并未共享内存,因此必须采用一些进程间通信方式,在进程间进行信息交换。但多个线程共享进程的内存,如代码段、数据段、扩展段,线程间进行信息交换十分方便。(2)调用 fork() 来创建进程的代价相对较高,即便利用写时复制技术,仍然需要复制诸如内存页表和文件描述符表之类的多种进程属性,这意味着 fork() 调用在时间上的开销依然不菲。但创建线程比创建进程通常要快 10 倍甚至更多。线程间是共享虚拟地址空间的,无需采用写时复制来复制内存,也无需复制页表。

[124]单核机器上写多线程程序,是否要考虑加锁,为什么

是的。因为线程锁通常用来实现线程的同步和通信。在单核机器上的多线程程序,仍然存在线程同步的问题。因为在抢占式操作系统中,通常为每个线程分配一个时间片,当某个线程时间片耗尽时,操作系统会将其挂起,然后运行另一个线程。如果这两个线程共享某些数据,不使用线程锁的前提下,可能会导致共享数据修改引起冲突。

[125]多线程和多进程的不同

(1)一个线程从属于一个进程;一个进程可以包含多个线程。(3)进程系统开销显著大于线程开销;线程需要的系统资源更少。(4)多个进程在执行时拥有各自独立的内存单元,多个线程共享进程的内存,如代码段、数据段、扩展段;但每个线程拥有自己的栈段和寄存器组。(5)多进程切换时需要刷新TLB并获取新的地址空间,然后切换硬件上下文和内核栈;多线程切换时只需要切换硬件上下文和内核栈。(6)通信方式不一样。7)多进程适应于多核、多机分布;多线程适用于多核

[126]互斥锁的机制,互斥锁与读写的区别?互斥锁机制:mutex,用于保证在任何时刻,都只能有一个线程访问该对象。当获取锁操作失败时,线程会进入睡眠,等待锁释放时被唤醒。

用互斥锁保护临界区,从而防止竞争条件。也就是说,一个线程在进入临界区时应得到锁,它在退出临界区时释放锁

互斥锁和读写锁:(1) 读写锁区分读者和写者,而互斥锁不区分(2)互斥锁同一时间只允许一个线程访问该对象,无论读写;读写锁同一时间内只允许一个写者,但是允许多个读者同时读对象。

[127]信号量,有什么作用?

实现进程、线程的互斥、同步

[128]进程、线程的中断切换的过程是怎样的?

上下文切换指的是内核(操作系统的核心)在CPU上对进程或者线程进行切换。而非内核态与用户态之间切换进程上下文切换(1)保护被中断进程的处理器现场信息(2)修改被中断进程的进程控制块有关信息,如进程状态等(3)把被中断进程的进程控制块加入有关队列(4)选择下一个占有处理器运行的进程(5)根据被选中进程设置操作系统用到的地址转换和存储保护信息切换页目录以使用新的地址空间切换内核栈和硬件上下文(包括分配的内存,数据段,堆栈段等)(6)根据被选中进程恢复处理器现场

线程上下文切换(1)保护被中断线程的处理器现场信息(2)修改被中断线程的线程控制块有关信息,如线程状态等(3)把被中断线程的线程控制块加入有关队列(4)选择下一个占有处理器运行的线程(5)根据被选中线程设置操作系统用到的存储保护信息切换内核栈和硬件上下文(切换堆栈,以及各寄存器)(6)根据被选中线程恢复处理器现场

[129]自旋锁和互斥锁的使用场景

互斥锁用于临界区持锁时间比较长的操作,比如下面这些情况都可以考虑  (1)临界区有IO操作  (2)临界区代码复杂或者循环量大  (3)临界区竞争非常激烈  (4)单核处理器自旋锁就主要用在临界区持锁时间非常短且CPU资源不紧张的情况下。

[130]多线程编程要注意什么,多线程加锁需要注意什么

1多线程编程需要考虑同步的问题。线程间的同步方式包括互斥锁、信号量、条件变量、读写锁。2多线程加锁,主要需要注意死锁的问题。破坏死锁的必要条件从而避免死锁。

[121]sleep和wait的区别?

(1)sleep是一个延时函数,让进程或线程进入休眠。休眠完毕后继续运行。(2)wait是父进程回收子进程PCB(Process Control Block)资源的一个系统调用。

[131]线程池的设计思路,线程池中线程的数量由什么确定?设计思路:生产者消费者模型

实现线程池有以下几个步骤:(1)设置一个生产者消费者队列,作为临界资源。(2)初始化n个线程,并让其运行起来(3)当任务队列为空时,所有线程阻塞。(4)当生产者队列来了一个任务后,先对队列加锁,把任务挂到队列上,然后使用条件变量去通知阻塞中的一个线程来处理,解锁(5)消费者队列加锁,从消费者队列里取任务,执行,然后解锁。(没任务,阻塞解锁;有任务,不阻塞不解锁)

线程数量:线程数量和哪些因素有关:CPU,IO、并行、并发如果是CPU密集型应用,则线程池大小设置为:CPU核心数+1如果是IO密集型应用,则线程池大小设置为:2CPU核心数+1 最佳线程数目 = (线程等待时间与线程CPU时间之比 + 1) CPU数目所以线程等待时间所占比例越高,需要越多线程。线程CPU时间所占比例越高,需要越少线程。

[132]为什么要创建线程池

创建线程和销毁线程的花销是比较大的,这些时间有可能比处理业务的时间还要长。这样频繁的创建线程和销毁线程,再加上业务工作线程,消耗系统资源的时间,可能导致系统资源不足。同时线程池也是为了提升系统效率。

[133]线程池的核心线程与普通线程

线程池中有两类线程:核心线程和非核心线程。核心线程默认情况下会一直存在于线程池中,即使这个核心线程什么都不干,而非核心线程如果长时间的闲置,就会被销毁。

线程总数量最大值=核心线程数+非核心线程数

任务队列可以存放100个任务,此时为空,线程池里有10个核心线程,若突然来了10个任务,那么刚好10个核心线程直接处理;若又来了90个任务,此时核心线程来不及处理,那么有80个任务先入队列,再创建核心线程处理任务;若又来了120个任务,此时任务队列已满,不得已,就得创建20个普通线程来处理多余的任务。

[134]进程和线程相比,为什么慢?

1进程系统开销显著大于线程开销;线程需要的系统资源更少。

2进程切换开销比线程大。多进程切换时需要刷新TLB并获取新的地址空间,然后切换硬件上下文和内核栈;多线程切换时只需要切换硬件上下文和内核栈。

3进程通信比线程通信开销大。进程通信需要借助管道、队列、共享内存,需要额外申请空间,通信繁琐;而线程共享进程的内存,如代码段、数据段、扩展段,通信快捷简单,同步开销更小。

[135]Linux零拷贝的原理?

什么是零拷贝:「零拷贝」描述的是计算机操作系统当中,CPU不执行将数据从一个内存区域,拷贝到另外一个内存区域的任务。通过网络传输文件时,这样通常可以节省 CPU 周期和内存带宽。

零拷贝的好处:(1)节省了 CPU 周期,空出的 CPU 可以完成更多其他的任务(2)减少了内存区域之间数据拷贝,节省内存带宽(3)减少用户态和内核态之间数据拷贝,提升数据传输效率(4)应用零拷贝技术,减少用户态和内核态之间的上下文切换

零拷贝原理:(用户态和内核态之间没有拷贝,内核态和硬件发生拷贝)

Linux 提供了 sendfile() 用来减少我们的数据拷贝和上下文切换次数。

a. 发起 sendfile() 系统调用,操作系统由用户态空间切换到内核态空间(第一次上下文切换)b. 通过 DMA 引擎将数据从磁盘拷贝到内核态空间的输入的 socket 缓冲区中(第一次拷贝)c. 将数据从内核空间拷贝到与之关联的 socket 缓冲区(第二次拷贝)d. 将 socket 缓冲区的数据拷贝到协议引擎中(第三次拷贝)e. sendfile() 系统调用结束,操作系统由用户态空间切换到内核态空间(第二次上下文切换)根据以上过程,一共有 2 次的上下文切换,3 次的 I/O 拷贝。我们看到从用户空间到内核空间并没有出现数据拷贝,从操作系统角度来看,这个就是零拷贝。内核空间出现了复制的原因: 通常的硬件在通过DMA访问时期望的是连续的内存空间。

[136]多进程多线程和IO复用区别

I/O的多路复用定义:单个线程通过记录、跟踪每一个I/O流的状态来同时管理多个I/O流。

当有多个并发连接请求时,多线程或者多进程模型需要为每个连接创建一个线程或者进程,而这些进程或者线程中大部分是被阻塞起来的(受cpu个数限制)

使用I/O多路复用时,处理多个连接只需要1个线程监控就绪状态,对就绪的每个连接开一个线程处理(由线程池支持)就可以了,这样需要的线程数大大减少,减少了内存开销和上下文切换的CPU开销。

[137]同步异步阻塞非阻塞

同步和异步:描述用户线程与内核的交互方式。(同步:用户线程发起I/O请求后需要等待或轮询内核I/O操作完成后才能继续执行。异步:用户线程发起I/O请求后继续执行,当内核I/O操作完成则会通知用户线程,或调用用户注册的回调函数。)

阻塞和非阻塞:描述用户线程调用内核I/O操作的方式。(阻塞:I/O操作在没有接收完数据或者没有得到结果之前不返回,需要彻底完成后才返回到用户空间。非阻塞:I/O操作被调用后立即返回给用户一个状态值,无需等到IO操作彻底完成。)

[138]简述epoll和select的区别,epoll为什么高效区别:

(1)每次调用select,都需要把fd集合从用户态拷贝到内核态,这个开销在fd很多时会很大;而epoll保证了每个fd在整个过程中只会拷贝一次。(2)每次调用select都需要在内核遍历传递进来的所有fd;而epoll只需要轮询一次fd集合,同时查看就绪链表中有没有就绪的fd就可以了。(3)select支持的文件描述符数量太小了,默认是1024;而epoll没有这个限制,它所支持的fd上限是最大可以打开文件的数目,这个数字一般远大于2048。

epoll为什么高效:其他两个需要拷贝、轮询(1)select,poll实现需要自己不断轮询所有fd集合,直到设备就绪,期间可能要睡眠和唤醒多次交替。而epoll只要判断一下就绪链表是否为空就行了,这节省了大量的CPU时间。(2)select,poll每次调用都要把fd集合从用户态往内核态拷贝一次,并且要把当前进程往设备等待队列中挂一次,而epoll只要一次拷贝,而且把当前进程往等待队列上挂也只挂一次,这也能节省不少的开销。

[139]同步/异步io,同步异步区别在哪⾥根据系统IO操作的就绪状态分为阻塞和非阻塞;

根据应用程序和内核的交互方式分为同步和异步,其中同步才区分阻塞和非阻塞,异步则一定是非阻塞

同步IO和异步IO的区别就在于: 数据拷贝的时候进程是否阻塞

阻塞IO和非阻塞IO的区别就在于: 应用程序的调用是否立即返回

同步:指用户线程发起IO请求后需要等待或者轮询内核IO操作完成后才能继续执行异步:指用户线程发起IO请求后仍继续执行,当内核IO操作完成后会通知用户线程或者调用用户线程注册的回调函数阻塞:指IO操作需要彻底完成后才返回到用户空间,如果不就绪就一直等待非阻塞:指IO操作被调用后立即返回给用户一个状态值,无需等待IO操作彻底完成,不管就不就绪,都立即返回同步,就是在发出一个功能调用时,在没有得到结果之前,该调用就不返回。也就是必须一件一件事做,等前一件做完了才能做下一件事。对于同步调用来说,很多时候当前线程还是激活的,只是从逻辑上当前函数没有返回,它还会抢占cpu去执行其他逻辑,也会主动检测io是否准备好

异步过程调用发出后,调用者不能立刻得到结果。实际处理这个调用的部件在完成后,通过状态、通知和回调来通知调用者。

阻塞是指调用结果返回之前,当前线程会被挂起(线程进入非可执行状态,在这个状态下,cpu不会给线程分配时间片,即线程暂停运行)。函数只有在得到结果之后才会返回。

非阻塞指在不能立刻得到结果之前,该函数不会阻塞当前线程,而会立刻返回

  1. 同步,就是我调用一个功能,该功能没有结束前,我死等结果。
  2. 异步,就是我调用一个功能,不需要知道该功能结果,该功能有结果后通知我(回调通知)。
  3. 阻塞,就是调用我(函数),我(函数)没有接收完数据或者没有得到结果之前,我不会返回。
  4. 非阻塞,就是调用我(函数),我(函数)立即返回,通过select通知调用者

这四种在描述的时候以用户线程描述,不要加主线程子线程这类型的

[140]多路IO复用技术有哪些,区别是什么?

select,poll,epoll都是IO多路复用的机制,I/O多路复用就是通过一种机制,可以监视多个文件描述符,一旦某个文件描述符就绪(一般是读就绪或者写就绪),能够通知应用程序进行相应的读写操作。区别:(1)poll与select不同,通过一个pollfd数组向内核传递需要关注的事件,故没有描述符个数的限制,pollfd中的events字段和revents分别用于标示关注的事件和发生的事件,故pollfd数组只需要被初始化一次(2)select,poll实现需要自己不断轮询所有fd集合,直到设备就绪,期间可能要睡眠和唤醒多次交替。而epoll只要判断一下就绪链表是否为空就行了,这节省了大量的CPU时间。(3)select,poll每次调用都要把fd集合从用户态往内核态拷贝一次,并且要把当前进程往设备等待队列中挂一次,而epoll只要一次拷贝,而且把当前进程往等待队列上挂也只挂一次,这也能节省不少的开销。

[续]C++岗位求职面试八股文第三十七篇(操作系统)

更多关于算法题解、软件开发面经、机器学习算法面经、各企业面试问题记录,关注Fintech砖,持续更新中。https://www.nowcoder.com/users/873777317

企业面试记录专栏https://www.nowcoder.com/creation/manager/columnDetail/0YBWnm

机器学习面经专栏https://www.nowcoder.com/creation/manager/columnDetail/j8nNy0

软件开发面经专栏https://www.nowcoder.com/creation/manager/columnDetail/0aXKaM

更多校园招聘常见面试问题(开发、算法、编程题目)参见CSDN博客:http://t.csdn.cn/V4qbH

欢迎关注、收藏、点赞后进行问题咨询及秋招建议

#晒一晒我的offer##牛客在线求职答疑中心##牛客解忧铺##软件开发薪资爆料##我的实习求职记录#
软件开发八股面经 文章被收录于专栏

包含C++、操作系统、数据库、计算机组成、计算机网络、设计模式、操作系统、牛客网服务器项目、综合智力题等

全部评论

相关推荐

dongsheng66:如果想进大厂的话,在校经历没必要占这么大篇幅,可以把专业技能单独放一个专栏写,可以加个项目经历
点赞 评论 收藏
分享
Yushuu:你的确很厉害,但是有一个小问题:谁问你了?我的意思是,谁在意?我告诉你,根本没人问你,在我们之中0人问了你,我把所有问你的人都请来 party 了,到场人数是0个人,誰问你了?WHO ASKED?谁问汝矣?誰があなたに聞きましたか?누가 물어봤어?我爬上了珠穆朗玛峰也没找到谁问你了,我刚刚潜入了世界上最大的射电望远镜也没开到那个问你的人的盒,在找到谁问你之前我连癌症的解药都发明了出来,我开了最大距离渲染也没找到谁问你了我活在这个被辐射蹂躏了多年的破碎世界的坟墓里目睹全球核战争把人类文明毁灭也没见到谁问你了😆
点赞 评论 收藏
分享
3 34 评论
分享
牛客网
牛客企业服务