操作系统进程管理

1 进程概述

进程: 一个具有一定的功能的程序在一个数据集合上的一次动态执行过程.

1.1 进程组成

一个进程应该包括:

  • 程序的代码
  • 程序处理的数据
  • 程序计数器中的值, 指使下一条将运行的指令
  • 一组通用的寄存器的当前值, 堆, 栈
  • 一组系统资源(如打开的文件)

总之, 进程包含了正在运行的一个程序的所有状态信息.

1.2 进程和程序的联系

  • 程序是产生进程的基础
  • 程序的每次运行构成不同的进程
  • 进程是程序功能的体现
  • 通过多次执行, 一个程序可对应多个进程, 通过调用关系, 一个进程可包括多个程序.

进程和程序的区别:

  • 进程是动态的, 程序是静态的, 程序时有序代码的集合, 进程是程序的执行, 进程有核心态/用户态.
  • 进程是暂时的, 程序是永久的, 进程是一个状态变化的过程, 程序可长久保存
  • 进程与程序的组成不同, 进程的组成包括程序, 数据和进程控制块(如进程状态信息)

1.3 进程的特点

  • 动态性: 可动态地创建, 结束进程
  • 并发性: 进程可以被独立调度并占用处理器运行: 并发并行.
  • 独立性: 不同进程的工作不相互影响.
  • 制约性: 因访问共享数据/资源或进程间同步而产生制约

1.4 进程控制结构

进程控制块: 操作系统管理控制进程运行所用的信息集合. 操作系统用PCB(process control block)来描述进程的基本情况以及运行变化的过程, PCB是进程存在的唯一标志.

进程控制块的使用:

  • 进程的创建: 为该进程生成一个PCB
  • 进程的终止: 回收它的PCB
  • 进程的组织管理: 通过对PCB的组织管理来实现

PCB含有一下三大类信息:

1. 进程标识信息. 如本进程的标识, 本进程的产生者标识(父进程标识), 用户标识.

2. 处理器状态信息保存区. 保存进程的运行现场信息:

  • 用户可见寄存器, 用户程序可以使用的数据, 地址等寄存器.
  • 控制和状态寄存器, 如程序计数器(PC), 程序状态字(PSW).
  • 栈指针, 过程调用/系统调用/中断处理和返回时都需要用到它.

3. 进程控制信息:

  • 调度和状态信息, 用于操作系统调度进程并占用处理器使用.
  • 进程间通信信息, 为支持进程间的与通信相关的各种标识, 信号, 信件等, 这些信息存在接收方的进程控制块中.
  • 存储管理信息, 包含有指向本进程映像存储空间的数据结构.
  • 进程所用资源, 说明由进程打开, 使用的系统资源, 如打开的文件等.
  • 有关数据结构连接信息, 进程可以连接到一个进程队列中, 或者连接到相关的其他进程的PCB.

PCB的组织方式:

链表: 同一状态的进程其PCB成一链表, 多个状态对应多个不同的链表. 各状态的进程形成不同的链表: 就绪链表, 阻塞链表.

索引表: 同一状态的进程归入一个index表(由index指向PCB), 多个状态对应多个不同的index表. 各状态的进程形成不同的索引表: 就绪索引表, 阻塞索引表.

2 进程状态

2.1 进程的生命周期管理

2.1.1 进程创建

引起进程创建的三个主要条件:

  • 系统初始化时
  • 用户请求创建一个新进程
  • 正在运行的进程执行了创建进程的系统调用

2.1.2 进程运行

内核选择一个就绪的进程, 让它占用处理器并执行

2.1.3 进程等待

在以下情况下, 进程等待(阻塞):

  1. 请求并等待系统服务, 无法马上完成
  2. 启动某种操作, 无法马上完成
  3. 需要的数据没有到达

进程只能自己阻塞自己, 因为只有进程自身才知道何时需要等待某种事件发生.

2.1.4 进程唤醒

唤醒进程的原因:

  • 被阻塞进程需要的资源可被满足
  • 被阻塞进程等待的事件到达
  • 将该进程的PCB插入到就绪队列

