操作系统-进程(1)进程与进程调度「建议收藏」

2022-09-06 17:32:00 浏览数 (1)

大家好,又见面了,我是你们的朋友全栈君。

操作系统必须全方位地管理计算机系统中运行的程序。因此,操作系统为正在运行的程序建立了一个管理实体——进程

进程是一个具有一定独立功能的程序关于某个数据集合的一次运行活动,是操作系统进行资源分配和调度的一个独立单位

OS应能管理与控制进程的执行、协调管理处理器、主存储器等各类资源在进程间的使用

一个进程包括五个实体部分,分别是:

  • (OS管理运行程序的)数据结构P
  • (运行程序的)内存代码C
  • (运行程序的)内存数据D
  • (运行程序的)通用寄存器信息R
  • (OS控制程序执行的)程序状态字信息PSW

不同程序在不同数据集上运行:构成两个无关进程

不同程序在相同数据集上运行:构成两个共享数据的交往进程

相同代码在不同数据集上运行:构成两个共享代码的无关进程(共享的代码称为可再入程序,它是纯代码的,在执行中不变化,如编辑器)

前述的程序与数据集均是内存级的。那么,在不同时段中针对同一个外存数据文件运行同一个外存程序文件,两次运行构成两个不同的进程,因为意味着完全不同的P、C、D、R、Psw。

进程的引入除了为应用程序提供了一个独立的逻辑控制流,使得程序员以为自己的程序在执行过程中独占拥有处理器;还为应用程序提供了一个私有的地址空间(虚拟地址空间),使得程序员以为自己的程序在执行过程中独占拥有存储器。

Intel架构下linux操作系统中的一个进程对应的虚拟地址空间映像如图所示:

整个虚拟地址空间分为两大部分:内核虚拟存储空间(简称内核虚拟空间)和进程虚拟存储空间(简称用户空间)。

在采用虚拟存储机制的系统中,每个程序的可执行目标文件在装入时都被映射到相同的虚拟空间中。

进程的三态模型:

运行态指进程占有处理器运行,处于运行态的进程个数不能大于处理器个数

就绪态指进程具备运行条件等待处理器运行

等待态指进程由于等待资源、输入输出、信号等而不具备运行条件

(1)运行态→等待态:出现等待事件,如等待资源、I/O、信号

(2)等待态→就绪态:等待事件完成,如资源满足、I/O结束、信号完成

(3)就绪态→运行态:处理器空闲时会选择更高优先权进程抢占

(4)运行态→就绪态:运行时间片到、有更高优先权进程

OS无法预期进程的数目与资源需求,计算机系统在运行过程中可能出现资源不足的情况,运行资源不足表现为性能低和死锁两种情况。

解决办法为进程挂起:剥夺某些进程的内存及其他资源,调入OS管理的对换区,不参加进程调度,待适当时候再调入内存、恢复资源、参与运行

一般选择等待态进程进入挂起等待态,也可选择就绪态进程进入挂起就绪态,运行态进程还可以挂起自己进入挂起就绪态

等待事件结束后,挂起等待态进入挂起就绪态,一般选择挂起就绪态进程予以恢复

⭐️挂起态与等待态有着本质区别,等待态占有已申请到的资源处于等待,挂起态没有任何资源

进程映像(Process Image)是某一时刻进程的内容及其执行状态集合,是内存级的物理实体,又称为进程的内存映像,包括了:

(1)进程控制块PCB(Process Control Block)是OS用于记录和刻画进程状态及环境信息的数据结构。

借助PCB,OS可以全面管理进程的物理实体,刻画进程的执行现状,控制进程的执行

  • 标识信息:用于存放唯一标识该进程的信息

系统分配的标识号、系统分配的进程组标识号、用户定义的进程名、用户定义的进程组名

  • 现场信息:用于存放该进程运行时的处理器现场信息,:

用户可见寄存器内容:数据寄存器、地址寄存器

控制与状态寄存器内容:PC、IR、PSW

