32道操作系统高频题整理(附答案背诵版)

谈一谈你对操作系统的理解?

操作系统是一种软件,它是计算机系统中的核心组件,负责管理和协调计算机硬件资源,为应用程序提供运行环境和服务。

操作系统的主要作用包括:

  1. 资源管理:操作系统负责管理计算机的硬件资源,如处理器、内存、硬盘和外部设备等,以便合理地分配和利用这些资源。它通过调度算法和资源分配机制,确保每个任务或进程都能得到适当的资源。

  2. 进程管理:操作系统能同时运行多个程序,通过进程管理,它可以控制程序的执行、调度和协作,以便提高计算机的整体效率。它负责创建、终止、挂起和恢复进程,以及管理进程之间的通信与同步。

  3. 文件管理:操作系统负责管理计算机的文件系统,方便用户存储和获取数据,确保数据的安全性和完整性。它提供了文件的创建、读写、删除和重命名等操作,以及文件的权限管理和保护。

  4. 用户界面:操作系统提供了与计算机交互的用户界面,可以是命令行界面或图形用户界面(GUI),使得用户可以方便地使用计算机。用户可以通过输入指令或点击图标进行操作和访问系统功能。

  5. 错误检测和恢复:操作系统能够监测和处理软件和硬件错误,提供错误检测和恢复的机制,以保证计算机的稳定性和可靠性。它可以监测和捕获程序的异常、处理硬件故障、提供备份和恢复机制等。

操作系统是计算机系统中的大管家,它负责管理和协调计算机的各种资源,为应用程序提供一个安全、高效的运行环境。操作系统的设计和优化对于提高计算机的性能、可靠性和用户体验至关重要。

简单说下你对并发和并行的理解?

当谈到计算机系统中的并发和并行时,它们具有不同的含义。

并发(Concurrency)是指系统能够处理多个任务的能力,这并不意味着这些任务一定会同时进行。并发的任务可能会交错进行,因此并发可以在单核CPU上实现。这是因为CPU可以通过时间片轮转或其他任务切换策略,在各个任务之间快速切换,给人以它们在同时进行的错觉。一个简单的例子就是我们的操作系统,它可以在运行大量应用程序(如我们的浏览器,文档编辑器,音乐播放器等)同时,保持系统稳定和响应,尽管实际上,那些进程并不总是“同时”运行。

而并行(Parallelism)则是指系统同时执行多个任务的能力。并行显然需要硬件的支持,如多核心或多处理器。在这种情况下,多个任务确实可以在同一时间内进行。例如,现代的多核CPU可以让我们在看电影的同时进行视频编码,每一个任务在不同的处理器核心上执行,这就是并行。

总的来说,如果你有两个线程在单核心的CPU上,那么可能会通过交错执行达到并发。如果你的电脑有多个核心或处理器,你就可以在多个核心或处理器上同时执行多个线程,这是并行。

同步和异步有什么区别?

同步和异步是操作系统中的两种重要概念,它们主要涉及到程序的运行方式和时间管理。

  1. 同步(Synchronous)操作是在一个操作完成之前,不进行下一个操作。这是一种阻塞调用,也就是说,进行某项操作的过程中,不得不停下来等待,直到这个操作完成。例如,当你在核对大批量的数据时,你需要等待所有数据都加载完毕才能继续进行下一项操作,这就是同步。

  2. 异步(Asynchronous)操作是不需要立刻得到结果,即使未完成也可进行其它操作。这是一种非阻塞调用,也就是说,还没得到结果,就继续做别的事情,不会因为单一操作的等待而阻塞。例如,你去网上订一张火车票,由于网站服务器繁忙,订票需要一些时间,但是你不会就一直盯着屏幕等,而是可以一边浏览新闻或者查看其他信息一边等待订票结果,这就是异步操作。

这两种方式各有利弊,选择使用同步还是异步,主要取决于具体的需求和场景。

阻塞和非阻塞有什么区别?

阻塞和非阻塞是描述任务或操作在等待结果时的行为方式的概念。

阻塞是指任务在等待某个操作完成时,暂停自己的执行,并等待操作完成后再继续执行。在阻塞状态下,任务会一直等待,直到所需的资源或结果就绪。在此期间,任务不能执行其他操作。例如,当一个线程调用阻塞式IO操作时,它会被挂起,直到IO操作完成后才能继续执行。