进程只能被别的进程或操作系统唤醒.

2.1.5 进程结束

在以下四种情形下, 进程结束:

  • 正常退出(自愿的)
  • 错误退出(自愿的)
  • 致命错误(强制性的)
  • 被其他进程所杀(强制性的)

2.2 进程状态变化模型

进程的三种基本状态:

进程在生命周期结束前处于且仅处于三种基本状态之一, 不同系统设置的进程状态数目不同:

  • 运行状态: 当一个进程正在处理器上运行时.
  • 就绪状态: 一个进程获得了除处理器之外的一切所需资源, 一旦得到处理器即可运行.
  • 等待状态: 一个进程正在等待某一事件而暂停运行时. 如等待某资源, 等待输入/输出完成.

进程其他的基本状态:

  • 创建状态: 一个进程正在被创建, 还没被转到就绪状态之前的状态.
  • 结束状态: 一个进程正在从系统中消失时的状态, 这是因为进程结束或由于其他原因所导致.

状态变化:

  • NULL->New: 一个新进程被产生出来执行一个程序.
  • New->Ready: 当进程被创建完成并初始化后, 一切就绪准备运行时, 变为就绪状态.
  • Ready->Running: 处于就绪状态的进程被进程调度程序选中后, 就分配到处理器上来运行.
  • Runing->Exit: 当进程表示它已经完成或者因出错, 当前运行进程会由操作系统结束处理.
  • Runing->Ready: 处于运行状态的进程在其运行过程中, 由于分配给它的处理器时间片用完而让出处理器.
  • Runing->Blocked: 当进程请求某样东西且必须等待时.
  • Blocked->Ready: 当进程要等待的某事件到来时, 它从阻塞状态变到就绪状态.

2.3 进程挂起模型

进程在挂起状态时, 意味着进程没有占用内存空间, 处在挂起状态的进程映像在磁盘上.

2.3.1 进程的挂起状态

挂起状态有两种:

  • 阻塞挂起状态: 进程在外存并等待某事件的出现.
  • 就绪挂起状态: 进程在外存, 但只要进入内存, 即可运行.

2.3.2 挂起相关的状态转换

把一个进程从内存转到外存(挂起), 可能有以下几种情况:

  • 阻塞到阻塞挂起: 没有进程处于就绪状态或就绪进程进程要求更多内存资源时, 会进行这种转换, 以提交新进程或进行就绪进程.
  • 就绪到就绪挂起: 当有高优先级阻塞(系统认为会很快就绪的)进程和低优先就绪进程时, 系统会选择挂起低优先级就绪进程.
  • 运行到就绪挂起: 对抢先式分时系统, 当有高优先级阻塞挂起进程因事件出现而进入就绪状态时, 系统可能会把运行进程转到就绪挂起状态.

在外存时的状态转换:

  • 阻塞挂起到就绪挂起: 当有阻塞挂起进程因相关事件出现时, 系统会把阻塞挂起进程转换为就绪挂起进程.

解挂/激活(把一个进程从外存转到内存)的情况:

  • 就绪挂起到就绪: 没有就绪进程或挂起进程优先级高于就绪进程时, 会进行这种转换.
  • 阻塞挂起到阻塞: 当一个进程释放足够内存时, 系统会把一个高优先级阻塞挂起(系统认为会很快出现所等待的事件)进程转换为阻塞进程.

2.4 状态队列

  • 由操作系统来维护一组队列, 用来表示系统当中所有进程的当前状态
  • 不同的状态分别用不同的队列来表示(就绪队列, 各种类型的阻塞队列)
  • 每个进程的PCB都根据他的状态加入到相应的队列当中, 当一个进程的状态发生变化时, 它的PCB从一个状态队列中脱离出来, 加入到另外一个状态队列.

(此处为个人理解, 应该只是PCB数据结构的指针进行各个队列的出队/入队.)

3 线程

3.1 线程的使用意义

需要提出一种新的实体, 满足以下特性:

  • 实体之间可以并发地执行
  • 实体之间共享相同的地址空间