栈指针内容:核心栈与用户栈指针

  • 控制信息:用于存放与管理、调度进程相关的信息

调度相关信息:状态、等待事件/原因、优先级

进程组成信息:代码/数据地址、外存映像地址

进程队列指引元:进程队列指针、父子兄弟进程指针

进程通信相关信息:消息队列、信号量、锁

进程处理器使用信息:占用的处理器、时间片、处理器使用时间/已执行总时间、记账信息

进程特权信息:如内存访问权限、处理器特权

进程资源清单信息:如正占有的资源、已使用的资源

(2)进程程序块: 进程执行的程序空间

(3)进程数据块: 进程处理的数据空间,包括数据、处理函数的用户栈和可修改的程序

(4)进程核心栈: 进程在内核模式下运行时使用的堆栈,中断或系统过程使用

除了进程映像,进程的执行还需要环境支持,包括CPU现场和Cache中的执行信息, OS中的进程物理实体(代码和数据等)和支持进程运行的环境合成进程上下文,用于刻画进程的执行情况,进程在当前上下文中运行。

进程上下文包括:

(1)用户级上下文:用户程序块/用户数据区/用户堆栈/用户共享内存组成的用户空间信息

(2)寄存器上下文:即进程的现场信息,包括PSW/栈指针/通用寄存器。

(3)系统级上下文:由进程控制块(进程的状态)、内存管理信息(进程页表或段表)和系统核心栈(进程内核态运行时的工作区)等操作系统管理进程需要的信息

用户级上下文地址空间和系统级上下文地址空间一起构成了一个进程的整个存储器映像。

关键的进程管理软件包括:

(1)系统调用/中断/异常处理程序

(2)队列管理模块

(3)进程控制程序

(4)进程调度程序(独立进程居多)

(5)进程通信程序(多个程序包)

(6)终端登录与作业控制程序、性能监控程序、审计程序等外围程序

把处于同一状态的所有进程的PCB链接在一起的数据结构称为进程队列,有两种常用的队列组织方式:

(1)索引方式:系统建立若干索引表,各索引表在内存中的起始地址放在内核专用指针单元。

(2)链接方式:队列中的进程可以通过PCB中的队列指引元采用单向链接或双向链接,系统为每个队列设置队列标志以标志和识别队列。

进程实现的队列模型如图所示:

队列管理模块是操作系统实现进程管理的核心模块。进程与资源调度围绕进程队列展开。

操作系统建立多个进程队列,如只有一个进程的运行队列、按照优先级或FCFS排列的就绪队列、等待I/O操作完成的队列、等待信号量的队列等。按需组织为先进先出队列与优先队列

当发生某个事件使进程状态发生转换时,此进程退出所在队列进入另一个队列。

进程的控制与管理:

  • 进程创建:进程列表加一项,申请PCB并初始化,分配唯一进程标识符,建立映像,分配资源,移入就绪队列
  • 进程撤销:从队列中移除,归还资源,撤销标识符,回收PCB,移除进程表项(先要撤销子进程)
  • 进程阻塞:保存现场信息,修改PCB,移入等待队列,转向进程调度程序调度其他进程执行
  • 进程唤醒:等待队列中移出,修改PCB,移入就绪队列(该进程优先级高于运行进程,则重新设置调度标志)
  • 进程挂起:修改状态并出入相关队列,收回内存等资源送至对换区
  • 进程激活:分配内存,修改状态并出入相关队列
  • 其他:如修改进程特权

进程控制过程中涉及对OS核心数据结构(进程表/PCB池/队列/资源表)的修改,为防止与时间有关的错误,应使用原语(由若干条指令构成的完成某种特定功能的程序,执行上具有不可分割性,执行可以通过关中断实现)。进程控制使用的原语称为进程控制原语。

PS:另一类常用原语是进程通信原语。

Linux将用户空间对应的进程虚拟空间组织成若干区域(area)的集合,这些区域是指在虚拟存储空间中的连续片,而且是已分配页。

