(学习笔记-进程管理)进程

进程

我们编写的代码只是一个存储在硬盘的静态文件,通过编译后会生成二进制可执行文件,当我们运行这个可执行文件后,它会被装载到内存中,接着CPU会执行程序中的每一条指令,那么这个运行中的程序就被称为进程

现在我们考虑有一个会读取硬盘文件数据的程序执行了,那么当运行到读取文件指令时,就会去从硬盘读取数据,但是硬盘的读写速度相比于CPU的处理速度是非常慢的,那么在这个时候,如果CPU一直等待硬盘返回数据的话,CPU的利用率是非常低的。

类比,当你去烧开水的时候,你不会傻傻等水壶烧开。我们可以在水壶烧开之前去做其他事情。当水壶烧开了,我们自然会听到"滴滴滴"的声音,于是再把烧开的水倒入到水杯中就好了。

所以,当进程要从硬盘读取数据时,CPU不需要阻塞等待数据的返回,而是去执行另外的进程。当硬盘数据返回时,CPU会收到一个中断,于是CPU会再继续运行这个进程。

 这种多个程序、交替执行的思想,就有CPU管理多个进程的初步想法。

对于一个支持多进程的系统,CPU会从一个进程快速切换到另一个进程,期间每个进程各运行几十或几百毫秒。

虽然大单核CPU在某个瞬间,只能运行一个进程。但在一秒钟内,他可能会运行多个进程,这样就产生了并行的错觉,实际上这是并发

并行和并发的区别

 进程与程序的关系

到了晚饭时间,一对小情侣肚子都咕咕叫了,于是男生见机行事,就想给女生做晚饭,所以他就在网上找了辣子鸡的菜谱,接着买了一些鸡肉、辣椒、香料等材料,然后边看边学边做这道菜。

突然,女生说她想喝可乐,那么男生只好把做菜的事情暂停一下,并在手机菜谱标记做到哪一个步骤,把状态信息记录了下来。

 然后男生听从女生的指令,跑去下楼买了一瓶冰可乐后,又回到厨房继续做菜。

这体现了,CPU 可以从一个进程(做菜)切换到另外一个进程(买可乐),在切换前必须要记录当前进程中运行的状态信息,以备下次切换回来的时候可以恢复执行。

所以,可以发现进程有着「运行 - 暂停 - 运行」的活动规律。


进程的状态

我们知道了进程有着 [运行-暂停-运行] 的活动规律。一般来说,一个进程并不是自始至终连续不停地运行的,它与并发执行中的其他进程的执行是相互制约的。

它有时处于运行状态,有时又由于某种原因而暂停运行处于等待状态,当使他暂停的原因消失后,它又进入准备运行状态。

所以,在一个进程的活动期间至少具备三种基本状态,即运行状态、就绪状态、阻塞状态

  • 运行状态:该时刻进程占用CPU
  • 就绪状态:可运行,由于其他进程处于运行状态而暂时停止运行
  • 阻塞状态:该进程正在等待某一事件发生(如等待输入/输出操作完成)而暂停运行,这时,及时给它CPU控制权,它也无法运行。

当然,进程还有另外两个基本状态:

  • 创建状态:进程正在被创建时的状态
  • 结束状态:进程正在从系统中消失时的状态

于是完整的进程状态图为:

  • NULL -> 创建状态:一个新进程被创建时的第一个状态
  • 创建状态 -> 就绪状态:当进程被创建完成并初始化后,一切就绪准备运行时,变成就绪状态,这个过程很快。
  • 就绪状态 -> 运行状态:处于就绪状态的进程被操作系统的进程调度器选中后,就分配给CPU正式运行该进程。
  • 运行状态 -> 结束状态:当进程已经完成或出错时,会被操作系统作结束状态处理
  • 运行状态 -> 就绪状态:处于运行状态的进程在运行过程中,由于分配给它的时间片用完,操作系统会把该进程变为就绪状态,接着从就绪态中选中另外一个进程运行
  • 运行状态 -> 阻塞状态:当进程请求某个事件且必须等待时,例如I/O事件
  • 阻塞状态 -> 就绪状态:当进程要等待的事件完成时,它从阻塞状态变到就绪状态

