操作系统 ch3 进程 processes
概念
在执行的程序。不只是执行中的程序代码,还包括当前活动(通过程序计数器的值和处理器寄存器的内容来表示)、进程堆栈段(包括临时数据如函数参数、返回地址和局部变量)、数据段(包括全局变量)、堆(在进程运行期间动态分配的内存)。
内存中的进程结构:
进程由代码(可能共享)、数据、状态组成。
多个进程与一个程序相关时,他们的文本段是共享的
Trace of the Process
进程的指令序列为Trace
Dispatcher负责进程的切换
User view of processes
Process Creation
- 父进程可以与子进程一起执行
- 父进程也可以等子进程结束再执行
进程树
两种方式:
- fork() 系统调用创建新进程,两个进程都继续执行 fork 之后的指令
- exec() 系统调用用新程序替换进程内存空间
Process Termination进程终止
exit 主动
进程执行完成最后语句,使用 exit 系统调用来请求操作系统删除自身。
- 可以通过 wait 向父进程返回状态值
- 所有进程资源被释放
abort 被动
父进程执行 abort 等系统调用终止子进程。有如下等原因:
- 使用超过分配到的资源
- 被分配的任务已不再需要
- 父进程终止
Kernel view of processes
PCB
一个进程在运行时包含很多信息,如标识符、状态、程序计数器、内存指针、上下文数据、输入输出状态信息等。这些信息存储在进程控制块(Process Control Block, PCB) 中。PCB 是进程的快照。
进程状态
进程有如下状态:
- new 新的: 进程正在被创建
- ready 就绪: 等待分配处理器
- running: 正被执行
- waiting: 等待某个事件的发生(如 I/O 完成)
- terminated 终止: 完成执行
进程创建
当操作系统想要创建新的进程时,要:
- 分配唯一的进程标识符
- 为进程分配空间
- 初始化PCB
- 设置适当的链接
- 创建或扩展其他数据结构
进程切换
该过程也成为上下文切换 context switch。
进程切换的具体步骤:
- 保存处理器的上下文,包括程序计数器和其他寄存器
- 更新正在运行的进程的PCB
- 将PCB移到合适的队列
- 选择另一个进程执行
- 更新被选择进程的PCB
- 更新内存管理数据结构
- 还原所选进程的上下文
进程调度队列 Process Scheduling Queues
-
Job queue – set of all processes in the system.
-
Ready queue – 主存中准备就绪并等待执行的进程集合
-
Device queues – 等待 IO 设备的进程集合
PCB 随着其状态的变化在进程中移动。
调度程序 Schedulers
Long-term scheduler(job scheduler)
从缓冲池中选择进程装入内存中以准备执行。控制多道程序设计的程度(内存中的进程数量)。执行不频繁,有更多时间选择进程。比如进程有I/O-bound(IO操作多) 和 CPU-bound(cpu操作多)两种,在选择进程时需要合理的选择两种进程。
Short-term scheduler(CPU scheduler)
从准备执行的进程中选择接下来应执行的进程并分配 CPU。
必须频繁为cpu 选择进程,执行要快。
进程间通信 Interprocess Communication(IPC)
协作进程Cooperating process:会被其他进程的执行影响或影响其他进程。
独立进程Independent process:与其他进程无关
进程协作的优点:
- 信息共享 Information sharing
- 提高运算速度 Computation speed-up
- 模块化Modularity
- 方便 Convenience
IPC允许协作进程交换数据与信息,即进行进程间通信。
进程间通信有两种方法:
- 消息传递。通常用系统调用来实现,适用于交换数量少的数据。
- 共享内存。仅在建立共享内存区时用到系统调用,速度更快。
共享内存系统——生产者-消费者问题
生产者进程产生信息供消费者进程消费。
Shared data
#define BUFFER_SIZE 10
Typedef struct {
. . .
} item;
item buffer BUFFER_SIZE;
int in = 0;
int out = 0;
in 指向缓冲中下一个空位,out 指向缓冲中第一个满位。
Producer process
item nextProduced;
while (1) {
while (((in + 1) % BUFFER_SIZE) == out)
; / do nothing /
bufferin = nextProduced;
in = (in + 1) % BUFFER_SIZE;
}
Consumer process
item nextConsumed;
while (1) {
while (in == out)
; / do nothing /
nextConsumed = bufferout;
out = (out + 1) % BUFFER_SIZE;
}
这种方法最大缓冲项数为 BUFFER_SIZE - 1.
消息传递系统
信息传递工具提供至少两种操作:
- send(message) – 消息可以定长、变长
- receive(message)
如果进程 P,Q 想要通信,那么一定要有通信线路(communication link)来实现彼此发送、接收消息。
通信线路的实现有物理实现和逻辑实现,这里仅说明逻辑实现的一些方法:
- 直接或间接通信
- 同步或异步通信
- 自动或显式缓冲
直接通信 Direct Communication
进程必须明确命名接收者、发送者。
send (P, message) – 发送消息到进程 P。
receive(Q, message) – 接收消息从进程 Q。
间接通信 Indirect Communication
通过邮箱 mailbox 或者端口发送接收消息。每个邮箱都有唯一标识符。要进行通信的进程要共享至少一个邮箱。
send(A, message) – send a message to mailbox A。
receive(A, message) – receive a message from mailbox A。
问题:P1, P2, and P3 共享邮箱 A.
P1发送信息; P2 and P3 谁接收信息?
解决方案:
- 一个线路最多关联两个进程
- 一次最多允许一个进程去接收
- 系统随便选择一个进程接收消息。给发送者标识接受者。
同步 Synchronization
消息传递可以是阻塞 blocking、非阻塞 Non-blocking 的,即同步 synchronous、异步asynchronous。
发射与接收可以进行任意的组合。
缓冲
通信进程交换的信息都停留在临时队列中,队列有三种方式:
- 0容量。线路中不能有消息在等待,故必须阻塞发送,直到接收者收到信息
- 有限容量。
- 无限容量。
0容量为没有缓冲的消息系统,其他成为自动缓冲。
管道 pipe
管道本质上就是一个文件,前面的进程以写方式打开文件,后面的进程以读方式打开。这样前面写完后面读,于是就实现了通信。
ls | wc 在ls 和 wc 进程之间创建了管道。
本文来自博客园,作者:流云轻响,转载请注明原文链接:https://www.cnblogs.com/wozra/p/16256714.html