3.2 线程

3.2.1 线程特性

线程可以定义为: 进程当中的一条执行流程.

从两个方面来重新理解进程:

  • 从资源组合的角度: 进程把一组相关的资源组合起来, 构成了一个资源平台(环境), 包括地址空间(代码段, 数据段), 打开的文件等各种资源.
  • 从运行的角度: 代码在这个资源平台上的一条执行流程(线程).

线程的优点:

  • 一个进程中可以同时存在多个线程
  • 各个线程之间可以并发地执行
  • 各个线程之间可以共享地址空间和文件等资源

线程的缺点:

  • 一个线程崩溃, 会导致其所属进程的所有线程崩溃.

3.2.2 不同操作系统对线程的支持

3.2.3 线程所需的资源

3.2.4 线程与进程的比较

  • 进程是资源分配单位, 线程是CPU调度单位
  • 进程拥有一个完整的资源平台, 而线程只独享必不可少的资源, 如寄存器和栈
  • 线程同样具有就绪, 阻塞和执行三种基本状态, 同样具有状态之间的转换关系
  • 线程能减少并发执行的时间和空间开销:
  • 线程的创建时间比进程短
  • 线程的终止时间比进程短
  • 同一进程内的线程切换时间比进程短
  • 由于同一进程的各线程见共享内存和文件资源, 可直接进行不通过内核的通信.

3.3 线程的实现

主要有三种线程的实现方式:

  • 用户线程: 在用户空间实现
  • 内核线程: 在内核中实现
  • 轻量级进程: 在内核中实现, 支持用户线程

用户线程和内核线程的对应关系:

  • 多对一
  • 一对一
  • 多对多

3.3.1 用户线程

在用户空间实现的线程机制, 它不依赖于操作系统的内核, 由一组用户级的线程库函数来完成线程的管理, 包括进程的创建, 终止, 同步和调度等.

  • 由于用户线程的维护由相应进程来完成(通过线程库函数), 不需要操作系统内核了解用户线程的存在, 可用于不支持线程技术的多进程操作系统.
  • 每个进程都需要它私有的线程控制块(TCB)列表, 用来跟踪记录它的各个线程的状态信息(PC, 栈指针, 寄存器), TCB由线程库函数来维护.
  • 用户线程的切换也是由线程库函数来完成, 无需用户态/核心态切换, 所以速度特别快.
  • 允许每个进程拥有自定义的线程调度算法.

用户线程的缺点:

  • 阻塞性的系统调用如何实现? 如果一个线程发起系统调用而阻塞, 则整个进程在等待.
  • 当一个线程开始运行后, 除非它主动地交出CPU的使用权, 否则它所在的进程当中的其他线程将无法运行.
  • 由于时间片分配给进程, 故与其他进程比, 在多线程执行时, 每个线程得到的时间片较少, 执行会较慢.

3.3.2 内核线程

是指在操作系统的内核当中实现的一种线程机制, 由操作系统的内核来完成线程的创建, 终止和管理.

  • 在支持内核线程的操作系统中, 由内核来维护进程和线程的上下文信息(PCB和TCB)
  • 线程的创建, 终止和切换都是通过系统调用/内核函数的方式来进行, 由内核来完成. 因此系统开销较大.
  • 在一个进程当中, 如果某个内核线程发起系统调用而被阻塞, 并不会影响其他内核线程的运行.
  • 时间片分给线程, 多线程的进程获得更多CPU时间
  • Windows NT和Windows 2000/XP支持内核线程.

3.3.3 轻量级进程

它是内核支持的用户线程, 一个进程可有一个或者多个轻量级进程, 每个轻量级进程由一个单独的内核线程来支持.(Solaris/Linux)

3.4 多线程编程接口举例

4 进程控制

4.1 进程切换

停止当前运行进程(从运行状态改变成其他状态)并且调度其他进程(转变成运行状态)

  • 必须在切换之前存储许多部分的进程上下文
  • 必须能够在之后恢复他们, 所以进程不能显示它曾经被暂停过
  • 必须快速(上下文转换是非常频繁的)

