操作系统(第二章)进程与线程

第二章

  • 2.1 进程
    • 2.1.1进程模型
    • 2.1.2 进程的创建
    • 2.1.3 进程的终止
    • 2.1.4 进程的层次结构
    • 2.1.5 进程的状态
    • 2.1.6 进程的实现
  • 2.2 线程
    • 2.2.1 线程模型
    • 2.2.2 线程的使用
    • 2.2.3 在用户空间实现线程
    • 2.2.4 在内核中实现线程
    • 2.2.5 混合实现
    • 2.2.6 调用程序激活机制
    • 2.2.7 弹出式线程
  • 2.3 进程间通信
    • 2.3.1 竞争条件
    • 2.3.2 临界区
    • 2.3.3 忙等待的互斥
    • 2.3.4 休眠与唤醒
    • 2.3.5 信号量
    • 2.3.6 互斥信号量
    • 2.3.7 管程
    • 2.3.8 消息传递
    • 2.3.9 屏障
  • 2.4 经典的IPC问题
  • 2.5 调度
    • 2.5.1 调度介绍
    • 2.5.2 批处理系统中的调度
    • 2.5.3 交互式系统中的调度
    • 2.5.4 实时系统中的调度
    • 2.5.5 策略和机制
    • 2.5.6 线程调度

2.1 进程

  • 严格的说,在某一个瞬间,CPU只能运行一道程序。

2.1.1进程模型

  • 在进程模型中,计算机上所有可运行的软件,通常也包括操作系统,被组织成若干顺序进程,简称进程。
  • 一个进程就是一个正在执行的程序,包括程序计数器、寄存器和变量的当前值。
  • 从概念上来说,每个进程拥有他自己虚拟CPU。当然,实际上真正的CPU在各进程之间来回切换,这种快速的切换成为多道程序设计
  • 由于CPU在各个进程之间来回切换,所以每个进程之间执行其运算的速度是不确定的,而且当同一进程再次运行时,其运行速度通常也不可再现。所以,在进程编程时绝不能对时序做任何确定的假设。
  • 一个进程时某种类型的一个活动,它有程序、输入、输出以及状态。单个处理机可以被若干 进程共享,它使用某种调度 算法决定何时停止一个进程的工作,并转而为另一个进程提供服务。

2.1.2 进程的创建

  • 有四种原因导致进程的创建:

(1)系统初始化
(2)执行了从事创建进程的一个系统调用,该系统调用被正在运行的进程所调用
(3)用户请求创建一个新进程
(4)一个批处理作业的初始化

  • 在UNIX系统中,只能一个系统调用可以来创建新进程:fork。
  • 在UNIX和Windows中,进程创建之后,父进程和子进程都有各自不同的地址空间。

2.1.3 进程的终止

  • 进程的终止通常是由下列条件引起的:

(1)正常退出(自愿的)
(2)出错退出(自愿的)
(3)严重错误(非自愿)
(4)被其他进程杀死(非自愿)

2.1.4 进程的层次结构

  • 在UNIX中,进程和它的所有子女以及后裔共同组成一个进程组。
  • 在Windows中不存在任何进程层次结构的概念,所有的进程都是地位相同的。唯一有一些类似于进程层次结构存在的是在创建进程的时候,父进程得到一个特殊的令牌(称为句柄),该句柄可以用来控制子进程。但是,它有权把这个令牌传送给某个其他进程,这样就不存在层次结构。
  • 在UNIX中,进程就不能拒绝其子女的继承权。

2.1.5 进程的状态

  • 进程的三种状态:

(1)运行态(该时刻进程实际占用CPU)
(2)就绪态(可运行,但因为其他进程正在运行而暂时停止)
(3)阻塞态(除非某种外部事件发生,否则进程不能运行)

操作系统(第二章)进程与线程_第1张图片

2.1.6 进程的实现

  • 为了实现进程模型、操作系统维护着一张表格(一个结构数组),即进程表。
  • 每个进程占用一个进程表项。
