参考资料 :小林Coding、阿秀、代码随想录
一、什么是进程?
1. 基本概念
进程是具有独立功能的程序在一个数据集合上运行的过程,是系统进行资源分配和调度的一个独立单位。
2. 进程控制块
系统通过进程控制块PCB描述进程的进本情况和运行状态,进而控制和管理进程进程,PCB是进程存在的唯一标识,包括以下信息:
- 进程描述信息:进程标识符、用户标识符;
- 进程控制和管理信息:进程当前状态、进程优先级;
- 进程资源分配清单:有关内存地址空间或虚拟地址空间的信息,所打开文件的列表和所使用的I/O设备信息;
- CPU相关信息:进程切换时,CPU寄存器的值都被保存在相应的PCB中,以便重新执行该进程时能从断点处继续执行。
3. 并发与并行
- 单个处理核在很短的时间内分别执行多个进程,称为并发;
- 多个处理核同时执行多个进程称为并行;
并发需要CPU从一个进程切换到另一个进程,在切换前必须要记录当前进程中运行的状态信息,以备下次切换回来的时候可以恢复执行。
4. 进程的上下文切换
一个进程切换到另一个进程运行,称为进程的上下文切换,进程的上下文切换不仅包含了虚拟内存、栈、全局变量等用户空间资源,还包括了内核堆栈、寄存器等内核的空间资源。
发生进程上下文切换有哪些场景?
- 进程的时间片耗尽
- 阻塞等待
- 高优先级进程运行
- 中断处理
- 进程通过睡眠函数Sleep这样的方法将自己主动挂起
二、进程状态
在一个进程的活动期间至少具备三种基本状态,即运行状态、就绪状态、阻塞状态。
- 就绪状态:可以运行,但是由于其他进程处于运行状态而暂时无法运行,等待调度;
- 阻塞状态:该进程正在等待某一事件发生而暂时停止运行,等待资源;
- 运行状态:该时刻进程占用CPU;
此外,进程还有另外两个基本状态:
- 创建状态:进程正在被创建;
- 结束状态:进程正在从系统中消失。
如果有⼤量处于阻塞状态的进程,进程可能会占用物理内存空间,所以系统通常会把阻塞状态进程的物理内存空间换出到硬盘,等需要再次运行的时候,再从硬盘换入物理内存,那么,就需要⼀个新的状态,来描述进程没有占用实际的物理内存空间的情况,这个状态就是挂起状态。
这跟阻塞状态是不⼀样,阻塞状态是等待某个事件的返回。 挂起状态可以分为两种:
- 阻塞挂起状态:进程在外存(硬盘)并等待某个事件的出现;
- 就绪挂起状态:进程在外存(硬盘),但只要进入内存,立刻运⾏;
- 只有就绪态和运行态可以相互转换,其他的都是单向转换。就绪态的进程通过调度算法获得CPU时间,转为运行态;而运行态进程,在分配给它的CPU时间片用完之后就会转为就绪态,等待下一次调度;
- 阻塞状态时缺少需要的资源而由运行态转换而来,但该资源不包括CPU时间,缺少CPU时间会从运行态转为就绪态;
- 当进程等待的外部事件发生时,由阻塞态转换为就绪态,如果此时没有其他进程运行,则转为运行态,否则该进程将处于就绪态,等待CPU空闲。
三、进程控制
1. 进程创建
⼀个进程可以创建另⼀个进程,此时创建者为父进程,被创建的进程为子进程,操作系统创建⼀个新进程的过程如下:
- 为新进程分配⼀个独特的进程控制块(PCB)
- 为新进程分配所需要的资源,比如内存、CPU时间
- 初始化进程控制块(PCB)的各种字段,包括状态、优先级、寄存器初始值等。
- 将其状态设置为就绪状态,使其能够被调度执行。进程进入就绪队列,等待分配处理器时间。
2. 进程终止
- 根据标识符,查找需要终止的进程的 PCB;
- 如果进程处于执行状态,则立即终止该进程的执行,然后将处理器资源分配给其他进程;
- 如果其还有子进程,则应将该进程的子进程交给 1 号进程接管;
- 将该进程所拥有的全部资源都归还给操作系统;
- 将其从 PCB 所在队列中删除。
3. 阻塞进程
- 找到被阻塞进程的标识符对应的PCB
- 如果该进程为运行状态,则保护其现场,将其状态转为阻塞状态,停⽌运⾏;
- 将该 PCB 插⼊到等待队列中,将处理机资源调度给其他就绪进程
4. 唤醒进程
- 在该事件的阻塞队列中找到相应进程的 PCB;
- 将其从阻塞队列中移出,并置其状态为就绪状态;
- 把该 PCB 插⼊到就绪队列中,等待调度程序调度。
四、进程间通信方式
进程通信指的是进程之间的信息交换,进程之间⼀般是相互独⽴的,但内核空间是每个进程都共享的,所以进程之间要通信必须通过内核。
1. 管道(匿名管道)
管道是指用于连接⼀个读进程和⼀个写进程以实现它们之间的通信的⼀个共享文件,⼜名pipe文件,向管道提供输入的发送进程(写进程),以字符流形式将大量的数据送入(写)管道,而接收管道输出的接收进程 (即读进程)则从管道中接收(读)数据。
- 管道传输数据是半双⼯通信,某⼀时刻只能单向传输。
- 写入管道中的数据遵循先入先出的规则
- 管道所传送的数据是无格式的,这要求管道的读出方与写入方必须事先约定好数据的格式,如多少字节算⼀个消息等
- 管道不是普通的文件,不属于某个文件系统,其只存在于内存中
- 管道在内存中对应⼀个缓冲区, 不同的系统其大小不⼀定相同
- 从管道读数据是⼀次性操作,数据⼀旦被读⾛,它就从管道中被抛弃,释放空间以便写更多的数据
- 管道通信效率低,不适合进程间频繁地交换数据
匿名管道:没有名字的管道,⽤完就销毁,只适⽤于父子进程之间的通信。
2. 命名管道
命名管道(FIFO)不同于匿名管道之处在于它提供了⼀个路径名与之关联,以 FIFO 的⽂件形式存在于文件系统中,这样,即使与 FIFO 的创建进程不存在亲缘关系的进程,只要可以访问该路径,就能够彼此通过 FIFO 相互通信。当使用FIFO的进程退出后,FIFO文件将继续保存在文件系统中以便之后使用。
3. 消息队列
消息队列是保存在内核中的消息链表,在发送数据时,会分成一个一个独立的数据单元,也就是消息体(数据块),消息体是用户自定义的数据类型,消息的发送方和接收方要约定好消息体的数据类型,所以每个消息体都是固定大小的存储块,不像管道是无格式的字节流数据。如果进程从消息队列中读取了消息体,内核就会把这个消息体删除。
消息队列克服了信号承载信息量少,管道只能承载无格式字节流以及缓冲区大小受限等缺点。
4. 信号量
信号量⽤于控制多个进程对共享资源的访问,比如避免因为多个进程同时修改同⼀个共享内存造成冲突,信号量可以使共享的资源在任意时刻只能被⼀个进程访问。
信号量其实是一个整型的计数器,主要用于实现进程间的互斥与同步,而不是用于缓存进程间通信的数据。信号量维护⼀个整数值,通常称为计数器。进程可以执⾏两种基本操作来操作信号量:
- P(Wait)操作:这个操作会把信号量减去 1,相减后如果信号量 < 0,则表明资源已被占⽤,进程需阻塞等待;相减后如果信号量 >= 0,则表明还有资源可使⽤,进程可正常继续执⾏。
- V(Signal)操作:这个操作会把信号量加上 1,相加后如果信号量 <= 0,则表明当前有阻塞中的进程,于是会将该进程唤醒运行;相加后如果信号量 > 0,则表明当前没有阻塞中的进程;
P 操作是用在进入共享资源之前,V 操作是用在离开共享资源之后,这两个操作是必须成对出现的。
5. 共享内存
共享内存的机制,就是拿出一块虚拟地址空间来,映射到相同的物理内存中。这使得多个进程可以访问同一块内存空间,通过对共享空间进行写/读操作实现进程之间的信息交换,是最快的可用IPC模式。
6. 信号
信号事件的来源主要有硬件来源(如键盘 Cltr+C )和软件来源(如 kill 命令)。 信号是进程间通信机制中唯⼀的异步通信机制,它可以在⼀个进程中通知另⼀个进程发生了某种事件从而实现进程通信。
7. 内存映射
内存映射允许任何多个进程间通信,每一个使用该机制的进程通过把一个共享的文件映射到自己的进程地址空间实现通信。
8. Socket
Socket 通信是⼀种网络编程中常见的通信方式,不仅可以跨网络与不同主机的进程间通信,还可以在同主机上进程间通信。