需要存储的上下文:

  • 寄存器(PC, SP, ..), CPU状态, ...
  • 一些时候可能会费时, 所以我们应该尽可能避免

进程控制块PCB: 内核的进程状态记录

  • 内核为每个进程维护了对应的进程控制块
  • 内核将相同状态的进程的PCB放置在同一个队列(就绪队列, I/O等待队列--每一个设备一个队列, 僵尸队列等)

4.2 进程创建

进程创建是操作系统提供给用户使用的系统调用, 完成新进程的创建工作.

不同系统的进程创建API不同, 如下:

  • Windows进程创建API: CreateProcess(filename)
  • Unix/Linux进程创建系统调用: fork/exec, 其中fork完成把一个进程复制成两个进程, 两个进程只有进程ID不同(PID), 复制完成后exec把新程序加载进来重写当前进程(PID没有改变)

Unix/Linux进程创建系统调用示例如下:

int pid = fork();                //创建子进程//父进程执行完这一行之后, 创建出来的子进程和本身的父进程都会//继续向下执行, 只不过此时子进程的pid是0, 父进程返回的是子//的pid
if (pid == 0) {//此时说明是子进程, 就掉用exec执行想要执行的文件
}

fork()创建一个继承的子进程:

  • 复制父进程的所有变量和内存
  • 复制父进程的所有CPU寄存器(有一个寄存器例外)

fork()的地址空间复制:

  • fork()执行过程对于子进程而言, 是在调用时间对父进程地址空间的一次复制(对于父进程fork()返回child PID, 对于子进程返回值为0).
  • 系统调用exec()加载新程序取代当前运行进程.

4.3 进程加载

在Linux中会调用exec来加载新程序取代当前运行进程:

  • exec()调用允许一个进程"加载"一个不同的程序并且在main开始执行(事实上 _start)
  • 它允许一个进程指定参数的数量(argc: argument count)和它字符串参数数组(argv).
  • 如果调用成功, 进程PID还是原来的PID, 但是运行的程序改变了(原来运行的是父进程程序, 调用后运行加载的程序)
  • 其代码段, stack, heap都会重写

fork()的优化:

首先由前面已知, fork()的简单实现:

  • 对子进程分配内存
  • 复制父进程的内存和CPU寄存器到子进程里
  • 开销昂贵

但是, 在99%的情况里, 我们在调用fork()之后会继续调用exec(), 也就意味着:

  • 在fork()操作中内存复制是没有作用的
  • 子进程将可能关闭打开的文件和链接
  • 开销因此是高的
  • 为什么不能结合它们在一个调用中

vfork() --- 早期Unix系统提供

  • 一个创建进程的系统调用, 不需要创建一个同样的内存映像
  • 一些时候称为轻量级fork()
  • 子进程应该几乎立即调用exec()
  • 现在不再使用如果我们使用Copy on Write(COW)技术

4.4 进程的等待与退出

wait()系统调用是被父进程用来等待子进程的结束.

当一个进程结束之后, 一些资源(比如PCB等)是无法进行自我回收的.

一个子进程向父进程返回一个值, 所以父进程必须接受这个值并处理, wait()系统调用担任这个要求

  • 它使父进程去睡眠来等待子进程的结束
  • 当一个子进程调用exit()的时候, 操作系统解锁父进程, 并且将通过exit()传递得到的返回值作为wait调用的一个结果(连同子进程的pid一起), 如果这里没有子进程存在, wait()立即返回.
  • 当然, 如果这里有为父进程的僵尸等待, wait()立即返回其中一个值(并且解除僵尸状态).

具体步骤如下:

  • 进程结束执行之后, 它调用exit() -- 系统调用
  • 这个系统调用:
  • 将这个程序的"结果"作为一个参数
  • 关闭所有打开文件, 连接等等
  • 释放内存
  • 释放大部分支持进程的操作系统结构
  • 检查是否父进程是存活着的, 如果存活, 它保留结果的值直到父进程需要它: 在这种情况里, 进程没有真正死亡, 但是它进入了僵尸状态. 如果父进程没有存活 它释放所有的数据结构, 这个进程死亡.
  • 清理所有等待的僵尸进程
  • 进程终止是最终的垃圾收集(资源回收)

