操作系统之进程和线程

3 进程和线程

3.1 进程

进程的定义与组成 🔹

进程是 进程实体 的运行过程,是系统进行 资源分配和调度 的一个独立单位;

进程实体包括:PCB + 程序段 + 数据段 三部分;

​ PCB:进程描述信息、进程控制和管理信息、资源分配信息;
​ 程序段:程序的代码;
​ 数据段:运行过程中出生的各种数据;

PCB(Process Control Block) 即进程控制块,是操作系统中用来管理和跟踪进程的数据结构,每个进程都对应着一个独立的 PCB。可将 PCB 视为进程的大脑。

当操作系统创建一个新进程时,会为该进程分配一个唯一的进程 ID,并且为该进程创建一个对应的进程控制块。当进程执行时,PCB 中的信息会不断变化,操作系统会根据这些信息来管理和调度进程。

PCB 主要包含下面几部分的内容:进程描述信息、进程控制和管理信息、资源分配信息

  • 进程的描述信息,包括进程的名称、标识符等等;
  • 进程的调度信息,包括进程阻塞原因、进程状态(就绪、运行、阻塞等)、进程优先级(标识进程的重要程度)等等;
  • 进程对资源的需求情况,包括 CPU 时间、内存空间、I/O 设备等等。
  • 进程打开的文件信息,包括文件描述符、文件类型、打开模式等等。
  • 处理机的状态信息(由处理机的各种寄存器中的内容组成的),包括通用寄存器、指令计数器、程序状态字 PSW、用户栈指针。

进程的特征

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qLz1Djrt-1684159490193)(C:\Users\DoubleC\AppData\Roaming\Typora\typora-user-images\image-20230418091440793.png)]

进程的状态与转换 ⭐️

我们一般把进程大致分为 5 种状态,这一点和线程很像!

  • 创建状态(new) :进程正在被创建,尚未到就绪状态。
  • 就绪状态(ready) :进程已处于准备运行状态,即进程获得了除了处理器之外的一切所需资源,一旦得到处理器资源(处理器分配的时间片)即可运行。
  • 运行状态(running) :进程正在处理器上上运行(单核 CPU 下任意时刻只有一个进程处于运行状态)。
  • 阻塞状态(waiting) :又称为等待状态,进程正在等待某一事件而暂停运行如等待某资源为可用或等待 IO 操作完成。即使处理器空闲,该进程也不能运行。
  • 结束状态(terminated) :进程正在从系统中消失。可能是进程正常结束或其他原因中断退出运行。

在这里插入图片描述

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ok8TI5bc-1684159490194)(C:\Users\DoubleC\AppData\Roaming\Typora\typora-user-images\image-20230418091919904.png)]

进程的组织方式

链接方式:将同一状态的PCB链接成一个队列

索引方式:将同一状态的进程组织在一个索引表中,索引表的表项指向相应的PCB;

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-J1y8ZDnD-1684159490195)(C:\Users\DoubleC\AppData\Roaming\Typora\typora-user-images\image-20230418092119008.png)]

进程控制

  1. 进程的创建

    申请空白 PCB; 为新进程分配所需资源; 初始化 PCB; 将 PCB 插入就绪队列;

  2. 进程的终止

    从 PCB 集中中找到终止进程的 PCB; 若进程正在运行,立刻剥夺 CPU, 将 CPU 分配给其它进程;

  3. 进程的阻塞

    找到要阻塞的进程对应的 PCB; 保护进程运行现场,将 PCB 状态信息设置为 阻塞态,暂时停止进程执行; 将 PCB 插入相应事件的等待队列;

  4. 进程的唤醒

    在事件等待队列中找到PCB; 将 PCB 从等待队列移除,设置进程为就绪态; 将 PCB 插入就绪队列,等待被调度;

  5. 进程状态的切换

    将运行环境信息存入 PCB; PCB 移入相应队列; 选择另一个进程执行,并更新其 PCB; 根据 PCB 回复新进程所需的运行环境;

进程的通信 ⭐️

  1. 共享存储

相互通信的进程 互斥地 共享 某些 数据结构 或 存储区,进程之间能够通过这些空间进行通信;

  1. 消息传递

进程之间的数据交换以 格式化的信息 为单位,将通信的数据封装在信息中,并利用操作系统提供的一组 通信命令(原语),在进程间进行信息传递,完成进程间的数据交换;

​ ① 直接通信方式:送货上门
​ ② 间接通信方式:快递到驿站

  1. 管道通信

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-259AlPVZ-1684159490195)(C:\Users\DoubleC\AppData\Roaming\Typora\typora-user-images\image-20230418093019638.png)]

