跳转至

Processes

约 2168 个字 25 行代码 5 张图片 预计阅读时间 15 分钟

进程的概念

进程是正在运行中的程序,进程的执行必须是有序的。

一个进程中包含如下部分

  • text section (code):存储代码
  • data section (global vars):存储全局变量和静态变量
  • stack (function parameters, local vars, return addresses):栈,存储函数参数、局部变量以及返回值等
  • heap (dynamically allocated memory):堆,由程序员动态分配的内存
  • program counter:指向当前正在执行指令的下一条指令
    a

思考:为什么堆和栈是反向的,而不是都是往同一个方向增长?

反向增长可以增加分配的灵活性,中间那部分空间既可以被堆使用,也可以被栈使用。如果二者是同向增长的,因为不知道进程执行中会使用多大的空间来分配给堆和栈,导致空间分配的不变。

中间那空的部分在实际的使用中并不是在进程启动的时候就分配的,而是一块虚拟的映射,只有在实际使用的时候才会分配具体的物理空间给它

进程状态(Process State)

  • 进程在运行的过程中会有不同的状态
    1. new:进程被创建
    2. running:进程中的指令正在被执行
    3. ready:进程准备完成,等待 CPU 资源进行执行(已经加载到内存中)
    4. waiting/blocked:进程处于等待或者阻塞的状态(比如等待 I/O 操作)
    5. terminated:进程已经完成执行

a

一个例子

运动会比赛模型

  • 运动员:Process
    • 号码簿:Process ID
  • 跑道:CPU core
    • 每条跑道只能有一个运动员
    • 运动场可以有一条/多条跑道
  • 跑步:Running
    • 允许打水喝
    • 接受调度,让出跑道
    • 离场地点必须记录以便继续
  • 口渴下场喝水:Wait I/O
    • 打水过程运动员处于wait状态,直到喝完才能返回运动场
    • 打水很慢,其他人也打水
  • 等待上跑道: Ready 状态

进程控制块(PCB)

PCB 中存储着每个进程的相关信息

  • Process state:进程状态
  • Program counter:进程执行的位置,也就是下一条需要执行指令的位置
  • Contents of CPU registers:寄存器相关信息
  • CPU scheduling information:CPU 调度的参考信息(优先级、调度队列的指针、调度参数等)
  • Memory-management information:内存管理信息(页表、段表等信息,与具体的内存系统有关)
  • Accounting information:进程的动态数据的统计和记录(总计执行时间、运行时间限制、进程号等)
  • I/O status information:I/O 状态信息(分配给进程的 I/O 设备列表、打开的文件列表等)
    a

进程切换

a

图中显示的是从进程 P0 切换到进程 P1 的过程,首先将 PCB0 的信息存储到内存中,接着从内存中将 PCB1 的内容加载到 CPU 中,最后执行进程 P1 期望执行的内容。

进程调度

进程调度的队列

  • Job queue:系统中所有进程的集合
  • Ready queue:内存中所有处于 ready 态的进程的集合
  • Device queue:正在等待 I/O 设备资源的进程的集合

操作系统中的进程就不断地在各个队列之间切换

a

注意:具体一个时刻,某个进程只能处于一个队列中,不能同时在两个队列中。

Schedulers(调度器)

  • Long-term scheduler(or job scheduler):选择应将哪些进程放入内存中(就绪队列)
  • Short-term scheduler(or CPU scheduler):选择下一个执行的进程并且分配 CPU 资源
  • 有些时候还需要进程的换入换出

UNIX 和 Windows 不使用 long-term scheduling。

  • Short-term scheduler 的调用是非常频繁的,所以必须要非常快
  • Long-term scheduler 的调用则相对较少,所以可以稍微慢些
  • Long-term scheduler 决定多进程的数量

根据进程在运行时对不同硬件的需求情况,可以将硬件分为两类

  • I/O bound:花费更多的时间在 I/O 上的进程(下载)
  • CPU bound:花费更多时间在计算上的进程(科学计算、打游戏)

上下文切换(Context Switch)

CPU 切换进程的时候需要保存上一个进程的信息,并且加载下一个进程的相关信息。上下文切换的时间是多余的,系统在上下文切换的时候没有做任何实际有效的工作,而上下文切换的时间决定于硬件的支持情况。

进程操作

进程创建

