计算机基础之操作系统——进程与线程管理(一)

1、进程、线程、协程区别与联系?

进程、线程和协程是计算机程序执行的三个不同层次。

进程(Process)

  • 定义:进程是操作系统进行资源分配和调度的基本单位,每个进程都有自己的内存空间、系统资源和程序计数器。
  • 特点
    • 进程间相互独立。
    • 每个进程有自己的地址空间,无法直接访问其他进程的数据。
    • 进程之间的资源是相互隔离的,进程之间的通信需要通过进程间通信(IPC)机制,如管道、消息队列、共享内存等。
    • 开销较大,因为创建和销毁进程需要操作系统进行较多的资源管理。

线程(Thread)

  • 定义:线程是进程内的一个执行单元,是操作系统调度执行的最小单位,一个进程可以拥有多个线程,这些线程共享进程的资源(如内存空间、文件描述符等)。
  • 特点
    • 线程是操作系统调度执行的最小单位。
    • 由于线程共享相同的资源,线程间通信相对简单,可以直接通过共享变量、锁等方式进行。
    • 创建和销毁线程的开销较小,但由于共享内存空间,多个线程并发执行时,需要处理好同步和互斥问题,以避免数据不一致或竞争条件。

协程(Coroutine):

  • 定义:协程是一种用户态的轻量级线程,它的调度和切换完全由程序控制,不依赖于操作系统的调度。协程之间共享线程的资源,因此协程间通信也可以通过共享变量、锁等方式进行。协程可以在一个线程内实现多任务的切换。
  • 特点
    • 协程的切换开销非常小,因为它不需要进行系统调用(不像线程切换那样涉及内核调度)。协程的优势在于能够轻松地实现高并发。
    • 协程是协作式调度,即一个协程主动让出控制权,或者通过某些条件(如等待IO)挂起,其他协程得以执行。
    • 协程通常用于I/O密集型任务,因为它们能在等待I/O操作时切换到其他协程,提升效率。
    • 通常由单个线程管理多个协程。

联系

  • 线程属于进程,多个线程共享进程的资源。一个进程可以包含多个线程,这些线程共同完成任务,提高程序的并发性。
  • 协程属于线程,多个协程共享线程的资源。一个线程可以包含多个协程,这些协程协同完成任务,提高程序的性能。
  • 进程、线程和协程在执行程序时,都需要面对同步、互斥和通信等问题。

2、讲一讲用户线程与内核线程?

特性 用户线程 内核线程
管理者 用户空间的线程库 操作系统内核
切换开销 低(无需内核介入) 高(需系统调用)
阻塞问题 阻塞导致整个进程挂起 单个线程阻塞不影响其他线程
多核支持 无法直接多核并行 支持多核并行
典型应用 高并发但非阻塞的轻量任务(协程) 多核计算、阻塞操作

3、一个进程可以创建多少个线程?

一个进程可以创建的线程数没有固定的上限,它受到操作系统限制、系统资源和程序设计要求等多种因素的影响。

  • 操作系统限制:不同操作系统和平台对每个进程可以创建的线程数有不同的限制。例如,在Linux系统中,可以通过查看/proc/sys/kernel/threads-max文件获取系统级别的最大线程数限制。此外,可以使用ulimit命令查看和设置每个进程的线程数限制。在Windows系统中,线程数限制受到地址空间和其他资源限制的约束。
  • 系统资源:一个进程可以创建的线程数受到可用内存和CPU资源的限制。每个线程都需要一定的内存来存储线程栈和其他线程相关的数据结构。如果系统内存不足,可能无法创建更多线程。同样,系统的CPU资源也会影响线程的数量,因为大量线程可能导致频繁的上下文切换,从而降低系统性能。
  • 程序设计要求:程序的设计和性能要求也会影响一个进程可以创建的线程数。在面向并发性能的程序设计中,通常需要权衡线程数量和系统资源之间的关系。创建过多的线程可能导致资源竞争和上下文切换开销,从而降低程序性能。因此,合理的线程数量应该根据程序的具体需求和系统资源来确定。

4、进程的调度算法?

进程调度算法是操作系统的核心组件,负责决定 哪个进程(或线程)何时获得 CPU 资源

