文章目录
进程状态
宏观上操作系统层面上理解进程状态
进程状态类型有运行、挂起、等待、阻塞、就绪、等待、停止、挂机、死亡等等。那么进程为什么要有这么多类型的进程状态?1.是为了满足不同的运行场景。
根据冯诺依曼体系结构得知,程序在运行时要加载进内存中,即把进程加载到内存中。而进程想在cpu上运行起来,那么cpu就得在内核中去维护一个运行队列(runqueue)。**一般情况下,cpu的数量是远远少于进程数量的。**而cpu只有一个,进程这么多想在cpu上运行那咋办捏?cpu对进程说你们排队一个一个来。于是进程就在进程队列里排起了队伍。2.进程入队列本质上是进程的PCB即该进程的task_struct结构体对象放入队列 (一般情况下一个cpu配对一个内核专门为cpu准备的运行队列)
运行队列里有个头节点结构体,通过节点间联系找到相应结构体。因为cpu很快,每个进程都得随时准备好在给别人运行,3.被cpu运行的进程(而cpu运行太快了此时的进程可以忽略不记)和在运行队列里的进程的状态就被称为运行状态(R)!
pcb记录着进程的各种数据和地址,而状态也记录着。进程状态在pcb中就是个整数(int),比如1—R(运行状态),2—dead(死亡状态),3—hug(挂起状态)等等
看b站视频时要访问网卡,此时在微信上和朋友发短信,微信要访问网卡,epic在后台下游戏,e宝也要访问网卡,这时多个进程同时访问网卡,网卡的数量也是少于进程的。那么多个进程在访问硬件时就需要排队等待。那么硬件进程对应的pcb也要相应管理等待队列。当某个进程在被cpu运行但也需要访问某种硬件时,cpu等不起硬件会在该进程的pcb中把运行状态修改为阻塞状态,把进程放到等待硬件的队伍4.进程在等待外设资源的状态就称阻塞状态
但多个进程在等待硬件资源,而硬件非常的慢,这些进程的pcb和对应的代码和数据占用了一部分内存,那么这些阻塞状态的进程不会被立即调度,此时内存不够了,操作系统会把进程的代码和数据放回到磁盘上,把节省出来的空间给别人,但保留内核的数据结构。5.阻塞状态的进程的代码和数据被放回到磁盘上,此时该进程被称为挂起状态!
6.更深刻的理解:所谓的进程不同的状态,本质是进程在不同的队列中等待某种资源
当挂起状态的进程可以被调度时,操作系统会把进程对应的代码和数据从磁盘加载到内存,在pcb把挂起状态改成运行状态。7.将进程的相关数据加载到内存(换入),把进程的相关数据从内存放到磁盘(换出)—内存数据的换入换出
当内存不够时操作系统才会把阻塞状态的进程挂起,所以阻塞不一定挂起,但挂起一定阻塞。除了运行状态,挂起还可以跟其他状态组合
具体Linux操作系统的状态
为了更好的演示,我先写了一个简单程序。
然后编译运行**,运行后查看 stay表状态,此时R+ 就是运行状态(R—running)**
我修改一下程序
然后编译运行它然后再查看,发现已经不是R+而是S+
printf—打印到显示器上,显示器是外设,相对于cpu来说是相当慢的,等显示器就绪cpu就要花费很长时间,所以99%的时间都是在等IO就绪,1%再执行打印代码。此时的状态是睡眠状态【浅度睡眠—可以被终止】且是阻塞状态的一种(S—sleeping)
我们把代码改回原来
kill -19 pid :停止进程
输入kill -19 23884 停止进程后,再查看此时该进程就暂停状态(T—stopped),停止状态是阻塞状态的一种
kill -18 pid :继续进程
输入 kill -18 23884 继续进程,再查看该进程就是R,
然后再修改程序
编译再运行,这时候在xshell上输入任何指令都无效,但是能用ctrl+c结束掉的进程称为前台进程!—指运行起来就无法在前端获取命令行解析但能用ctrl+c终止的进程
现在我们重新运行程序,程序是S+,停止后是T,继续后是S
但我现在在命令行输入指令xshell执行了!但不能用ctrl+c去终止了,可以用kill -9 pid杀死进程!—现在是后台进程!
有+号的进程是前台进程,没有即是后台进程!
D(disk sleep)深度睡眠
一天用户要求磁盘往进程A里写入1w条数据,此时内存空间非常拥挤,就算把进程A挂起了也不能解决问题,这时操作系统会把进程A杀掉;而有些进程非常重要,为了防止这样的事情发生就有了D状态,D状态的进程无法被OS杀掉,只能通过断电或者进程自己醒来才能解决!
在高IO的情况下能出现D状态的进程,dd命令可以在短时间内形成非常大的临时文件之后会出现D状态的进程,有兴趣的小伙伴可以试试!
$@和 $^
在Makefile文件中,$@表示依赖关系的左边(冒号的左边), $^表示依赖关系的右边(冒号的右边)
新建文件myproc.c,
gdb调试,在第8行打断点,然后运行到第8行,此时用ps查看进程,可以看到该进程是t状态,表示该进程正在被追踪,是停止状态的一种(t—trancing stop)
僵尸状态和死亡状态
我们知道,一个进程被创建出来是为了完成用户要求的任务,而进程完成任务的结果如何是由其父进程查看的,因此在进程退出时,不会立即释放该进程对应的资源,而是保存一段时间,让父进程或者操作系统来读取检查,读取后父进程或者操作系统才会回收该进程的所有资源。**回收后该进程就是死亡状态(X—dead)**了。而进程退出到还没被回收的期间的状态就是僵尸状态,也称将死状态(Z—zombie)
僵尸进程
1.僵死状态(Zombies)是一个比较特殊的状态。当进程退出并且父进程(使用wait()系统调用)没有读取到子进程退出的返回代码时就会产生僵死(尸)进程
2.僵死进程会以终止状态保持在进程表中,并且会一直在等待父进程读取退出状态代码。
3.所以,只要子进程退出,父进程还在运行,但父进程没有读取子进程状态,子进程进入Z状态
那么我们可以做个实验证明他,让子进程退出,而父进程不退出也啥也不做。
这时候我写一个脚本让它不断打印进程状态
grep -v 名称表示不显示该进程
这边运行它是这样的
前者是父进程,后者是子进程,在前段时间时子进程还是阻塞状态,后面就变成僵尸状态了!
进程的名称加上了【】且后面跟着< defunct > (失效的)
维护退出状态本身就是要用数据维护,也属于进程基本信息,所以保存在task_struct(PCB)中,换句话说,Z状态一直不退出,PCB一直都要维护。
并且僵尸进程是要求回收的,不回收会占用内存,造成内存泄露。
孤儿进程
修改代码,让子进程和父进程同时不间断运行
然后杀掉父进程,子进程被编号为1的进程接管,该1号进程就是bash,而bash就是父进程的父进程,**父进程被杀死后,bash进程就接管了子进程,这种失去“爸爸”后被接管的进程就被称为孤儿进程。**且子进程从前台进程变成了后台进程。
进程优先级
优先级是啥?权限是关于能不能的问题,优先级是指先做后做的问题。由于资源匮乏,利用资源的顺序就自然而然的形成了。
而进程的优先级则是指cpu资源分配的先后顺序。优先级高的进程先使用,优先级低的进程后使用,大大改善了系统整体性能。
Linux优先级本质就是进程的pcb里面的一个或多个数字即编号。
创建一个test.c
编译后运行它,通过ps -la查看到test的各项数据
PRI指优先级(priority),而NI指nice值,在Linux下优先级=PRI+NI,数值越小优先级越高。
我们可以看到test的PRI是80,NI是0
修改优先级:输入top进入后按r->输入进程pid->输入nice值 回车
通过top指令修改优先级,由于修改优先级会影响整个系统的运作,所以我们要用sudo top,在命令行输入sudo top进入这样的界面
然后输入r,进入修改优先级,然后输入要修改进程的pid
按enter后输入要修改后的nice值,在这里我修改为-100然后按回车
然后再查看test优先级,可以看到NI为-20,而我修改的值是-100,说明NI的下限值为-20
我在把test的nice值修改为100
可以看到test的NI为19,但是我输入的值为100,说明NI的上限值为19
得出结论NI的范围为【-20,19】,且总是用PRI初始值80去加NI值得出最后的PRI(80-20=60,80+19=99);对应的PRI范围为【60,99】
由此衍生出另外几个概念
竞争性: | 系统进程数目众多,而CPU资源只有少量,甚至1个,所以进程之间是具有竞争性的。为了高效完成任务,更合理竞争相关资源,便具有了优先级 |
---|---|
独立性: | 多进程运行,需要独享各种资源,多进程运行期间互不干扰 |
并行: | 多个进程在多个CPU下分别、同时进行运行 |
并发: | 多个进程在一个CPU下采用进程切换的方式,在一段时间之内,让多个进程都得以推进 |
操作系统通过时间片轮转的方式,让一个进程在cpu上跑完一定非常短的时间,等到时间片到了,就把进程的临时数据保存到操纵系统中,就换到下一个进程跑,然后等到该进程再次运行时,就从上一次执行进程的地方继续执行。通过这样的方式让一个时间段内多个进程都在运行。就是所谓进程切换。
进程切换
一个cpu内有一套寄存器。当cpu要调度某个进程时,操作系统会把pcb的地址加载到cpu的某个寄存器中,自然而然的进程的地址和代码就能被cpu找到。并且在cpu中,有个叫eip的寄存器会存放下一个要运行的进程的地址。cpu一直都在做取指令,分析指令,执行指令这三件事。
当进程在运行时,会产生非常多的临时数据,这份数据属于当前进程。cpu内部虽然只有一套寄存器硬件,但寄存器里面保存的数据是属于当前进程的**。当进程在切换的时候,要进行进程的上下文(寄存器内的数据)保护(即保存临时数据到操作系统),当进程在恢复运行时,要进行上下文的恢复。**而寄存器是所有进程共享的,寄存器里的数据是每个进程各自私有的!
今天是我阳后第7天,大致症状也差不多消失了,那不得csdn启动。
以上的内容繁杂,这里做个小总结,进程为了满足不同的运行场景就出现了多种进程状态,比如R+,R,S+,S,D,t,Z,X等等状态。还有前台进程,后台进程的区别和特性。还浅谈了僵尸进程,孤儿进程,进程优先级,进程切换等等概念。