6.12 操作系统面试题 进程管理
用户态和内核态的区别?
主要区别在于权限和可执行的操作
-
内核态:CPU可以执行所有的指令和访问所有的硬件资源。内存管理、进程管理、设备驱动程序管理、系统调用等。
-
用户态:CPU只能执行部分指令集,无法直接访问硬件资源。
-
安全性:避免恶意程序对系统资源进行破坏
-
稳定性:用户态程序出问题不会影响系统
-
隔离性:使得操作系统内核与用户程序之间有了明确的边界,有利于系统的模块化和维护。
线程、进程和协程的区别是什么?
- 进程:进程是操作系统资源分配的基本单位,有独立的代码和数据空间(程序上下文),程序之间的切换会有较大的开销;进程中的子进程崩溃,并不会影响其他进程。系统在运行的时候会为每个进程分配不同的内存空间;进程间通信需要通过特定的机制,如管道、消息队列、信号量等。稳定性、安全性较高,上下文切换开销大。
- 线程:线程是任务调度和执行的基本单位,每个线程都有自己独立的运行栈和程序计数器(PC),线程之间切换的开销小。某个线程如果崩溃了,可能会导致整个进程都崩溃。除了CPU外,系统不会为线程分配内存(线程所使用的资源来自其所属进程的资源),线程组之间只能共享资源。存在数据竞争和线程安全的问题,需要通过同步和互斥机制来解决。
- 协程:一种用户态的轻量级线程,其调度完全由用户程序控制,而不需要内核的参与。拥有自己的寄存器上下文和栈,但与其他协程共享堆内存。协程需要程序员显式地进行调度和管理,相对于线程和进程来说,其编程模型更为复杂。
#为什么进程崩溃不会对其他进程产生很大影响
你说到进程是分配资源的基本单位,那么这个资源指的是什么?
CPU 时间、内存、I/O 设备、文件句柄、网络资源等多种资源的分配与管理。
讲下为什么进程之下还要设计线程?
多线程比单线程的优势,劣势?
- 优势:提高程序的运行效率,可以充分利用多核处理器的资源,同时处理多个任务,加快程序的执行速度。
- 劣势:存在多线程数据竞争访问的问题,需要通过锁机制来保证线程安全,增加了加锁的开销,并且还会有死锁的风险。多线程会消耗更多系统资源,如CPU和内存,因为每个线程都需要占用一定的内存和处理时间。
多线程是不是越多越好,太多会有什么问题?
不一定越多越好
线程的创建和切换会消耗系统资源,包括内存和CPU。如果创建太多线程,会占用大量的系统资源,导致系统负载过高,某个线程崩溃后,可能会导致进程崩溃。
过多的线程可能会导致竞争条件和死锁。竞争条件指的是多个线程同时访问和修改共享资源,如果没有合适的同步机制,可能会导致数据不一致或错误的结果。
进程切换和线程切换的区别?
进程切换涉及到更多的内容,包括整个进程的地址空间、全局变量、文件描述符等。
线程切换只涉及到线程的堆栈、寄存器和程序计数器等,不涉及进程级别的资源。
线程切换详细过程是怎么样的?上下文保存在哪里?
进程的状态(五种状态),如何切换?
- 运行状态 -> 就绪状态:处于运行状态的进程在运行过程中,由于分配给它的运行时间片用完,操作系统会把该进程变为就绪态,接着从就绪态选中另外一个进程运行;
- 运行状态 -> 阻塞状态:当进程请求某个事件且必须等待时,例如请求 I/O 事件;
- 阻塞状态 -> 就绪状态:当进程要等待的事件完成时,它从阻塞状态变到就绪状态;
进程上下文有哪些?
任务是交给 CPU 运行的,那么在每个任务运行前,CPU 需要知道任务从哪里加载,又从哪里开始运行。
操作系统需要事先帮 CPU 设置好 CPU 寄存器和程序计数器。
CPU 寄存器是 CPU 内部一个容量小,但是速度极快的内存(缓存)。
程序计数器则是用来存储 CPU 正在执行的指令位置、或者即将执行的下一条指令位置。
CPU 上下文切换就是先把前一个任务的 CPU 上下文(CPU 寄存器和程序计数器)保存起来,然后加载新任务的上下文到这些寄存器和程序计数器,最后再跳转到程序计数器所指的新位置。
所谓的「任务」,主要包含进程、线程和中断。所以,可以根据任务的不同,把 CPU 上下文切换分成:进程上下文切换、线程上下文切换和中断上下文切换。
进程的上下文切换不仅包含了虚拟内存、栈、全局变量等用户空间的资源,还包括了内核堆栈、寄存器等内核空间的资源。
进程间通讯有哪些方式?
- 管道:通信的数据是无格式的流并且大小受限,通信的方式是单向的。匿名管道是只能用于存在父子关系的进程间通信。进程写入的数据都是缓存在内核中,另一个进程读取数据时候自然也是从内核中获取,同时通信数据都遵循先进先出原则。
- 消息队列:每次数据的写入和读取都需要经过用户态与内核态之间的拷贝过程。
- 共享内存:直接分配一个共享空间,每个进程都可以直接访问。多进程竞争同个共享资源会造成数据的错乱。
- 信号:三种方式响应信号 1. 执行默认操作、2. 捕捉信号、3. 忽略信号。
- 信号量:信号量不仅可以实现访问的互斥性,还可以实现进程间的同步,PV操作
- socket:要与不同主机的进程间通信,那么就需要 Socket 通信了。TCP UDP
共享内存怎么实现的?
共享内存的机制,就是拿出一块虚拟地址空间来,映射到相同的物理内存中。
线程间通讯有什么方式?
- 互斥锁
- 条件变量:一个线程等待"条件变量的条件成立"而挂起;另一个线程使“条件成立”。为了防止竞争,条件变量的使用总是和一个互斥锁结合在一起。线程在改变条件状态前必须首先锁住互斥量。
- 自旋锁:自旋锁通过 CPU 提供的 CAS 函数(Compare And Swap),在「用户态」完成加锁和解锁操作,不会主动产生线程上下文切换,所以相比互斥锁来说,会快一些,开销也小一些。第一步,查看锁的状态,如果锁是空闲的,则执行第二步;第二步,将锁设置为当前线程持有;使用自旋锁的时候,当发生多线程竞争锁的情况,加锁失败的线程会「忙等待」,直到它拿到锁。原子指令,这样就保证了这两个步骤是不可分割的。
- 信号量:信号量表示资源的数量,两个原子操作的系统调用函数来控制信号量的PV
- 读写锁:读写锁适用于能明确区分读操作和写操作的场景,读写锁在读多写少的场景,能发挥出优势。
除了互斥锁你还知道什么锁?分别应用于什么场景?
进程调度算法有哪些?
- 先来先服务(First Come First Severd, FCFS)
- 最短作业优先(Shortest Job First, SJF)
- 高响应比优先 (Highest Response Ratio Next, HRRN)
- 时间片轮转(Round Robin, RR)
- 最高优先级(Highest Priority First,HPF)
- 多级反馈队列(Multilevel Feedback Queue)
兼顾了长短作业,同时有较好的响应时间。