例如:只读代码区、可读写数据区、已分配堆区、已分配栈区、共享映射区。每个区再被分配成等大页面。

每个进程主要通过一个称为进程描述符(process descriptor)的结构来描述,其结构类型定义为task_struct,包含了一个进程的所有信息:标识进程的PID、指向用户栈的指针、可执行目标文件的文件名、程序计数值PC等。

所有进程通过一个双向循环链表实现的任务列表(task list)来描述,任务列表中每个元素是一个进程描述符。

如图,task结构中有一个指针指向mm结构,mm结构描述对应进程虚拟空间的当前状态,其中有一个字段pgd,对应进程第一级页表(页目录表)的首地址,当处理器运行对应进程时,内核会将其送到CR3控制寄存器;以及一个字段mmap,指向一个由vm_area结构组成的链表表头。

每个vm_area结构了对应进程虚拟空间中的一个区域。包括指向区域开始位置和结束位置的vm_start和vm_end,描述区域包含的所有页面的访问权限的vm_prot,描述区域包含的页面是否和其它进程共享的vm_flags。以及指向下一个链表结点的vm_next。

例如,read不存在的区域,就会引起段故障;read可读写数据区一切正常;write只读代码区就会发生段故障的保护异常。

总结,Linux是以链表方式管理用户空间中的区域area,内核不需要记录那些不存在的页面。通过task结构、task结构指向的mm结构、mm结构指向的其它结构来记录进程标识信息、进程现场信息、进程控制信息。

进程切换指从正在运行的进程中收回处理器,让待运行进程来占有处理器运行,实质上就是被中断运行进程与待运行进程的上下文切换,处理过程是:

  1. 保存被中断进程的上下文
  2. 转向进程调度
  3. 恢复待运行进程的上下文

其一定发生在中断/异常/系统调用处理过程中,常见的情况是:

  • 阻塞式系统调用、虚拟地址异常导致被中断进程进入等待态
  • 时间片中断、I/O中断后发现更高优先级进程导致被中断进程转入就绪态
  • 终止用系统调用、不能继续执行的异常导致被中断进程进入终止态

进程切换必须在操作系统内核模式下完成,这就需要模式切换(处理器状态切换),模式切换包括:

  • (1)用户模式到内核模式,由中断/异常/系统调用中断用户进程执行而触发

由中断装置完成正向模式切换,包括(1)处理器模式转为内核模式;

(2)保存当前进程的PC/PSW值到核心栈;

(3)转向中断/异常/系统调用处理程序

  • 内核模式到用户模式,OS执行中断返回指令将控制权交还用户进程而触发

由中断返回指令完成逆向模式转换,包括(1)从待运行进程核心栈中弹出PSW/PC值;

(2)处理器模式转为用户模式

综上,完整的进程切换过程为

  1. (中断/异常等触发)正向模式切换并压入PSW/PC
  2. 保存被中断进程的现场信息
  3. 处理具体中断/异常
  4. 把被中断进程的系统堆栈指针SP值保存到PCB
  5. 调整被中断进程的PCB信息,如进程状态
  6. 把被中断进程的PCB加入相关队列
  7. 选择下一个占用CPU运行的进程
  8. 修改被选中进程的PCB信息,如进程状态
  9. 设置被选中进程的地址空间,恢复存储管理信息
  10. 恢复被选中进程的SP值到处理器寄存器SP
  11. 恢复被选中进程的现场信息进入处理器
  12. 中断返回指令触发逆向模式转换并弹出PSW/P

一些中断/异常不会引起进程状态转换,不会引起进程切换,只是在处理完成后把控制权交回给被中断进程,处理流程为

  1. 中断/异常触发正向模式切换压入PSW/PC
  2. 保存被中断进程的现场信息
  3. 处理中断/异常
  4. 恢复被中断进程的现场信息
  5. 中断返回指令触发逆向模式转换弹出PSW/PC

发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/155530.html原文链接:https://javaforall.cn

0 人点赞