# 二、进程管理

进程是系统进行资源分配和调度的基本单位。

# 1. 进程实体 —— PCB

PCB:

  • 用于描述和控制进程运行的通用数据结构。
  • 记录进程当前状态和控制进程运行的全部信息。
  • PCB 的使用进程是能够独立运行的基本单位。
  • PCB 是操作系统进行调度经常会被读取的信息。
  • PCB 是常驻内存的,存放在系统专门开辟的PCB区域内。
image-20210107114756329
# [标识符]
  • 标识符唯一标记一个进程,用于区别其他进程。
# [状态]
  • 标记进程的进程状态,如:运行态。
# [程序计数器]
  • 进程即将被执行的下一条指令的地址。
# [内存指针]
  • 程序代码、进程数据相关指针。
# [上下文数据]
  • 进程执行时处理器存储的数据。
# [IO 状态信息]
  • 被进程IO操作所占用的文件列表。
# [记账信息]
  • 使用处理器时间、时钟数总和等。
image-20210107115217782

# 2. 线程

# 2.1 定义

线程是进程内一个相对独立的、可调度的执行单元。

线程自己基本上不拥有资源,只拥有一点在运行时必不可少的资源(如程序计数器、一组寄存器和栈),但它可以与同属一个进程的其他线程共享进程拥有的全部资源。

  • 一个线程看一看创建和撤销另一个线程
  • 同一个进程的多个线程之间可以并发执行
  • 线程也有就绪、阻塞和执行三种基本状态
  • 一个进程至少有一个线程

# 2.2 实现

# 内核级线程
  • 依赖于内核,由操作系统内核完成创建和撤消工作。
  • 在支持内核级线程的OS中,内核维护进程和线程的上下文信息并完成线程切换。
  • 一个内核级线程阻塞时不会影响其他线程的运行。
  • 处理机时间分配的对象是线程,所以有多个线程的进程将获得更多处理机时间。
# 用户级线程
  • 不依赖于操作系统核心,由应用进程利用线程库提供创建、同步、调度和管理线程的函数来控制。
  • 用户级线程的维护由应用进程完成,可以用于不支持内核级线程的操作系统。
  • 当一个线程阻塞时,整个进程都必须等待,处理机时间是分配给进程的,进程内有多个线程时,每个线程的执行时间相对少一些。
# 两种方法的组合
  • 在这种系统中,内核支持多线程的建立、调度与管理;同时,系统中又提供使用线程库的便利,允许用户应用程序建立、调度和管理用户级的线程。
  • 因此可以很好地将内核级线程和用户级线程的优点结合起来。由此产生了不同的多线程模型。

# 2.3 模型

# 一对一模型
image-20200303151504081
# 多对一模型
image-20200303151521602
# 多对多模型
image-20200303151541776

# 3. 进程与线程的区别

# (1)进程
进程是程序的一次执行过程,是一个动态概念,是程序在执行过程中分配和管理资源的基本单位,每一个进程都有一个自己的地址空间,至少有 5 种基本状态,它们是:初始态,执行态,等待状态,就绪状态,终止状态。

# (2)线程
 线程是CPU调度和分派的基本单位,它可与同属一个进程的其他的线程共享进程所拥有的全部资源。

# (3)联系
 线程是进程的一部分,一个线程只能属于一个进程,而一个进程可以有多个线程,但至少有一个线程。

# (4)区别:从资源使用的角度出发。(所谓的资源就是计算机里的中央处理器,内存,文件,网络等等)
根本区别:进程是操作系统资源分配的基本单位,而线程是任务调度和执行的基本单位

在开销方面:每个进程都有独立的代码和数据空间(程序上下文),程序之间的切换会有较大的开销;线程可以看做轻量级的进程,同一类线程共享代码和数据空间,每个线程都有自己独立的运行栈和程序计数器(PC),线程之间切换的开销小。

所处环境:在操作系统中能同时运行多个进程(程序);而在同一个进程(程序)中有多个线程同时执行(通过CPU调度,在每个时间片中只有一个线程执行)

内存分配方面:系统在运行的时候会为每个进程分配不同的内存空间;而对线程而言,除了CPU外,系统不会为线程分配内存(线程所使用的资源来自其所属进程的资源),线程组之间只能共享资源。

