ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

操作系统概念第三章

2021-01-23 13:33:17  阅读:87  来源: 互联网

标签:第三章 操作系统 队列 调度 概念 进程 邮箱 执行 CPU


进程的概念

进程是执行的程序

程序本身并不是进程,程序只是被动的实体,如一个可执行文件,进程是一个活动的实体,具有一个程序计数器表示下一个执行命令和一组资源。

如果两个进程和同一个程序相关联,但是这两个进程回被当作两个不同的执行序列。虽然他们的文本段相同,但是数据,堆,堆栈却不同

进程也可以被当作为一个环境,用于执行其他代码,如java虚拟机

一个完整的进程由如下几部分组成

  • 文本段(有时也被称为代码段)
  • 当前活动:程序记数器(程序计数器就是一个指针变量,指向线程中代码执行到的位置。每执行完一条指令,计数器+1)的值,处理器寄存器的内容
  • 进程堆栈:临时数据,函数参数,返回地址和局部变量
  • 数据段:包括全局变量,static
  • 堆:这是在进程运行时动态分配的内存

进程状态

进程在执行时会改变状态,部分取决于进程的当前活动。

  • 新的:进程正在创建
  • 运行:进程正在执行
  • 等待:进程等待发生某个时间(io操作或者收到信号)
  • 就绪:进程等待分配处理器
  • 终止:进程已经完成执行

** 一次只能有一个进程可以在处理器上运行,但同时可以有很多进程处于等待或者就绪状态 **

进程控制块

操作系统每一个进程表示,采用进程控制块(pcb)也称为任务控制块,相当于进程的标签

pcb包含的内容如下

  • 进程状态:状态可以包括** 新的、运行、就绪、等待、终止 **
  • 程序计数器:计数器表示进程要执行下一条指令的地址
  • cpu寄存器: 包括累加器,索引寄存器,堆栈指针,通用寄存器和其他条件码信息寄存器,在发生中断时,这些状态信息要和程序计数器一起保存
  • cpu调度信息:包括进程优先级,调度队列的指针和其他调度参数
  • 内存管理系统:这些系统可以包括基地址,界限寄存器的值、页表、段表。
  • 记账信息:cpu时间,实际使用时间,时间期限,记账数据,进程数量。
  • io状态信息:分配给进程的io设备列表打开文件列表。

进程的切换图示

线程

在多核系统中,可以并行运行多个线程。在支持线程的系统中,pcb被扩展成包括每个线程的信息。

进程调度

多道程序设计的目的:无论何时都有进程运行,从而最大化cpu利用率

分时系统目的:在进程之间快速切换cpu,以便用户在程序执行的时候能与之交互

进程调度器:在多个可用进程中选用一个可用进程到cpu上执行。

调度队列

进程在进入系统时,会被加到作业队列(包含所有的进程)

就绪队列用链表实现,头节点有两个指针,一个指向链表的第一个pcb和最后一个pcb块。每个pcb包含一个指针指向队列中下一个pcb块

等待特性io的队列为设备队列,每个队列都有自己的设备队列

进程被放回到就绪队列之后可能发生的事情

调度程序

进程在整个生命周期中,会在各种调度队列之间迁移。操作系统为了按一定方式从这些队列中选择进程,进程选择通过适当调度器或调度程序(scheduler)来执行。

长期调度程序(long-term scheduler)从大容量存储设备(通常为磁盘)的缓冲池中选择进程,加到内存中,以便执行。

短期调度程序(short-term scheduler)或CPU调度程序(CPU scheduler)从准备执行的进程中选择进程,并分配给CPU。

这两种调度程序的主要区别是执行效率。

短期调度程序必须经常为CPU选择新的进程。进程可能执行几毫秒,就会等待I/O请求。通常,短期调度程序每100ms至少执行一次。由于执行之间的时间短,短期调度程序必须快速。

