【34】C++岗位求职面试八股文第三十三篇(操作系统)
系列文章目录
第一篇:语言基础
第二篇:设计模式
第三篇:数据库
第四篇:计算机网络
第五篇:操作系统
第六篇:LInux
第七篇:数据结构
第八篇:智力题
[81]内存池
内存池(Memory Pool)是一种内存分配方式,通常我们习惯直接使用new、malloc等API申请内存,这样做的缺点在于所申请内存块的大小不定,当频繁使用时会造成大量的内存碎片并进而降低性能
[82]说说Linux的fork的作用
fork函数用来创建一个子进程。对于父进程,fork()函数返回新创建的子进程的PID。对于子进程,fork()函数调用成功会返回0。如果创建出错,fork()函数返回-1。
fork()函数创建一个新进程后,会为这个新进程分配进程空间,将父进程的进程空间中的内容复制到子进程的进程空间中,包括父进程的数据段和堆栈段,并且和父进程共享代码段。这时候,子进程和父进程一模一样,都接受系统的调度。
写时拷贝在fork之后两个进程用的是相同的物理空间(内存区),子进程的代码段、数据段、堆栈都是指向父进程的物理空间,也就是说,两者的虚拟空间不同,但其对应的物理空间是同一个。当父子进程中有更改相应段的行为发生时,再为子进程相应的段分配物理空间,如果不是因为exec,内核会给子进程的数据段、堆栈段分配相应的物理空间(至此两者有各自的进程空间,互不影响),而代码段继续共享父进程的物理空间(两者的代码完全相同)。而如果是因为exec,由于两者执行的代码不同,子进程的代码段也会分配单独的物理空间。
子进程和父进程只共享代码段,父子进程并不共享栈、数据段、堆存储空间,子进程(栈、数据段、堆存储空间)虚拟内存到物理内存映射空间分配是在写时拷贝。

