大家好,我是阿Q。
就在上一期,结束了对C++方面的相关面试题总结,这么系统的总结也就这么一次了,后边可能再也不会进行这方面的总结了,所以说大家有需要PDF的也可以找我哈。
“面试连环问系列”也出了好几期文章,不知道大家看的时候有没有收获,虽然都是非常基础的一些面试八股文,但还是需要引起大家的重视。现在有多卷自己应该都知道,如果看我这个系列对你有所帮助的话,那就太好了,这就是我做这个系列的价值所在。
近期也在考虑如果把这些总结类的发完之后,这个公众号还能为大家再做些什么,所以在这儿的话,也来听听大家的意见,后面做哪些内容才能不浪费这个公众号哈哈,欢迎后台私信我,我们一起聊聊;如果有更好的想法,我也会采纳,也尽量做好!
跑题了跑题了...
这期部分目录如下:

1、进程和线程的区别?
进程和线程都是操作系统中进行任务调度的基本单位,二者之间的主要区别如下:
资源占用:进程是操作系统资源分配的基本单位,一个进程可以拥有多个线程,而线程是进程中的执行单元,是CPU调度的基本单位。每个线程共享所属进程的资源,如代码段、数据段、打开的文件等。而进程之间互相独立,互不干扰,每个进程有自己独立的资源空间,不同进程之间需要通过IPC(进程间通信)来进行通信和数据共享。
调度和切换:操作系统在调度和分配CPU时,将进程作为基本的调度和分配单位,即进程拥有自己的调度队列。而线程是依附于进程而存在的,一个进程中的多个线程共享进程的时间片和资源,因此在调度和切换时,线程切换比进程切换更快,也更加轻量级。
创建和销毁:进程的创建和销毁比线程更加复杂,创建一个进程需要为其分配资源、建立PCB(进程控制块)、建立内核对象等,而销毁进程需要回收资源、关闭打开的文件等。而线程的创建和销毁相对简单,只需要为其分配线程栈、建立TCB(线程控制块)等即可。
通信和同步:进程之间通过IPC(管道、套接字、消息队列等)进行通信和数据共享,而线程之间可以直接访问同一进程的共享数据区,也可以通过锁机制实现同步。
综上所述,进程和线程在资源占用、调度和切换、创建和销毁、通信和同步等方面有着不同的特点,开发者在实际编程时需要根据具体的情况选择使用进程还是线程来完成任务。
2、协程与线程的区别?
协程和线程都是用于实现多任务的技术,但是它们的实现方式有所不同,具体区别如下:
调度方式不同:线程由操作系统内核进行调度,而协程则是在用户空间中进行调度,不需要切换到内核态。
并发性不同:线程是操作系统调度的最小单位,多个线程可以并行执行;协程则是在单线程内部通过协作式调度实现并发。
内存使用不同:线程是由操作系统内核创建的,需要占用一定的系统资源,而协程则是由用户程序创建,不需要占用额外的系统资源。
上下文切换开销不同:线程在切换时需要保存和恢复所有的寄存器状态和内核堆栈,而协程只需要保存和恢复少量的寄存器状态,开销较小。
编程难度不同:线程的编程难度相对较大,因为多线程之间需要共享资源并进行同步,而协程则是在单线程内部调度,因此编程难度相对较小。
总之,线程是操作系统内核的调度对象,具有独立的系统资源,可以并行执行多个任务;而协程是用户程序的调度对象,不需要占用额外的系统资源,通过协作式调度实现任务之间的切换。
3、并发和并行的区别?
并发和并行都是指同时处理多个任务的方式,但是它们有不同的含义。
并发是指一个处理器同时处理多个任务,这些任务通常是通过在不同的时间间隔内交替进行的,这样在同一时刻可以看到有多个任务在运行。这些任务可以是在同一个程序内的不同线程,也可以是在不同程序之间的交互,例如客户端与服务器之间的通信。
并行是指使用多个处理器同时处理多个任务,这些任务在同一时刻可以看到有多个任务在同时运行。与并发不同的是,并行需要多个处理器或多个计算核心,而并发则可以在单个处理器上执行多个任务。
简单来说,并发是在一个处理器上同时执行多个任务,而并行是在多个处理器或计算核心上同时执行多个任务。
4、进程与线程的切换流程?
进程与线程的切换流程如下:
当前进程或线程执行到阻塞状态(如等待I/O完成)时,触发切换操作。
操作系统内核保存当前进程或线程的上下文(即当前的寄存器值和程序计数器等信息),并将处理器分配给另一个进程或线程。
内核从调度队列中选择另一个进程或线程,并恢复其保存的上下文信息。
处理器开始执行新的进程或线程,从之前保存的状态恢复执行。
在进程切换时,需要将整个进程的上下文信息保存下来,包括进程的虚拟内存、全局变量等,切换时还需要进行内存映射,开销比较大。
在线程切换时,只需要保存当前线程的上下文信息即可,线程共享进程的虚拟内存,切换时不需要进行内存映射,开销较小。
5、为什么虚拟地址空间切换比较耗时?
虚拟地址空间切换的耗时是因为它涉及到了硬件和操作系统的复杂操作。当进程或线程切换时,需要保存当前的程序状态(寄存器值、堆栈指针等)和上下文信息(当前指令位置、程序计数器等)。然后,内核必须选择另一个进程或线程,并将它的状态和上下文信息装入内存,这样才能保证程序能够继续运行。这个过程涉及到多个操作系统的内核和硬件机制,例如上下文切换、内存管理和硬件中断等。
在这个过程中,为了切换到另一个进程或线程,需要保存和恢复大量的状态信息,包括内核上下文和硬件寄存器等。这些操作需要耗费大量的CPU时间和内存带宽,因此切换过程通常是相对比较耗时的。
6、进程间通信方式有哪些?
进程间通信(IPC,Inter-process Communication)指的是在不同进程之间交换信息的机制和方法。常见的进程间通信方式有以下几种:
管道(Pipe):管道是一种半双工的通信方式,只能在具有公共祖先的进程之间使用。管道可以实现进程之间的通信,但只能在父子进程或兄弟进程之间使用,因为管道是单向的,而且只能在具有公共祖先的进程之间使用。
命名管道(Named Pipe):命名管道是一种有名的通信方式,可以实现无关进程之间的通信。它可以在不具有亲缘关系的进程之间传递数据,并且可以实现双向通信。
信号量(Semaphore):信号量是一种计数器,用于控制多个进程对共享资源的访问。它可以用来解决进程间的同步和互斥问题。
信号(Signal):信号是一种软件中断,用于通知进程发生了某个事件。它可以用于进程间的通信和同步。
共享内存(Shared Memory):共享内存是一种高效的进程间通信方式,它可以在多个进程之间共享内存区域,从而实现数据的快速交换。
消息队列(Message Queue):消息队列是一种进程间通信方式,可以实现不同进程之间的异步通信。
套接字(Socket):套接字是一种网络通信方式,可以实现不同主机之间的进程间通信。
每种进程间通信方式都有其优缺点和适用场景,需要根据具体的需求进行选择。
7、进程间同步的方式有哪些?
进程间同步是指在多个进程之间进行数据交换或共享资源的操作时,为了避免出现竞争和冲突,需要采用某种机制保证操作的正确性和一致性。常见的进程间同步方式有以下几种:
信号量:使用信号量作为锁,控制进程对共享资源的访问。当一个进程要访问共享资源时,先检查信号量的值,如果为正,则进程可以访问资源,并将信号量的值减1;否则,进程必须等待,直到信号量的值为正。当一个进程完成访问后,需要将信号量的值加1,以便其他进程可以访问资源。
互斥锁:使用互斥锁保护共享资源,同一时刻只能有一个进程访问资源。当一个进程要访问共享资源时,需要先获得互斥锁,如果锁已经被其他进程持有,则进程需要等待,直到锁被释放为止。当进程完成访问后,需要释放互斥锁,以便其他进程可以访问资源。
条件变量:使用条件变量实现进程间的通信和同步。当一个进程要访问共享资源时,如果发现资源不可用,则进程可以通过条件变量等待,直到资源可用为止。当另一个进程释放资源时,可以通过条件变量通知等待的进程,以便它们可以访问资源。
读写锁:读写锁是一种特殊的锁,可以在多个进程之间共享资源,但是只允许读操作同时进行,写操作必须独占资源。当一个进程要进行读操作时,需要获得读锁,如果没有其他进程持有写锁,则进程可以获得锁并进行读操作;否则,进程需要等待,直到写锁被释放为止。当一个进程要进行写操作时,需要获得写锁,此时必须独占资源,其他进程无法进行读或写操作,直到写锁被释放为止。
信号:进程可以通过信号来通知其他进程发生了某些事件。当一个进程需要通知其他进程时,可以向目标进程发送信号,目标进程可以根据信号进行相应的处理。常见的信号包括中断信号、终止信号、用户自定义信号等。
共享内存:使用共享内存实现进程间的数据共享。多个进程可以共享同一块内存区域,可以通过读写内存区域来进行数据交换。
8、线程同步的方式有哪些?
线程同步的方式有以下几种:
互斥量(Mutex):用于保护共享资源,只有一个线程可以获取到互斥量,其他线程需要等待该线程释放互斥量后才能继续执行。
信号量(Semaphore):用于控制访问一定数量的共享资源,通过计数器实现。
事件(Event):用于线程间的通信,一个线程发起事件后等待其他线程响应该事件。
条件变量(Condition Variable):用于线程间的协作,允许一个线程等待另一个线程满足某个条件。
屏障(Barrier):用于多个线程并发执行时,在特定点将线程阻塞,等待所有线程都达到这个点后再一起继续执行。
读写锁(Reader-Writer Lock):用于在多个线程中共享某些数据,读写锁允许多个线程同时读取共享数据,但只允许一个线程写入共享数据。
在实际的多线程应用中,不同的同步方式有不同的使用场景,需要根据具体情况选择合适的方式。
9、线程的分类?
线程可以分为用户线程和内核线程。
用户线程是由用户空间的线程库(如pthread库)实现的线程,也称为轻量级线程。用户线程的调度和管理由线程库完成,内核对它们一无所知,因此创建、切换和销毁用户线程的开销很小,但是由于不能直接调用系统调用,当用户线程被阻塞时,整个进程就会被阻塞,因此用户线程通常用于不需要频繁阻塞的场合。
内核线程是由操作系统内核实现的线程,也称为重量级线程。内核线程的调度和管理由操作系统完成,可以直接调用系统调用,因此可以处理更加复杂的任务。内核线程的创建、切换和销毁开销较大,但是由于可以使用多核,可以提高系统的并发度和吞吐量。
在实际应用中,用户线程和内核线程的使用是根据具体的情况而定,需要根据应用的特点进行权衡。
10、什么是临界区?怎么解决冲突?
临界区是指一段代码区域,在并发情况下被多个线程访问时,会导致共享数据出现冲突的区域。为了避免并发访问带来的问题,需要采用同步机制来对临界区进行保护。
解决临界区问题的常用方式有以下几种:
互斥锁:利用互斥锁来保护临界区。在进入临界区之前,线程必须先获得互斥锁的锁,进入临界区后执行代码操作,然后释放锁。只有获得锁的线程才能进入临界区执行操作。
读写锁:在多读少写的场景中,采用读写锁可以提高并发效率。读写锁允许多个线程同时读取共享数据,但只允许一个线程写入共享数据。在写入共享数据之前,线程必须获得写锁,进入临界区后执行代码操作,然后释放锁。在读取共享数据之前,线程必须获得读锁,读取完成后释放锁。
条件变量:条件变量是一种线程间的通信机制,用于协调线程的执行。它的使用需要和互斥锁配合。当一个线程进入临界区后,发现条件不满足时,会进入等待状态。此时,它会释放互斥锁并进入等待状态,等待条件变量被其它线程满足。当其它线程满足条件变量后,会通过唤醒等待线程的方式来使其从等待状态返回。
原子操作:原子操作是指不能被中断的操作,可以保证在并发情况下的数据一致性。在需要修改共享数据的场景中,可以使用原子操作来保护临界区。原子操作的执行过程中不会被其它线程中断,保证了线程安全。
11、什么是死锁?死锁产生的条件?
死锁(Deadlock)指的是在多个进程(线程)中,每个进程(线程)由于等待其他进程(线程)释放资源而被阻塞,进而导致整个进程(线程)系统无法前进的一种状态。
死锁产生的条件通常有以下四个必要条件:
互斥条件(Mutual exclusion):一个资源每次只能被一个进程(线程)使用,即在一段时间内只有一个进程(线程)能访问该资源。
请求与保持条件(Hold and wait):一个进程(线程)因请求资源而阻塞时,持有已获得的资源不放。
不剥夺条件(No preemption):一个进程(线程)已经获得的资源,在未使用完之前,不能被剥夺,只能在使用完后自己释放。
环路等待条件(Circular wait):若干进程(线程)之间形成一种头尾相接的循环等待资源关系。
解决死锁的方法有以下几种:
预防死锁:通过破坏死锁产生的四个必要条件之一,来避免死锁的产生。
避免死锁:通过动态地分配资源来避免死锁的产生,需要预知每个进程对资源的最大需求量和系统可用资源数。
检测死锁:通过检测系统中是否存在死锁,以及哪些进程或线程陷入了死锁状态,然后采取相应的措施来解除死锁。
解除死锁:通过剥夺进程或线程的某些资源来解除死锁,以恢复进程或线程的正常执行。
12、进程调度策略有哪几种?
在操作系统中,进程调度是指操作系统通过一定的调度策略来选择下一个需要执行的进程。下面是常见的进程调度策略:
先来先服务调度(First-Come, First-Served,FCFS):按照进程到达的先后顺序进行调度,先到先服务,无法解决短作业等待时间长的问题。
短作业优先调度(Shortest-Job-First,SJF):按照进程需要执行的时间长短进行排序,优先选择执行时间最短的进程,可以减少平均等待时间,但是需要预知每个进程的执行时间。
优先级调度(Priority Scheduling):按照进程的优先级进行调度,高优先级进程先执行,可以根据进程的重要程度进行调度,但是可能会导致低优先级进程长时间等待。
时间片轮转调度(Round-Robin,RR):每个进程被分配一个时间片,当时间片用完时,操作系统会调度下一个进程,并把当前进程加入到队列的末尾,可以保证公平性,但是当时间片过长或过短时,可能会影响进程的响应时间和吞吐量。
多级反馈队列调度(Multilevel Feedback Queue,MLFQ):将进程队列分成多个级别,每个级别都有不同的优先级和时间片大小,根据进程的运行情况动态调整进程的优先级和时间片大小,可以兼顾短进程和长进程的执行,但是需要复杂的算法和参数调整。
13、什么是缓冲区溢出?有什么危害?原因是什么?
缓冲区溢出(Buffer Overflow)是指程序尝试将数据写入超出预先分配的缓冲区的范围之外,导致数据覆盖了相邻的内存空间,可能会导致程序崩溃、数据损坏、系统崩溃、安全漏洞等问题。
缓冲区溢出通常是由于编程错误、缺陷或恶意攻击者利用程序漏洞而引起的。程序在处理输入数据时,如果没有对输入进行充分的检查和验证,就容易发生缓冲区溢出漏洞。攻击者可以通过利用这种漏洞,将有害代码注入程序,执行恶意操作,例如窃取敏感信息、执行未授权的操作或者引起拒绝服务攻击等。
缓冲区溢出是计算机系统中最常见的安全漏洞之一,因此在软件开发过程中,应该采取预防措施,例如输入验证、使用安全的编程语言和库、限制输入大小、使用防御性编程技术等,以减少缓冲区溢出的发生。同时,定期进行安全评估和测试,发现和修复漏洞,也是保障系统安全的重要措施。
14、操作系统的内存管理机制了解过吗?都有哪些?
内存管理是操作系统的重要功能之一,负责管理计算机的物理内存,以提供给应用程序使用。内存管理机制通常包括以下几个方面:
内存分配:操作系统需要负责为应用程序分配内存空间,并记录内存的使用情况。常见的内存分配算法包括首次适应、最佳适应、最坏适应等。
内存保护:操作系统需要保护应用程序不受其他程序或操作系统本身的干扰。内存保护机制包括权限管理、虚拟内存等。
内存映射:内存映射是将文件映射到内存空间的一种技术,使得应用程序可以直接访问文件的内容,而不需要通过文件 I/O 操作。这种技术可以提高程序的执行效率和数据传输速度。
内存回收:当应用程序不再使用某个内存块时,操作系统需要回收这些内存空间,以便重新分配给其他应用程序使用。
虚拟内存:虚拟内存是一种将物理内存和硬盘空间结合使用的技术。操作系统可以将一部分物理内存暂时保存到硬盘上,以便给其他应用程序使用,当应用程序再次需要该内存时,操作系统可以将其重新加载到物理内存中。
以上是操作系统内存管理的一些常见机制,不同操作系统实现可能会有所不同。这些机制可以提高计算机系统的内存利用率、执行效率和数据传输速度,同时也可以提高计算机系统的安全性和稳定性。
15、进程有哪些状态?
进程是计算机系统中的一个重要概念,可以理解为正在运行的程序的实例。在操作系统中,进程可以处于以下几种状态:
新建状态(New):当操作系统创建一个新进程时,进程处于新建状态。
就绪状态(Ready):当进程已经准备好执行,等待系统分配处理器资源时,进程处于就绪状态。
运行状态(Running):当操作系统分配处理器资源并开始执行进程时,进程处于运行状态。
阻塞状态(Blocked):当进程需要等待某些事件发生时,例如等待 I/O 操作完成或等待某个信号,进程会进入阻塞状态,直到事件发生才会被重新调度。
结束状态(Terminated):当进程完成其任务或被操作系统终止时,进程处于结束状态。
这些状态描述了一个进程在其生命周期中可能经历的状态变化。操作系统通过对进程状态的管理和调度,使得多个进程可以共享计算机资源,实现多任务操作系统的功能。
16、你能说说什么是分页和分段吗?都有哪些区别?
分页是将物理内存划分成固定大小的页面(Page),将逻辑地址空间划分成相同大小的页(Page)并映射到物理内存中。通过这种方式,可以将逻辑地址空间与物理内存空间分离,使得操作系统可以更加灵活地管理内存。在分页机制中,操作系统将内存划分成相同大小的页面,通常是4KB或者8KB。当应用程序访问某个内存地址时,操作系统会将该地址转换为对应的物理地址,然后访问该物理地址对应的内存单元。分页机制的优点是管理简单,适用于内存碎片较多的情况,缺点是由于每个内存块的大小相同,导致了一些浪费。
分段是将逻辑地址空间划分成若干个大小不同的段(Segment),每个段都有自己的逻辑地址空间和长度,并且可以按照应用程序的需要进行分配和释放。分段机制可以更好地反映应用程序的逻辑结构,使得内存使用更加高效。在分段机制中,每个段都有自己的基地址和长度,当应用程序访问某个地址时,操作系统会将该地址转换为对应的物理地址,然后访问该物理地址对应的内存单元。分段机制的优点是更加灵活,适用于内存碎片较少的情况,缺点是管理复杂,容易产生外部碎片。
分页和分段的主要区别在于内存管理的单位不同。分页是按照固定大小的页面进行管理,而分段是按照应用程序的逻辑结构进行管理。分页可以更好地控制内存使用,而分段可以更好地反映应用程序的逻辑结构。实际上,现代操作系统通常会将分页和分段结合起来使用,以充分发挥两种机制的优点。
17、什么是交换空间?
交换空间(Swap Space),也叫交换文件(Swap File),是指计算机硬盘中专门用于存放被操作系统交换出来的内存数据的空间。当计算机的物理内存不足时,操作系统会将一部分暂时不需要的内存数据(如进程占用的内存块)写入到交换空间中,以便释放物理内存供其他进程使用。
交换空间的作用是为了扩展物理内存容量,使得操作系统能够运行更多的进程。当物理内存不足时,操作系统会将一部分内存数据暂时写入交换空间中,直到需要时再从交换空间中读取数据回到物理内存中。在实际应用中,交换空间的大小通常是物理内存大小的两倍或三倍,以确保系统能够正常运行。
尽管交换空间可以扩展物理内存容量,但是过多的交换空间使用也会导致系统性能下降,因为硬盘访问速度远慢于内存访问速度。因此,在设置交换空间时需要权衡物理内存的容量和硬盘空间的使用情况,以达到最佳的系统性能和资源利用效率。
18、硬链接和软链接有什么区别?
硬链接和软链接是文件系统中两种常见的链接方式,它们的主要区别在于:
硬链接(Hard Link)是指在同一个文件系统内,通过建立一个新的目录项(也就是另一个文件名),将该文件的文件名和 inode(文件的唯一标识符)都指向同一个物理文件块,使得这个文件有了多个文件名,这些文件名指向同一个物理文件。当删除某个硬链接时,只是删除了目录项,而不会影响其他的硬链接和文件本身。因为多个文件名都指向同一个物理文件,所以修改其中任意一个文件名所代表的文件内容,其他文件名所代表的文件内容也会跟着修改。
软链接(Symbolic Link),也称为符号链接,是指在文件系统中建立一个新的文件,这个文件实际上只是一个指向另一个文件的指针,类似于快捷方式。软链接的文件名和 inode 号不同于被链接文件,它只是包含了指向被链接文件的路径信息。软链接可以跨越不同的文件系统,因此即使被链接的文件被删除,软链接仍然存在,但是指向的文件不存在了。
总的来说,硬链接创建的链接文件名和被链接的原始文件名的 inode 号是相同的,而软链接则是创建了一个新的文件,这个文件只包含指向被链接文件的路径信息。因此,硬链接不能跨越不同的文件系统,而软链接可以跨越不同的文件系统。另外,删除硬链接并不会删除原始文件,而删除软链接则可能导致被链接的原始文件无法访问。
19、中断的处理过程?
中断是计算机硬件或软件发生某些异常情况时的一种机制,它可以使 CPU 从当前正在执行的程序中断转到处理中断的程序中,以处理特殊事件或错误。
中断的处理过程一般包括以下几个步骤:
中断发生。当计算机硬件或软件发生异常情况时,会向 CPU 发送一个中断请求(Interrupt Request,IRQ)信号,以请求 CPU 执行相应的中断处理程序。
中断响应。CPU 接收到中断请求信号后,会立即停止当前正在执行的程序,并保存相关的寄存器和程序计数器等状态信息,以便稍后能够回到原来的程序继续执行。同时,CPU 会根据中断向量表(Interrupt Vector Table,IVT)中的中断号找到对应的中断处理程序的入口地址,并跳转到该地址开始执行中断处理程序。
中断处理。中断处理程序根据中断类型和具体情况执行相应的操作,如读取设备数据、保存进程状态、打印错误信息等。在中断处理过程中,CPU 会保持特权级别不变,以便能够访问操作系统的内核空间和执行特权指令。
中断结束。中断处理程序执行完毕后,CPU 会恢复保存的状态信息,并根据保存的程序计数器等信息返回到原来的程序继续执行。此时,CPU 会重新进入用户模式,并继续执行原来被中断的程序。
需要注意的是,不同类型的中断处理程序可能具有不同的优先级和响应时间要求。例如,紧急的硬件故障中断可能需要立即响应并处理,而一般的输入输出中断则可以稍后处理。因此,操作系统需要对不同类型的中断进行分类和优先级排序,以便能够高效地响应和处理中断请求。
20、中断和轮询有什么区别?
中断和轮询都是计算机处理输入输出设备的两种基本方式,它们的区别主要在于处理方式和效率上的不同。
中断是一种异步的处理方式,当输入输出设备有数据准备好或者发生异常情况时,设备会向处理器发送中断请求信号,以请求处理器执行相应的中断处理程序。中断处理程序会立即响应,对设备数据进行处理或者处理异常情况。中断处理程序的执行是由硬件中断控制器控制的,处理器不需要不断地检查设备状态,因此具有较低的处理器占用率和较高的响应速度。
轮询是一种同步的处理方式,处理器会不断地查询设备的状态,以确定设备是否有数据准备好或者发生了异常情况。如果设备有数据准备好或者发生了异常情况,处理器会立即对设备数据进行处理或者处理异常情况。轮询的处理方式需要不断地检查设备状态,因此具有较高的处理器占用率和较低的响应速度。
总的来说,中断和轮询都可以用来处理输入输出设备的数据,但中断处理方式具有较高的响应速度和较低的处理器占用率,适合于处理需要实时响应的任务;而轮询处理方式具有较低的响应速度和较高的处理器占用率,适合于处理较为简单的任务和对响应速度要求不高的任务。
21、你能说说孤儿进程,僵尸进程,守护进程吗?
孤儿进程(Orphan Process)
孤儿进程是指其父进程已经终止或者异常退出,而该进程还在运行。孤儿进程由于没有父进程来对其进行管理和回收,因此会被操作系统的init进程接管,成为init进程的子进程,init进程负责对其进行回收和管理。孤儿进程不会对系统造成太大的负担,但会占用系统资源,因此及时回收孤儿进程是良好的进程管理习惯。
僵尸进程(Zombie Process)
僵尸进程是指其已经执行完毕,但其父进程还没有对其进行回收,仍然占用系统资源。僵尸进程对系统造成的负担不大,但如果存在大量僵尸进程,会占用过多的系统资源,导致系统负载过高。操作系统会自动对已经执行完毕的进程进行回收,但如果父进程没有及时对其进行回收,就会产生僵尸进程。
守护进程(Daemon Process)
守护进程是一种在后台运行的进程,通常用于完成一些系统级别的任务,如系统服务的启动和管理、日志文件的维护等。守护进程通常在系统启动时启动,会常驻在内存中并且不会接收终端输入。守护进程不会受到终端关闭、退出等事件的影响,其生命周期通常由操作系统管理。守护进程通常需要以root权限运行,因为它们需要对系统资源进行操作。
总的来说,孤儿进程、僵尸进程和守护进程都是进程的一种状态,它们在操作系统中扮演不同的角色和任务。及时回收孤儿进程和僵尸进程是保持系统稳定和高效运行的必要措施,而守护进程则是完成系统级别任务的重要方式。
22、微内核和宏内核有什么区别?
微内核和宏内核是操作系统内核的两种设计范式,它们有以下区别:
架构设计
宏内核采用集成式的设计思路,将操作系统的所有功能都放在内核中实现,包括进程管理、内存管理、文件系统、网络协议栈等,因此内核体积庞大、复杂度高。而微内核则采用最小化的内核设计思路,只将最基本的功能放在内核中实现,其他功能则通过进程间通信(IPC)的方式在用户空间中实现,从而使得内核体积更小、复杂度更低。
系统稳定性
宏内核由于内核功能过于庞大,所以内核本身的稳定性就显得尤为重要。而微内核将大部分功能放在用户空间中,当某个服务进程崩溃时,只会影响该服务进程本身,不会对整个系统造成灾难性后果,从而提高了整个系统的稳定性。
系统性能
宏内核将大量的功能都实现在内核中,因此系统的性能相对微内核来说要更高一些,特别是在对于频繁的内核调用和对性能要求较高的场景下。而微内核由于采用了进程间通信机制,因此在某些场景下会因为通信的开销而影响系统性能。
系统可定制性
由于微内核只实现了最基本的功能,因此系统的可定制性更强。用户可以根据需要添加、删除或替换服务进程,以满足不同的应用需求。而宏内核的设计思路则限制了系统的可定制性,因为宏内核包含了大量的功能模块,要修改或替换其中的某一个模块通常需要对整个内核进行重新编译和部署。
总的来说,微内核和宏内核是两种不同的操作系统内核设计思路,它们都有自己的优缺点。在实际应用中,应根据具体的场景和需求选择合适的内核设计思路。
23、说一说静态链接库和动态链接库的区别?
静态链接库和动态链接库是两种不同的链接方式,它们的主要区别在于链接时机和占用的内存空间。
静态链接库
静态链接库是指在编译时将库文件中的函数代码和程序代码直接合并到一个可执行文件中,形成一个独立的可执行文件。在运行时,程序将整个可执行文件加载到内存中执行。这种方式的优点是链接后程序可以独立运行,不需要依赖外部库文件,可以保证程序的稳定性和可靠性;缺点是占用的磁盘空间较大,并且每个可执行文件都包含了相同的库代码,导致代码重复浪费。
动态链接库
动态链接库是指在编译时只将库文件的信息和程序代码链接在一起,而不将函数代码合并到可执行文件中,程序在运行时再去加载相应的动态链接库。这种方式的优点是节省了磁盘空间,并且多个程序可以共享同一个动态链接库,减少了代码重复;缺点是在程序运行时需要加载外部库文件,可能会降低程序的运行速度,也可能存在版本兼容性问题。
总的来说,静态链接库适合对可执行文件大小和程序稳定性有较高要求的场景,而动态链接库则适合对程序代码复用和占用空间有较高要求的场景。在实际应用中,应根据具体情况选择合适的链接方式。
24、什么是用户态和内核态?
用户态和内核态是指操作系统在运行进程时的两种不同的权限级别,也称为用户模式和核心模式。
用户态
用户态是指进程运行时的一种低特权级别状态,只能访问部分资源,例如进程自身的内存空间、进程的打开文件、设备等,不能直接访问操作系统内核的资源,例如系统调用、硬件中断等。在用户态运行时,进程只能执行部分指令,不包括特权指令,也无法直接对硬件进行操作。
内核态
内核态是指操作系统运行时的高特权级别状态,可以访问系统的全部资源,包括硬件、设备、内核数据结构等,可以执行特权指令和操作系统服务例程。在内核态运行时,操作系统可以执行任何指令,也可以访问和操作任何资源,包括硬件和内存。
25、用户态和内核态是怎么切换的?
中断切换
当系统发生硬件中断或软件中断时,CPU 会自动将当前正在执行的程序暂停下来,保存当前程序的执行现场,然后转入内核态,执行中断处理程序,处理完毕后再回到用户态继续执行程序。例如,当用户按下键盘或鼠标时,会触发硬件中断,操作系统会暂停正在执行的程序,处理键盘或鼠标事件,然后将控制权返回给程序。
异常切换
当程序运行出现了一些异常情况,例如除数为零、越界访问、内存访问错误等,CPU 会暂停正在执行的程序,转入内核态,执行相应的异常处理程序,处理完毕后再回到用户态继续执行程序。
系统调用切换
当用户程序需要访问内核态的资源时,例如读取文件、发送网络数据等,需要通过系统调用来向操作系统发出请求。系统调用是一种特殊的函数调用,将用户程序从用户态切换到内核态,执行相应的系统调用服务例程,然后再将程序切换回用户态继续执行。例如,用户程序通过系统调用 open() 打开一个文件,内核会为该进程分配文件描述符,然后返回给用户程序,用户程序再通过文件描述符进行文件读写等操作。
总之,用户态和内核态之间的切换需要花费一定的时间和开销,因此在程序设计时应该尽量减少不必要的切换,提高程序的运行效率。
26、什么是内核?
内核是操作系统的核心部分,也称为内核态或系统内核。它是操作系统的最底层部分,负责管理计算机的硬件资源,提供基本的系统服务和功能。内核通常具有以下特点:
系统资源管理:内核负责管理计算机的硬件资源,如CPU、内存、硬盘、网络、输入输出等,为应用程序提供资源分配、调度和访问服务。
安全保障:内核是操作系统的最核心部分,必须保证其安全性和稳定性。内核通常运行在特权模式下,可以对系统资源进行访问控制和保护。
驱动程序:内核包含了各种设备驱动程序,负责控制和管理计算机的硬件设备。
系统调用:内核提供系统调用接口,让应用程序可以访问操作系统的各种服务和资源。
多任务管理:内核负责管理系统的进程和线程,调度和切换任务,使多个任务可以在同一时间共享计算机资源。
总之,内核是操作系统最核心的部分,其设计和实现直接影响着操作系统的性能、安全性和稳定性。不同的操作系统有不同的内核类型和实现方式,例如微内核、宏内核、混合内核等。
27、什么是实时系统?
实时系统是一种特殊的计算机系统,其主要特点是能够对外部事件做出即时响应。实时系统通常需要满足以下条件:
响应时间:实时系统需要在特定时间内对外部事件做出响应,包括硬实时和软实时两种。硬实时要求系统必须在指定时间内完成任务,而软实时则允许在指定时间之后完成任务,但会影响系统性能。
可靠性:实时系统需要保证高度的可靠性和稳定性,任何故障都可能导致系统失效。
可预测性:实时系统需要对任务的执行时间和资源占用进行精确预测,以确保任务能够按时完成。
实时系统通常应用于工业控制、航空航天、军事指挥、医疗设备等领域,这些领域对系统的稳定性和可靠性要求极高。实时系统一般采用特殊的实时操作系统(RTOS),这些操作系统通常具有实时调度器、中断处理机制、任务优先级和信号量等特性,以满足实时系统的需求。
28、Linux操作系统的启动过程?
Linux操作系统的启动过程一般可以分为以下几个步骤:
BIOS/UEFI启动:计算机开机后首先由基本输入输出系统(BIOS)或统一固件接口(UEFI)负责初始化硬件设备和启动自检程序,然后加载位于引导设备(通常为硬盘)首扇区的引导程序(boot loader)。
引导程序加载:引导程序一般是Grub或LILO,其主要作用是在引导设备上查找并加载内核文件。在此过程中,引导程序会读取配置文件(grub.conf或lilo.conf)中的参数,如指定内核文件、根文件系统、启动参数等,并将这些参数传递给内核。
内核加载:引导程序会加载指定的内核文件(vmlinuz或bzImage),并解压缩到内存中。内核负责初始化硬件设备、创建进程、分配内存、加载模块、挂载文件系统等操作,并将控制权转交给init程序。
init进程启动:init进程是用户空间的第一个进程,其主要作用是启动和管理其他进程。init进程会根据配置文件(/etc/inittab)和运行级别(/etc/rc.d)启动相应的服务程序和守护进程,如网络服务、打印服务、登录管理等。
用户登录:一旦系统启动完成,用户可以通过登录界面(如GDM或KDM)输入用户名和密码登录系统。登录后,用户可以使用Shell或其他GUI界面进行操作。
在Linux操作系统启动过程中,BIOS/UEFI负责硬件初始化和自检,引导程序负责加载内核文件,内核负责初始化系统和启动用户空间进程,init进程负责启动和管理其他进程,而用户登录则标志着系统启动完成,可以开始正常使用。
29、使用多线程的好处是什么?
使用多线程有以下几个好处:
提高程序的性能:多线程可以充分利用多核CPU的处理能力,将一个大任务分成多个小任务并行执行,可以大大提高程序的执行效率。
提高程序的响应速度:多线程可以将一些耗时的操作放在后台线程中执行,避免阻塞主线程,从而提高程序的响应速度和用户体验。
改善程序的结构:多线程可以将程序中相关的操作放在同一个线程中执行,使程序的结构更加清晰,易于维护和扩展。
优化资源利用:多线程可以让程序更加高效地利用计算机资源,避免资源的浪费和过度占用。
实现并发处理:多线程可以让程序同时处理多个任务,实现并发处理,从而提高程序的处理效率和吞吐量。
总之,使用多线程可以提高程序的性能、响应速度和可维护性,优化资源利用,实现并发处理,是一种非常有用的编程技术。
30、进程终止的方式?
进程可以通过以下几种方式终止:
正常退出:进程执行完毕并返回退出码,操作系统会自动清理该进程的资源。
异常终止:进程在执行过程中发生了异常,如除零错误、访问非法内存等,导致进程异常终止。
被信号终止:进程接收到一个信号,如SIGTERM、SIGKILL等,操作系统会强制终止该进程。
被其他进程终止:一个进程可以通过调用kill系统调用或者向进程发送信号的方式来终止另一个进程。
退出父进程时被系统终止:子进程是由父进程创建的,如果父进程在子进程终止前退出了,那么子进程将被系统终止。
无论是哪种方式,操作系统都会回收被终止进程的资源,包括进程使用的内存、打开的文件、网络连接等等,以确保系统的稳定性和安全性。
31、你能说说快表和多级页表吗?
快表和多级页表都是用来解决虚拟内存管理中的地址转换问题的技术。
快表(Translation Lookaside Buffer,TLB)是一种硬件缓存,它存储最近被访问的一些页表项,以加快虚拟地址到物理地址的转换速度。当CPU执行一个内存访问操作时,首先在TLB中查找对应的页表项,如果找到了就直接进行地址转换,否则需要访问内存中的页表来查找对应的页表项。快表可以极大地提高虚拟地址到物理地址的转换速度,从而加速系统的运行。
多级页表(Multilevel Page Table)是一种虚拟内存管理技术,将一个大的页表分成多个较小的页表,每个页表中只包含一部分虚拟地址到物理地址的映射关系。例如,在32位系统中,可以将一个32位的虚拟地址分成10位页目录项、10位页表项和12位页内偏移量。当CPU执行一个内存访问操作时,先查找页目录表,找到对应的页表,再查找页表中的页表项,找到对应的物理地址。多级页表可以降低整个页表的大小,减少查找的时间和空间复杂度。
快表和多级页表都是为了加速地址转换和节省内存空间而设计的,它们可以结合使用,以达到更好的性能优化效果。
32、常见的内存管理机制?
常见的内存管理机制有以下几种:
静态分区分配:将内存空间划分为若干固定大小的分区,每个分区只能被一个进程占用,分配时固定分区大小,无法进行动态调整。优点是简单易懂,缺点是浪费内存空间和资源。
动态分区分配:将内存空间分成若干可变大小的分区,当进程请求内存时,根据分配算法为其分配合适的内存空间。动态分区分配可以高效利用内存资源,但需要考虑内存碎片问题,即空闲内存不连续,难以满足大块内存的申请需求。
页式存储管理:将内存空间划分为固定大小的页面,每个页面大小相同,且与外存中的页面大小相同,可以按需分配和置换,可以有效利用内存空间,但需要进行地址转换,增加了系统开销。
段式存储管理:将进程地址空间分为若干个段,每个段的大小不同,可以动态调整,但需要解决段间的内存碎片问题,以及地址空间的保护问题。
段页式存储管理:结合了段式存储管理和页式存储管理的优点,将进程地址空间分为若干个段,每个段再划分为若干个页面,可以灵活管理进程地址空间,但需要进行段表和页表的管理,增加了系统开销。
不同的内存管理机制适用于不同的场景,可以根据系统需求和性能要求进行选择和优化。
33、CPU 寻址了解吗?为什么需要虚拟地址空间?
CPU 寻址是指 CPU 访问内存时的地址寻址方式。在计算机系统中,CPU 访问内存时需要提供一个内存地址,以便将指令或数据加载到 CPU 中进行处理。不同的 CPU 有不同的寻址方式,例如 x86 CPU 使用的是逻辑地址,ARM CPU 使用的是虚拟地址。
虚拟地址空间是指一个进程所使用的地址空间,包括代码段、数据段、堆、栈等,是进程独立的一部分内存空间。虚拟地址空间的大小可以超出物理内存的大小,使得进程可以使用比物理内存更大的内存空间。虚拟地址空间还可以实现进程的隔离,保证进程之间不会相互干扰。
需要虚拟地址空间的原因有以下几点:
内存地址空间的隔离:不同进程之间的内存地址空间应该是相互隔离的,否则一个进程可以访问另一个进程的内存,导致数据的不安全和系统的不稳定。
内存地址空间的扩展:虚拟地址空间可以扩展到非常大的范围,远远超过物理内存的大小,这样就可以满足一些需要大量内存的应用程序的需求。
内存管理的灵活性:虚拟地址空间可以实现内存的动态分配和回收,以及内存映射等功能,提高了内存的利用率。
进程的隔离性和安全性:虚拟地址空间的隔离性和安全性可以保证进程之间不会互相干扰,同时也可以保证进程内部数据的安全性,防止数据泄露和篡改。
总之,虚拟地址空间是操作系统中非常重要的一个概念,可以实现进程之间的隔离和保护,提高了系统的稳定性和安全性,同时也可以实现内存的高效管理和利用。
34、虚拟内存技术是怎么实现的?
虚拟内存技术是一种将硬盘空间作为虚拟内存使用的技术,可以将物理内存和硬盘空间结合起来,扩展系统可用的内存。实现虚拟内存的关键是将主存和辅存进行有效地管理和协调。
具体实现过程如下:
将物理内存划分成大小相等的物理块,例如 4KB 的物理块。
将进程的地址空间划分成大小相等的虚拟页,例如 4KB 的虚拟页,这些虚拟页被映射到物理内存中。
当进程访问一个虚拟页时,CPU 将虚拟地址转换成物理地址。如果该虚拟页已经在物理内存中,则直接访问该物理页;否则,需要将该虚拟页从磁盘中加载到物理内存中。
当物理内存不足时,系统将某些不经常使用的物理页移动到磁盘上,释放出空间,这个过程叫做页面置换。页面置换的算法包括最优页面置换算法(OPT)、最近未使用页面置换算法(NRU)、先进先出页面置换算法(FIFO)等。
系统还可以采用预调页技术,即在进程访问某个虚拟页之前,将其预先加载到物理内存中,以提高访问速度和性能。
虚拟内存技术实现的优点是可以使得每个进程的地址空间独立,不会相互干扰,而且可以通过页面置换算法将磁盘上的数据调入物理内存中,以满足进程的内存需求。虚拟内存技术也可以为操作系统提供更加灵活的内存管理方式,增强了系统的稳定性和可靠性。同时,虚拟内存技术的实现也带来了一定的开销,例如磁盘读写和页面置换等,需要在效率和性能之间做出权衡。
既然都看完了,那也别忘了我们的约定,如果有好点的想法,一定一定要告诉我,让我再为大家奉献一下自己的绵薄之力。




