Linux 的进程管理
进程的类型:
- 前台进程
- 后台进程
- 守护进程
前台进程
前台进程就是具有终端,可以和后台进程进行交互的进程
后台进程
与前台进程相对,没有占用终端的就是后台进程
后台程序不和用户进行交互,优先级比前台进程低
需要执行的命令以 & 符号结束
守护进程
守护进程是特殊的后台进程
很多守护进程在系统引导的时候启动,一直运行知道系统关闭
Linux有很多典型的守护进程
以d结尾的一般是守护进程
进程的标记:
进程ID
进程ID是进程的唯一标识符,每个进程拥有不同的id
进程id表现为一个非负整数,最大值由操作系统限定
父进程,子进程
父子进程关系可以通过pstree命令进行查看
Id 为0的进程为idle进程,是系统创建的第一个进程
id为1的进程为init进程,是0号进程的子进程,完成系统初始化
init进程是所有用户进程的祖先进程
进程的状态
进程的5个状态:创建,就绪,阻塞,执行,终止
常用linux命令: ps, top, kill
作业管理之进程调度
进程调度概述
进程调度是指计算机通过决策决定哪个就绪进程可以获得CPU使用权
也是多道程序设计
1.保留旧进程的运行信息,请出旧进程 (收拾包袱)
2.选择新进程,准备运行环境并分配CPU (新进驻)
进程调度包括:
1.就绪队列的排队机制
2. 选择运行进程的委派机制
3. 新老进程的上下文切换机制
就绪队列的排队机制
将就绪进程按照一定的方式排列成队列,以便调度程序可以最快找到就绪进程
选择运行进程的委派机制
调度程序以一定的策略选择就绪进程,将CPU资源分配给它
新老进程的上下文切换机制
保存当前进程的上下文信息,装入被委派执行进程的运行上下文。
进程的调度可以分为两大类:
- 非抢占式的调度
- 抢占式的调度
非抢占式的调度:
处理器一旦分配给某个进程,就让该进程一直使用下去
调度程序不以任何原因抢占正在被使用的处理器
直到进程完成工作或因为IO阻塞才会让出处理器
抢占式的调度:
允许调度程序以一定的策略暂停当前运行的进程
保存好旧进程的上下文信息,分配处理器给新进程
进程调度算法
- 先来先服务的调度算法
- 短进程优先调度算法
- 高优先权优先调度算法
- 时间片轮转调度算法
->先来先服务的调度算法
先调用就绪进程1,再调用就绪进程2…
->短进程优先调度算法
调度程序优先选择就绪队列中估计运行时间最短的进程
短进程优先调度算法不利于场作业进程的执行
->高优先权优先调度算法
进程附带优先权,调度程序优先选择权重高的进程
高优先权优先调度算法使得紧迫的任务可以优先处理
->时间片轮转调度算法
先来先服务原则,排队就绪进程
每次从队列头部取出执行进程,分配一个时间片去执行
是相对公平的调度算法,但不能保证及时响应用户
作业管理之死锁
->死锁
死锁是指两个或两个以上的进程在执行过程中,由于竞争资源或者由于彼此通信而造成的一种阻塞的现象,若无外力作用,它们都将无法推进下去。此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等待的进程成为死锁进程。
- 死锁的产生 (包括,死锁的四个必要条件)
- 死锁的处理
->死锁的产生
- 竞争资源
- 进程调度顺序不当
A. 竞争资源
共享资源数量不满足各个进程需求
各个进程之间发生资源进程导致死锁
B. 进程调度顺序不当
->死锁的四个必要条件
- 互斥条件
- 请求保持条件
- 不可剥夺条件
- 环路等待条件
->互斥条件
- 进程对资源的使用是排他性的使用
- 某资源只能由一个进程使用,其他进程需要使用只能等待
->请求保持条件
- 进程至少保持一个资源,又提出新的资源请求
- 新资源被占用,请求被阻塞
- 被阻塞的进程不释放自己保持的资源
->不可剥夺条件
- 进程获得的资源在未完成使用前不能被剥夺
- 获得的资源只能由进程自身释放
->环路等待条件
- 发生死锁时,必然存在进程-资源环形链
->死锁的处理
- 预防死锁的方法
- 银行家算法
->预防死锁的方法
破坏其中一个或几个死锁产生的必要条件
->摒弃请求保持条件
- 系统规定进程运行前,一次性申请所有需要的的资源
- 进程在运行期间不会提出资源请求,从而摒弃请求保持条件
->摒弃不可剥夺条件
- 当一个进程请求新的资源得不到满足时,必须释放占有的资源
- 进程运行时战友的资源可以被释放,意味着可以被剥夺
->摒弃环路等待条件
- 可用资源线性排序,申请必须按照需要递增申请
- 线性申请不再形成环路,从而摒弃了环路等待条件
->银行家算法
->策略基础:
- 客户申请的贷款是有限的,每次申请需要声明最大的资金量
- 银行家在能够满足贷款时,都应该给用户贷款
- 客户在使用贷款后,能够及时归还贷款
具体步骤:
->3个表
->做减法
存储管理只内存分配与回收
目的
- 确保计算机有足够的内存处理数据
- 确保程序可以从可用内存中获取一部分内存使用
- 确保程序可以归还使用后的内存以供其他程序使用
内存分配的过程
-> 单一连续分配
- 单一连续分配是最简单的内存分配方式
- 只能再单用户,单进程的操作系统中使用
-> 固定分区分配
- 固定分区分配是支持多道程序的最简单存储分配方式
- 内存空间被划分为若干固定大小的区域
- 每个分区只提供给一个程序使用,互不干扰
-> 动态分区分配
- 根据进程实际需要,动态分配内存空间
- 相关数据结构,分配算法
补充数据结构:
->空闲表数据结构
-> 动态分区空闲链数据结构
把空闲区,首尾相连,连接起来
- 节点续记录可存储的容量
->动态分区分配算法
- 首次适应算法 (FF算法)
- 最佳适应算法(BF算法)
- 快速适应算法(QF算法)
-> 首次适应算法,使用空闲链
- 分配内存时从开始顺序查找适合内存区
- 若没有合适的空闲区,则该分配失败
- 每次从头部开始,使得头部地址空间不断地被划分
->循环适应算法 (首次适应算法改进版)
- 从上一次检索结束的位置开始继续检索,不从头开始
-> 最佳适应算法
- 最佳适应算法要求空闲区链表按照容量大小排序
- 遍历空闲区链表找到最佳合适空闲区
-> 快速适应算法
- 快速适应算法要求有多个空闲区链表
- 每个空闲区链表存储一种容量的空闲区
内存回收的过程
Case 1:
- 不需要新建空闲链表节点
- 只需要把 空闲区1的容量增大为空闲区即可
Case 2:
- 将回收区与空闲区合并
- 新的空闲区使用回收区的地址
Case 3:
- 将空闲区1, 空闲区2, 和回收区合并
- 新的空闲区使用空闲区1的地址
Case 4:
- 为回收区创建新的空闲节点
- 插入到相应的空闲区链表中去
存储管理之段页式存储管理
页式存储管理
- 字块是相对物理设备的定义
- 页面则是相对逻辑空间的定义
- 讲进程逻辑空间等分成若干大小的页面
- 相应的把物理内存空间分成与页面大小的物理块
- 以页面为单位把进程空间装进物理内存中分散的物理块
页片大小,不适合太大,也不适合太小,太小的话内存碎片过多。
-> 页表
- 页表记录进程逻辑空间与屋里空间的映射
现代计算机系统中,可以支持非常大的逻辑地址空间, (2^ 32 ~ 2^ 64), 这样,页表就变得非常大,要占用非常大的内存空间,如,具有32位逻辑地址空间的分页系统,规定页面大小为4KB, 则在每个进程页表中的页表项可达到1M (2^20) 个,如果每个页表项占用1Byte, 故每个进程仅仅页表就要占用1MB的内存空间。
32位系统进程的寻址空间为4G, 4G/4KB = 2^20
->多级页表
->缺点: 有一段连续的逻辑分部在多个页面中,将大大降低执行效率
段式存储管理
- 将进程逻辑空间划分成若干段
- 段的长度由连续逻辑的长度决定
- 主函数MAIN, 子程序段X, 子函数Y等
重点:
段式存储和页式存储都离散地管理了进程的逻辑空间
对比:
- 页是物理空间,段是逻辑空间
- 分页是为了合理利用空间,分段是满足用户要求
- 页大小由硬件固定,段长度可动态变化
- 页表信息是一维的,段表信息是二维的
段页式存储管理
- 分页可以有效提高内存利用率
- 分段可以更好满足用户需求
- 两者结合,形成段页式存储管理
主要思想:
- 先将逻辑空间按段式管理分成若干段
- 再把段内空间按页式管理分成若干页
存储管理的虚拟内存
虚拟内存概述
- 有些进程实际需要的内存很大,超过物理内存的容量
- 多道程序设计,使得每个进程可用物理内存更加稀缺
- 不可能无限增加物理内存,物理内存总有不够的时候
- 虚拟内存是操作系统内存管理的关键技术
- 使得多道程序运行和大程序运行成为现实
- 把程序使用内存划分,将部分暂时不适用的内存防止在辅存
程序的局部性原理
局部性原理是指CPU访问存储器时,无论是存取指令还是存取数据,所访问的存储但愿都趋于聚集在一个较小的连续区域中。
- 程序运行时,无需全部装入内存,装载部分即可
- 如果访问页不在内存,则发出缺页中断,发起页面置换
- 从用户层面看,程序拥有很大的空间,即是虚拟内存
虚拟内存实际是对物理内存的补充,速度接近于内存,成本接近于辅存
虚拟内存的置换算法
- 先进先出算法 FIFO
- 最不经常使用算法 LFU
- 最近最少使用算法 LRU
- 替换策略发生在Cache-主存层次、主存-辅存层次
- Cache- 主存层次的替换策略主要是为了解决速度问题
- 主存-辅存层次主要是为了解决容量问题
Linux的存储管理
Buddy内存管理算法
- Buddy算法是经典的内存管理算法
- 算法基于计算机处理二进制的优势具有极高的效率
- 算法主要是为了解决内存外碎片的问题
页内碎片:
内部碎片是已经被分配出去,能明确指出属于哪个进程,的内存空间大于请求所需的内存空间,不能被利用的内存空间就是内部碎片
页外碎片:
外部碎片是指还没分配出去,不属于任何进程,但是由于大小而无法分配给申请内存空间的新进程的内存空闲块。
->因此,Buddy内存管理算法的目的是:
努力让内存分配与相邻内存合并并能快速进行。
->伙伴系统
- 伙伴指的是内存的伙伴
- 一片连续内存的伙伴是相邻的另一片大小一样的连续内存
->规则:
- 向上取整为2的幂大小 ,例如,70k -> 128k, 129k -> 256k, 666k -> 1024k
具体流程:
- 创建一系列空闲块链表,每一种都是2的幂
- 回收刚才分配的内存
Note: 该视频6-10分钟,提供2个例子,说明如何分配,如何回收
意义:
- Buddy算法是经典的内存管理算法
- 算法基于计算机处理二进制的优势具有极高的效率
- 算法主要是为了解决内存外碎片的问题
Linux的交换空间
- 交换空间(swap)是磁盘的一个分区
- Linux物理内存存满时,会把一些内存交换至Swap空间
- Swap空间是初始化系统时配置的
- 冷启动内存依赖
- 系统睡眠依赖
- 大进程空间依赖
操作系统的文件管理
文件的逻辑结构
->逻辑结构文件分为
- 有结构文件
- 无结构文件
->有结构文件:
- 文件内容由定长记录和可变长记录组成
- 定长记录存储文件格式,文件描述等结构化数据线
- 可变长记录存储文件具体内容
Eg.
->无结构文件
- 也称为流式文件
- 文件内容长度以字节为单位, 如exe文件,dll文件,so文件
->顺序文件
- 顺序文件是按照顺序存放在存储介质中的文件
- 磁带的存储特性使得磁带文件只能存储顺序文件
- 顺序文件是所有逻辑文件当中存储效率最高的
->索引文件
- 可变长文件不适合使用顺序文件格式存储
- 索引文件是为了解决可变长文件存储而发明的一种文件格式
- 索引文件需要配合索引表完成存储的操作
Eg.
辅存的存储空间分配
->辅存的分配方式
- 连续分配
- 链接分配
- 索引分配
->连续分配
- 顺序读取文件内容非常容易,速度很快
- 对存储要求高,要求满足容量的连续存储空间
EG. 某个程序使用6个扇区
->链接分配
- 链接分配可以将文件存储在离散的盘块中
- 需要额外的存储空间存储文件的盘块链接顺序
隐式分配:
- 隐式分配的下一个链接指向存储在当前盘块内
- 隐式分配适合顺序访问,随机访问效率很低
显式分配
- 不支持高效的直接存储(FAT记录项多)
- 检索时FAT表占用较大的存储空间,需要将整个FAT加载到内存
索引分配
- 把文件的所有盘块集中存储
- 读取某个文件时,将文件索引读取进内存即可
- 每个文件拥有一个索引块,记录所有盘块信息
- 索引分配方式支持直接访问盘块
- 文件较大时,索引分配方式具有明显优势
->存储空间管理
- 空闲表
- 空闲链表
空闲表补充:
空闲链表:
- 空闲链表把所有的空闲盘区组成一个空闲链表
- 每个链表节点存储空间盘块和空闲的数目
位示图:
- 位示图维护成本很低
- 位示图可以非常容易找到空闲盘块
- 位示图使用0/1比特位,占用空间很小
目录管理
->目录树
目录管理:
- 任何文件或目录都只有唯一的路径
0 赞 Like