3.2 进程与线程

  • 进程(Process) 是指计算机中正在运行的一个程序实例。举例:你打开的微信就是一个进程。

  • 线程(Thread) 也被称为轻量级进程,更加轻量。多个线程可以在同一个进程中同时执行,并且共享进程的资源比如内存空间、文件句柄、网络连接等。举例:你打开的微信里就有一个线程专门用来拉取别人发你的最新的消息。

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UwHGcApB-1684159490195)(C:\Users\DoubleC\AppData\Roaming\Typora\typora-user-images\image-20230418093659970.png)]

进程和线程的区别

  • 线程是进程划分成的更小的运行单位,一个进程在其执行的过程中可以产生多个线程。
  • 线程和进程最大的不同在于基本上各进程是独立的,而各线程则不一定,因为同一进程中的线程极有可能会相互影响。
  • 线程执行开销小,但不利于资源的管理和保护;而进程正相反。

有了进程为什么还需要线程?

  • 进程切换是一个开销很大的操作,线程切换的成本较低。

  • 线程更轻量,一个进程可以创建多个线程。

  • 多个线程可以并发处理不同的任务,更有效地利用了多处理器和多核计算机。

    而进程只能在一个时间干一件事,如果在执行过程中遇到阻塞问题比如 IO 阻塞就会挂起直到结果返回。

  • 同一进程内的线程共享内存和文件,因此它们之间相互通信无须调用内核。

为什么要使用多线程?

先从总体上来说:

  • 从计算机底层来说: 线程可以比作是轻量级的进程,是程序执行的最小单位,线程间的切换和调度的成本远远小于进程。另外,多核 CPU 时代意味着多个线程可以同时运行,这减少了线程上下文切换的开销
  • 从当代互联网发展趋势来说: 现在的系统动不动就要求百万级甚至千万级的并发量,而多线程并发编程正是开发高并发系统的基础,利用好多线程机制可以大大提高系统整体的并发能力以及性能。

再深入到计算机底层来探讨:

  • 单核时代: 在单核时代多线程主要是为了提高单进程利用 CPU 和 IO 系统的效率。 假设只运行了一个 Java 进程的情况,当我们请求 IO 的时候,如果 Java 进程中只有一个线程,此线程被 IO 阻塞则整个进程被阻塞。CPU 和 IO 设备只有一个在运行,那么可以简单地说系统整体效率只有 50%。当使用多线程的时候,一个线程被 IO 阻塞,其他线程还可以继续使用 CPU。从而提高了 Java 进程利用系统资源的整体效率。
  • 多核时代: 多核时代多线程主要是为了提高进程利用多核 CPU 的能力。举个例子:假如我们要计算一个复杂的任务,我们只用一个线程的话,不论系统有几个 CPU 核心,都只会有一个 CPU 核心被利用到。而创建多个线程,这些线程可以被映射到底层多个 CPU 上执行,在任务中的多个线程没有资源竞争的情况下,任务执行的效率会有显著性的提高,约等于(单核时执行时间/CPU 核心数)。

线程间的同步方式 ⭐️

线程同步是两个或多个共享关键资源的线程的并发执行。同步线程以避免关键的资源使用冲突。

下面是几种常见的线程同步的方式:

  1. 互斥锁(Mutex):采用互斥对象机制,只有拥有互斥对象的线程才有访问公共资源的权限。因为互斥对象只有一个,所以可以保证公共资源不会被多个线程同时访问。比如 Java 中的 synchronized 关键词和各种 Lock 都是这种机制。
  2. 读写锁(Read-Write Lock):允许多个线程同时读取共享资源,但只有一个线程可以对共享资源进行写操作。
  3. 信号量(Semaphore) :它允许同一时刻多个线程访问同一资源,但是需要控制同一时刻访问此资源的最大线程数量。
  4. 屏障(Barrier) :屏障是一种同步原语,用于等待多个线程到达某个点再一起继续执行。当一个线程到达屏障时,它会停止执行并等待其他线程到达屏障,直到所有线程都到达屏障后,它们才会一起继续执行。比如 Java 中的 CyclicBarrier 是这种机制。
  5. 事件(Event) :Wait/Notify:通过通知操作的方式来保持多线程同步,还可以方便的实现多线程优先级的比较操作。

3.3 进程调度

三层调度的联系与对比

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vgkgTzcG-1684159490195)(C:\Users\DoubleC\AppData\Roaming\Typora\typora-user-images\image-20230418102051111.png)]