非阻塞是指任务在等待某个操作完成时,不会暂停自己的执行,而是立即返回,继续执行其他任务。非阻塞的任务会周期性地查询所需资源或结果的状态,判断是否就绪,从而决定是否继续执行。例如,在进行非阻塞式IO操作时,任务会立即返回,并周期性地检查IO操作的状态,直到IO完成后再处理结果。

简单来说,阻塞是等待结果时暂停自己的执行;非阻塞是等待结果时继续执行其他任务。

在实际应用中,阻塞和非阻塞可以用在不同的场景中。阻塞适用于需要确保结果完整性和依赖顺序的情况,而非阻塞适用于需要提高并发性和响应性的情况。选择适合的阻塞和非阻塞方式可以提高程序的效率和性能。

什么是进程?

在操作系统中,进程是指正在执行的程序实例。它是计算机系统中的基本执行单位,拥有独立的内存空间和系统资源。每个进程都有自己的指令序列、数据和执行环境。

进程的创建是通过操作系统调度和管理的,当一个程序被执行时,操作系统会为其创建一个独立的进程。每个进程都有一个唯一的进程标识符(PID),用于在系统中标识和管理进程。

进程的主要特征包括:

  • 独立性:每个进程都有独立的内存空间和系统资源,不会受其他进程的影响。
  • 执行状态:进程可以处于运行、就绪、阻塞等不同的执行状态,根据进程调度算法决定执行顺序。
  • 上下文切换:由于操作系统需要在不同进程之间进行切换,进程可以通过上下文切换保存和恢复自己的执行环境。
  • 通信与同步:进程可以通过进程间通信机制实现信息的交换和共享资源,也可以通过同步机制实现协调和合作。

进程是计算机系统中的重要概念,操作系统通过进程管理,实现了多任务的并发执行和资源的合理利用。

什么是线程?

在操作系统中,线程是进程的一部分,是进程内的一个执行单元。与进程相比,线程更轻量级,多个线程可以在同一个进程中并发执行。

线程共享进程的内存空间和系统资源,每个线程有独立的程序计数器(PC)和栈空间,但它们可以访问共享的数据和全局变量。

线程的主要特征包括:

  • 并发执行:多个线程可以在不同的处理器或核心上同时执行,从而实现并发性。
  • 共享内存:线程之间共享同一个进程的地址空间,可以互相访问和修改共享数据。
  • 轻量级:相对于进程来说,线程的创建、销毁和切换开销较小,执行效率更高。
  • 协作与通信:线程之间可以通过共享内存进行通信和协作,也可以使用同步机制控制线程的执行顺序。

线程在实现并发编程时非常有用,可以将复杂的任务划分为多个线程并行执行,提高程序的性能和响应性。同时,线程间的通信和协作也更加灵活方便。但在多线程编程中需要注意线程同步和资源竞争的问题,以确保线程的正确执行和数据的一致性。

进程与线程有什么区别?

它们有以下几个主要区别:

  1. 资源占用:
  • 进程:每个进程拥有独立的内存空间和系统资源,如文件描述符、打开的文件等。进程间的通信需要使用进程间通信(IPC)机制。
  • 线程:多个线程共享同一个进程的内存空间和系统资源,线程之间可以通过共享内存进行通信。
  1. 调度和切换:
  • 进程:进程是独立的执行实体,操作系统以进程为单位进行调度,进程的切换开销相对较大。
  • 线程:线程是进程的一部分,线程的调度和切换开销较小,因为它们共享进程的上下文。
  1. 并发性和并行性:
  • 进程:多个进程可以并发执行,每个进程都有自己的地址空间,可以在多个处理器或核心上并行执行。
  • 线程:多个线程可以在同一个进程内并发执行,共享进程的地址空间,可以在同一个处理器或核心上并行执行。
  1. 用户态与内核态:
  • 进程:进程切换涉及到用户态到内核态的切换,需要较高的权限和开销。
  • 线程:线程切换只涉及用户态的切换,开销较小。
  1. 创建和销毁:
  • 进程:创建和销毁进程的开销较大,包括分配独立的内存空间、初始化数据结构等。
  • 线程:创建和销毁线程的开销相对较小,线程依赖于进程的内存和资源完成创建过程。