包含关系:没有线程的进程可以看做是单线程的,如果一个进程内有多个线程,则执行过程不是一条线的,而是多条线(线程)共同完成的;线程是进程的一部分,所以线程也被称为轻权进程或者轻量级进程。

# 4. 五状态模型

image-20210107144259618
# [创建]
  • 创建进程时拥有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 是进程的唯一标记,表现为一个非负整数。

image-20210108091839899

# [进程的状态标记]
image-20210108092122480

# 7.3 显示系统执行的进程 —— ps

ps 显示的信息选项

  • PID:进程标识号
  • TTY:终端机号
  • TIME:此进程所耗CPU时间
  • CMD:正在执行的命令或进程名

ps 工具标识进程的 5 种状态:

  • D:不可中断
  • R:运行
  • S:中断
  • T:停止
  • Z:僵死
  • W:无驻留页
  • <:高优先级进程
  • N:低优先级进程
  • L:内存锁页
  • +:位于后台进程组

image-20201010164827068

# ps -a
  • 显示当前终端的所有进程信息。

    image-20200908095919569
# ps -u
  • 以用户的格式显示进程信息。

    image-20200908095941248
# ps -x
  • 显示后台进程运行的参数。

    image-20200908100005954

△一般使用的参数是 ps -aux

image-20200908100305403

# 查看是否存在某个进程 ps -aux | grep xxxx

image-20201118155537007

# 以全格式显示进程 ps -ef

ps -ef 是以全格式显示进程,包括父进程

- e:显示所有进程

- f:全格式

image-20201118155733033

PS:0号代表没有父进程。

  • C:CPU 用于计算执行优先级的因子。数值越大,表明进程是 CPU 密集型运算,执行优先级会降低;数值越小,表明进程是 I/O 密集型运算,执行优先级会提高。
  • STIME:进程启动的时间。
  • PPID:父进程ID
# 查看进程树 ps -ef --forest

image-20210108092824037

# 排序 ps -aux --sort=-p[字段]

如按照 CPU 使用率进行排序:ps -aux --sort=-pcpu

image-20210108093150394

# 7.4 看出进程状态 —— top

image-20210108093353751

# 7.5 终止某个进程 —— kill

# 基本语法

kill [选项] 进程号(功能描述:通过进程号杀死进程)

killall 进程名称(功能描述:通过进程名称杀死进程,也支持通配符,这在系统因负载过大而变 得很慢时很有用)

# 常用选项

- 9:表示强迫进程立即停止

# 7.6 查看进程树 —— pstree

- p:显示进程的 PID

-u:显示进程所属的用户

image-20201118162046264

# centos7 需要自行安装 tree
yum tree

# 7.7 实践

# [1] 踢掉某个非法登录用户

先用 ps -aux | grep sshd 查看有哪些用户已经登录:

image-20201118160931388

然后 kill 掉 hedon:

image-20201118161046895

这样 hedon 就被 kill 了:

image-20201118161110684

# [2] 终止远程登录服务 sshd, 在适当时候再次重启 sshd 服务

image-20201118161132546

直接 kill 掉 1373 进程号就可以了。

# [3] 终止多个 gedit 编辑器
killall gedit   #通过进程名称来 kill,一次性 kill 多个
# [4] 强制杀掉一个终端

终端名称:bash

image-20201118161723950

这个时候会发现 kill 不掉,因为它会认为这是一个比较重要的进程,忽略掉了 kill 指令。

这个时候我们需要用 -9 来强制停止。

kill -9 7884

# 8. 进程调度

进程调度是指计算机通过决策决定哪个就绪进程可以获得 CPU 使用权。

两个步骤:

  • 收拾包袱:保留旧进程的运行信息,请出旧进程。
  • 新人入驻:选择新进程,准备运行环境并分配 CPU

# 8.1 三种机制

# [就绪队列的排队机制]

将就绪进程按照一定的方式排成队列,以便调度程序可以最快找到就绪进程。

image-20210108094401423
# [选择运行进程的委派机制]

调度程序以一定的策略选择就绪进程,将 CPU 资源分配给它。

# [新老进程的上下文切换机制]
image-20210108094517202

保存当前进程的上下文信息,装入被委派执行进程的运行上下文。

# 8.2 调度方法

见《作业管理》

上次更新: 8/6/2021, 8:10:03 PM