细刨进程状态,浅谈僵尸进程,孤儿进程,进程切换
创始人
2024-05-03 07:42:12

image-20221230191214470

文章目录

  • 进程状态
    • 宏观上操作系统层面上理解进程状态
    • 具体Linux操作系统的状态
        • kill -19 pid :停止进程
        • kill -18 pid :继续进程
          • D(disk sleep)深度睡眠
        • $@和 $^
        • 僵尸状态和死亡状态
        • 僵尸进程
        • 孤儿进程
    • 进程优先级
        • 由此衍生出另外几个概念
        • 进程切换

进程状态

宏观上操作系统层面上理解进程状态

进程状态类型有运行、挂起、等待、阻塞、就绪、等待、停止、挂机、死亡等等。那么进程为什么要有这么多类型的进程状态?1.是为了满足不同的运行场景。

image-20221228184917747

根据冯诺依曼体系结构得知,程序在运行时要加载进内存中,即把进程加载到内存中。而进程想在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操作系统的状态

为了更好的演示,我先写了一个简单程序。

image-20221228193316081

然后编译运行**,运行后查看 stay表状态,此时R+ 就是运行状态(R—running)**

image-20221228193548821

我修改一下程序

image-20221228194030316

然后编译运行它然后再查看,发现已经不是R+而是S+

image-20221228194726728

printf—打印到显示器上,显示器是外设,相对于cpu来说是相当慢的,等显示器就绪cpu就要花费很长时间,所以99%的时间都是在等IO就绪,1%再执行打印代码。此时的状态是睡眠状态【浅度睡眠—可以被终止】且是阻塞状态的一种(S—sleeping)

我们把代码改回原来

image-20221228193316081

image-20221228201853036

kill -19 pid :停止进程

输入kill -19 23884 停止进程后,再查看此时该进程就暂停状态(T—stopped),停止状态是阻塞状态的一种

image-20221228202335993

kill -18 pid :继续进程

输入 kill -18 23884 继续进程,再查看该进程就是R,

image-20221228202315780

然后再修改程序

image-20221228202854745

编译再运行,这时候在xshell上输入任何指令都无效,但是能用ctrl+c结束掉的进程称为前台进程!—指运行起来就无法在前端获取命令行解析但能用ctrl+c终止的进程

现在我们重新运行程序,程序是S+,停止后是T,继续后是S

image-20221228203931816

但我现在在命令行输入指令xshell执行了!但不能用ctrl+c去终止了,可以用kill -9 pid杀死进程!—现在是后台进程!

image-20221228204128695

有+号的进程是前台进程,没有即是后台进程!

D(disk sleep)深度睡眠

一天用户要求磁盘往进程A里写入1w条数据,此时内存空间非常拥挤,就算把进程A挂起了也不能解决问题,这时操作系统会把进程A杀掉;而有些进程非常重要,为了防止这样的事情发生就有了D状态,D状态的进程无法被OS杀掉,只能通过断电或者进程自己醒来才能解决!

在高IO的情况下能出现D状态的进程,dd命令可以在短时间内形成非常大的临时文件之后会出现D状态的进程,有兴趣的小伙伴可以试试!

$@和 $^

在Makefile文件中,$@表示依赖关系的左边(冒号的左边), $^表示依赖关系的右边(冒号的右边)

image-20221230144523603

新建文件myproc.c,

image-20221230145036209

gdb调试,在第8行打断点,然后运行到第8行,此时用ps查看进程,可以看到该进程是t状态,表示该进程正在被追踪,是停止状态的一种(t—trancing stop)

image-20221230145440777

僵尸状态和死亡状态

我们知道,一个进程被创建出来是为了完成用户要求的任务,而进程完成任务的结果如何是由其父进程查看的,因此在进程退出时,不会立即释放该进程对应的资源,而是保存一段时间,让父进程或者操作系统来读取检查,读取后父进程或者操作系统才会回收该进程的所有资源。**回收后该进程就是死亡状态(X—dead)**了。而进程退出到还没被回收的期间的状态就是僵尸状态,也称将死状态(Z—zombie)

僵尸进程

