# 二、进程管理
进程是系统进行资源分配和调度的基本单位。
# 1. 进程实体 —— PCB
PCB:
- 用于描述和控制进程运行的通用数据结构。
- 记录进程当前状态和控制进程运行的全部信息。
- PCB 的使用进程是能够独立运行的基本单位。
- PCB 是操作系统进行调度经常会被读取的信息。
- PCB 是常驻内存的,存放在系统专门开辟的PCB区域内。
# [标识符]
- 标识符唯一标记一个进程,用于区别其他进程。
# [状态]
- 标记进程的进程状态,如:运行态。
# [程序计数器]
- 进程即将被执行的下一条指令的地址。
# [内存指针]
- 程序代码、进程数据相关指针。
# [上下文数据]
- 进程执行时处理器存储的数据。
# [IO 状态信息]
- 被进程IO操作所占用的文件列表。
# [记账信息]
- 使用处理器时间、时钟数总和等。
# 2. 线程
# 2.1 定义
线程是进程内一个相对独立的、可调度的执行单元。
线程自己基本上不拥有资源,只拥有一点在运行时必不可少的资源(如程序计数器、一组寄存器和栈),但它可以与同属一个进程的其他线程共享进程拥有的全部资源。
- 一个线程看一看创建和撤销另一个线程
- 同一个进程的多个线程之间可以并发执行
- 线程也有就绪、阻塞和执行三种基本状态
- 一个进程至少有一个线程
# 2.2 实现
# 内核级线程
- 依赖于内核,由操作系统内核完成创建和撤消工作。
- 在支持内核级线程的OS中,内核维护进程和线程的上下文信息并完成线程切换。
- 一个内核级线程阻塞时不会影响其他线程的运行。
- 处理机时间分配的对象是线程,所以有多个线程的进程将获得更多处理机时间。
# 用户级线程
- 不依赖于操作系统核心,由应用进程利用线程库提供创建、同步、调度和管理线程的函数来控制。
- 用户级线程的维护由应用进程完成,可以用于不支持内核级线程的操作系统。
- 当一个线程阻塞时,整个进程都必须等待,处理机时间是分配给进程的,进程内有多个线程时,每个线程的执行时间相对少一些。
# 两种方法的组合
- 在这种系统中,内核支持多线程的建立、调度与管理;同时,系统中又提供使用线程库的便利,允许用户应用程序建立、调度和管理用户级的线程。
- 因此可以很好地将内核级线程和用户级线程的优点结合起来。由此产生了不同的多线程模型。
# 2.3 模型
# 一对一模型
# 多对一模型
# 多对多模型
# 3. 进程与线程的区别
# (1)进程
进程是程序的一次执行过程,是一个动态概念,是程序在执行过程中分配和管理资源的基本单位,每一个进程都有一个自己的地址空间,至少有 5 种基本状态,它们是:初始态,执行态,等待状态,就绪状态,终止状态。
# (2)线程
线程是CPU调度和分派的基本单位,它可与同属一个进程的其他的线程共享进程所拥有的全部资源。
# (3)联系
线程是进程的一部分,一个线程只能属于一个进程,而一个进程可以有多个线程,但至少有一个线程。
# (4)区别:从资源使用的角度出发。(所谓的资源就是计算机里的中央处理器,内存,文件,网络等等)
根本区别:进程是操作系统资源分配的基本单位,而线程是任务调度和执行的基本单位
在开销方面:每个进程都有独立的代码和数据空间(程序上下文),程序之间的切换会有较大的开销;线程可以看做轻量级的进程,同一类线程共享代码和数据空间,每个线程都有自己独立的运行栈和程序计数器(PC),线程之间切换的开销小。
所处环境:在操作系统中能同时运行多个进程(程序);而在同一个进程(程序)中有多个线程同时执行(通过CPU调度,在每个时间片中只有一个线程执行)
内存分配方面:系统在运行的时候会为每个进程分配不同的内存空间;而对线程而言,除了CPU外,系统不会为线程分配内存(线程所使用的资源来自其所属进程的资源),线程组之间只能共享资源。
包含关系:没有线程的进程可以看做是单线程的,如果一个进程内有多个线程,则执行过程不是一条线的,而是多条线(线程)共同完成的;线程是进程的一部分,所以线程也被称为轻权进程或者轻量级进程。
# 4. 五状态模型
# [创建]
- 创建进程时拥有PCB但其他资源尚未就绪的状态称为创建状态。
- 操作系统提供 fork() 函数接口创建进程。
# [就绪]
- 当进程被分配到除CPU以外所有必要的资源后,只要再获得CPU的使用权,就可以立即运行,其他资源都准备好、只差CPU资源的状态为就绪状态。
# [执行]
- 进程获得CPU,其程序正在执行称为执行状态。
- 在单处理机中,在某个时刻只能有一个进程是处于执行状态。
# [阻塞]
- 进程因某种原因如:其他设备未就绪而无法继续执行,从而放弃CPU的状态称为阻塞状态。
# [终止]
- 进程结束由系统清理或者归还 PCB 的状态称为终止状态。
# 5. 进程同步
原则:
- 空闲让进:资源无占用,允许使用
- 忙着等待:资源有占用,请求进程等待
- 有限等待:保证有限等待时间能够使用资源
- 让权等待:等待时,进程需要让出 CPU
方法:
- 消息队列
- 共享存储
- 信号量
- 管程
# 5.1 生产者-消费者问题
有一群生产者进程在生产产品,并将这些产品提供给消费者进程进行消费,生产者进程和消费者 进程可以并发执行,在两者之间设置了一个具有n可缓冲区的缓冲池,生产者进程需要将所生产的产品放到一个缓冲区中,消费者进程可以从缓冲区取走产品消费。
# 5.2 读者-写者问题
# 5.3 哲学家进餐问题
有五个哲学家,他们的生活方式是交替地进行思考和进餐,哲学家们共同使用一张圆桌,分别坐 在周围的五张椅子上,在圆桌上有五个碗和五支筷子。平时哲学家们只进行思考,饥饿时则试图 取靠近他们的左、右两支筷子,只有两支筷子都被他拿到的时候就能进餐,进餐完毕之后,放下左右筷子继续思考。
# 5.4 睡眠理发师问题
# 6. 线程同步
进程的多个线程共享进程资源。
- 互斥锁
- 自旋锁
- 读写锁
- 条件变量
# 6.1 互斥锁
# 6.2 自旋锁
# 6.3 读写锁
# 6.4 条件变量
# 7. Linux 进程管理
# 7.1 进程的类型
# [前台进程]
前台进程就是具有终端,能够跟用户进行交互的进程。
# [后台进程]
没有占用终端的进程就是后台进程,基本不和用户交互,优先级比前台进程低。
将需要执行的命令以 “&” 符号结束就可以启动一个后台进程。
# [守护进程]
守护(daemon)进程是特殊的后台进程。
很多守护进程在系统引导的时候启动,一直运行到系统关闭。
Linux 中典型的守护进程:名字以“d”结尾的一般都是守护进程:
- crond:定时任务守护进程
- httpd:http 服务守护进程
- sshd:终端守护进程
- mysqld:mysql 守护进程
# 7.2 进程的标记
# [进程ID]
进程 ID 是进程的唯一标记,表现为一个非负整数。
# [进程的状态标记]
# 7.3 显示系统执行的进程 —— ps
ps 显示的信息选项
- PID:进程标识号
- TTY:终端机号
- TIME:此进程所耗CPU时间
- CMD:正在执行的命令或进程名
ps 工具标识进程的 5 种状态:
- D:不可中断
- R:运行
- S:中断
- T:停止
- Z:僵死
- W:无驻留页
- <:高优先级进程
- N:低优先级进程
- L:内存锁页
- +:位于后台进程组
# ps -a
显示当前终端的所有进程信息。
# ps -u
以用户的格式显示进程信息。
# ps -x
显示后台进程运行的参数。
△一般使用的参数是 ps -aux
# 查看是否存在某个进程 ps -aux | grep xxxx
# 以全格式显示进程 ps -ef
ps -ef 是以全格式显示进程,包括父进程
- e:显示所有进程
- f:全格式
PS:0号代表没有父进程。
- C:CPU 用于计算执行优先级的因子。数值越大,表明进程是 CPU 密集型运算,执行优先级会降低;数值越小,表明进程是 I/O 密集型运算,执行优先级会提高。
- STIME:进程启动的时间。
- PPID:父进程ID
# 查看进程树 ps -ef --forest
# 排序 ps -aux --sort=-p[字段]
如按照 CPU 使用率进行排序:ps -aux --sort=-pcpu
# 7.4 看出进程状态 —— top
# 7.5 终止某个进程 —— kill
# 基本语法
kill [选项] 进程号(功能描述:通过进程号杀死进程)
killall 进程名称(功能描述:通过进程名称杀死进程,也支持通配符,这在系统因负载过大而变 得很慢时很有用)
# 常用选项
- 9:表示强迫进程立即停止
# 7.6 查看进程树 —— pstree
- p:显示进程的 PID
-u:显示进程所属的用户
# centos7 需要自行安装 tree
yum tree
# 7.7 实践
# [1] 踢掉某个非法登录用户
先用 ps -aux | grep sshd
查看有哪些用户已经登录:
然后 kill 掉 hedon:
这样 hedon 就被 kill 了:
# [2] 终止远程登录服务 sshd, 在适当时候再次重启 sshd 服务
直接 kill 掉 1373 进程号就可以了。
# [3] 终止多个 gedit 编辑器
killall gedit #通过进程名称来 kill,一次性 kill 多个
# [4] 强制杀掉一个终端
终端名称:bash
这个时候会发现 kill 不掉,因为它会认为这是一个比较重要的进程,忽略掉了 kill 指令。
这个时候我们需要用 -9 来强制停止。
kill -9 7884
# 8. 进程调度
进程调度是指计算机通过决策决定哪个就绪进程可以获得 CPU 使用权。
两个步骤:
- 收拾包袱:保留旧进程的运行信息,请出旧进程。
- 新人入驻:选择新进程,准备运行环境并分配 CPU
# 8.1 三种机制
# [就绪队列的排队机制]
将就绪进程按照一定的方式排成队列,以便调度程序可以最快找到就绪进程。
# [选择运行进程的委派机制]
调度程序以一定的策略选择就绪进程,将 CPU 资源分配给它。
# [新老进程的上下文切换机制]
保存当前进程的上下文信息,装入被委派执行进程的运行上下文。
# 8.2 调度方法
见《作业管理》