而长期调度程序执行并不频繁,在新进程的创建之前,可能有几分钟的间隔。长期调度程序控制多道程序程度(内存中的进程数量)。因此,只有在进程离开系统时,才需要长期调度程序的调度。由于每次执行之间的更长时间间隔,长期调度程序可以负担得起更多时间,以便决定选择执行那个进程。长期调度程序需要认真选择。

** 大多数进程可分为:I/O为主或CPU为主 **

I/O密集型进程(I/O-bound process),执行I/O比执行计算需要花费更多时间。

CPU密集型进程(CPU-bound process)很少产生I/O请求,而是将更多时间用于执行计算。

所以,长期调度程序应该选择I/O密集型和CPU密集型的合理进程组合。

如果所有进程都是I/O密集型的,那么就绪队列几乎总是为空,从而短期调度程序没有什么可做。
如果所有进程都是CPU密集型的,那么I/O等待队列几乎总是为空,从而设备没有得到使用,因而系统会不平衡。
所以,为了使得性能最佳,系统需要I/O密集型和CPU密集型的进程组合。

有的操作系统如分时系统,可能引入一个额外的中期调度程序(medium-term scheduler)。

中期调度程序的核心思想是可将进程从内存(或从CPU竞争)中移出,从而降低多道程序程度。之后,进程可被重新调入内存,并从中
断处继续执行。这种方案称为交换(swap)。通过中期调度程序,进程可换出(swap out),并在后来可换入(swap in)。
为了改善进程组合,或者由于内存需求改变导致过度使用内存从而需要释放内存,就有必要使用交换

三者之间的差异

短期调度:短期调度在内存进程中选择就绪执行的进程加载到CPU
中期调度:中期调度将部分运行进程移出内存,之后又加载进程到内存,从中断处运行
长期调度:长期调度从大容量存储设备的缓冲池中选择进程加载到内存

上下文切换

上下文切换:操作系统保存正在运行的进程中的上下文,然后恢复将要运行进程的上下文

进程上下文采用PCB表示,包括CPU寄存器的值,进程状态和内存信息管理等。

通常,通过执行状态保存(state save),保存CPU当前状态(包括内核模式和用户模式),之后,状态恢复(state restore)重新开始运行。

进程运行

大多数系统的进程能够并发执行,它们可以动态创建和删除。

进程创建

进程在执行过程中可能创建多个新的进程。创建进程称为父进程,而新的进程称为子进程。每个新进程可以在创建其他的进程,从而形成进程树(process tree)。

大多数的操作系统对进程的识别采用的是唯一的进程标识符(pid)这通常是一个整数值。

系统内的每个进程都有唯一的pid,它可以用作索引,以便访问内核中的进程的各种属性。

当一个进程创建子进程时,该子进程会需要一定的资源(CPU时间,内存等)来完成任务。

子进程可以从操作系统那里直接获得资源
子进程也可以父进程那里获得资源子集。父进程可能会在子进程之间分配资源或共享资源

当进程创建新进程时,可有两种执行可能:

父进程与子进程并发执行
父进程等待,直到某个或全部子进程执行完

新进程的地址空间也有两种可能:

子进程是父进程的复制品
子进程加载另一个程序(如使用系统调用exec())

进程终止

当进程完成执行最后语句并且通过系统调用exit()请求操作系统删除自身时,进程终止。

父进程终止子进程的原因有很多,如以下三种:

子进程使用了超过它所分配的资源(为判定是否发生这种情况,父进程应有一个机制,以检查子进程的状态)。
分配给子进程的任务,不再需要。
父进程正在退出,而且操作系统不允许无父进程的子进程继续执行。

级联终止:如果一个进程终止,那么它的所有子进程也应终止。这种现象,就叫做级联终止。

当一个进程终止时,操作系统会释放其资源。但它位于进程表中的条目还是在的,直到它的父进程调用wait(),这是因为进程表包含了进程的退出状态。

僵尸进程(zonbie process):当进程已经终止,但是其父进程尚未调用wait()