如果有大量处于阻塞状态的进程,进程可能会占用着物理内存空间。显然不是我们所希望的,因为物理内存空间有限,被阻塞状态的进程占用物理内存就是一种浪费物理内存的行为。

所以,在虚拟内存管理的操作系统中,通常会把阻塞状态的进程的物理内存换出到硬盘,等需要再次运行的时候,再从硬盘换入到物理内存。

那么,就需要一个新的状态,来描述进程没有占用实际的物理内存空间的情况,这个状态就是挂起状态。这跟阻塞状态是不一样的,阻塞状态是等待某个事件的返回。 

挂起状态可以分为两种:

  • 阻塞挂起状态:进程在外存(硬盘),并等待某个事件的出现
  • 就绪挂起状态:进程在外存(硬盘),但只要进入内存,即刻运行。

这两种状态加上前面的五种状态,就变成了七种状态变迁:

导致进程挂起的原因不只是因为进程所使用的内存空间不在物理内存,还包括如下情况:

  • 通过 sleep 让进程间歇性挂起,其工作原理是设置一个定时器,到期后唤醒进程
  • 用户希望挂起一个程序的执行,比如在Linux中用 Ctrl + Z 挂起程序

进程的控制结构

在操作系统中,是用进程控制块(process control block ,PCB) 数据结构来描述进程的。

PCB是进程存在的唯一标识,这意味着一个进程的存在,必然会有一个PCB,如果进程消失了,那么PCB也会随之消失。

PCB具体包含什么信息呢?

进程描述信息:

  • 进程标识符:标识各个进程,每个进程都有一个并且唯一的标识符(通常为进程的序号)
  • 用户标识符:进程归属的用户,用户标识符主要为共享和保护服务

CPU状态信息:

  • 当处理机被中断时,其寄存器中的信息都必须保存在进程的PCB中,以便该进程从新执行时,能从断点继续执行

进程调度信息:

  • 进程状态,如 new、ready、running、waiting和blocked等,作为进程调度和对换的依据
  • 进程优先级:用于描述进程使用CPU的优先级,优先级高的进程应该优先获取CPU
  • 进程调度所需信息:如进程已等待CPU的时间总和,进程已执行的时间总和等
  • 事件:进程由执行状态转变为阻塞状态所等待发生的事件,即阻塞原因

进程控制信息:

  • 程序和数据的地址(进程的程序和数据所在的内存或外存首地址,以便在调度该进程的时候能从PCB中找到其程序和数据)
  • 进程同步和通信机制(实现进程同步和进程通信时必需的机制,如消息队列指针,信号量等)
  • 资源清单(除CPU外的进程所需的全部资源以及已经分配到该进程的资源的清单)
  • 链接地址(本进程PCB所在队列中的下一个进程的PCB的首地址)

每个PCB是如何组织的?

通常是通过链表的方式进行组织,把具有相同状态的进程链在一起,组成各种队列。比如:

  • 将所有处于就绪状态的进程链在一起,称为就绪队列
  • 把所有因等待某事件而处于等待状态的进程链在一起,组成各种阻塞队列
  • 对于运行队列在单核CPU系统中则就只有一个运行指针了,因为单核CPU在某个时间只能运行一个程序。

那么,就绪队列和阻塞队列链表的组织形式如下:

 除了链接的组织方式,还有索引方式,它的工作原理:将同一状态的进程组织在一个索引表中,索引表项指向相应的PCB,不同状态对应不同的索引表。

一般会选择链表,因为可能面临进程创建,销毁等调度导致进程状态发生变化,所以链表能够更加灵活的插入和删除。


进程的控制

这里我们介绍进程的创建、终止、阻塞、唤醒的过程,这些过程也就是进程的控制

创建进程

操作系统允许一个进程创建另一个进程,而且运行子进程继承父进程所拥有的资源。

创建进程的过程如下:

  • 申请一个空白的PCB,并向PCB中填写一些控制和管理进程的信息,比如进程的唯一标识等
  • 为该进程分配运行时所必需的资源,以及新进程的程序和数据以及用户栈分配必要的内存空间
  • 将PCB插入到就绪队列,等待被调度运行

终止进程

进程可以有3种终止方式:正常结束、异常结束以及外界干预(信号 kill 掉)

