admin管理员组

文章数量:1570208

  前言👀~

上一章我们介绍了计算机组成的入门知识,了解这些之后,今天来聊聊进程

进程

PCB

         pcb中的常见属性

进程调度

进程的状态

进程的优先级

上下文

记账信息

虚拟地址空间


如果各位对文章的内容感兴趣的话,请点点小赞,关注一手不迷路,如果内容有什么问题的话,欢迎各位评论纠正 🤞🤞🤞

个人主页:N_0050-CSDN博客

相关专栏:java SE_N_0050的博客-CSDN博客 java数据结构_N_0050的博客-CSDN博客


进程

正在运行的程序,已经跑起来的程序。有些进程是自动创建的,有些进程是我们自己手动创建的。自动创建的就是你一开机操作系统中有些程序就跟着一起运行,下面这张图里的就是一个个正在运行的程序也就是我们的进程


每个进程要想执行,会消耗一定的系统资源(硬件资源),可以这样理解就比如你要办一个生日那肯定需要钱才能办,所以进程执行也是一个道理,但是不同进程执行消耗的资源不一样,例如你现在要建一栋楼,那需要人力、财力等等的资源才行


每个进程,都是操作系统资源分配的基本单位。怎么理解呢?程序在运行的时候,系统以进程为单位进行分配资源。可以这么理解,疫情期间出不了门,政府要给我们发放一些资源,这时候呢以家庭为单位进行发放,总不可能以个人为单位每个都发放。从下面这张图中我们可以看到每个进程都会占用一定的资源,例如CPU、内存等系统资源

进程在系统中如何进行管理的?首先管理的两个角度来看,先是描述再是组织,描述我们使用类/结构体,把被管理的一个对象抽离出来,提取出属性表示出来,组织我们使用数据结构把这些表示出来的对象串起来,为了后续的增删改查


描述和组织的细致解释:操作系统中有一个专门的结构体(操作系统内核是用C/C++写的)描述进程的属性,这个结构体称为进程控制块(PCB),使用这个PCB描述进程的属性,一个进程可以使用一个PCB或多个PCB来表示,然后我们会使用双向链表这样的数据结构来组织多个进程也就是PCB。在Java语言中,我们可以使用类/对象来描述,每一个 PCB 对象,就代表着一个实实在在运行着的程序,也就是进程。操作系统通过双向链表的数据结构组织多个PCB对象,创建新的进程,就是把这个PCB对象添加到链表中,销毁进程就是把PCB对象从链表中进行删除并释放(操作系统会回收它所占用的资源),展示进程就是遍历这个链表的每一个结点


总结就是在我们使用java语言把进程抽象出来,抽象成PCB对象,这个PCB对象就代表我们正在运行的程序,然后我们可以通过数据结构的方式对其进行管理


PCB

是操作系统用来管理和描述进程的数据结构,pcb是一个非常庞大的结构体,包含很多属性,其中包含的属性是进程相关联的属性,是操作系统在进程切换时保存和恢复进程状态的关键(进程调度),pcb是一个通用的名字,linux中,pcb叫做task_struct

pcb中的常见属性

1.pid:进程的身份标识,每一个进程都会有一个pid,同一时刻(瞬间),不同进程之间的pid是不同的。主要就是用来区分不同的进程,但是这个进程结束了,其他新的进程就可以用它的进程号了


2.内存指针(一组属性):我们知道进程要运行的话需要消耗一定的系统资源才能进行运行,每个进程在运行的时候,都会分配到一定的内存空间。此时我们要想知道进程 内存空间 具体在哪里,分配的内存空间中有哪些部分,每个部分是干啥的,我们用这一组内存指针来进行区分,也可以说是描述。

举个例子最典型的就是进程的内存空间,需要专门的区域存储执行的指令,以及指令依赖的数据,同时还需要存储一些运行时产生的临时数据。

进程的内存空间例子:放暑假老师会发暑假作业(老师自己出的)给我们并且老师说要做多少做哪些,这个过程可以理解为C语言编写的程序生成了一个exe的可执行文件,这个可执行文件包含了一些二进制指令以及一些数据(这些指令还会依赖数据)指令依赖数据可以理解为老师说要做暑假作业这个指令,做哪里做哪些可以理解为数据,我们打开这个练习册并且读取到老师说的这些话并且记录到自己的本子上,这个过程可以理解为系统读取到可执行文件的内容,并且把二进制指令和数据内容从硬盘上加载到内存中,回去的时候我们写作业的时候,打开自己记录的本子看要写哪些写哪里然后再去写,这个过程可以理解为从内存中读取指令和数据,然后去执行指令