注意:

操作系统根进程(初始进程)会定期扫描僵尸进程, 并代替僵尸进程的父进程对其进行释放.

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

vs code ipynb文件_UE4引擎 源码的获取、安装,以及VS配置

1.首先我们需要注册一个Epic账户,网址如下http://api.unrealengine.com/CHN/GettingStarted/Installation/index.html#bookmark12.创建GitHub账户https://github.com/3.登录UE4社区点击个人进入到个人之后点击连接的账户,之后在下面填写我们GITHUB的昵称…

js bind 传参、_js中的面向对象(一)

面向对象要解决的问题提到面向对象,大家的第一反应就是封装、继承和多态。对其做如下解释:封装:影藏细节(A对A——将多行代码取个名字或A对B——API调用合作)继承:继承的意思就是同上跟上述一样&#xff0c…

计算机网络中的物理层

1 基础概念 物理层解决如何在链接各种计算机的传输媒体上传输数据比特流, 而不是指具体的传输媒体. 物理层的主要任务, 确定与传输媒体接口有关的一些特性. -> 定义标准 1.1 物理层规定的特性: 机械特性: 定义物理连接的特性, 规定物理连接时所采用的规格, 接口形状, 引…

二元置信椭圆r语言_医学统计与R语言:多分类logistic回归HosmerLemeshow拟合优度检验...

微信公众号:医学统计与R语言如果你觉得对你有帮助,欢迎转发输入1:multinominal logistic regression "nnet")结果1: test (multinomial model)输入2:ordinal logistic regression "MASS")结果2&am…

python3.7.2安装与配置_python3.7.0 安装与配置

python 3.7.0 X64下载地址: https://www.python.org/ftp/python/3.7.0/python-3.7.0-amd64.exe 更多版本下载请移步到:https://www.python.org/downloads/release/python-370/ python可以在同一台机器上进行多版本的安装使用。 安装好python3.7.0后确认系…

python3设置编码_python3 中文乱码与默认编码格式设定方法

python默认编码格式是utf-8。在python2.7中,可以通过sys.setdefaultencoding(gbk)设定默认编码格式,而在python3.3中sys.setdefaultencoding()这个函数已经没有了。在python3.3中该如何设置内置的默认编码格式啊!急求!&#xff01…

操作系统处理器调度