当子进程被终止时,其在父进程处继承的资源应当还给父进程。而当父进程被终止时,该父进程的子进程就变为孤儿进程,会被 1 号进程收养,并由 1 号进程对它们完成状态收集工作。

终止进程的过程如下:

  • 根据被终止的进程的标识符,查找需要终止的进程的PCB
  • 如果处于执行状态,则立即终止该进程的执行,然后将CPU资源分配给其他进程
  • 如果其还有子进程,则应将进程的子进程终止,防止它们成为不可控的进程
  • 将该进程所拥有的全部资源或归还于其父进程或都归还给操作系统
  • 将其从 PCB 所在队列中移出,等待其他程序来搜集信息

阻塞进程

引起进程阻塞的与唤醒的事件如下:

  1. 请求系统服务:当正在执行的进程请求操作系统提供服务时,由于某种原因,操作系统并不立即满足该进程的要求,该进程只能被转换为阻塞状态来等待
  2. 启动某种操作:当进程启动某种操作后,如果该进程必须在该操作完成之后才能继续执行,则必须先使该进程阻塞,以等待该操作完成
  3. 新数据尚未到达:对于相互合作的进程,如果其中一个进程需要先获得另一合作进程提供的数据后才能对数据进行处理,则只要其所需数据尚未到达,该进程只有(等待)阻塞
  4. 无新工作可做:系统往往设置了一些具有某些特定功能的系统进程,每当这种进程完成任务后,便把自己阻塞起来等待新任务的到来。

进程阻塞的步骤如下:

  • 找到将要被阻塞进程标识号对应的PCB
  • 如果该进程为运行状态,则保护其现场,将其状态转为阻塞状态,停止运行
  • 将该PCB插入到阻塞队列中去

唤醒进程

进程由 [运行] 转变为 [阻塞] 状态是由于进程必须等待某一事件的完成,所以处于阻塞状态的进程是绝对不可能唤醒自己的。

当被阻塞进程所期待的事件出现时,如I/O完成获其所期待的数据已经到达,则由有关进程(如用完并释放I/O设备的进程)调用唤醒语句wakeup,将等待该事件的进程唤醒,首先将被阻塞的进程从等待该事件的阻塞队列中移出,将其PCB中的现行状态由阻塞改为就绪,然后再将该PCB插入到就绪队列中。值得注意的是,block原语与wakeup原因应该在不同进程中执行

唤醒进程的过程如下:

  • 在该事件的阻塞队列中找到相应进程的 PCB
  • 将其从阻塞队列中移出,并置其状态为就绪状态
  • 把该PCB插入到就绪队列中,等待调度程序调度

进程的阻塞和唤醒是一对功能相反的语句,如果某个进程调用了阻塞语句,则必有一个与之对应的唤醒语句。


进程的上下文切换

各个进程之间是共享CPU资源的,在不同的时候进程之间需要切换,让不同的进程可以在CPU执行,那么这个一个进程切换到另一个进程运行,称为进程的上下文切换

CPU的上下文切换

大多数操作系统都是多任务,通常支持大于CPU数量的任务同时运行。实际上,这些任务并不是同时运行的,只是因为系统在很短的时间内让各个任务分别在CPU上运行,于是就造成了同时运行的错觉。

任务是交给CPU运行的,那么在每个任务运行前,CPU需要知道任务从哪里加载,又从哪里开始运行。

所以,操作系统事先需要帮CPU设置好CPU寄存器和程序计数器

CPU寄存器是CPU内部一个容量小,但速度极快的内存(缓存)。

程序计数器则是用来存储CPU正在执行的指令位置,或者即将执行的下一条指令位置。

所以,CPU寄存器和程序计数器是CPU在运行任何任务前,所必须依赖的环境,这些环境就叫做CPU上下文

CPU上下文切换就是把前一个任务的上下文(CPU寄存器和程序计数器)保存起来,然后加载新任务的上下文到这些寄存器和程序计数器,最后再跳转到程序计数器所指的新位置,运行新任务。

系统内核会存储保存下来的上下文信息,当此任务再次被分配给CPU运行时,CPU会重新加载这些上下文,这样就能保证任务原来的状态不受影响,让任务看起来还是连续运行。

上面说到所谓的 [任务],主要包含进程、线程和中断。所以,可以根据任务的不同,把CPU上下文切换分为:进程上下文切换、线程上下文切换和中断上下文切换