[83]说说什么是孤儿进程,什么是僵尸进程,如何解决僵尸进程
孤儿进程:是指一个父进程退出后,而它的一个或多个子进程还在运行,那么这些子进程将成为孤儿进程。孤儿进程将被init进程(进程号为1)所收养,并且由init进程对它们完整状态收集工作。僵尸进程:是指一个进程使用fork函数创建子进程,如果子进程退出,而父进程并没有调用wait()或者waitpid()系统调用取得子进程的终止状态,那么子进程的进程描述符仍然保存在系统中,占用系统资源,这种进程称为僵尸进程。如何解决僵尸进程:1.在fork子进程之后我们都要及时使用wait系统调用;2.子进程退出的时候,内核都会给父进程一个SIGCHLD信号,所以我们可以建立一个捕获SIGCHLD信号的信号处理函数,在函数体中调用wait(或waitpid),就可以清理退出的子进程以达到防止僵尸进程的目的。3. 结束其父进程 使用kill命令。 kill -s SIGCHLD pid(父进程pid)
[84]说说什么是守护进程,如何实现?
守护进程:守护进程是运行在后台的一种生存期长的特殊进程。它独立于控制终端,处理一些系统级别任务。web服务器进程http⼀般采⽤以d结尾的名字,特殊的孤⼉进程如何实现:(1)fork创建子进程,终止父进程。(2)调用setsid() 创建一个新会话,脱离父进程影响。(3)将当前目录更改为根目录。使用fork() 创建的子进程也继承了父进程的当前工作目录。(4)重设文件权限掩码。文件权限掩码是指屏蔽掉文件权限中的对应位。(5)关闭不再需要的文件描述符。子进程从父进程继承打开的文件描述符。
Linux内核是不区分进程和线程的, 只在⽤户层⾯上进⾏区分。所以,线程所有操作函数 pthread_* 是库函数,⽽⾮系统调⽤。
[85]系统调用与库函数区别:库函数是对系统调用的封装
系统调用:操作系统为用户提供了一系列接口,这些接口提供了对硬件设备的操作。举个例子我们用printf想终端打印hello world,程序中调用printf,而printf实际上调用的是write,从而打印信息到终端。库函数:库函数是对系统调用的封装。系统调用作为内核提供给用户的接口,它执行的效率是比较高效和精简的,但有时候我们需要对获取的信息进行一些处理,我们把这些处理过程封装起来提供给程序员,有利于编码。库函数有可能包含一个系统调用,有可能包含几个系统调用,也有可能不包含系统调用,一些简单的操作就涉及到内核的功能。系统调用的意义:安全方便
- 避免了用户直接对底层硬件的编程。比如像终端打印信息,终端对系统来说是硬件资源,如果没有系统调用,用户则需要编写终端设备驱动的代码,以及控制终端如何显示的代码
- 隐藏背后的技术细节:使用write系统调用,用户则不用关系数据在磁盘的那个磁道的那个扇区,以及数据要加载到内存的什么位置。
- 保证系统的安全性和稳定性:避免了用户直接对内核空间的操作,避免了安全隐患。
- 方便程序的编程:大家都使用一个接口,移植起来就很方便,如果是自己写自己的,移植性会不好。
系统调用和库函数的比较(以下前提是库函数中没有使用系统调用)
- 所有c函数库是相同的,但是不同操作系统的系统调用则不相同
- 函数库调用是调用函数库中的程序,而系统调用调用的是内核的服务
- 库函数的调用是在用户空间执行,而系统调用则是在内核空间执行
- 函数库调用属于过程调用,开销较小,而系统调用需要进行用户态和内核态的上下文切换,开销较大
[86]多进程与多线程区别与适用场景
多进程优点:1、每个进程互相独立,不影响主程序的稳定性,子进程崩溃没关系;2、通过增加CPU,就可以容易扩充性能;3、可以尽量减少线程加锁/解锁的影响,极大提高性能4、每个子进程都有2GB地址空间和相关资源,总体能够达到的性能上限非常大。多进程缺点:1、逻辑控制复杂,需要和主程序交互;2、需要跨进程边界,如果有大数据量传送,就不太好,适合小数据量传送、密集运算 多进程调度开销比较大;3、最好是多进程和多线程结合,即根据实际的需要,每个CPU开启一个子进程,这个子进程开启多线程可以为若干同类型的数据进行处理。当然你也可以利用多线程+多CPU+轮询方式来解决问题……
多线程的优点:1、无需跨进程边界;2、程序逻辑和控制方式简单;3、所有线程可以直接共享内存和变量等;4、线程方式消耗的总资源比进程方式好。多线程缺点:1、每个线程与主程序共用地址空间,受限于2GB地址空间;2、线程之间的同步和加锁控制比较麻烦;3、一个线程的崩溃可能影响到整个程序的稳定性;4、到达一定的线程数程度后,即使再增加CPU也无法提高性能,例如Windows Server 2003,大约是1500个左右的线程数就快到极限了(线程堆栈设定为1M),如果设定线程堆栈为2M,还达不到1500个线程总数;适用场景:频繁修改:需要频繁创建和销毁的优先使用多线程计算量:需要大量计算的优先使用多线程 因为需要消耗大量CPU资源且切换频繁,所以多线程好一点相关性:任务间相关性比较强的用多线程,相关性比较弱的用多进程。因为线程之间的数据共享和同步比较简单。多分布:可能要扩展到多机分布的用多进程,多核分布的用多线程。
线程切换也会导致上下文切换(因为线程函数在代码区,系统调用在内核态)
[87]三种线程的实现
用户线程、内核线程、轻量级线程LWP用户线程:⽤户空间实现的线程,由基于⽤户态的线程库管理优点: 1. 管理不需要内核直接参与; 2. ⽤户线程切换由线程库调度,不需要⽤户态与内核态之间转换。缺点: 1. ⼀旦⽤户线程发起系统调⽤⽽阻塞;其他线程无法执行 2. ⼀旦某个⽤户线程正在运⾏,只有当其交出CPU执⾏权,其他⽤户线程才可以运⾏,⽆法被打断, 3. ⽤户线程的创 建、终⽌、同步、调度等都不是由操作系统直接参与。
内核线程:由操作系统管理、调度,其TCB是存放在内核中。⼀般由操作系统事先创建内核线程集(类似 于线程池),数量ᰁ有限。优点: 1. 当⼀个内核线程发起系统调⽤阻塞时不会影响其它内核线程的执⾏;缺点: 1. 需要由内核来维护内核线程的上下⽂信息及运⾏状态等,占⽤内核资源; 2. 内核线程创建、终⽌、切换都是在内核中进⾏,开销⽐较⼤轻量级线程 LWP: 内核⽀持的⽤户线程,每个LWP都需要⼀个内核线程的⽀持(CPU资源分配、调度),实际上⽤户线程是运⾏在LWP上 的(本质是用户线程,受内核控制)
内核线程切换需要内核态与用户态切换;而用户线程不需要。
[88]进程与线程的关系
1.进程是资源分配的基本单位,线程是CPU调度和分派的基本单位
2.线程是进程的一部分,一个线程只能属于一个进程,一个进程可以有多个线程,但至少有一个线程
3.每个进程都有独立的代码和数据空间(程序上下文),程序间的切换开销大,线程可看做轻量级的进程,同一类线程共享代码和数据空间,每个线程都有自己独立的运行栈和程序计数器(PC),寄存器,线程间切换开销小
4.在操作系统中能同时运行多个进程(程序)在同一个进程(程序)中多个线程同时执行(通过CPU调度,在每个时间片中只有一个线程执行)同一个进程中的线程无法实现并行,线程是串行的
5.系统在运行的时候会为每个进程分配不同的内存空间线程除了CPU外,系统不会为线程分配内存(线程所使用的资源来自其所属进程的资源),线程组之间只能共享资源
6.没有现成的进程可以看做单线程的,如果一个进程内有多个线程,则执行过程不是一条线的,维斯多条线(线程)共同完成线程是进程的一部分,故线程被称为轻权进程/轻量级进程
[89]线程的优缺点
优点: 1. 提⾼程序并发性 2. 开销⼩ 3. 数据通信、共享数据⽅便缺点: 1. 库函数,不稳定 2. 调试、编写困难3. 对信号⽀持不好
[90]线程如何减少开销
- 线程创建快,进程创建需要资源管理信息,⽐如内存管理信息和⽂件管理信息,⽽线程创 建后是共享其所属进程的资源管理信息;
- 线程终⽌时间快,需要回收的仅有少ᰁ寄存器和私有的栈区;
- 线程切换快,因为线程切换仅涉及到少ᰁ寄存器和栈区,(指的是用户线程)⽽进程上下⽂切换有CPU寄存器 和程序计数器(CPU上下⽂)、虚拟内存空间、⻚表切换、TLB失效等;
- 线程因为创建时共享了其所述进程绝⼤多数资源,因此天⽣具有很好的线程间通信交互效率。
[91]线程栈地址:
当进程栈地址空间不够⽤时,指定新建线程使⽤由malloc分配的空间作为⾃⼰的栈空间。应避免在多线程引⼊信号机制
[92]多线程优点
1.多线程有共享同⼀地址空间和可⽤数据的能 ⼒,这是多进程没有的。 2.线程⽐进程开销⼩,更容易创建和释放。 3.多个线程是IO密集型时,多线程可以使这些活动彼此᯿叠运⾏,可以加快程序执⾏的速度
[93]任务调度算法:
⾮抢占式:FCFC 先来先服务、SJF短作业优先 (有枪战式和非强占式)抢占式:SRTN最短剩余时间优先时间片轮转、优先级调度、多级反馈队列
[94]页面淘汰算法:
- 最佳算法(OPT算法) 每次选择的淘汰⻚⾯将是以后永不使⽤,或者在最⻓时间内都不再访问的⻚⾯
- 先进先出算法(FIFO算法) 每次淘汰选择在主存中居留时间最⻓(即进⼊最早)的⼀⻚淘汰
- 最近最久未使⽤淘汰算法(Least Recently Used)(LRU算法)看时间
- 最不经常使⽤淘汰算法(LFU算法)淘汰最近应⽤次数最少的⻚;先看次数,再看时间 颠簸:导致系统效率急剧下降的主存和辅存之间的频繁⻚⾯置换现象 缺页率:(缺⻚次数/访问总次数)
[95]说说进程通信的方式有哪些,优缺点,为什么要通信
数据传输、资源共享、通知事件、进程控制进程间通信主要包括管道、系统IPC(包括消息队列、信号量、信号、共享内存,内存映射)、套接字socket
管道:包括无名管道和命名管道,无名管道半双工,只能用于具有亲缘关系的进程直接的通信(父子进程或者兄弟进程),可以看作一种特殊的文件,存在于内核;命名管道可以允许无亲缘关系进程间的通信,存在于硬盘。
系统IPC消息队列:消息的链接表,放在内核中。消息队列独立于发送与接收进程,进程终止时,消息队列及其内容并不会被删除;消息队列可以实现消息的随机查询,可以按照消息的类型读取。
信号量semaphore:是一个计数器,可以用来控制多个进程对共享资源的访问。信号量用于实现进程间的互斥与同步。信号:用于通知接收进程某个事件的发生。内存共享:使多个进程访问同一块内存空间。套接字socket:用于不同主机直接的通信。
优缺点管道:速度慢,容量有限消息队列:容量受到系统限制,且要注意第一次读的时候,要考虑上一次没有读完数据的问题。信号量:不能传递复杂消息,共享内存区:能够很容易控制容量,速度快,最快但要保持同步,比如一个进程在写的时候,另一个进程要注意读写的问题,相当于线程中的线程安全(信号量保证),当然,共享内存区同样可以用作线程间通讯,不过没这个必要,线程间本来就已经共享了一块内存的。
[96]多进程通信