每个进程从系统中获取到的(可以看作一块蛋糕)内存空间是分割成多个区域的(这些内存区域是独立的),每个区域存储不同类型的数据和指令,通过内存指针和相关数据结构进行管理,内存指针用于指向这些不同的内存区域,帮助操作系统管理和分配进程的内存资源。

总结就是这组内存指针用来区分内存空间中有哪些内存区域,不同的内存区域存储不同的内容,指令、数据等,比如这块用来存储指令、这块用来存储数据,可以说它是用来描述进程持有的"内存资源"是啥样的


3.文件描述符表:类似顺序表这样的数据结构,顺序的存储很多元素,记录当前进程打开的所有文件。文件描述符表和文件有关也可以说和硬盘有关,因为文件呢又存储在硬盘上,但是呢计算机操作硬盘并不是直接操作这个硬件设备,而是把硬盘上的存储空间以文件这样的抽象形式抽象出来进行表示,可以参考上面的PCB对象应该是一个道理,然后对其进行操作。然后呢我们在代码里操作的是文件,实际在硬件操作的是硬盘

文件描述符:可以看作是在文件描述符表中的下标,通过下标访问的内容就是文件表项(一个结构体也可以看作是对象)

文件表项:可以看作是文件描述符下的元素,这个元素又包含具体文件的详细信息,例如文件状态、访问模式、当前读写位置等,其中包含了一个指针,指向的内容包含文件大小、创建时间等文件的元数据

总结文件描述符表用来描述进程持有的"硬盘资源"是啥样的,举个例子我们安装的游戏,不是系统自带的自己手动安装的这个是存储在硬盘中的,你可以在去硬盘文件下找到它的可执行文件或者使用快捷方式运行,运行的时候这个文件描述符表就是记录了执行这个程序所打开的所有文件夹,这个文件描述符表中又描述了你的文件的一些相关信息


进程调度

下面要讲的也是属于PCB中的属性,这些属性 支持操作系统 实现进程调度 的效果(但是并不是进程调度的全部,进程调度最核心的模块操作系统里的调度器,调度器里的调度算法)

进程持有的cpu资源如何体现?这里牵扯到进程的调度,操作系统执行多个进程的基础

早期的操作系统是"单任务操作系统"什么意思呢,手机举例就比如我们现在可以边回消息边打游戏,而单任务呢同一时间只有一个进程能运行,举个例子我们要么只能打游戏要么只能聊天,打游戏的时候收不到消息,回消息就不能打游戏,选择打游戏的话就要退出回消息这个进程才能开始玩游戏这个进程,相当于你去打游戏这个聊天软件给你自动退出了

一个进程要运行,需要cpu来执行这里面的指令,早期的cpu都是单核一个核心,同一时间只能运行一个进程,也就是cpu只能执行这一个进程的指令(例如你打开qq,这里cpu执行的都是qq的指令)。操作系统通过进程调度(进程调度的核心,分时复用也可以叫并发的思想)来管理多个进程的执行,什么意思呢?我们可以把一个cpu核心当作是一个舞台,进程代表演员,指令代表剧本,每个演员按照剧本一人上去演一段表演就得下来,只要轮转的速度(你下来的瞬间我里立马上去)够快就感觉好多个演员同时在表演一样,也可以想象我们小时候在一个本子的每一页边角都画上不同的火柴人,画完后,我们从头开始快速的翻,这个火柴人很连贯的在变化


并行:现在的cpu都是多核心的,当两个进程同时在两个核心上运行(可以理解为当一个核心忙不过来了,另外一个核心来帮忙),这时才是真正的同时执行,就拿刚才那个演员的例子举例,你在一个舞台表演我在一个舞台表演,我们同时在不同的舞台进行表演。这样的情况我们称为并行

并发:一个核心的cpu,通过快速轮转的方式让我们看上去实现了"同时执行",实际上是有先后顺序的,这种情况我们称为并发


业内会把并行和并发统一叫并发,也可以叫并发编程,现在多核心cpu的时代,一个系统会有多个进程的时候,多核心起着大作用,前提是有多个进程这个是关键,不然你只有一个进程,一个核心在那干活,其他核心在那看着不帮忙。在这种多进程多任务的情况下,操作系统通过并发编程充分利用多核心cpu的能力,实现更高的效率。多核心的出现是为了实现并发编程的效果