所有进程终止时都会过度到这种状态,但是一般僵尸只是短暂存在。一旦父进程调用了wait(),僵尸进程的进程标识符和它在进程
表中的条目就会释放。

如果父进程没有调用wait()就终止,子进程就会称为孤儿进程。但linux和unix对此的处理:把init进程当成孤儿的爸爸。init定期调用wait()帮助孤儿超度。

进程间通信

操作系统内的并发执行进程可以是独立的也可以是协作的。

如果一个进程不能影响其它进程或受其他进程影响,那么该进程是独立的。显然,不与任何其他进程共享数据的进程是独立的。
如果一个进程能影响其他进程或受其他进程所影响,那么该进程是协作的。显然,与其他进程共享数据的进程为协作进程

提供环境允许进程协作,有很多理由:

  • 信息共享(information sharing):由于多个用户可能对同样的信息感兴趣(例如共享文件),所以应提供环境以允许并发访问这些信息。
  • 计算加速(computation speedup):可以把一个任务分成多个子任务,每个子任务可以与其他子任务并发执行。
  • 模块化(modulrity):可能需要按模块化方式构造系统,可将系统功能分成独立的进程或线程。
  • 方便(convenience):即使单个用户也可能同时执行许多任务。

协作进程需要有一种进程间通信(InterProcess Communication,IPC)机制,以允许进程相互交换数据与信息。

进程间通信有两种基本模型:

  • 共享内存(shared memory): 共享内存会建立一块供协作进程共享的内存区域,进程通过向此共享区域读出与写入数据来交换信息
  • 消息传递(message passing): 消息传递模型通过在协作进程间交换消息来实现通信

两者的比较:

消息传递对于交换较少数量的数据很有用,因为无需避免冲突。对于分布式系统,消息传递也比共享内存更易实现。
共享内存可以快于消息传递。这是因为消息传递实现经常采用系统调用,因此需要消耗更多时间以便内核介入。与此相反,共享内存
系统仅在建立共享区域时需要调用系统调用,一旦建立共享内存,所有访问都可以作为常规内存访问,无需借助内核。

共享内存系统

采用共享内存的进程间通信,需要通信进程建立共享内存区域。

生产者-消费者问题

** 生产者(producer)进程生产信息,以供消费者(consumer) **进程消费,解决生产者消费者的问题的方法之一是,采用共享内存。为了允许生产者进程和消费者进程并发执行,应有一个可用的缓冲区,以被生产者填充和被消费者清空。这个缓冲区驻留在生产者进程和消费者进程的共享区域内。当消费者使用一项时,生产者可产生另一项。

生产者和消费者必须同步,这样消费者和不会试图消费一个尚未生产出来的项。

同步:一件事情必须先做什么再做什么,否则不能继续下去。

缓冲区类型分为两种:

无界缓冲区(unbounded-buffer):没有限制缓冲区的大小。 消费者不得不等待新的项,但生产者总是可以产生新项。

有界缓冲区(bounded-buffer):固定大小的缓冲区。如果缓冲区为空,消费者必须等待。如果缓冲区已满,生产者必须等待。

消息传递系统

操作系统提供机制,以便协作进程通过消息传递功能进行通信。
这有三种方法,用于实现链路和操作send()/receive():

  • 直接或间接的通信
  • 同步或异步的通信
  • 自动或显式的缓冲

命名

** 直接通信(direct communication) **:直接通信需要通信的每个进程必须明确指定通信的接收者或发送者。

send(p,message): 向进程P发送message
receive(Q,message):从进程Q接收message

这种方案具有以下三种属性:

  • 需要通信的每对进程之间,自动建立链路。进程仅需知道对方身份就可进行交流。
  • 每个链路只与两个进程相关
  • 每对进程之间只有一个链路

这种方案展示了寻址的对称性(symmetry),即发送和接收进程必须指定对方,以便通信。

下面一种采用寻址的非对称性(asymmetry),即只要发送者指定接收者,而接收者不需要指定发送者。