综上所述,进程是独立的执行实体,拥有独立的内存空间和系统资源;而线程是进程内的执行单元,共享进程的内存空间和系统资源。线程的切换和通信开销较小,并发性更高。选择使用进程还是线程,取决于具体的应用需求。

为什么有了进程,还要有线程呢?

为了回答这个问题,首先让我们明确什么是进程和线程。

  1. 进程:操作系统中运行的每一个程序或应用被称为一个进程。每个进程都有自己的内存空间,CPU时间片以及其他用来运行程序的系统资源。因此,每个进程都独立运行并且与其他进程隔离。

  2. 线程:线程是进程中的执行单元,所有线程在同一进程下共享资源。这些资源包括内存,文件句柄和其他。由于资源共享,所以线程间的通信会比进程间的通信快得多,创建或撤销一个线程也比创建或撤销一个进程来得快。

现在,让我们来看看为什么在有了进程以后,还要引入线程。

  1. 提高系统的并发性能:在单个进程内运行多个线程可以提高系统并行处理能力,使得CPU的利用率更高。

  2. 简化程序设计:当程序需要处理一些异步或并行的任务时,使用线程可以使程序设计变得更简单。例如,在一个文本编辑器中,一个线程用于键盘输入,另一个线程用于屏幕刷新,这样保证了用户的输入和界面的显示可以同时进行。

  3. 资源共享:线程之间可以共享进程资源,在很多场景下这是非常有用的。例如,在Web服务器中,每个用户的请求可能会生成一个线程,所有线程共享服务器的资源,如内存、硬盘等,以处理多个并发的用户请求。

总的来说,线程在提高系统并发性能,简化程序设计,资源共享等方面都有显著的优势,这就是为什么在有了进程之后,我们还需要线程的原因。

进程有哪些常见状态?

在现代操作系统中,进程常常可以处于以下五种状态:

  1. 运行状态(Running):正在CPU上执行指令的进程处于运行状态。

  2. 等待状态(Waiting):也称作阻塞状态。当进程需要某些资源以继续运行(例如,等待用户输入或等待文件读取)时,它将转入等待状态。直到所需资源可用时,才会被重新放入可运行队列。

  3. 就绪状态(Ready):当进程已经准备好在CPU上运行,但由于其他进程正在CPU上运行,而暂时无法运行,此时就处于就绪状态。就绪状态的进程会被放在一个队列中,等待CPU资源。

  4. 创建状态(New):当进程刚被创建但还未被调度到运行时,它处于创建状态。

  5. 终止状态(Terminated):一个进程完成了它的全部工作,或者被其他进程杀死,或者出现异常终止时,它就处于终止状态。此时,操作系统将回收进程占用的资源并销毁该进程。

这些状态之间的转变会根据CPU调度,资源申请等情况来进行。

进程间的通信方式有哪些?各自有哪些优缺点?

进程间通信(Inter Process Communication,IPC)是一个进程与另一个进程传输和分享数据的机制。主要有以下几种方式:

  1. 管道(Pipe):管道是最早的进程间通信机制,数据可以在父子或兄弟进程间单向流动。管道的优点是简单易用,但缺点是数据只能在有亲缘关系的进程之间传输,并且是无格式的字节流,需要进程自行解析。

  2. 消息队列(Message Queue):消息队列是一种先进先出的队列结构,允许进程将消息发送到队列,并允许其他进程根据消息的优先级从队列中读取。优点是可以在无关进程间传输数据,支持数据的优先级设定。缺点是数据读写需要系统调用,消耗相对较高,复杂消息可能需要额外处理逻辑。

  3. 共享内存(Shared Memory):共享内存允许多个进程访问同一块内存空间,是最快的IPC方式。优点是无需系统调用,直接读写内存,效率较高。缺点是需要手动解决进程间的同步问题,开发难度相对较高。

  4. 信号(Signal):信号是一种简单的进程间通信方式,用来通知接收进程有某事件发生。它的优点是简单,可以异步地通知事件。缺点是信息量有限,只能传递一个数量,不能携带更复杂的信息。

  5. 套接字(Socket):套接字可以在不同机器上的进程间通信。它的优点是可以进行跨机器的通信,通用性强。缺点是开发相对复杂,数据读写需要系统调用,效率较低。

  6. 信号量(Semaphore):信号量常用于多个进程间的同步和互斥问题。。

以上每种通信方式都有其适用的场景,选择哪一种取决于实际需求。

