Linux——进程(下)
目录
一、Linux状态
1、运行状态
编辑2、 浅度休眠(阻塞状态)
3、深度睡眠(D状态)
4、暂停(T状态)
5、追踪状态(t状态)
6、僵尸状态(Z状态)
7、结束状态(X状态)
二、进程的优先级
1、是什么
2、为什么
3、查看进程的优先级
三、Linux优先级怎么做的
1、调整优先级
2、为什么nice有范围
为什么
3、竞争独立并行并发
4、进程切换
四、Liunx如何调度的
1、大O(1)调度算法
五、实时操作系统
一、Linux状态
1、运行状态
2、 浅度休眠(阻塞状态)
浅度:能够响应外部的的时间
深度睡眠:D状态(如下)
上图一致不停的向显示器打印(硬件),一直不停的再从调度队列到显示器队列,再从显示器队列到调度队列,因为cpu太快而硬件代码所以我们大多数看到的是阻塞状态
3、深度睡眠(D状态)
不对任何事件进行相应的响应,操作系统也杀不掉,重启也没用,除非进程自己醒来。(如:向磁盘中写入数据)
4、暂停(T状态)
当我们使用kill -19命令可以使进程暂停进入T状态
5、追踪状态(t状态)
当我们使用gdb调试程序的时候我们运行的时候是gdb创建子进程,让子进程执行代码,如果我们打了断点,停下来的也是子进程,这种状态叫t状态(因为追踪,进程因为断点而停下来)
6、僵尸状态(Z状态)
进程结束,不能立即释放该进程的所有资源,所以要先处于一种僵尸状态,代码释放掉,但是会把task_struct保留(会记录进程退出的时候,退出信息,方便父进程读取退出码)等到父进程读取完退出码后,状态会从Z状态变成X状态
如上图我们写一个父进程始终存在但子进程结束的程序,我们可以发现在子进程结束之后我们我的状态会出现 Z状态,如果父进程将来不处理,这个僵尸进程会一直存在,最终造成内存泄漏
如上图我们写一个代码父进程先退出,子进程始终存在(孤儿进程),我们可以观察到当父进程退出的时候,子进程被一号(系统)领养了(因为孤儿进程也会退出,但是父进程没有,如果没有被领养就会变成僵尸,造成内存泄漏)
7、结束状态(X状态)
进程结束了,是进程创建的反过程,当父进程回收子进程之后状态就变成X状态(瞬时状态)
二、进程的优先级
1、是什么
进程得到某种资源的先后顺序
2、为什么
本质:就是资源少,进程多(进程竞争CPU资源)
3、查看进程的优先级
查看优先级PRI
ps -al
ps -l
UID :代表执行者的身份
PID: 代表这个进程的代号
PPID: 代表这个进程可被执行的优先级,其值越小越早被执行
NI:代表这个进程的nice值 (修正数据)
三、Linux优先级怎么做的
进程真正的优先级 : PRI(new) = PRI(old)+nice (调整优先级就是调整nice)
1、调整优先级
top
进入top后按"r"->输入进程PID->输入nice值(如果显示输入不成功可以使用超级用户)
注意:这里的nice是覆盖式设置设置为多少直接就是多少且nice的范围从-20到19,PID(old)固定为80
2、为什么nice有范围
为什么
我们所用的操作系统一般都是分时操作系统,尽可能的公平公正,所以即使优先级要变,也要在可控的范围内变化,否则会造成有的进程常时间调度不了,造成进程ji e问题
3、竞争独立并行并发
竞争性: 系统进程数⽬众多,⽽CPU资源只有少量,甚⾄1个,所以进程之间是具有竞争属性 的。为了⾼效完成任务,更合理竞争相关资源,便具有了优先级
独⽴性: 多进程运⾏,需要独享各种资源,多进程运⾏期间互不⼲扰
并⾏: 多个进程在多个CPU下分别,同时进⾏运⾏,这称之为并⾏
并发: 多个进程在⼀个CPU下采⽤进程切换的⽅式,在⼀段时间之内,让多个进程都得以推进, 称之为并发
4、进程切换
- CPU上下⽂切换:其实际含义是任务切换, 或者CPU寄存器切换。当多任务内核决定运⾏另外的任务时, 它保存正在运⾏任务的当前状态, 也就是CPU寄存器中的全部内容。这些内容被保存在任务⾃⼰的堆栈中, ⼊栈⼯作完成后就把下⼀个将要运⾏的任务的当前状况从该任务的栈中重新装⼊CPU寄存器,并开始下⼀个任务的运⾏, 这⼀过程就是context switch。
- CPU内寄存器,就是一套存储空间,寄存器只有一套,属于CPU本身,但是寄存器内部的数据,可以有很多
- 当前系统,都是分时系统,每一个进程都有自己的"时间片"(当代计算机都是分时操作系统,每一个进程都有它的时间片,当时间片被耗尽,进程就被操作系统从CPU中剥离下来)
四、Liunx如何调度的
1、大O(1)调度算法
- 如上图调度队列中有一个queue【140】是struct task_struct*的类型的,指向一个140的数组,该数据的前[0,99]不管,剩下的【100,139】刚好和CPU的范围一致,每一个位置后面都有可能挂着大量的进程,如果每一次一个一个的扫描【100,139】,再优先级高的列入到CPU中太过于浪费时间,所以进程调度队列中还有一个bitmap[5](一个int 是32个字节,如果是4个就是128太少,所以个为5个),比特位的位置表示是数组第几个(第几个队列),比特位的内容表明该队列是否位空。利用位图操作,来替换,遍历数组的在操作,可以提高效率
- 观察上图发现queue[140]其实有两个,且调度队列中有两个指针*active (活跃指针)和 *expired (过期指针)指向两个(queue[140], nr_active, bitmap[5]为一个结构)
- CPU调度的时候,直接从active指针,找到对应的queue[140]
- 新增进程、或者是时间片到了的进程,被从CPU中剥离下来,被剥离的进程,只能重新入队列,入过期队列(调度完所有的队列,所有的进程,全部会跑到过期队列中)
- 一个*active 所指向的指针中的queue[140]为空,就会交换两个指针
- 不存在饥饿问题,因为即使我们更改了进程的nice,也要等CPU调度完所有的队列,下一次调度的时候才有效
五、实时操作系统
实时操作系统,会优先把优先级高的级的执行完才会执行下一个,实时操作系统也可以实现分时操作系统,调度区间为【0,99】