进程的上下文切换到底是切换什么呢?

进程是由内核管理和调度的,所以进程的切换只能发生在内核态

所以,进程的上下文切换不仅包含了虚拟内存、栈、全局变量等用户空间的资源,还包括了内核堆栈、寄存器等内核空间的资源

通常,会把交换的信息保存在进程的 PCB,当要运行另外一个进程的时候,我们需要从这个进程的 PCB 取出上下文,然后恢复到 CPU 中,这使得这个进程可以继续执行,如下图所示:

 需要注意,进程的上下文开销是很关键的,我们希望它的开销越小越好,这样可以使得进程可以把更多时间花费在执行程序上,而不是耗费在上下文切换。

发生进程上下文切换有哪些场景?

  • 为了保证所有进程可以得到公平调度,CPU 时间被划分为一段段的时间片,这些时间片再被轮流分配给各个进程。这样,当某个进程的时间片耗尽了,进程就从运行状态变为就绪状态,系统从就绪队列选择另外一个进程运行;
  • 进程在系统资源不足(比如内存不足)时,要等到资源满足后才可以运行,这个时候进程也会被挂起,并由系统调度其他进程运行;
  • 当进程通过睡眠函数 sleep 这样的方法将自己主动挂起时,自然也会重新调度;
  • 当有优先级更高的进程运行时,为了保证高优先级进程的运行,当前进程会被挂起,由高优先级进程来运行;
  • 发生硬件中断时,CPU 上的进程会被中断挂起,转而执行内核中的中断服务程序;

以上,就是发生进程上下文切换的常见场景了。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/59301.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

关于docker的一些深入了解

本文将深入介绍一下docker方面的知识,不尽完全,慢慢完善。 进程 进程的概念 在介绍docker的相关知识前,先了解一下相关概念。进程就是系统中正在运行的程序,进程是操作系统的概念,每当我们执行一个程序时&#xff0…

【unity】Pico VR 开发笔记(视角移动)

【unity】Pico VR 开发笔记(视角移动) 视角移动是简单的基础功能,这里区别于头显定位获得的小范围位移,是长距离不影响安全边界的位移方式。的常见的位移方式有两种,其一是触发后瞬间传送到指定位置,其次是…

Linux: 设置qmake的Qt版本

Qt开发,qmake会对应一个Qt版本,有时候需要切换这个版本,例如把qmake从Qt5.12切换到Qt5.9, 怎么操作呢? 案例如下: 银河麒麟V10系统,下载安装了Qt5.9.8,但是检查qmake发现它使用的是5.12.8&…

OPC DA 客户端与服务器的那点事

C#开发OPC客户端,使用OPCDAAuto.dll。在开发过程中偶遇小坎坷,主要记录一下问题解决办法。 1、建立客户端,参考链接。建立WinFrom工程,将博客中代码全部复制即可运行: https://www.cnblogs.com/kjgagaga/p/17011730.…

Java阶段五Day19

Java阶段五Day19 问题解析 需求单查询列表功能的bug 业务逻辑: 需要用户登录,师傅入驻,审核入驻通过 查询师傅详情(areaIds,categoryIds) demand-server-dao-impl 包含持久层实现 requestOrderMappe…

Vue——formcreate表单设计器自定义组件实现(二)

前面我写过一个自定义电子签名的formcreate表单设计器组件,那时初识formcreate各种使用也颇为生疏,不过总算套出了一个组件不是。此次时隔半年又有机会接触formcreate,重新熟悉和领悟了一番各个方法和使用指南。趁热打铁将此次心得再次分享。…

身体原来是一份宝贵的“情绪地图”, 疾病都在教导我们如何与世界相处

当我们生病时 很多时候,是一个契机 让我们来倾听自己内心的压抑的真实 聆听身体的声音 身体能够教会我们如何对待情绪 进而教导我们如何与世界相处 -1- 身体上,有你的情绪地图 皮肤是身体的镜子,身体则是心灵的镜子。生病&#xff0c…

什么是微服务

微服务的架构特征: 单一职责:微服务拆分粒度更小,每一个服务都对应唯一的业务能力,做到单一职责自治:团队独立、技术独立、数据独立,独立部署和交付面向服务:服务提供统一标准的接口&#xff0…

