目录
一、进程概念
1.进程
进程
:进程是活动的实体,是执行中的程序。当一个可执行文件被加载到内存时,这个程序就成为进程。
程序是被动的实体
,如存储在磁盘上的包含一系列指令的文件内容,进程是活动的实体
。
作业是任务的一个实例。
进程在内存中的表现形式
:
一个进程一般由以下内容,即进程在内存中的结构形式。
代码段
(code section)又称文本段(text section)
通过程序计数器和处理器寄存器的内容来表示当前活动(current activity)栈
(stack):
包含临时数据,如函数参数,返回地址,局部变量数据段
(data section)
包含全局变量堆
(heap)
在进程运行期间动态分配的内存
2.进程状态
进程在执行是会改变状态
。
每个进程可能处于以下状态:
新的
(new): 进程正在被创建运行
(running): 指令正在被执行等待
(阻塞)waiting(blocking): 进程等待某个事件的发生就绪
(ready): 进程等待分配处理器终止
(terminated): 进程完成执行
3.进程控制块
操作系统是通过“控制表”对系统中的每个资源进行管理。例如,进程表、内存表、I/O 设备表,文件表等
每个进程在操作系统内用进程控制块
(Process Control Block:PCB)来表示,又称任务控制块(Task Control Block:TCB)即,进程在操作系统中体现的数据结构。它包含许多与一个特定进程相关的信息。
- 进程ID:PID。大部分操作系统是通过唯一的进程标识符来识别系统的进程
- 进程状态: 新的、就绪、运行、等待、停止等
- 进程计数器: 表示进程要执行的下一个指令的地址
- CPU 寄存器: 包括累加器、索引寄存器、堆栈指针、通用寄存器和其他条件码信息寄存器
- CPU 调度信息:进程的优先级、调度队列的指针和其他调度参数
- 内存管理信息:包括基地址和界限地址、页表或段表等
- 记账信息:CPU 使用时间, 时间界限等
- I/O 状态信息:I/O 设备进程分配状态, 打开文件表等
二、进程调度
多道程序(multiprogramming)的目的是无论何时都有进程在运行,从而使CPU的利用率达到最大
。为此,CPU需要在多个可用进程之间进行快速切换,调度程序从多个可用进程中选择一个进程运行。
1.调度队列
操作系统持有就绪队列
和一组设备队列
,进程可以在多个调度队列之间移动。
就绪队列
驻留在内存中的就绪的、等待运行的进程(如进程创建时,被放到该队列),即等待分配CPU的进程,一般用链表来实现设备队列
等待特定I/O设备的进程队列
进程调度通常用队列图
来表示。
当进程分配到CPU并执行时(运行状态),也就是进程运行过程中,可能发生下面事件中的一种并进入到就绪状态:
- 进程可能
发出一个I/O 请求
,并被放到I/O 队列 - 进程可能
创建一个新的子进程
,并等待该子进程结束 - 进程可能会由于
中断
而强制释放CPU,并被放回到就绪队列 用完时间片
(time slice / time quantum),并被放到就绪队列
2.调度程序
进程在整个生命周期中,会在各种调度队列之间迁移,操作系统必须按一定调度算法从这些队列中选择进程。
进程的选择通过适当的调度程序
来执行。
根据使用频率
分类为:
长期调度程序
(作业调度程序) :
进程会被保存在大容量存储设备的缓冲池中。从存储设备的缓冲池中选择进程,并装入就绪队列中等待执行(如:I/O调度)中期调度程序
: 分时系统中期调度程序的核心思想是能将进程从内存中移出(从CPU竞争中移出),从而降低多道程序设计的程度(Swap In and SwapOut)。进程可被重新调入内存,并从中断处继续执行,成为交换
。通过中期调度程序,进程可以换出
,并在后来换入
。短期调度程序
(CPU调度程序)
从准备执行队列中选择一个进程,并为之分配CPU(CPU调度)
3.上下文切换
当CPU从当前进程切换到另一个进程时,系统必须保存当前进程的相关信息,以备被切换的进程恢复运行。
将CPU切换到另一个进程需要保存当前进程的状态,并恢复另一个进程状态,这一任务称为上下文切换
上下文的切换依赖于硬件支持,如内存速度、寄存器数量、指令运行时间、载入/保存时间等。
可以看出,上下文切换时间是额外的开销,因为上下文切换时系统不能做什么有用的工作
。
三、进程运行
1.进程创建
操作系统是根据一个唯一的进程标识符(PID)来识别系统中的进程。
一个进程可以创建另一个新进程,那么,创建的进程称为父进程
,被创建的新进程称为子进程
(child process)
系统中的进程结构是树形结构
,进程和进程之间存在着父子关系,即父进程与子进程。
进程创建的选项:
- 资源共享选项
① 父进程和子进程共享所有资源
② 子进程共享父进程的部分资源
③ 父进程和子进程不共享资源 - 执行选项
① 父进程和子进程同时执行
② 父进程等待子进程结束再执行 - 地址空间选项
① 子进程完全复制父进程内容
② 子进程覆盖父进程内存空间
以UNIX 系统为例,提供fork( )创建进程系统调用,用fork( ) 系统调用创建进程
之后,一般是用exec( ) 系统调用覆盖进程内存空间
。
创建流程
:
- 在系统内部创建进程控制块
- 分配内存
- 载入可执行文件(通过调用exec()系统调用)
- 初始化程序
在系统调用fork()后,新进程使用系统调用exec(),以新程序来取代进程的内存空间。系统调用exec()加载二进制文件到内存(破坏了包含系统调用exec()的原来程序的内存内容),并开始执行
2.进程终止
进程完成最后语句并使用exit( )
系统调用,请求操作系统删除自身,并终止运行,这时,进程可以返回状态值给父进程(通过系统调用wait( )
获取 )。
父进程可以通过系统调用wait(),等待子进程的结束。
父进程可以用abort( ) 系统调用终止子进程的执行, 父进程终止子进程的原因可能如下:
- 子进程使用了超过它所分配到的资源
- 分配给子进程的任务不在需要
- 父进程终止导致子进程终止,即父进程终止,操作系统不允许子进程继续运行
如果一个进程终止,它的所有子进程也将终止,这种终止被称为级联终止
(Cascading Termination)。
当一个进程终止,操作系统会释放其资源,但,它位于进程表中的条目还存在,直到它的父进程调用wait();这是因为进程表包含了进程的退出状态。
当一个进程结束,但是他的父进程没有等待他(调用wait/waitpid),那么他将成为一个僵尸进程
。
四、进程间通信
系统内并发运行的进程可以是相互独立
或协作工作
,
进程协作的理由有信息共享、提高运算速度、模块化、方便。
- 如果一个进程不影响其他进程或不被其他进程所影响,那么该进程是独立的,即进程之间没有共享数据
- 如果一个进程影响其他进程或被其他进程所影响,那么该进程是协作的,即进程之间有数据共享
协作进程需要一种进程间的通信机制
进程间通信有两种基本模型:
- 消息传递
• 适合传递较少数量的数据
•需要内核的干涉
• 易于实现 - 共享内存
• 允许以最快的速度进行方便的通信
•不需要内核的干涉
• 比消息传递速度快
1.共享内存系统
我们认识的系统环境一般如下:
- 每个进程都有自己受保护的内存地址空间
- 通常操作系统试图阻止一个进程访问另一个进程的内存地址空间
所以,为了实现共享内存、便于两个或多个进程可以访问内存,共享区域应取消这个限制
,而且,必须保障不能有两个以上的进程同时向共享区域写入数据,即需要一个同步机制
共享内存典型范例为生产者进程产生信息以供消费者进程消费的问题,即生产者和消费者问题
为了允许生产者进程和消费者进程能并发运行,必须要有缓冲区被生产者和消费者所使用,此缓冲区为共享内存区域
,该区域的实现可以采用以下两种方式:
无限缓冲
(unbounded buffer): 对缓冲大小无限制。如果缓冲为空,消费者必须等待,而生产者总是可以产生新的信息。有限缓冲
(bounded buffer): 缓冲大小固定。如果缓冲为空,消费者必须等待,如果缓冲为满,生产者不能产生新的信息。
2.消息传递系统
另一种方式:操作系统提供机制,以便协作进程通过消息传递
功能进行通信。
消息传递功能提供了两种操作:发送消息和接收消息
。进程发送的消息可以是定长的或变长的
如果进程P和Q需要通信,它们之间必须互相发送消息和接收消息:它们之间要有通信链路
该链路实现有多种方法。这里只关心链路的逻辑实现。用于逻辑实现链路和操作send()/receive()的几种方法:
- 直接或间接通信(direct or indirect)
- 同步或异步通信(blocking or non-blocking)
- 自动或显式缓冲(通信缓冲)
直接通信(包括对称寻址和非对称寻址)
:
对于直接通信,需要通信的每个进程必须明确地命名通信的接受者和发送者。
(1).对称寻址(一对一,即发送和接受进程必须指定对方)
- send(P, message) : 向进程P 发送消息
- receive(Q, message) : 接收进程Q 发来的消息
通信线路的属性:
- 线路是自动建立的
- 一个线路只与两个进程相关
- 两个进程之间只有一个线路
(2).非对称寻址(多对一,即只要发送者指定接收者)
- send(P, message)
- receive(id, message):接收任何进程发送的消息
间接通信
:
通过端口(port)或邮箱(email)来发送或接受消息。每个邮箱都有一个唯一的标识符,进程之间可以通过共享端口来进行通信
通信线路具有以下属性:
- 两个进程共享一个邮箱(端口)才可以建立通信线路
- 一个链路(端口)可以与多个进程相关联
- 两个通信进程之间可有多个通信链路,每个线路对应一个邮箱(端口)
同步和异步
:
消息传递可以是同步或异步,又称为阻塞(blocking)或非阻塞(non-blocking)
发送者:
- 阻塞(同步)发送:发送进程阻塞,直到消息被对方进程接收
- 非阻塞(异步)发送:发送进程发送消息并继续操作
接受者:
- 阻塞(同步)接收:接收者阻塞,直到有消息可用
- 非阻塞(异步)接收:接收者收到一个有效消息或空消息
缓存
不管通信是直接或间接的,通信进程所交换的消息都驻留在临时的队列中,即缓冲区里
消息队列的实现方式有以下三种:
- 零容量(zero capacity)
队列的最大长度为0。因此,链路中没有等待的消息。发送方只能阻塞直到接收方接受 - 有限容量(bounded capacity)
队列长度为有限的。如果线路为满,发送者必须等待,直到队列中的空间可用为止 - 无限容量(unbounded capacity)
队列长度为无限。不管多少消息在等待,从不阻塞发送者,即发送者不必等待
五、客户机/服务器通信
1.Socket套接字
套接字被定义为通信的端点。套接字由IP地址和端口号连接组成。
分为面向连接套接字和无连接套接字。
2.远程过程调用(RPC)
远程过程调用(Remote Procedure Call:RPC)抽象化了通过网络连接的进程之间过程调用。
Stubs(存根):远程过程的代理,隐藏了通信发生的细节。每个独立的远程过程都有一个存根
客户机调用位于远程主机上的过程时,
- 客户端存根编组参数,并向服务器相应存根发送参数
- 服务器存根接收参数,解组参数,并调用相应过程
3.远程方法调用
Remote Method Invocation:RMI类似于远程过程调用,是RPC的JAVA特性
与RPC的不同
- RPC调用远程子程序或函数,RMI调用远程对象的方法
- RPC参数传递方式是普通数据结构,RMI参数传递方式可以是对象
4.管道
进程之间进行通信的另一种方式,管道通信方式的中间介质是文件
,通常称这种文件为管道文件。
如两个进程利用管道文件进行通信时,一个进程为写进程,另一个进程为读进程。
提供进程同步(synchronization)运行
管道分为匿名管道和命名管道
匿名管道
: Ordinary pipes (unnamed/anonymous pipes)
(1)临时的,完成通信后便不存在了;
(2)管道是半双工的,数据只能单向通信;
(3)双方通信时,需要建立起两个管道;
(4)只能用于父子进程或者兄弟进程之间(具有亲缘关系的进程)命名管道
:named pipe
(1)持久的;
(2)可以是双向的;
(3)父子关系不是必须的;
(4)可在同一台计算机的不同进程之间或在跨越一个网络的不同计算机的不同进程之间,支持可靠的、单向或双向的数据通信