操作系统——进程

整理自《操作系统概念第七版》

进程概念

进程是系统进行资源分配和调度的基本单位,程序本身不是进程。
不只包括程序代码,还包括以进程计数器的值和处理器寄存器的内容表示的当前活动。另外,进程通常还包括堆栈段(临时数据如函数参数、返回地址和局部变量)和数据段(全局变量)。进程还可能包括(在进程运行期间动态分配的内存)。

进程状态

1.新的(创建):进程正在被创建
2.运行:指令正在被执行
3.等待(阻塞):进程等待某个事件的发生(如I/O完成或收到信号)
4.就绪:进程等待分配处理器
5.终止:进程完成执行

进程控制块(PCB)包括:进程状态、程序计数器、CPU寄存器、CPU调度信息、内存管理信息、记账信息、I/O状态信息。


进程调度

进程进入系统时,会被加到作业队列中,该队列包括系统中的所有进程。驻留在内存中就绪的、等待运行的进程保存在就绪队列中。该队列通常用链表来实现,其头节点指向链表的第一个和最后一个PCB块的指针。每个PCB包括一个指向就绪队列的下一个PCB的指针域。
图源:《操作系统概念》
进程被放到大容量存储设备(磁盘)的缓冲池中,长期调度程序/作业调度程序从该池中选择进程,并装入内存以准备执行。短期调度程序/CPU调度程序从准备执行的进程中选择进程,为之分配CPU。
主要区别:执行的频率。
长期调度程序控制多道程序设计的程度(内存中的进程数量),必须仔细选择进程(I/O为主或CPU为主)。
中期调度程序的核心思想是将进程从内存(或从CPU竞争)中移出。该方案被称为交换

上下文切换:当发生一个中断时,系统需要保存当前运行在CPU中进程的上下文,从而在其处理完之后能恢复上下文。上下文切换时间是额外开销。


进程操作

进程创建

大多数操作系统根据一个唯一的进程标识符来识别进程,pid(process identifier,pid)通常是一个整数值。

在一个进程创建子进程时,子进程可能从操作系统直接获得资源,或从其父进程获得资源。父进程可能必须在其子进程之间分配或共享资源。限制子进程只能使用父进程的资源,防止创建过多的进程带来系统超载。

以UNIX操作系统为例。fork()创建新进程(复制原来进程的地址空间形成),子进程的返回值为0,父进程的返回值非0;exec()用新进程取代进程的内存空间,两个进程能相互通信,并能按各自的方法执行;wait()等待子进程的完成。
以WINDOWS为例,采用CreateProcess(),fork继承了父进程的地址空间,而这个函数则需要将一个特殊程序装入子进程的地址控件。fork不需要传参,该函数需要至少传递10个参数。其中STARTUPINFO指的是新进程的特性如窗口大小、标准输入输出等;PROCESS_INFORMATION包含一个句柄以及新的生成进程和线程的标识。ZeroMemory()为每个结构清空内存。

进程终止

原因:
1.子进程使用了超过它所分配到的资源
2.分配给子进程的任务不需要
3.父进程退出

有些系统具有级联终止现象,父进程终止,所有的子进程都将终止。有些系统的子进程会以init进程重新作为父进程。


进程间通信

模式:共享内存/消息传递
共享内存:建立一块供协作进程共享的内存区域,进程通过向此共享区域读或写入数据来交换信息。允许以最快的速度进行通信,可以达到内存的速度。不需要相比于信息传递的内核介入的时间消耗。
信息传递:通过在协作进程间交换信息来实现通信。不需要避免冲突,比共享内存更容易实现。

生产者——消费者模型

生产者进程产生信息以供消费者进程消费。采用共享内存是解决生产者——消费者模型的一种方法。为了允许生产者进程和消费进程能并发执行,必须有一个缓存来被生产者填充并被消费者使用。此缓冲驻留在生产者进程和消费者进程的共享内存区域内,当消费者使用一项时,生产者能产生另一项。
通过循环数组和两个逻辑指针实现:in和out。
in = out 缓冲为空
(in+1)%BUFFER_SIZE = out 缓冲为满