线程间的通信方式有哪些?各自有哪些优缺点?

线程间的通信方式通常利用同一个进程下线程所共享的资源来实现。主要有以下几种方式:

  1. 锁机制(Locks):当多个线程需要访问共享资源时,可以使用锁机制来避免并发问题。一个线程在访问资源时可以"锁定"该资源,阻止其他线程的访问,直到该线程释放锁。锁机制简单而直接,但必须小心处理,否则可能导致死锁。

  2. 信号量(Semaphores):信号量是一个更为高级的同步机制,可以控制多个线程对共享资源的访问。信号量有一个计数器和一个等待队列组成,计数器表示可用的资源数目。优点是可以控制资源的同时访问数,缺点是使用不当也可能导致死锁。

  3. 条件变量(Condition Variables):条件变量是另一种同步机制,允许一个线程等待某个条件满足。当条件满足时,可以通知一个或多个正在等待的线程。条件变量通常与互斥锁一起使用。优点是能够实现更复杂的同步,如按顺序访问等。缺点是使用不当可能导致死锁或饥饿现象。

  4. 事件驱动(Event-driven):在事件驱动的模型中,线程之间通过等待和触发事件来进行通信。这种方式不仅适用于线程间的通信,也可以用于进程或异步输入/输出等的通信。优点是适应性强,可以应对多种不同的通信需求。缺点是需要编程模型支持,且在设计和实现上可能较为复杂。

  5. 线程本地存储(Thread-Local Storage,TLS):有些变量是线程不安全的,例如静态变量,全局变量等,这些变量如果在多线程环境下共享,可能会造成不可预料的结果。为了解决这个问题,我们可以为每个线程提供一份该变量的副本,这就是线程本地存储。此方案的优点是能避免资源竞争,缺点是会增加内存的使用。

以上就是一些常见的线程间通信方式,各有其适用场景和优缺点。

进程的地址空间里面有什么?

进程的地址空间是指操作系统为每个进程分配的虚拟内存空间,用于存储进程的代码、数据和堆栈等信息。进程的地址空间通常分为以下几个部分:

  1. 代码段(Text Segment):也称为程序段,用于存放进程的可执行代码。该部分通常是只读的,包含了程序的指令集,如函数、循环、条件语句等。

  2. 数据段(Data Segment):用于存储全局变量、静态变量和常量等数据。数据段可以分为初始化的数据段(Initialized Data Segment)和未初始化的数据段(Uninitialized Data Segment)。

    • 初始化的数据段包含了已经初始化的全局变量和静态变量等数据,存储在静态存储区,通常是可读写的。
    • 未初始化的数据段,也称为BSS段(Block Started by Symbol),包含了未初始化的全局变量和静态变量等数据,存储在静态存储区,通常是可读写但初始值为0。
  3. 堆(Heap):堆是动态分配的内存空间,用于存储动态分配的数据。堆空间通常由程序员通过动态内存分配函数(如malloc()、new)进行管理,用于存储动态数组、链表等动态数据结构。堆的大小和生命周期由程序员显式控制,需要在不再使用时手动释放。

  4. 栈(Stack):栈用于存储函数调用时相关的信息,如局部变量、函数参数、返回地址等。栈的生命周期与函数的调用和返回有关,每当调用一个函数时,在栈上会创建一个新的栈帧用于保存函数的信息,当函数返回时,栈帧会被销毁。

除了上述部分,还有一些特殊的地址空间区域,如共享库、内核空间等,根据不同的操作系统和架构可能具体实现有所不同。不同的进程的地址空间是相互隔离的,每个进程都有自己独立的地址空间,使得多个进程能够同时运行而不会相互干扰。

线程切换要保存哪些上下文?

当发生线程切换时,操作系统需要保存当前线程的“上下文”,以便在下次线程被再次调度执行时得以恢复。上下文主要包括以下内容:

  1. 寄存器值:这包括了通用寄存器,程序计数器(存放当前线程正在执行的指令地址),程序状态字(存放执行指令的结果的状态,如零,负,溢出等)等。

  2. 堆栈指针:每个线程有自己的函数调用栈,堆栈指针标识了当前线程在自己的栈空间中的位置。回到这个线程时,它可以恢复到正确的函数调用位置。

  3. 程序计数器:这个值标识了线程执行到哪里。当线程切换回来时,它将从这个位置继续执行。

  4. 内核栈指针:每个线程有一个内核栈,存放在内核中的数据,这个指针标识当前线程在内核内存中的位置。

  5. 线程状态:这包括了线程的优先级,信号掩码,错误码等。

  6. 虚拟内存信息:这通常包括有关线程内存管理的信息,比如页表等。