调度器主要考虑两个问题,需要调度哪个任务;每个任务执行多长时间。对于现代操作系统来说,需要着重考虑的一点是如何调度让每个任务从用户的眼中是在同时进行的。之后才会考虑如何调度让性能最佳。

先来先服务(FCFS,First-Come First-Served)

  • 规则:按进程到达就绪队列的顺序分配 CPU。
  • 特点
    • 非抢占式,在任务执行完前不会让出CPU,适合批处理系统。
    • 对短任务不友好,可能导致“护航效应”(短进程被长进程阻塞)。
    • 对IO密集型不友好,当IO密集型需要读写IO而进入阻塞让出CPU时,假设后序是一个长时间运行的任务,那么当IO读写完了也需要等待很长时间。
    • 没有考虑响应时间,对交互式任务很不友好。
  • 示例:银行柜台排队场景

短作业优先(SJF, Shortest Job First)

  • 规则:优先调度预计运行时间最短的进程。
  • 变种
    • 非抢占式(SJF):进程运行完成才释放 CPU。
    • 抢占式(SRTN, Shortest Remaining Time Next):新进程到达时若剩余时间更短,则抢占 CPU。
  • 特点:最小化平均等待时间,但需要预知作业运行时间(实际中难以实现)。

时间片轮转(RR, Round Robin)

  • 规则:每个进程分配固定时间片(如 10ms),超时后强制释放 CPU,重新排队。
  • 特点
    • 抢占式,适合交互式系统(如 GUI)。
    • 时间片过大会退化为 FCFS,过小会导致频繁上下文切换。
    • RR策略保证了任务的公平性,但是公平必然会损失性能。
  • 示例:现代操作系统的默认调度策略(如 Linux 的 CFS 结合时间片)。

优先级调度(Priority Scheduling)

  • 规则:为每个进程分配优先级,优先运行高优先级进程。
  • 变种
    • 静态优先级:优先级固定(可能导致低优先级进程“饥饿”)。
    • 动态优先级:根据等待时间、资源使用等动态调整。
  • 示例:实时系统或关键任务进程优先执行。

 多级反馈队列(MLFQ, Multilevel Feedback Queue)

  • 规则
    • 设置多个优先级队列,高优先级队列时间片更短。
    • 新进程进入最高优先级队列,若未完成则降级到低优先级队列。
    • 低优先级队列进程可被高优先级队列抢占。

具体策略:

  • 短任务具有更高的优先级,这样主要是为了降低平均周转时间;IO密集型的任务因为其CPU运行时间比较短,所以它的优先级一般也比较高,有利于提高IO资源的利用率;交互式任务一般是短任务,所以其优先级一般也比较高。
  • 在真实系统中,可能无法去预测是短任务还是长任务,因此需要动态的去调整,当任务第一次进入运行队列时,系统会假定该任务是最高优先级,如果该任务运行时间超过最大运行时间,那么系统自动会给其降低优先级。
  • 为了缓解低优先级的饥饿问题,调度器会定时的将所有低优先级的队列重新提到最高。保证低优先级有机会执行。

  • 特点
    • 结合了 FCFS、RR、优先级调度的优点。
    • 平衡响应时间和吞吐量,广泛用于通用操作系统(如 Unix、Windows)。

实时调度算法

  • 硬实时调度(严格截止时间):
    • 最早截止时间优先(EDF):优先调度截止时间最近的进程。
    • 单调速率调度(RMS):周期任务按执行频率分配优先级。
  • 软实时调度(允许偶尔超时):
    • 结合优先级和时间片,如 Windows 实时扩展。

调度算法评价指标

  1. 周转时间:进程从提交到完成的总时间。
  2. 响应时间:从提交请求到首次获得 CPU 的时间。
  3. 吞吐量:单位时间内完成的进程数。
  4. 公平性:避免高优先级进程垄断 CPU。
  5. 可预测性:实时系统的截止时间保障。

5、进程间通信方式?

进程间通信(IPC, Interprocess Communication)是操作系统提供的机制,允许不同进程(可能运行在同一或不同主机上)通过特定的方式交换数据或协调行为。

