操作系统笔记-2-进程

进程是什么

大部分资料都描述进程是资源分配的基本单位,但是这个描述并不能很好的描述进程的特性;另一个种描述是进程是对运行程序的一种抽象,我更赞同这种说法,第一它说明进程和程序有关系,第二它说明必须是运行中的程序。我们看一下Linux下的进程。

进程概念

进程内存布局

进程的内存布局被划分为多个分段,具体如图

img

  • text分段:存放可执行代码,也就是程序的代码
  • data分段:存放全局变量
  • heap分段:程序运行期间动态分配的内存
  • stack分段:方法调用的临时内存(比如方法参数、返回地址和临时变量)

一个进程内存布局例子

img

进程状态

进程五状态变化图

img

  • new:进程new状态,创建之后就会进入ready状态
  • ready:当ready状态的线程被调度器选择时进入running状态,而被中断时又会重新进入ready状态
  • running:处于ready状态的进程被调度器调度时会进入running状态执行,此时进程持有cpu执行权
  • waiting:当runing状态的进程I/O或事件等待时,会进入waiting状态,当I/O或事件完成时会进入ready状态等待调度器调度
  • terminated:当处于running状态的进程运行退出时会进入终止状态
进程控制块
  • 进程控制块定义:在多道程序系统中,多个程序并发执行,也就是多个进程并发执行,依赖调度器调度进程获得CPU执行权。这就需要操作系统维护各个进程的信息,比如说当前运行的线程被中断,那下一次要调度时肯定需要知道中断前的状态(比如代码执行到哪一行,寄存器的值等)。这些信息都被存在进程表中,每个进程对应一个表项,这些表项被称为进程控制块

  • 进程控制块结构(PCB)

    img

    主要分为进程管理、内存管理以及进程打开的文件管理三块,有几个重点关注的属性

    1. Process state:也就是上边介绍的进程的五种状态new, ready, running, waiting, halted等
    2. Program counter:指向进程下一条执行的指令地址
    3. CPU registers:cpu寄存器状态,用于被重新调度时,恢复cpu寄存器使进程正确的从上一次被中断处继续运行
    4. 其他信息在后面的笔记中介绍
线程

在支持线程的系统中,每个进程至少拥有一个线程,此时系统调度的便是线程而不是进程,进程成为线程的容器,PCB中也会额外的记录线程信息。现代的进程一般都拥有多个线程,这样可以提升程序的性能,因为在多核处理器上,多个线程可以并行执行。对于线程的,下一篇笔记中会详解介绍。注意线程是不能脱离进程独立存在的,因为操作系统不会为线程分配系统资源,因此线程要依附进程存在。

进程调度

线程调度是为了充分利用CPU和程序并发执行,因为当一个进程等待I/O或某个事件时,CPU不能做任何事,这个时候就可以调度其他进程执行。那进程是如何调度呢?下面来分析

调度队列

一个进程创建完成时,通常是进入就绪队列,就绪队列是等待调度获得CPU执行权的一个链表队列,如下图所示,链表头指向第一个PCB。

img

当然也有其他队列,比如wait队列,wait队列中的进程通常都在等待一个确定的事件,等到事件发生时,它们将会加入就绪队列中。一个进程cpu->wait队列->ready队列的转变如下图所示

img

CPU调度

这一部分在后边的笔记中做详细介绍

上下文切换
  • 上下文:上下文指的是进程运行时的状态,这些状态包括寄存器值、进程状态和内存管理信息,都存储在上边介绍的PCB中

  • 上下文切换:指的是,CPU在通过调度由执行A进程换成B进程时,需要将A进程的状态保存到A的PCB中,然后从B的PCB中加载上下文信息,这是一个纯开销的操作,因为此时CPU不能做其他有用的工作,其速度取决于内存的速度、需要复制的寄存器数和指令。整个过程的示意图如下

    img

进程间通信(IPC)

进程通信的必要性
  • 信息共享:如果多个应用都对某个信息有兴趣,必须对信息的访问作并发控制
  • 加速计算:把一个任务拆分成多个子任务,子任务可以并行计算
  • 模块化:用不同的进程或线程划分系统功能独立运行,使得系统具有模块化
IPC方式-共享内存
  • 共享内存结构

    img

  • 共享内存优点

    速度快:相比消息传递,共享内存只需要在创建共享内存时需要系统调用,消息传递每次都需要系统调用

  • 共享内存缺点

    实现比消息传递复杂,需要避免冲突,分布式共享内存实现复杂

  • 共享内存的并发(在后续的并发笔记中介绍)

IPC方式-消息传递
  • 消息传递结构

    img

  • 消息传递的优点

    1. 可以用于分布式环境
    2. 不需要相同的内存地址空间
  • 消息传递-命名

    1. 直接相连:当两个进程需要通信时,如果建立直接link,则需要互相精确知道进程
    2. 间接相连:进程不直接相连而是通过额外的结构,比如mailboxes或ports
  • 消息传递-通信方式

    1. 阻塞:如果阻塞的方式,那么send方法将阻塞直到被其他进程receive(直接相连)或者发送到mailboxes,receive方法将阻塞直到接收到消息
    2. 非阻塞:进程在调用send方法时不阻塞,receive方法也是直接返回消息或者null
  • 消息传递-queue缓存区

    1. Zero容量:queue没有缓冲区,因此sender将阻塞直到recipient接收消息
    2. Bounded:有界队列,当queue满时,sender阻塞直到queue有空间容纳消息
    3. Unbounded:无界队列,可以容纳任意数量的消息

总结

进程是操作系统中非常重要的一部分,一篇笔记是不可能记录得了进程的所有内容,这里忽略了很多细节,比如进程的调度算法,进程内存不足时内存置换算法,进程的同步方式,这些都会在后边详细介绍。