1 背景 1.1 上下文切换: 切换CPU的当前任务, 从一个进程/线程到另一个保存当前进程/线程在PCB/TCB中的执行上下文(CPU状态)读取下一个进程/线程的上下文 1.2 CPU调度: 从就绪队列中挑选一个进程/线程作为CPU将要运行的下一个进程/线程调度程序: 挑选进程/线程的内核函数(通过…

c# 操作redisclient 设置过期时间_C# Redis分布式锁单节点

(给DotNet加星标,提升.Net技能)转自:热敷哥cnblogs.com/refuge/p/13774008.html为什么要用分布式锁?先上一张截图,这是在浏览别人的博客时看到的.在了解为什么要用分布式锁之前,我们应该知道到底什么是分布式锁.锁按照不同的维度,有多种分类.比如1、悲观…

计算机网络数据链路层检错编码 --- 循环冗余码CRC

实例说明 假如要发送的数据是1101 0110 11, 采用CRC校验, 生成多项式是10011, 那么最终发送的数据应该是? 发送端发送过程: 1. 最终发送的数据 要发送的数据 帧检验序列FCS(冗余码) 2. 利用生成多项式计算冗余码 计算冗余码的方法: 1. 加0, 要根据生成多项式中的阶为, 则…

python和arduino串口通信_利用串行通信实现python与arduino的同步

我有一个需要:使用arduino将伺服电机移动到某个位置并在该位置停止 让一个由python控制的相机在那个位置获取图像 当图像被采集到时,伺服机构应该移动到一个对称的位置 这个序列重复N次 所以我尝试使用串行通信同步arduino和python代码。在arduino端&…

计算机网络中数据链路层编码纠错编码 --- 海明码

1 概述 首先, 海明码是计算机网络中数据链路层的针对帧的位错提出的一种纠错编码方式. 海明码可以发现双比特错, 但纠正单比特错. 工作原理(简单解释): 牵一发动全身 2 工作流程 2.1 确定校验码位数r 海明不等式: 其中为冗余信息位数, 为信息位数 如果给定要发送的数据, …

python在教育领域的应用_浅谈Python的主要应用领域

Python的用途较为广泛,小编也会经常接触到各种与Python有关的项目,也算是一名忠实的开发者。能够遇到关于Python用途的问题,也很乐意回答。Python这个概念非常大,它的定位是“计算机程序设计语言”,从它的特点来看&…

计算机操作系统同步互斥

1 背景 在计算机系统里面, 多道程序设计是现代操作系统的重要特征, 且并行起到了很大的作用, 所以操作系统抽象出来了线程/进程的概念用来支持多道程序设计, 同时, 各个进程之间需要进行交互, CPU也需要进行调度来支持多进程. 多进程会涉及到共享资源访问的问题, 如果操作系统…

leetcode 26 --- removeDuplicates

1 题目 给你一个有序数组 nums ,请你 原地 删除重复出现的元素,使每个元素 只出现一次 ,返回删除后数组的新长度。 不要使用额外的数组空间,你必须在 原地 修改输入数组 并在使用 O(1) 额外空间的条件下完成。 2 思路 此题要利…

conda安装tensorflow-gpu简洁版_win10 tensorflow2.2 安装注意事项

学习新技术有两座大山,一座是安装配置环境,另一座是调试bug。对于想学习人工智能开发的人来说,安装配置tensorflow是必不可少的一步,这个过程对于初次接触的人来说,到处都是火坑。下面大家跟我一起,看看都会…

python九九乘法表右对齐_python语法练习题之九九乘法表

九九乘法表 for...in方法实现 #方法一 for i in range(1, 10):for j in range(1, i1):print({}*{}{:<4}.format(j, i, i*j), end )print()#输出 1*11 1*22 2*24 1*33 2*36 3*39 1*44 2*48 3*412 4*416 1*55 2*510 3*515 4*520 5*525 1*66 2*612 3*618 4*624 5*630 6*636 1*7…

操作系统信号量和管程

1 背景 同步互斥回顾: 并发问题: 竞争条件(竞态条件) 多程序并发存在大量问题 同步 多线程共享公共数据的协调执行包括互斥与条件同步互斥: 在同一时间只有一个线程可以执行临界区 确保线程同步 需要高层次的编程抽象(如: 锁)从底层硬件支持编译 2 信号量 信号量是抽象数…

python里元组和列表的共同点和不同点_Python元组与列表的相同点与区别

列表和元组都属于有序序列&#xff0c;支持使用双向索引访问其中的元素、使用内置函数len()统计元素个数、使用运算符in测试是否包含某个元素、使用count()方法统计指定元素的出现次数和index()方法获取指定元素的索引。虽然有着一定的相似之处&#xff0c;但列表和元组在本质上…

操作系统中死锁避免算法 --- 银行家算法

1. 背景 在银行系统中, 客户完成项目需要申请贷款的数量是有限的, 每个客户在第一次申请贷款时要声明完成该项目所需的最大资金量, 在满足所有贷款要求并完成项目时, 客户应及时归还. 银行家在客户申请的贷款数量不超过自己拥有的最大值时, 都应尽量满足客户的需要. 在这样的描…

python字符串对齐_Python - 字符串对齐

字符串对齐 本文地址: http://blog.csdn.net/caroline_wendy/article/details/20463231 Python中, 字符串对齐, 使用ljust(), 左对齐;rjust(), 右对齐; center(), 中间对齐; 也可以修改第三个参数, 修改填充数据, 默认使用空格; 代码如下: # -*- coding: utf-8 -*- # #File: Te…