《Java-SE-第二十八章》之CAS

前言 在你立足处深挖下去,就会有泉水涌出!别管蒙昧者们叫嚷:“下边永远是地狱!” 博客主页:KC老衲爱尼姑的博客主页 博主的github,平常所写代码皆在于此 共勉:talk is cheap, show me the code 作者是爪哇岛的新手,水平很有限&…

AI绘图实战(十二):让AI设计LOGO/图标/标识 | Stable Diffusion成为设计师生产力工具

S:AI能取代设计师么? I :至少在设计行业,目前AI扮演的主要角色还是超级工具,要顶替?除非甲方对设计效果无所畏惧~~ 预先学习: 安装及其问题解决参考:《Windows安装Stable Diffusion …

Kali部署dvwa和pikachu靶场

kali换源 进入 vim /etc/apt/sources.list deb https://mirrors.aliyun.com/kali kali-rolling main non-free contrib deb-src https://mirrors.aliyun.com/kali kali-rolling main non-free contrib替换完后更新源 apt-get upadteDVWA靶场环境搭建 使用git从github上把DV…

项目中引用svg图标,公共组件SvgIcon使用,注册全局组件,使用自定义插件注册全局组件

在开发项目的时候经常会用到svg矢量图,而且我们使用SVG以后,页面上加载的不再是图片资源, 这对页面性能来说是个很大的提升,而且我们SVG文件比img要小的很多,放在项目中几乎不占用资源。 1、安装依赖插件 pnpm install vite-plugin-svg-ic…

以产品经理的角度去讲解原型图---会议OA项目

目录 一.前言 二.原型图 2.1 原型图是什么 3.1 原型图的作用 三.演示讲解 3.1 项目背景 3.2 项目介绍 3.2.1 会议管理(会议的发起,通知) 3.2.2 投票管理(会议的流程重大决策记录) 3.2.3 会议室管理 3.2.4 系统管…

2023年第三届工业自动化、机器人与控制工程国际会议 | IET独立出版 | EI检索

会议简介 Brief Introduction 2023年第三届工业自动化、机器人与控制工程国际会议(IARCE 2023) 会议时间:2023年10月27 -30日 召开地点:中国成都 大会官网:www.iarce.org 2023年第三届工业自动化、机器人与控制工程国际…

Android 获取网络连接状态新方法

一. 问题背景 Android12上,有的app模块判断当前网络的类型和连接状态时,还是使用的旧的API,导致返回的结果不准确,影响代码逻辑判断,本篇文章就这一问题,整理一下判断网络类型和连接状态的新方法。 二. 原因…

Selenium上传文件有多少种方式?不信你有我全!

Selenium 封装了现成的文件上传操作。但是随着现代前端框架的发展,文件上传的方式越来越多样。而有一些文件上传的控件,要做自动化控制会更复杂一些,这篇文章主要讨论在复杂情况下,如何通过自动化完成文件上传 input 元素上传文件…

go env 配置(环境变量)说明

前提:已经安装好 golang 可正确的运行下面这段命令,来查看 go 的配置: go env 输出示例: 以上是我本地(windows)环境下输出的配置信息(环境变量) 我们这次就针对每个配置信息进行一个说明,具体到每个字段是什么意思…

前端(十一)——Vue vs. React:两大前端框架的深度对比与分析

😊博主:小猫娃来啦 😊文章核心:Vue vs. React:两大前端框架的深度对比与分析 文章目录 前言概述原理与设计思想算法生态系统与社区支持API与语法性能与优化开发体验与工程化对比总结结语 前言 在当今快速发展的前端领…

iOS——Block回调

先跟着我实现最简单的 Block 回调传参的使用,如果你能举一反三,基本上可以满足了 OC 中的开发需求。已经实现的同学可以跳到下一节。 首先解释一下我们例子要实现什么功能(其实是烂大街又最形象的例子): 有两个视图控…

性能测试怎么做?测试工具怎么选择?

在当前软件测试行业,熟练掌握性能测试已经是测试工程师们面试的敲门砖了,当然还有很多测试朋友们每天的工作更多的是点点点,性能方面可能也只是做过简单的并发测试,对于编写脚本,搭建环境方面也比较陌生。今天这篇文章…