父进程创建子进程,子进程进一步创建其他进程,最终形成一棵进程树。

  • 资源共享
    1. 父进程和子进程共享资源
    2. 子进程共享父进程的部分资源
    3. 父进程和子进程不共享资源
  • 执行
    1. 父进程和子进程同时执行
    2. 父进程等待子进程执行完成后执行
  • 地址空间
    1. 子进程是父进程的复制品(一段程序)

进程中断

  • 进程执行完最后一条语句,请求操作系统删除
    1. 从子进程到父进程输出数据(通过 wait)
    2. 进程的资源会被操作系统回收
  • 父进程可以终止子进程的执行(abort)
    1. 子进程使用的资源已经超过了分配给它的资源
    2. 分配给子进程的任务不再被需要了
    3. 如果父进程被取消了
      1. 一些操作系统当父进程取消后,就不允许子进程的继续运行,也就是说需要删除这个父进程的全部子进程(cascade)
      2. 另外一些操作系统中允许子进程继续存在,并且会设置父进程位初始化进程

合作进程

  • 独立的进程不能被被的进程影响,也不能影响别的进程
  • 合作进程可以被被的进程影响,也可以影响别的进程
  • 进程合作的优势
    1. 信息共享
    2. 多 CPU 情况下可以加快计算速度
    3. 模块化
    4. 方便

生产者消费者模型

生产者进程生产信息,消费者进程消费信息。

  • unbounded-buffer:对缓冲区的大小没有限制。如果缓冲区中没有资源,消费者进程就必须等待。
  • bounded-buffer:缓冲区的大小是固定的。如果缓冲区中的资源已经满了,生产者进程必须等待。
Shared data
#define BUFFER_SIZE 10
typedef struct {
    ...
}item;

item buffer[BUFFER_SIZE];
int in = 0;
int out = 0;
Producer
while (true) {
    Produce an item;

    while (((in + 1) % BUFFER_SIZE) == out)
        ; // do nothing -- no free buffers
    buffer[in] = item;
    in = (in + 1) % BUFFER_SIZE;
}
Consumer
while (true) {
    while (in == out)
        ; //do nothing -- nothing to consume

    Remove an item from the buffer;
    item = buffer[out];
    out = (out + 1) % BUFFER SIZE;
    return item;
   }

进程间通信(IPC)

IPC 的两种模型:消息传递和共享内存

  • 消息传递(message passing)
    1. 进程间通过两个操作函数来进行消息传递
      1. send(message):消息的长度可以是固定的,也可以是可变的
      2. receive(message)
    2. 如果两个进程之间想要交流,就需要
      1. 首先建立通信连接:这个连接的实现可以是物理层面上的(共享内存、硬件总线),也可以是逻辑层面上的(逻辑属性)
      2. 通过两个操作函数进程信息交换
  • 直接通信
    1. 进程之间必须要显示命名
      1. send(P, message):向进程 P 发送消息
      2. receive(Q, message):从进程 Q 接收到消息
    2. 通信连接的属性
      1. 连接时自动建立的
      2. 一个连接仅支持一对进程间的通信
      3. 连接既可以是单向的,也可以是双向的
  • 间接通信
    1. 信息是通过mailboxes(或者是 ports)来传递的
      1. 每一个邮箱都有唯一的 id
      2. 共享同一个邮箱的进程之间可以通信
    2. 通信连接的属性
      1. 仅当进程共享同一个邮箱时才建立连接
      2. 一个连接中可能会有多个进程
      3. 每一对进程可能处于多个通信连接中
      4. 连接既可以是单向的,也可以是双向的

间接通信存在的问题

三个进程共享同一个邮箱时,如果 P1 发送了消息,P2 和 P3 同时接收了消息,那么这个消息是谁收到的?

解决方案

  • 一个连接最多允许两个进程
  • 同一时刻只允许一个进程调用 receive 函数
  • 允许系统任意选择接收端,发送方被系统通知接收方是谁

同步和异步

信息的传输有两种形式:blocking 和 non-blocking

  • Blocking 被认为是同步的
    1. 发送发只有接收方接收信息后才能继续发送信息
    2. 接收方只有有消息能接收时才能调用接收函数
  • Non-blocking 被认为是异步的
    1. 发送发可以连续发送信息
    2. 接收方无论是否有信息,都可以调用接收函数

评论