[97]多线程通信
共享内存、管道通信(Linux)、future通信机制
1.共享内存多线程会共享全局变量区,所以可以多个线程去option 这个临界区的XXX;但是通常 共享内存会引发不安全的结果 ==》所以就有了一些保护机制:互斥锁mutex、条件变量cv、原子操作和线程局部存储等。
2.管道通信(Linux)如:int fd[2];pipe(fd);
将int fd[2]置为全局,fd[0]为读端口 另一个为写端口。就可以:一个线程向fd[1] write,一个线程向fd[0] read。
3.future通信机制头文件<future>
std::future 可以和 std::promise配对,形成信道传输data或异常。std::future 可以和 std::packaged_task 配对,形成信道传输data或异常。
基于生产者和消费者模型:(1)std::future 可以和 std::promise配对std::future 是消费者,使用来自生产者的数据;std::promise是生产者,产生数据,并给予消费者。
[98]进程互斥锁
信号量:进程、线程都可以用P(wait)-1 小于等于0阻塞 没资源了V(post)+1 大于0则唤醒 有资源了
互斥:信号量初始为1同步:信号量初始为0

互斥锁:进程、线程都可以用
信号量可实现同步和互斥锁只能实现互斥
盲等待锁:自旋锁,当获取不到锁时,线程就会⼀直 wile 循环,不做任何事情,无等待锁:那当没获取到锁的时候,就把当前线程放⼊到锁的等待队列,然后执⾏调度程序,把 CPU 让给其他线程执⾏
[99]自旋锁互斥锁



线程上下文切换指的是切换线程的寄存器、栈等信息。

[100]生产者消费者问题


[续]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##我的求职思考##实习,投递多份简历没人回复怎么办##互联网没坑了,还能去哪里?##23届找工作求助阵地#包含C++、操作系统、数据库、计算机组成、计算机网络、设计模式、操作系统、牛客网服务器项目、综合智力题等