进程调度的时机

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vN3qNf8T-1684159490196)(C:\Users\DoubleC\AppData\Roaming\Typora\typora-user-images\image-20230418102249825.png)]

进程调度的方式

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-oagdFXsU-1684159490196)(C:\Users\DoubleC\AppData\Roaming\Typora\typora-user-images\image-20230418102514724.png)]

调度算法 ⭐️

  1. 先来先服务(FCFS) 按照进程到达的先后顺序;

  2. 短作业优先(SJF) 服务时间最短的进程优先;
    抢占式版本:最短剩余时间优先算法 SRTN;

  3. 高响应优先(HRRN) 响应比 = (等待时间 + 要求服务时间) / 要求服务时间

  4. 时间片轮转调度算法(RR) 根据进程到达就绪队列的顺序,轮流调度;

  5. 优先级调度算法 调度时选择优先级最高的;

  6. 多级反馈队列调度算法

    设置多级就绪队列;
    各队列按照 FCFS + 时间片,时间片结束进入下一级队列队尾;
    只有第 k 级队列为空时,才会为 k+1 级分配时间片;

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-QvABdfTi-1684159490196)(C:\Users\DoubleC\AppData\Roaming\Typora\typora-user-images\image-20230418102957666.png)]

在 Unix/Linux 系统中,子进程通常是通过 fork()系统调用创建的,该调用会创建一个新的进程,该进程是原有进程的一个副本。子进程和父进程的运行是相互独立的,它们各自拥有自己的 PCB,即使父进程结束了,子进程仍然可以继续运行。

当一个进程调用 exit()系统调用结束自己的生命时,内核会释放该进程的所有资源,包括打开的文件、占用的内存等,但是该进程对应的 PCB 依然存在于系统中。这些信息只有在父进程调用 wait()或 waitpid()系统调用时才会被释放,以便让父进程得到子进程的状态信息。

这样的设计可以让父进程在子进程结束时得到子进程的状态信息,并且可以防止出现“僵尸进程”(即子进程结束后 PCB 仍然存在但父进程无法得到状态信息的情况)。

  • 僵尸进程子进程已经终止,但是其父进程仍在运行,且父进程没有调用 wait()或 waitpid()等系统调用来获取子进程的状态信息,释放子进程占用的资源,导致子进程的 PCB 依然存在于系统中,但无法被进一步使用。这种情况下,子进程被称为“僵尸进程”。避免僵尸进程的产生,父进程需要及时调用 wait()或 waitpid()系统调用来回收子进程。
  • 孤儿进程一个进程的父进程已经终止或者不存在,但是该进程仍在运行。这种情况下,该进程就是孤儿进程。孤儿进程通常是由于父进程意外终止或未及时调用 wait()或 waitpid()等系统调用来回收子进程导致的。为了避免孤儿进程占用系统资源,操作系统会将孤儿进程的父进程设置为 init 进程(进程号为 1),由 init 进程来回收孤儿进程的资源。

Linux 下可以使用 Top 命令查找,zombie 值表示僵尸进程的数量,为 0 则代表没有僵尸进程。

下面这个命令可以定位僵尸进程以及该僵尸进程的父进程:

ps -A -ostat,ppid,pid,cmd |grep -e '^[Zz]'

3.4 同步和互斥

临界资源与临界区

一次仅允许一个进程使用的资源称为 临界资源

对于 临界资源 的访问,必须是 互斥 进行的;每个进程中,访问临界资源的那段代码成为 临界区

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1Mbbk1zL-1684159490197)(C:\Users\DoubleC\AppData\Roaming\Typora\typora-user-images\image-20230418103434562.png)]

进程同步与互斥 ⭐️

进程同步 是 直接制约关系,进程互斥 是 间接制约关系。

同步:并发进程为 完成同一任务 所进行的 工作顺序协调

互斥:并发进程为 竞争临界资源 所进行的 资源分时占用

在这里插入图片描述

进程互斥软、硬件实现

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZeFUf6Tj-1684159490197)(C:\Users\DoubleC\AppData\Roaming\Typora\typora-user-images\image-20230418104202242.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zvG5rLYS-1684159490197)(C:\Users\DoubleC\AppData\Roaming\Typora\typora-user-images\image-20230418104244597.png)]

3.5 死锁 🌟

死锁(Deadlock)描述的是这样一种情况:多个进程/线程同时被阻塞,它们中的一个或者全部都在等待某个资源被释放。由于进程/线程被无限期地阻塞,因此程序不可能正常终止。