1.僵死状态(Zombies)是一个比较特殊的状态。当进程退出并且父进程(使用wait()系统调用)没有读取到子进程退出的返回代码时就会产生僵死(尸)进程

2.僵死进程会以终止状态保持在进程表中,并且会一直在等待父进程读取退出状态代码。

3.所以,只要子进程退出,父进程还在运行,但父进程没有读取子进程状态,子进程进入Z状态

那么我们可以做个实验证明他,让子进程退出,而父进程不退出也啥也不做。

image-20221230163500190

这时候我写一个脚本让它不断打印进程状态

image-20221230164130285

grep -v 名称表示不显示该进程

这边运行它是这样的

image-20221230164209960

前者是父进程,后者是子进程,在前段时间时子进程还是阻塞状态,后面就变成僵尸状态了!

进程的名称加上了【】且后面跟着< defunct > (失效的)

image-20221230164249834

维护退出状态本身就是要用数据维护,也属于进程基本信息,所以保存在task_struct(PCB)中,换句话说,Z状态一直不退出,PCB一直都要维护。

并且僵尸进程是要求回收的,不回收会占用内存,造成内存泄露。

孤儿进程

修改代码,让子进程和父进程同时不间断运行

image-20221230170406008

然后杀掉父进程,子进程被编号为1的进程接管,该1号进程就是bash,而bash就是父进程的父进程,**父进程被杀死后,bash进程就接管了子进程,这种失去“爸爸”后被接管的进程就被称为孤儿进程。**且子进程从前台进程变成了后台进程。

image-20221230170708927

进程优先级

优先级是啥?权限是关于能不能的问题,优先级是指先做后做的问题。由于资源匮乏,利用资源的顺序就自然而然的形成了。

而进程的优先级则是指cpu资源分配的先后顺序。优先级高的进程先使用,优先级低的进程后使用,大大改善了系统整体性能。

Linux优先级本质就是进程的pcb里面的一个或多个数字即编号。

创建一个test.c

image-20221230175308922

编译后运行它,通过ps -la查看到test的各项数据

image-20221230175423827

PRI指优先级(priority),而NI指nice值,在Linux下优先级=PRI+NI,数值越小优先级越高。

我们可以看到test的PRI是80,NI是0

修改优先级:输入top进入后按r->输入进程pid->输入nice值 回车

通过top指令修改优先级,由于修改优先级会影响整个系统的运作,所以我们要用sudo top,在命令行输入sudo top进入这样的界面

image-20221230175726385

然后输入r,进入修改优先级,然后输入要修改进程的pid

image-20221230180128783

按enter后输入要修改后的nice值,在这里我修改为-100然后按回车

image-20221230180209633

然后再查看test优先级,可以看到NI为-20,而我修改的值是-100,说明NI的下限值为-20

image-20221230180401280

我在把test的nice值修改为100

image-20221230180538492

可以看到test的NI为19,但是我输入的值为100,说明NI的上限值为19

image-20221230180530696

得出结论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等等状态。还有前台进程,后台进程的区别和特性。还浅谈了僵尸进程,孤儿进程,进程优先级,进程切换等等概念。

相关内容

热门资讯

北京的名胜古迹 北京最著名的景... 北京从元代开始,逐渐走上帝国首都的道路,先是成为大辽朝五大首都之一的南京城,随着金灭辽,金代从海陵王...
苗族的传统节日 贵州苗族节日有... 【岜沙苗族芦笙节】岜沙,苗语叫“分送”,距从江县城7.5公里,是世界上最崇拜树木并以树为神的枪手部落...
世界上最漂亮的人 世界上最漂亮... 此前在某网上,选出了全球265万颜值姣好的女性。从这些数量庞大的女性群体中,人们投票选出了心目中最美...
长白山自助游攻略 吉林长白山游... 昨天介绍了西坡的景点详细请看链接:一个人的旅行,据说能看到长白山天池全凭运气,您的运气如何?今日介绍...
应用未安装解决办法 平板应用未... ---IT小技术,每天Get一个小技能!一、前言描述苹果IPad2居然不能安装怎么办?与此IPad不...