消息传递机制

消息传递工具提供至少两种操作:发送send(消息)和接收receive(消息)。
逻辑实现的几个问题:直接或间接?同步或异步?自动或显式?
直接通信每个进程明确命名通信的接收者和发送者
1.对称寻址
send(P,message)发送消息到P
receive(Q,message)接收来自Q的消息
2.非对称寻址
send(P,message)发送信息到进程P
receive(id,message)接收来自任何进程的消息,id设置成与其通信的进程名称
间接通信
通过邮箱或接口来发送和接收信息。进程或操作系统可以拥有邮箱。
send(A,message)发送消息到邮箱A
receive(A,message)接收从邮箱A的信息

同步/异步 阻塞/非阻塞
阻塞send:发送进程阻塞,直到消息被接收(对方收了才继续发)
非阻塞send:发送进程发送消息并再继续操作(一直发)
阻塞receive:接收者阻塞,直到有消息可用(有消息才收)
非阻塞receive:接收者收到一个有效消息或空消息(一直收)
如果都阻塞,则在发送者和接收者之间会有一个集合点。如果都非阻塞,则生产者消费者模型无意义。

缓冲
通信进程所交换的信息都驻留在临时队列中。零容量被称为“没有缓冲”,其他均为“自动缓冲”。
零容量:最大容量为0,不允许消息处于等待状态。
有限容量:最大长度为有限n。
无限容量:队列长度无限,从不阻塞发送者。


客户机——服务器系统通信

Socket

Socket(套接字)可以定义为通信的端点,由IP地址和一个端口号连接组成。通常,Socket采用客户机——服务器结构。服务器通过监听指定端口来等待进来的客户请求。所有低于1024的服务器端口都被认为是众所周知的,用来实现标准服务。
以JAVA为例,提供了TCP(面向连接)、UDP(无连接)和多点传送Socket类三种不同类型的Socket。

远程过程调用(RPC)

RPC设计成抽象过程调用机制,用于通过网络连接系统。每个消息传递给位于远程系统上监听端口号的RPC服务器,每个都包含要执行函数的名称和传递给函数的参数。该函数根据请求而执行,任何结果通过另一个消息送回给请求者。
通过在客户端提供存根,RPC系统隐藏了允许通信发生的必要细节。
问题一:处理客户机和服务器系统的数据表示的差别
在客户机端参数编组涉及将机器有关数据在被发送到服务器之前编组成XDR(外部数据表示)。在服务器端,XDR数据重新转换成服务器所用的机器有关表示。
问题二:调用的语义(RPC可能会失败或多次重复执行)
操作系统确保消息刚好执行一次,需要消除服务器从未收到消息的风险。如为“最多一次”,则可以通过为每个消息附加时间戳做到。
问题三:客户机与服务器的通信问题
方法一:绑定信息以固定端口地址形式预先固定;方法二:绑定通过集合点机制动态进行
在这里插入图片描述

远程方法调用(RMI)

类似于RPC的Java特性。RMI允许线程调用远程对象的方法。如果对象位于不同的JVM上,那么就认为它是远程的。
区别:RPC支持子程序编程,只能调用远程的子程序或函数;RMI基于对象,它支持调用远程对象的方法。RPC的参数是普通数据结构,RMI可以将对象作为参数传递给远程方法。
RMI采用存根和骨干实现远程对象。存根为远程对象的代理,驻留在客户机中。骨干负责重新编排参数并调用服务器上索要执行的方法。
参数传递的规则:
如果编排参数是本地对象,那么通过对象串行化的技术来复制传递。如果参数也是远程对象,可通过引用传递。如果本地对象需要作为参数传递给远程对象,必须实现接口java.io.Serializable。对象串行化允许将对象状态写入字节流。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章