进程管理 存储管理 文件管理
寄存器 正文段指针 根目录
程序技术器 数据段指针 根目录
程序状态字 堆栈段指针 文件描述符
堆栈指针 用户ID
进程状态 组ID
优先级
调度参数
进程ID
父进程
进程组
信号
进程开始时间
使用的CPU时间
子进程的CPU时间
下次报警时间
  • 中断发生后操作系统最底层的工作步骤:

1.硬件压入堆栈程序计数器等
2.硬件从中断向量装入新的程序计数器
3.汇编语言过程保存寄存器值
4.汇编语言过程设置新的堆栈
5.C中断服务例程运行(典型的读和缓存输入)
6.调度程序决定下一个将运行的进程
7.C过程返回至汇编代码
8.汇编语言过程开始运行新的当前进程

2.2 线程

  • 在传统操作系统中,每个进程有一个地址空间和一个控制线程。不过经常存在同一个地址空间中准并行运行多个一个控制线程的情形,这些线程就像分离的进程(共享地址空间除外)。

2.2.1 线程模型

  • 进程拥有一个执行的线程,通常简称为线程。
  • 线程拥有寄存器,用来保存线程当前的工作变量。
  • 线程还拥有一个堆栈,用来记录执行历史,其中每一帧保存了一个已调用的但是还没有从中返回的过程。
  • 进程用于把资源集中到一起,而线程则是在CPU上被调度执行的实体。

2.2.2 线程的使用

  • 构造服务器的三种方法:
模型 特性
多线程 并行性、阻塞系统调用
单线程进程 无并行性、阻塞系统调用
有限状态机 并行性、非阻塞系统调用、中断

2.2.3 在用户空间实现线程

操作系统(第二章)进程与线程_第2张图片

  • 用户级线程包可以在不支持线程的操作系统上实现。
  • 在用户空间管理线程时,每个进程需要有其专用的线程表,用来跟踪该进程中的线程。
  • 用户级线程允许每个进程有自己定制的调度算法。
  • 用户级线程问题:

如何实现阻塞系统调用
页面失效问题
如果一个线程开始运行,那么在该进程中的其他线程就不能运行,除非第一个线程自动放弃CPU。

2.2.4 在内核中实现线程

操作系统(第二章)进程与线程_第3张图片

  • 此时不再需要运行时系统了。
  • 每个进程中也没有线程表
  • 在内核中有用来记录系统中所有线程的线程表
  • 没有用户级线程的问题
  • 系统调用的代价比较大

2.2.5 混合实现

  • 使用内核级线程,然后将用户级线程与某些或则全部内核线程多路复用起来。

2.2.6 调用程序激活机制

  • 调度程序激活工作的目标是模拟内核线程的功能,但是为线程包提供通常在用户空间中才能实现的封号的性能和更大的灵活性。
  • 由于避免了在用户空间和内核空间之间的不必要转换,从而提高了效率

2.2.7 弹出式线程

  • 在分布式系统中经常使用线程。
  • 一个消息的到达导致系统创建一个处理该消息的线程,这种线程成为弹出式线程。·

2.3 进程间通信

2.3.1 竞争条件

  • 两个或多个进程读写某些共享数据,而最后的结果取决于进程运行的精确时序,称为竞争条件。

2.3.2 临界区

  • 我们把对共享内存进行访问的程序片段称作临界区域或则临界区。
  • 避免竞争条件的好的方案,需要满足以下4个条件:

(1)任何两个进程不能同时处于临界区。
(2)不应对CPU的速度和数量做任何假设
(3)临界区外运行的进程不得阻塞其他进程
(4)不得使进程无限期等待进入临界区

2.3.3 忙等待的互斥

  • 1.禁止中断

最简单的方法是使每个进程在刚刚进入临界区后立即禁止所有中断,并在就要离开之前再打开中断。CPU只有发生时钟中断或其他中断时才会进行进程切换,这样再禁止中断后,CPU将不会切换到其他进程。

禁止中断对于操作系统本身而言是一项很有用的技术,但对于用户进程则不是一种合适的通用互斥机制。

  • 2.锁变量

设想有一个共享锁变量,其初值为0.当一个进程想要进入临界区,它首先测试这把锁。如果该锁的值为
0,则该进程将其设置为1并进入临界区。若这把锁的值已经为1,则该进程将等待直到其值变为0。于是,0就表示临界区内没有进程,1表示已经有某个进程进入临界区。