于是,当线程切换发生时,操作系统会保存当前线程的上述上下文,加载目标线程的上下文,然后将控制权转交给目标线程,这样目标线程就能接着上次的运行状态继续执行了。

值得注意的是,线程切换是有性能开销的,因为涉及到保存和加载上下文的操作,所以过于频繁的线程切换可能会影响性能。

什么是协程吗?和线程有什么区别?

协程(Coroutine)是一种用户级别的轻量级线程。它们的调度完全由用户控制,而不是由操作系统内核控制。与线程不同,协程的上下文切换极其快速且成本低,主要因为它所需保存和恢复的状态较少。

对于协程和线程的比较,参考以下四个方面:

  1. 切换开销:线程由系统内核控制,切换开销大;协程由程序员在用户空间控制,切换开销小。

  2. 调度:线程是抢占式调度,需要操作系统来进行线程的调度切换;协程是非抢占式的,由协程自身决定何时进行切换,这也是其使用复杂性的来源之一。

  3. 数据共享和同步:线程并发编程需要考虑锁等同步机制的问题;而协程在同一时间只有一个运行,它对共享资源的访问不需要加锁,只需要确保在协程切换的时候保存好共享资源的状态即可。

  4. 应用场景:线程适合cpu密集型任务; 协程适合IO密集型任务。

以Python为例,其中有个名为greenlet的第三方库就为我们提供了协程的支持。在网络请求处理的场景中,由于网络IO等待时间较长,使用线程处理可能会导致大量的线程阻塞在等待 I/O,而协程可以在等待IO的时候主动让出CPU让其他协程执行,然后在恢复等待的协程,在每一次IO等待的时候都可以主动让出CPU让其他协程利用,这样就可以充分利用CPU,提高执行效率。

什么是僵尸进程?

僵尸进程(Zombie Process)指的是一个已经结束执行的子进程,但其父进程尚未调用wait()或waitpid()函数来获取子进程的终止状态信息。在这种情况下,子进程的进程控制块(PCB)仍然存在系统中,但没有正常退出,因此处于僵尸状态。

僵尸进程的主要原因是进程在结束执行后,父进程并没有及时处理子进程的终止状态信息。通常,父进程会通过调用wait()或waitpid()函数来等待子进程的退出,并获取其终止状态。若父进程没有这样做,子进程就会成为僵尸进程。

僵尸进程不会占用系统资源(如CPU、内存等),它们只占用一个进程ID(PID)和一些系统资源(如进程表项、部分内存等)。但如果系统中存在大量僵尸进程,可能会耗尽可用的资源。

虽然僵尸进程本身无害,但过多的僵尸进程可能是不可取的。为了避免僵尸进程的积累,父进程应适时调用wait()或waitpid()来获取终止状态信息,并通过kill()或终止自身来回收僵尸进程。在某些情况下,可以使用信号处理程序,如SIGCHLD信号来自动处理子进程的退出状态。

总之,僵尸进程是指在父进程没有及时回收子进程终止状态时,子进程成为已经结束但仍占用系统资源的状态。及时处理子进程的终止状态,是保持系统健康运行的重要措施。

由于内容太多,更多内容以链接形势给大家,点击进去就是答案了

16. 什么是缓冲区溢出?有什么危害?

17. 分页与分段的区别?

18. 物理地址、逻辑地址、虚拟内存的概念

19. 页面置换算法有哪些?

20. 谈谈你对动态链接库和静态链接库的理解?

21. 外中断和异常有什么区别?

22. 一个程序从开始运行到结束的完整过程,你能说出来多少?

23. 什么是用户态和内核态

24. 用户态和内核态是如何切换的?

25. 进程终止的方式

26. 守护进程、僵尸进程和孤儿进程

27. 如何避免僵尸进程?

28. 介绍一下几种典型的锁?

29. 常见内存分配内存错误

30. 内存交换中,被换出的进程保存在哪里?

31. 原子操作的是如何实现的

32. 抖动你知道是什么吗?它也叫颠簸现象

  • 36
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值