操作系统概念 第三章 进程

文末有图片,格式更方便阅读,不知道为什么md文件导入后会这样。

#第三章 进程管理
本章目标:
-引入进程概念,即执行程序,这是所有计算的基础。
-讨论进程的各类特性,包括调度、创建和终止。
-探讨通过共享内存和消息传递的进程间通信。
-讨论客户机与服务器系统间的通信。

##3.1 进程概念

###3.1.1 进程
进程是执行的程序,这是一种非正式的说法,进程是活动的实体,进程包括当前的活动如程序计数器(program
counter)的值和处理器寄存器的内容,还包括进程堆栈(stack)、堆(heap)等。虽然两个进程可以与同一程序相关
联,这两个进程所保持的状态不同,如同时调用Web浏览器程序的多个副本,每个都是单独进程(虽然文本段相同,但是数
据、堆、栈等却不同)。进程本身也可以作为一个环境,用于执行其他的代码(如作为一个进程来执行的JVM,而这个作为
进程的JVM又可以执行Java程序。

###3.1.2 进程状态
-新的(new):进程正在创建
-运行(running):指令正在执行
-等待(waiting):进程等待发生某个事件
-就绪(ready):进程等待分配处理器
-终止(terminated):进程已完成执行
一个处理器一次只能运行一个进程,但是有多个进程可处于ready或waiting状态。

###3.1.3 进程控制块
操作系统内的每个进程表示,使用进程控制块(Process Control Block,PCB),也称任务控制块(task control
block)。PCB包含许多与某个特定进程相关的信息:
-进程状态(process state)
-程序计数器(PC)
-CPU寄存器(CPU register):根据计算机体系结构不同,寄存器的类型和数量也不同。
-CPU调度信息(CPU-scheduling information):包括进程优先级、调度队列的指针和其他调度参数。
-内存管理信息(memory-management information):根据操作系统使用的内存系统,可包括基地址和界限寄存器
的值、页表或段表。
-记账信息(accounting information)
-I/O状态信息(I/O status information):包括分配给进程的I/O设备列表、打开文件列表等。

简言之,PCB作为这些信息的仓库,当需要从一个进程(P0)切换到另一个进程(P1)时,就需要先将P0的状态保存到
PCB0,然后从PCB1将P1的状态加载出来,执行P1,返回线程P0同理。

###3.1.4 线程

##3.2 进程调度
多道程序设计的目标是无论何时都有进程在运行,从而最大化CPU利用率;分时系统的目的是在进程间快速切换CPU,以便
用户在程序运行时能与之交互。为满足这些目标,进程调度器(process scheduler)会选择一个可用进程到CPU执行。

###3.2.1 调度队列
进程在进入系统时,会被加到作业队列上(job queue),这个对列包括系统内的所有进程。驻留在内存中的、就绪的、
等待运行的进程保存在就绪队列(ready queue)上。这个队列用链表实现,其头节点有两个指针,分别指向链表的第一
个和最后一个PCB块,每个PCB块还包含一个指向就绪队列下一个PCB块的指针。

系统还有其他列。等待特定I/O设备的进程列表,称为设备队列(device queue)。每个设备都有自己的设备队列(当一
个进程请求一个设备,但当前该设备正被其他进程占用,则请求该设备的进程也位于该设备的设备列表。

最初,新进程被加到就绪队列;在就绪队列中等待,直到被选中执行或被分派(dispatched),当该进程分配到CPU并执
行时,有以下几种情况:
    -发出I/O请求,并被放到I/O队列
    -创建一个新的子进程,并等待其终止
    -由于中断被强制释放CPU,并被放回到就绪队列

前两种情况进程最终从等待状态切换到就绪状态。进程重复上述循环直到终止;然后它会从所有队列中删除,其PCB和资源
也被释放。

###3.2.2 调度程序
进程整个生命周期中在各种调度队列中的迁移由调度器(调度程序/scheduler)来实现。
对于批处理系统,提交的进程多于可以立即执行的。
短期调度程序和长期调度程序:
两者主要区别是执行频率,短期调度程序必须经常为CPU选择新的进程;长期调度程序控制躲到程序程度(degree
of multiprogramming)(内存中的进程数量)。多道程序程度稳定则创建进程的平均速度必须等于进程离开系统的
平均速度。

大多数进程可分为I/O为主(I/O密集型进程(I/O-bound process))或CPU为主(CPU密集型进程(CPU-bound 
process))。长期调度程序应该选择两种进程的合理组合。若所有都是I/O密集型,那么就绪队列几乎总为空,短期调度
程序无事可做;反之,I/O等待队列几乎为空,设备没有很好利用。 

###3.2.3 上下文切换
切换CPU到另一个进程需要保存当前进程状态(通过执行状态保存)和回复另一个进程的状态(进程上下文采用进程PCB表
示),这个任务称为上下文切换。上下文切换(切换时间与硬件支持密切相关)的时间是纯粹的开销(如果有多个寄存器
组,只需简单改变当前寄存器组的指针,但当活动进程数量超过寄存器组数,那么切换上下文时也需要保存数据,即在寄
存器和内存之间进行数据复制)。

##3.3 进程运行

###3.3.1 进程创建
一个进程可以在创建新的进程,形成进程树。
大多操作系统(包括UNIX、Linux、Windows)通过唯一的进程标识符(process identifier,pid)标识进程。系统内
每个进程有一个唯一的pid,它可以用作索引,以便访问内核中进程的各种属性。

UNIX和Linux系统可通过ps命令得到一个进程列表
    ps -el

一个进程创建子进程时,子进程需要的资源可以从操作系统直接获得,也可以只从父进程处获得资源子集。限制子进程只
能使用父进程的资源可以防止创建过多进程,导致系统超载。

除提供各种物理逻辑资源外,父进程也可能向子进程传递初始化数据。

当进程创建新进程时有两种执行可能:
    -两个进程并发执行
    -父进程等待,知道某个或全部子进程执行完

新进程的地址空间也有两种可能:
    -子进程时父进程的复制品(程序和数据与父进程相同)
    -子进程加载另一个新程序

UNIX操作系统通过系统调用fork()创建新进程,新进程地址空间复制于父进程,这种机制允许父子进程轻松通信。这两个
进程都继续执行fork()之后的指令,不同的是,新进程中fork()返回值为0,父进程中fork()返回值为子进程的pid。

通常在fork()之后,会调用系统调用exec(),以新程序来取代进程的内存空间。exec()会加载指定的二进制文件到内存
中(破坏了包含系统调用exec()的原来程序的内存内容)开始执行。

###3.3.2 进程终止
进程执行完所有语句后通过调用exit()系统调用请求操作系统删除自身,进程终止,此时进程可返回状态值到父进程,所
有的进程资源将会由操作系统释放。
还有的情况下父进程可以通过系统调用利用子进程的标识符终止子进程。父进程终止子进程的原因有很多,如:
-子进程使用了超过它所分配的资源。
-分配给子进程的任务不在需要。
-父进程正在退出,而操作系统不允许无父进程的子进程继续执行

级联终止:如果一个进程终止,那么它的所有子进程也终止。(通常由操作系统来启动,有的系统不允许子进程在父进程
已经终止的情况下存在)

父进程可以通过系统调用wait(),等待子进程的终止,wait()可以通过参数获得子进程的退出状态;这个系统调用也返回
终止子进程的标识符:
    pid_t pid;
    int status;
    pid = wait(&status);

进程终止时操作系统会释放其占用的资源,但它位于进程表中的条目仍然存在,直到它的父进程调用wait()。若一个进程
已经终止,但其父进程没有调用wait(),那么这个进程被称为僵尸进程(zombie process)(僵尸进程一般是短暂的存
在)。如果父进程没有调用wait()就终止,那么子进程就成为了孤儿进程(orphan process)。Linux和UNIX将init进
程作为孤儿进程的父进程。进程init定期调用wait(),以收集任何孤儿进程的退出状态并释放孤儿进程标识符和进程表条
目。

##3.4 进程间通信
操作系统内的并发执行进程可以是独立的,也可以是协作的。一个线程能影响其他线程或受其他线程影响或与其他线程共
享数据,则为协作线程。
提供环境允许进程协作具有许多理由:
-信息共享(information sharing)
-计算加速(computation speedup)
-模块化(modularity)
-方便(convenience)

协作进程需要一种进程间通信(InterProcess Communication,IPC)机制,以允许进程交换数据与信息。进程间通信
的两种基本模型:
    -共享内存(shared memory):通过向共享区域读写信息交换信息。仅在建立共享区域是有系统调用,后续访问共
    享内存为常规内存访问,速度比消息传递更快。
    -消息传递(message passing):通过在协作进程间交换消息实现通信。对于交换少量数据有用,实现时采用系统
    调用,耗时更多

###3.4.1 共享内存系统
共享内存系统需要通信进程建立共享内存区域(通常驻留在创建共享内存段的进程的地址空间,其他希望使用该共享内存
段进行通信的进程应将其附加到自己的地址空间。)

生产者-消费者问题:生产者进程生成信息供消费者进程消费。
    采用共享内存,允许生产者填充和被消费者清空。两者必须同步,防止消费者清空未生产出来的项。
    -无界缓冲区(unbounded-buffer):生产则可持续生产,消费者不得不等待新的项。
    -有界缓冲区(bounded-buffer):缓冲区为空,消费者需等待生产者生产;缓冲区慢,生产者需等待消费者消费。

###3.4.2 消息传递系统
消息传递提供一种机制是需要协作的进程间通信以“聊天”“收发信息”的方式进行。
进程发送的信息如果是定长则系统级实现简单,编程任务困难;变长则相反。
通信进程之间要有通信链路(communication link),实现通信链路的几个方法:
-直接或间接的通信
-同步或异步的通信
-自动或显式的缓冲

###3.4.2.1 命名
直接通信,需要每个进程必须明确指定通信的接收者或发送者,这种方案,原语send()和receive()定义如下:
-send(P,message):向进程P发送message。
-receive(Q,message):从进程Q接受message。

这种方案的通信链路具有以下属性:
    -需通信的每对进程间自动建立链路,进程仅需知道对方身份即可交流。
    -每个链路只与两个进程相关。
    -每对进程间只有一个链路。
该方案展示了寻址的对称性(symmetry),还可变形为采用寻址的非对称性(asymmetry),只需发送者指定接收者,接
收者无需指定发送者(receive(id,message):从任何进程接收message,id被设置成与其通信的进程的名称)。这样的
硬编码(hard-coding)技术比下面采用间接的技术要差。

间接通信(indirect communication)通过邮箱或端口来发送或接收信息。邮箱可抽象成一个对象,进程向其中存放信
息或从中删除信息(POSIX消息队列采用一个整数值来标识一个邮箱)。一个进程可通过多个不同邮箱与另一个进程通信,
但两个进程只有拥有一个共享邮箱时才能通信。原语定义:
    -send(A,message):像邮箱A发送message。
    -receive(A,message):从邮箱A接收message。
这种方案通信链路特点:
    -只有两个进程共享一个邮箱时才能建立通信链路。
    -一个链路可以与两个及以上进程关联。
    -两个进程间可以有多个不同的链路,每个链路对应于一个邮箱。
假设进程A、B、C都共享邮箱M,A发送一个消息到M,B、C都对M执行receive(),那么哪个进程会收到A发送的消息取决于
选择的方案:
    -允许一个链路最多只能与两个进程关联。
    -允许一次最多一个进程执行receive()。
    -允许系统随意选择一个进程接收消息。系统可定义算法来决定哪个接收消息。

若邮箱归进程所有,所有者只能从邮箱接收消息,使用者只能向邮箱发送消息。所有者进程终止邮箱消息。
若归操作系统所有,操作系统必须提供机制允许进程:创建新邮箱;通过邮箱收发消息;删除邮箱。

####3.4.2.2 同步
消息传递可以是阻塞(blocking)或非阻塞(nonblocking),也称同步(synchronous)或异步(asynchronous)
-阻塞发送(blocking send):发送进程阻塞,知道消息被进程或邮箱接收。
-非阻塞发送(nonblocking send):发送消息后恢复操作。
-阻塞接收(blocking receive):接收进程阻塞,直到有消息可用。
-非阻塞接收(nonblocking receive)
可以使用不同的send()和receive()组合。

####3.4.2.3 缓存
不管通信是直接还是间接,消息总是驻留在临时队列中,简单来说队列实现有三种方法:
-零容量(zero capacity)
-有限容量(bounded capacity)
-无限容量(unbounded capacity)
前两种在队列满时,发送者阻塞,而第三种发送者从不阻塞。零容量情况称为无缓冲消息系统,其他情况称为自动缓存的
消息系统。

#3.5 IPC系统例子
####3.5.1 POSIX共享内存
####3.5.2 Mach
####3.5.3

##3.6 客户机/服务器通信
上述技术(共享内存、消息传递)也可用于客户机/服务器系统通信;客户机/服务器系统通信的三种其他策略:套接字、远程程序调用(RPC)和管道。

###3.6.1 套接字
套接字(socket)为通信的端点。通过网络通信的每对进程都使用一对套接字,每个套接字由一个IP地址和一个端口号组
成。通常套接字采用C/S架构。服务器通过监听指定端口等待客户请求。客户端服务器通过一对套接字建立连接,并且通过
套接字进行交流(客户端发请求,服务器提供服务)。使用套接字通信虽然常用高效,但只允许通信线程交换无结构的字
节流。

###3.6.2 远程过程调用
RPC是一种最为常见的远程服务,RPC对于通过网络连接系统之间的过程调用进行了抽象。许多方面类似IPC机制,并且通
常建立在IPC之上。RPC通信交换的消息具有明确的结构。消息传到RPC服务,RPC服务监听远程系统的端口号;消息包含用
于指定:执行函数的一个标识符以及传递给函数的一些参数。然后函数按要求执行,而所有结果会通过另一消息传递回到
请求者。

端口知识一个数字,位于消息分组头部。如果一个系统允许其他系统累出当前用户,那么它有一个相应的支持的RPC服务,
该服务监听某个端口,如5200。任何一个远程系统要得到所需信息(即列出当前用户),只要想服务器端口5200发出一个
RPC消息,就可通过回复消息收到数据。还需注意处理客户机与服务器系统的不同数据表示。

另外一个重要事项是需要保证每个消息执行“正好一次”,而非“最多一次”。由于常见网络错误,RPC可能执行失败或多次重
复执行。考虑“最多一次”,服务器对所处理的消息应有一个完整的足够长的时间戳历史,如果消息的时间戳已经出现过则
忽略,这样客户端发送一次及以上消息,最多执行了一次。而要实现“正好一次”,只需在“最多一次”的基础上,服务器向
客户确认:RPC调用已经收到并且已经执行。客户机应周期性重发RPC调用,直到它接收到对该调用的ACK(确认)。

还有一个问题,RPC方案要有一个类似于客户机和服务器端口之间的绑定。这里有两种常见的方法。第一种方法:绑定信息
按固定的端口地址形式预先固定(个人理解就是把要用到的端口事先固定下来,只用 监听这个端口);第二种方法:操作
系统在一个固定RPC端口上提供交会服务程序或月老(matchmaker)。客户程序发送一个包括RPC名称的消息到交会服务程
序,请求所需执行RPC的端口地址,得到返回的端口号后,RPC调用发送给这一端口号。

###3.6.3 管道
管道是早期UNIX系统最早使用的一种IPC机制,允许两个进程进行通信。

####3.6.3.1 普通管道
普通管道允许两个进程按标准的生产者-消费者方式通信:生产者向管道的一端(写入端)写,消费者从管道的另一端(读
出端)读。
UNIX系统上普通管道的创建:
pipe(int fd[])
这个函数创建一个管道,以便通过文件描述符int fd[] 来访问:fd[0]为管道的读出端,fd[1]为管道的写入端,UNIX将
管道作为一种特殊类型的文件,访问管道可以采用普通的系统调用read(),write()。

普通管道只能由创建进程所访问。通常情况下,父进程创建一个管道,并使用它来与其子进程(由fork()创建)通信。子
进程继承了父进程的打开文件,由于管道是一种特殊类型的文件,因此也被继承。

笔记中例子主要为Linux,所以部分Windows系统相关例子不再描述。

####3.6.3.2 命名管道
命名管道通信可以是双向的,父子关系不是必须的,建立一个命名管道后可被多个进程使用于通信,通信进程完成后管道
仍然存在(普通管道不存在)。

对于UNIX,命名管道为FIFO。一旦创建,它们表现为文件系统的典型文件。通过系统调用mkfifo()创建。通过系统调用
open(),read(),write(),close()操作。FIFO会一直存在直到被显示地从文件系统中删除。虽然FIFO允许双向通信,但
是只允许半双工运输(同一时间只能按一个方向传输),如果要在两个方向上运输,通常使用两个FIFO。

在这里插入图片描述
在这里插入图片描述

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值