进程的状态

1.运行:cpu正在处理你的进程并且运行着,此时你的进程占用着cpu的资源

2.就绪:此时进程的准备工作都做好了,比如系统资源的分配,就差系统调用cpu去处理,就能运行了

3.阻塞:想象你给你的游戏充钱的场景,你充了钱才能回到游戏,你也可以点击取消充值回到游戏

进程的优先级

操作系统在调度多个进程的时候不会人人平等,就拿刚才的演员举例子,比如一个舞台你是主角你和其他演员的区别,一眼就看出了肯定是主角的优先级高,可以把操作系统调度多个进程看作导演在为多个角色分配优先权,优先级高的进程会优先获得 CPU 时间。就像舞台上的主角会比配角有更多的表演时间,权力也大

上下文

切换进程的时候把你上一个进程的相关信息记录下来,例如你打游戏打着打着然后切到微信回消息,此时cpu各种寄存器的状态会被记录下来记录到内存当中,然后你切回来的时候,cpu把刚才记录在内存的上一个进程的信息拿回来接着处理。就类似闯关游戏,玩累了闯到第几关保存下来,去吃个饭回来接着从这关开始。

下面这几个cpu中的寄存器涉及到上下文:

程序计数器(寄存器):是一个2字节/4字节/八字节 这个整数存的是一个内存地址(程序下一条要执行的指令的地址),初始情况,程序计数器指向进程指令的入口(可以理解为main方法),然后一般都是顺序执行的并且取完一条指令值会自动更新,如果遇到跳转类指令就会设置成跳转的地址

维护栈相关的寄存器:通过这一组(一般是两个)寄存器来维护当前程序的调用栈,栈也是一块内存,保存当前程序 方法调用过程中 一系列的关系(包括局部变量、方法参数)就想象成一个方法调用另外一个方法,另外一个又调用其他的。ebp寄存器始终指向栈底,esp寄存器始终指向栈顶。所以修改esp的值就可以实现出栈和入栈。有了这个寄存器我们就能知道一个方法执行完要回到哪里执行,可以想象递归。

其他通用寄存器:通用寄存器主要负责存储临时的数据和指令,记住cpu拿数据不是直接从内存中拿的,是通过寄存器中获取的


记账信息

记录当前进程持有的cpu的情况(在cpu执行多久了,占用内存大小),作为操作系统调度进程的参考依据。通过优先级机制,对不同的进程分配了不同权重的资源。可能会出现一个情况,还是拿演员的例子举例,你是主角你分配到的上场时间比其他演员多,如果没有导演做出分配或者约束,你一直在那表演其他演员肯定不乐意,于是操作系统拿记账信息作为调度进程的参考依据,导演看你上场的时间太多了,其他演员都没有上场时间,于是对上场时间进行重新分配。或者你玩游戏的时候想能收到女朋友的消息,虽然游戏占的资源多,但是聊天软件这个进程的资源总不可能一点都没有吧,不然收不到消息后果自己品


虚拟地址空间

操作系统为了应用程序提供稳定的运行环境,引入虚拟地址空间的概念,早期的操作系统,程序运行时分配的内存就是"物理内存" 可以理解为宿舍楼 (这样有很多个房间,每个房间都是一个字节,有一个编号,从0开始依次累加,这个编号就是"内存地址")

这样分配的内存后会出现一个问题,我运行两个进程A和B,一个进程一块物理内存,然后B进程出现bug内存访问越界,访问到A进程的物理内存,并且把A进程的内存的一些值改了导致A进程崩了。就好比你住宾馆开的房间是101,结果你冲去102里面一男一女,这你不就gg了

所以为了进程之间的稳定性有了虚拟地址空间这么一说,现在我们一个程序运行时分配的内存是 虚拟内存,什么意思呢?对内存又进行抽象,把这个物理内存抽象出来,搞了一个虚拟内存,我们通过操作虚拟地址来访问物理内存,此时操作系统会对你的虚拟地址进行翻译(翻译成物理地址,这里可以看作是一个hash表这样的映射结构),并且会对虚拟地址做出校验(这样发生越界的访问的时候,操作系统做出校验会打回报错),从而访问物理内存

以上便是进程的相关内容,我们java程序员了解这么多即可,我们更关注线程方面的相关知识,下一章我们讲解线程💕
 

本文标签: 进程