此为自己学习课程的笔记,供自己复习用。
前言
本文主要介绍了进程的相关概念、组成、特征以及比较重要的进程的状态转换,最后介绍了进程的通信方式。
一、进程概念
程序:是静态的,是存放在磁盘里的可执行文件,就是一系列的指令集合。
进程(Process):是动态的,是程序的一次执行过程。
注意:同一个程序多次执行会对应多个进程。
当进程被创建时,操作系统会为该进程分配一个唯一的、不重复的“身份证号”—— PID (Process ID,进程ID)
操作系统需要对各个并发的进程进行管理,要记录PID,进程所属用户UID(进程描述信息),给进程分配了哪些资源(资源分配清单),进程的运行情况(进程控制和管理信息),处理机相关信息等。这些信息存储在数据结构PCB(Process Control Block)中,即,进程控制块中。
PCB是进程存在的唯一标志,当进程被创建时,操作系统为其创建PCB,当进程结束时,会回收其PCB。
二、进程组成
进程实体(进程映像)由PCB,数据段和程序段组成。其中,PCB是给操作系统用的;程序段和数据段是给进程自己使用的。
进程是动态的,进程实体(进程映像)是静态的。
- 进程实体反映了进程在某一时刻的状态。
- 进程是进程实体的运行过程,是系统进行资源分配和调度的一个独立单位。
一个进程被“调度”,就是指操作系统决定让这个进程上CPU运行。
三、进程的特征
- 动态性:进程是程序的一次执行过程,是动态地产生、变化和消亡的。(进程的最基本特征)
- 并发性:内存中有多个进程实体,密进程可并发执行。
- 独立性:进程是能独立运行、独立获得资源、独立接受调度的基本单位。
- 异步性:各进程按各自独立的、不可预知的速度向前推进,操作系统要提供"进程同步机制”来解决异步问题。
- 结构性:每个进程都会配置一个PCB。结构上看,进程由程序段、数据段、PCB组成。
四、进程的状态与转换
进程的三种基本状态:
- 就绪态:占有CPU,并在CPU上运行
- 运行态:已经具备运行条件,但由于没有空闲CPU,而暂时不能运行。
- 阻塞态:因等待某一事件而暂时不能运行。
还有另外两种状态是:
- 创建态:进程正在被创建,操作系统为进程分配资源、初始化PCB。
- 终止态:进程正在从系统中撤销,操作系统会回收进程拥有的资源、撒销PCB。
五、进程的组织方式
- 链接方式:按照进程状态将PCB分为多个队列,操作系统持有指向各个队列的指针。
- 索引方式:根据进程状态的不同,建立几张索引表,操作系统持有指向各个索引表的指针。
六、进程控制
1. 如何实现进程控制?
答:通过“原语”来实现。原语是内核中一种特殊的程序,它的执行具有原子性。也就是说,这段程序的运行必须一气呵成,不可中断。
可以用 “关中断指令”和“开中断指令”这两个特权指令实现原子性
- 操作系统创建一个进程时,会使用创建原语,具体的操作为:
- 申请空白PCB
- 为新进程分配所需资源
- 初始化PCB
- 将PCB插入就绪队列,此时进程状态由创建态变为就绪态。
- 操作系统终止一个进程时,会使用撤销原语,具体的操作为:
- 从PCB集合中找到终止进程的PCB
- 若进程正在运行,立即剥夺CPU,将CPU分配给其他进程
- 终止其所有子进程
- 将该进程拥有的所有资源归还给父进程或操作系统
- 删除PCB
- 操作系统执行阻塞原语实现进程从运行态到阻塞态,具体操作如下:
- 找到要阻塞的选程对应的PCB
- 保护进程运行现场,将PCB状态信息设置为“阻塞态",暂时停止进程运行
- 将PCB插入相应事件的等待队列
- 操作系统通过唤醒原语实现进程从阻塞态到就绪态,具体操作如下:
- 在事件等待队列中找到PCB
- 将PCB从等待队列移除,设置进程为就绪态
- 将PCB插入就绪队列,等待被调度
阻塞原语和唤醒原语是成对使用的。
- 操作系统通过切换原语实现进程的切换,具体操作如下:
- 将进程的运行环境信息存入PCB
- PCB移入相应队列
- 选择另一个进程执行,并更新其PCB
- 根据PCB恢复新进程所需的运行环境
七、进程间通信
进程间通信(Inter-Process Communication,IPC)是指两个进程之间产生数据交互。
进程是分配系统资源的单位(包括内存地址空间),因此各进程拥有的内存地址空间相互独立。
为了保证安全,一个进程不能直接访问另一个进程的地址空间。
三种进程间通信方式:
- 共享存储
- 消息传递
- 管道通信
1、共享存储
共享存储区可以被多个进程共享。
Linux中实现共享内存的方法:
(1)通过shm_open 系统调用,申请一片共享内存区
(2)通过mmap 系统调用,将共享内存区映射到进程自己的地址空间
调用mmap后进程的页表项/段表项就会增加一项,它们会映射到共享的内存存储区。
要保证不同进程对共享内存区的互斥访问(由通信进程自己负责互斥)
- 基于数据结构的共享:比如共享空间里只能放一个长度为10的数组。这种共享方式速度慢、限制多,是一种低级通信方式。
- 基于存储区的共享:操作系统在内存中划出一块共享存储区,数据的形式、存放位置都由通信进程控制,而不是操作系统。这种共享方式速度很快,是一种高级通信方式。
2、消息传递
进程间的数据交换以格式化的消息(消息头/消息体)为单位。进程通过操作系统提供的“发送消息/接收消息”两个原语进行数据交换。
消息传递分为直接通信方式和间接通信方式:
- 直接通信方式
消息发送进程要指明接收进程的ID。 - 间接通信方式
以“信箱”作为中间实体进行消息传递。
可以多个进程往同一个信箱send消息,也可以多个进程从同一个信箱中receive消息。
3、管道通信
- “管道”是一个特殊的共享文件,又名pipe文件。其实就是在内存中开辟一个大小固定的内存缓冲区。(循环队列)
- 数据流向是单向的,数据的读写是先进先出的。
- 管道中的数据一旦被读出,就彻底消失
管道通信的读写操作是有顺序的,是先进先出的,不能想读哪就读哪,也不能想写在哪就写在哪;
而共享内存的读写是没有顺序的,可以在任意位置写入数据,也可在任意位置读取数据。
- 管道只能采用半双工通信,某一时间段内只能实现单向的传输。如果要实现双向同时通信,则需要设置两个管道。
- 各进程要互斥地访问管道(由操作系统实现)
- 当管道写满时,写进程将阻塞,直到读进程将管道中的数据取走,即可唤醒写进程。
- 当管道读空时,读进程将阻塞,直到写进程往管道中写入数据,即可唤醒读进程。
- 在实际应用中,一个管道是允许多个读进程,多个写进程的。但系统会让各个读进程轮流从管道中读数据。