send(P,message):向进程P发送message
receive(id,message):从任何进程,接受message,这里变量id被设置成与其通信进程的名称。

这两个方案都有一定的缺点:

生成进程定义的有限模块化。
更改进程标识符可能需要分析所有其他进程定义,所有旧的标识符的引用都应被找到,以便修改成为新标识符。

邮箱

** 间接通信(indirect communication) **:间接通信通过邮箱或端口来发送和接收消息。

邮箱可以抽象成一个对象,进程可以向其中存放消息,也可从中删除消息,每个邮箱都有一个唯一的标识符。

一个进程可以通过多个不同邮箱与另一个进程通信

send(A, message):向邮箱A发送message
receive(A, message):从邮箱A接受message

这种方案有以下三种特点:

只有在两个进程共享一个邮箱时,才能建立通信线路。
一个链路可以与两个甚至更多进程相关联。
两个通信进程之间可有多个不同链路,每个链路对应于一个邮箱

假设进程P1,P2和P3都共享邮箱A,进程P1发送一个消息到A,而进程P2和P3都对A执行receive()。那么哪个进程会收到P1发送的消息?
答案不是唯一的,取决于所选择的方案:

  • 允许一个链路最多与两个进程关联
  • 允许一次最多一个进程执行receive()
  • 允许系统随意选择一个进程以便接收消息(即P2和P3两者之一都可以接收消息,但不能两个都可以)

** 系统同样可以定义一个算法选择哪个进程是接收者,系统还可以让发送者指定接收者 **

邮箱可以为进程或操作系统拥有

如果邮箱为进程所拥有(即邮箱是进程地址空间的一部分),那么需要区分所有者(只能从邮箱接受消息)和使用者(只能向邮箱发送消息)。每个邮箱都有唯一的标识符。当拥有邮箱的进程终止,那么邮箱就会消失。任何进程后来向该邮箱发送消息,都会得知邮箱不存在。

如果邮箱为操作系统拥有,那么邮箱是独立的,他不属于某个特定进程。因此操作系统必须提供机制以便进程进行如下操作

  • 创建新的邮箱
  • 通过邮箱发送和接受消息
  • 删除邮箱

创建新邮箱的进程缺省为邮箱的所有者,所有者是唯一能够通过邮箱接受消息的进程,不过通过系统调用可以把拥有权和接受权限传给其他进程,这样就会有多个接受者。

同步

进程间通信可以通过调用原语send()和receive()来实现

消息传递可以是阻塞(blocking)或非阻塞(nonblocking),也称为同步(synchronous)或异步(asynchronous)。

发送接收有以下四种:

  • 阻塞发送(blocking send):发送进程阻塞,直到消息由接收进程或邮箱所接收
  • 非阻塞发送(nonblocking send):发送进程发送消息,并且恢复操作,不会等待
  • 阻塞接收(blocking receive):接收进程阻塞,直到有消息可用
  • 非阻塞接收(nonblocking receive):接收进程收到一个有效消息或空消息

缓存

不管通信是直接的还是间接的,通信交换的消息总是驻留在临时队列中。也就是缓存

队列实现有三种方法:

  • 零容量(zero capacity):队列的最大长度为0,因此,链路中不能有任何消息处于等待,这种情况下,发送者应该阻塞,直到接收者接收到消息。
  • 有限容量(bounded capacity):队列长度为有限的n,因此最多只能有n个消息驻留其中,如果在发送新消息时队列未满,那么该消息可放在队列中,且发送者可以继续执行而不必等待。然而,链路容量有限,如果链路已满,那么发送者应该阻塞,知道队列空间有可用的为止。
  • 无限容量(unbounded capacity):队列长度可以无限。因此,不管多少消息都可在其中等待。发送者从不阻塞。

标签:第三章,操作系统,队列,调度,概念,进程,邮箱,执行,CPU
来源: https://www.cnblogs.com/mots/p/14317351.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有