管道(Pipe)

  • 原理
    • 匿名管道:单向通信,基于内核缓冲区(如 Linux 的 pipe() 创建),仅用于父子进程或兄弟进程。
    • 命名管道(FIFO):通过文件系统路径标识(如 mkfifo 创建),支持无亲缘关系的进程通信。
  • 特点
    • 数据以字节流形式传输,无消息边界(是指通信过程中接收方能明确区分每条消息的起始和结束位置的能力),只能单项传输数据
    • 容量有限(默认 64KB),写满时阻塞,读空时阻塞。
  • 示例:Shell 命令 ls | grep "txt" 使用匿名管道连接 ls 和 grep

消息队列(Message Queue)

  • 原理
    • 消息队列在内核中的数据结构是一个单链表构成的队列,最初会有个消息头部指针,保存着消息队首与相应的权限;每个消息都会有下一个消息的指针,以及消息本身的内容。
    • 支持优先级和异步通信。
  • 特点
    • 唯一一个以消息为数据抽象的通信方式。
    • 消息有边界,可区分不同类型。
    • 消息队列的内存空间有限,一般来说传递长消息时采用共享内存的方式,而非消息队列。
  • 示例:分布式系统中任务分发。

共享内存(Shared Memory)

  • 原理
    • 允许一个或者多个进程所在的虚拟地址空间中映射相同的物理页,从而进行通信
    • 共享内存的实现机制:首先内核会给全局的共享内存维护一个全局的队列结构,这个队列的每一项是一个shmid_kernel结构体与一个IPC key来绑定的,各进程可以通过key来找到并使用同一段共享内存;该进程能否操作这段共享内存时SystemV的权限检查机制来判断;当两个进程同时对一个共享内存建立了映射后,内核会给他们分配两个VMA结构体,进程可以通过他们各自的虚拟地址来访问VMA并访问其背后的共享内存空间。 
    • 需配合同步机制(如信号量)避免竞态条件。
  • 特点
    • 速度最快(无需拷贝数据到内核)。
    • 数据直接读写,无序列化开销。
  • 示例:大数据传输(如图像处理)。

信号量(Semaphore)

  • 原理
    • 信号量不同于消息队列这种明确是传递消息的,它主要是用来同步,用来辅助控制多个访问线程访问有限数量资源。它传递一个整数,一般还是0,1。
    • 信号量操作主要有两个原语,支持 P(等待)和 V(释放)操作。P操作就是申请资源,信号量减1,如果失败,进程进入阻塞状态,被放入信号量的等待队列中,直到可以减;V操作就是信号量+1,V操作可以唤醒一个因P操作阻塞的进程。
  • 特点
    • 不直接传递数据,仅协调资源访问。
    • 可解决生产者-消费者问题。
  • 示例:控制对共享内存的并发访问。

信号(Signal)

  • 原理
    • 管道、消息队列、共享内存主要是关注数据传输设计,而信号的作用是单项的事件通知能力。
    • 通过发送特定信号通知进程事件。
    • 使用 kill() 或 sigqueue() 发送信号。
  • 特点
    • 轻量级,但信息量小(仅信号编号和少量附加数据)。
    • 异步处理,可能打断进程正常执行。
  • 示例:终止进程(SIGTERM)或调试(SIGTRAP)。

套接字(Socket)

  • 原理
    • 基于网络协议(TCP/UDP)或本地域(Unix Domain Socket)的通信端点。
    • 支持跨主机通信。
  • 特点
    • 灵活性高,支持多种协议和复杂数据格式。
    • 需处理序列化(如 JSON、Protobuf)。
  • 示例:客户端-服务器模型(如 Web 服务)。
方式 数据传输 同步/异步 适用场景 性能 复杂度
管道 字节流 同步(等待对方响应或完成操作) 父子进程简单通信
消息队列 结构化消息 异步 任务队列、优先级通信
共享内存 直接访问内存 需同步 大数据量、低延迟
信号量 无数据 同步 资源竞争控制
信号 信号编号 异步 事件通知、简单控制
Socket 字节流/消息 同步/异步 跨网络、复杂协议 低-中

    你可能感兴趣的:(计算机八股,linux)