但是有可能另一个进程在锁的值变为1之前就读取到锁的值,所以还是会发生竞争条件

  • 3.严格轮换法

避免了竞争条件,但是违背 了条件3,不是最好的方案

  • 4.Peterson解法

将锁变量与警告变量的思想相结合。

  • 5.TSL指令

2.3.4 休眠与唤醒

  • Peterson解法和TSL解法都是正确的,但它们都有忙等待的缺点。这些解法在本质上是这样的:当一个进程想要进入临界区时,先检查是否允许进入,若不允许,则该进程将原地等待,直到允许为止。
  • sleep和wakeup

2.3.5 信号量

  • 信号量使用一个整形变量来累计唤醒次数,供以后使用。

2.3.6 互斥信号量

  • 如果不需要信号量的计算能力,有时可以使用信号量的一个简化版本,成为互斥信号量。
  • 互斥信号量仅仅适用于管理共享资源或一小段代码。
  • 互斥信号量是一个可以处于两态之一的变量:解锁和加锁。

2.3.7 管程

  • 为了更易于编写正确的程序,Hoare和Brinch提出了一种高级同步原语,成为管程。
  • 一个管程是一个由过程、变量以及数据结构等组成的集合。
  • 管程有一个跟重要的特性,即任一时刻管程中只能有一个活跃进程,着一特性使管程能有效的完成互斥。

2.3.8 消息传递

  • 信号量太低级了,而管程除了在少数几种编程语言之外又无法使用,并且,这些原语均未提供机器间信息交换方法。
  • 消息传递:这种进程间通信的方法使用两条原语send和receive,他们像信号量而不像管程,是系统调用而不是语言成分。因此,可以很容易地将他们加入到库例程中去。

2.3.9 屏障

  • 最后一个同步机制是准备用于进程组而不是用于双进程的生产者-消费者类情形的。在这些应用中划分了若干阶段。并且规定,除非所有的进程都就绪准备着手下一个阶段,否则任何进程都不能进入下一个阶段。可以通过在每个阶段的结尾安置屏障来实现这种行为。

2.4 经典的IPC问题

  • 1.哲学家就餐问题
  • 2.读者-写者问题
  • 3.睡眠理发师问题

2.5 调度

2.5.1 调度介绍

  • 1.进程行为
  • 2.何时调度

(1)在创建一个新进程后,需要决定是运行父进程还是子进程
(2)在一个进程退出时必须做出调度决策
(3)当一个进程阻塞在I/O和信号量上或由于其他原因阻塞时,必须选择另一个进程运行
(4)在一个I/O中断发生时,必须做出调度决策

根据如何处理时钟中断,可以把调度算法分为两类。非抢占式调度和抢占式调度

  • 3.调度算法分类

(1)批处理
(2)交互式
(3)实时

2.5.2 批处理系统中的调度

  • 1.先来先服务

在所有的调度算法中,最简单的时非抢占式的先来先服务算法

  • 2.最短作业优先

非抢占式的批处理调度算法
在所有的作业都同时可运行的情形下,最短作业优先算法是唯一最优化的

  • 3.最短剩余时间优先

最短作业优先的抢占式版本
使用这个算法,调度程序总是选择其剩余运行时间最短的那个进程运行

  • 4.三级调度

接纳调度程序
内存调度程序
CPU调度程序
操作系统(第二章)进程与线程_第4张图片

2.5.3 交互式系统中的调度

  • 1.轮换调度
  • 2.优先级调度
  • 3.多级队列
  • 4.最短进程优先
  • 5.保证调度
  • 6.彩票调度
  • 7.公平分享调度

2.5.4 实时系统中的调度

  • 实时系统通常可以分为硬实时和软实时,前者的含义是必须满足绝对的截至时间,后者的含义是虽然不希望偶尔错失截至时间,但是可以容忍。
  • 实时系统中的事件可以按照响应方式进一步分类为周期性和非周期性事件。
  • 实时系统的调度算法可以是静态或动态的。

2.5.5 策略和机制

2.5.6 线程调度

你可能感兴趣的:(操作系统,unix,windows,服务器)