① 死锁 各进程互相等待对方的资源,导致各进程都阻塞。(资源永远不会释放)

特点:至少两个或两个以上的进程同时死锁; 处于阻塞态;

② 饥饿 长期得不到想要的资源。(资源会释放,但不会被分配)

特点:一个进程也可能出现饥饿现象; 可能阻塞态 (等 IO),也可能就绪态 (等 CPU);

③ 死循环 死锁和饥饿是由资源的不合理分配导致,死循环是由代码逻辑错误导致。

产生死锁的必要条件

互斥条件 只有对互斥资源的争抢才会导致死锁。

不可剥夺条件 进程保持的资源只能主动释放,不可强行剥夺。

请求和保持条件 保证着某些资源不放的同时,请求别的资源

循环等待条件 存在一种进程资源的循环等待链;
循环等待未必死锁,死锁必定循环等待。

注意 ⚠️ :这四个条件是产生死锁的 必要条件 ,也就是说只要系统发生死锁,这些条件必然成立,而只要上述条件之一不满足,就不会发生死锁。

公式:资源 大于 进程个数*(每个线程需要的最大资源总数-1)
m>n*(w-1) 【m = n * (w - 1) + 1时可以避免死锁】
习题:一台计算机有8台磁带机,它们由N个进程竞争使用,每个进程可能需要3台磁带机。请问N为多少时,系统没有死锁危险

总资源:8 8> n(3-1) n小于4的时候都可以

解决死锁的方法

解决死锁的方法可以从多个角度去分析,一般的情况下,有预防,避免,检测和解除四种

  • 预防 是采用某种策略,限制并发进程对资源的请求,从而使得死锁的必要条件在系统执行的任何时间上都不满足。
  • 避免则是系统在分配资源时,根据资源的使用情况提前做出预测,从而避免死锁的发生
  • 检测是指系统设有专门的机构,当死锁发生时,该机构能够检测死锁的发生,并精确地确定与死锁有关的进程和资源。
  • 解除 是与检测相配套的一种措施,用于将进程从死锁状态下解脱出来
死锁的预防

思路:破坏死锁的四个必要条件 (完全没有死锁的可能)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Ho8sAv8x-1684159490198)(C:\Users\DoubleC\AppData\Roaming\Typora\typora-user-images\image-20230418110923539.png)]

死锁的避免

思路:避免系统进入不安全状态 (有可能死锁,避免陷入死锁)
**​ 银行家算法 **:在资源分配之前,先判断此次分配是否会导致系统进入 不安全状态 ,再决定是否分配资源。

  • 安全状态一定不会发生死锁;
  • 不安全状态可能会发生死锁;

银行家算法用一句话表达就是:当一个进程申请使用资源的时候,银行家算法 通过先 试探 分配给该进程资源,然后通过 安全性算法 判断分配后系统是否处于安全状态,若不安全则试探分配作废,让该进程继续等待,若能够进入到安全的状态,则就 真的分配资源给该进程

死锁的避免(银行家算法)改善了 资源使用率低的问题 ,但是它要不断地检测每个进程对各类资源的占用和申请情况,以及做 安全性检查 ,需要花费较多的时间。

死锁的检测和解除

① 死锁检测算法

  • 定时运行一个“死锁检测程序”,用于检测系统当前是否发生死锁;

  • 资源分配图:如果最终 不能消除所有边 ,此时就是发生了 死锁 。

    死锁检测步骤
    1. 如果进程-资源分配图中无环路,则此时系统没有发生死锁
    2. 如果进程-资源分配图中有环路,且每个资源类仅有一个资源,则系统中已经发生了死锁。
    3. 如果进程-资源分配图中有环路,且涉及到的资源类有多个资源,此时系统未必会发生死锁。如果能在进程-资源分配图中找出一个 既不阻塞又非独立的进程 ,该进程能够在有限的时间内归还占有的资源,也就是把边给消除掉了,重复此过程,直到能在有限的时间内 消除所有的边 ,则不会发生死锁,否则会发生死锁。(消除边的过程类似于 拓扑排序)

② 死锁解除算法

  • 当发生死锁时,将系统从死锁状态中解脱出来;
  • 如何解除:
    • 资源剥夺法;从涉及死锁的一个或几个进程中抢占资源,把夺得的资源再分配给涉及死锁的进程直至死锁解除
    • 终止进程法;立即结束所有进程的执行,重新启动操作系统
    • 进程回退法;逐个撤销涉及死锁的进程,回收其资源直至死锁解除
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值