哪些是实名制网站,广西网站制作,班组建设展板哪个网站有,滕州网站建设制作目录 1. 进程状态的概念 1.1 课本上的说法#xff1a;名词提炼
1.2 运行#xff0c;阻塞和挂起
1.2.1 什么叫做运行状态#xff08;running#xff09;#xff1f;
1.2.2 什么叫做阻塞状态#xff08;sleeping#xff09;#xff1f;
1.2.3 什么叫做挂起状态…目录 1. 进程状态的概念 1.1 课本上的说法名词提炼
1.2 运行阻塞和挂起
1.2.1 什么叫做运行状态running
1.2.2 什么叫做阻塞状态sleeping
1.2.3 什么叫做挂起状态pending
2. linux下的进程状态 2.1 R运⾏状态running
2.2 S睡眠状态sleeping)
2.3 D磁盘休眠状态深度睡眠Disk sleep
2.4 T/t暂停状态stopped 2.5 X死亡状态dead 2.6 Z僵尸状态zombie 如何模拟Z状态
僵尸进程危害
浅谈
3. 孤儿进程 接前文Linux系统 —— 进程系列 - 进程的概念PCB与PID和fork-CSDN博客https://blog.csdn.net/hedhjd/article/details/144299919?spm1001.2014.3001.5501 1. 进程状态的概念 ⼀个进程可以有多个状态在Linux内核⾥进程有时候也叫做任务打个比方我们现在正在上课这叫做上课中上完课回到宿舍睡觉这叫做休息中休息完跑到操场是跑步这叫做运动中 所以每一个人都有自己对应的状态状态决定了我们当前正在做什么事情以及系统应该如何看待我们比如你每天准时上课那么你就是一个好学生 对于进程来说这个进程当前是需要被使用还是正在休眠正在等待所以进程的状态决定了当前进程在系统里应该被如何处理 进程状态的本质其实就是task_state结构体内部的一个整数 1.1 课本上的说法名词提炼 由上图可以得知进程具有多种状态状态之间是可以相互转化的 1.2 运行阻塞和挂起 PCB即属于双链表又属于队列但是我们可以把队列也看作是一个双链表只不过这个双链表遵守的是尾进头出 在这里有一个既不属于Linux也不使用其他操作系统的调度算法之一的 —— FIFO先进先出也就是说在这个队列当中在头部的优先级高尾部的优先级低优先级按照顺序排 我们下面这张图就是CPU调度按照顺序来依次调度 1.2.1 什么叫做运行状态running 当一个进程只有CPU在跑的时候它就是运行状态但是在当代计算机里面只要一个进程在调度队列当中它就是运行状态running 处于running状态的进程也么是正在被运行要么就是已经准备好了随时都可以被调度 运行状态对于的是创建就绪和运行其中运行和就绪可以当作一种状态 1.2.2 什么叫做阻塞状态sleeping 举个例子C语言当中的scanf函数当我们scanf的时候其实我们并不是在等待用户输入内容而是在等待键盘硬件就绪也就是在等待键盘上有按键被按下了如果没有被按下就称之为键盘不就绪那么scanf就要等 阻塞就是等待某种设备或者资源就绪在等待的期间如果一直不就绪那么我的进程就不会被调动那么就会卡在哪里不动 我们以一个问题来理解一下操作系统os是怎么对软硬件进行管理的答案是先描述再组织 我们先拿硬件来举例子实际上因为操作系统要管理硬件所以操作系统os也要创建数据结构struct_device 这个数据结构里包含的就是目标设备的所有属性那么就说明struct_device可以直接或者间接获得我们对应的数据 上面这张图可以称之为设备队列而下面的图片叫做运行队列 我们都知道在内存当中每一种设备都要对应一种struct_device结构体当我们读磁盘读网卡的时候如果设备上对应的设备没有就绪那么我们的进程就要阻塞等待了那么在操作系统中我们如何理解阻塞等待呢我们可以在数据结构体里加上一个等待队列 所以我们对应的每一个设备它都有一个等待队列 我们假设我们的CPU正在运行当运行的时候执行我们的代码假设是scanf需要就绪读取读取的时候OS发现需要去读取键盘然后OS去检查键盘的状态然后发现键盘没有任何活跃的状态那么你这个进程无法读到键盘的任何数据进程就无法继续执行了所以操作系统把这个进程从cpu上拿下来啊并且把这个进程从运行队列当中移走然后把它链入到我们对应的特定设备的等待队列当中那么这个进程就不会再被调度了那么这个进程此时就处于阻塞状态 只有在运行队列里的进程才会被CPU调度不在运行队列里转而在设备队列里等待那么这个进程就叫做阻塞 1.2.3 什么叫做挂起状态pending 当我们有一个进程处于阻塞状态的时候 如果这个时候又来了几个进程 而这个时候操作系统的内存不足了那么这个时候 操作系统就需要在保持正常的情况下节省出来内存资源 而我们知道一个进程如果在阻塞状态 那么它的代码和数据就是处于一个空闲的状态。 这个时候操作系统就会将进程的PCB保留 而进程的代码和数据就会被放到外设当中 当下次资源就绪的时候进程就会被重新唤醒。 那么这个时候代码和数据再次从磁盘放到内存中而这个过程就叫做换出和换入操作而换出后 也就是代码和数据在磁盘时 就叫做挂起状态这种挂起状态称为阻塞挂起状态那么当它换入时我们就可以将阻塞挂起状态重新改为运行状态那么该进程就可以程序被调度了 2. linux下的进程状态
static const char* const task_state_array[] {R (running), /*0 */S (sleeping), /*1 */D (disk sleep), /*2 */T (stopped), /*4 */t (tracing stop), /*8 */X (dead), /*16 */Z (zombie), /*32 */
}; 2.1 R运⾏状态running 运行状态并不意味着进程⼀定在运⾏中它表明进程要么是在运⾏中要么在运⾏队列⾥ 我们先简单创建个代码 运行结果 我们再打开一个xshell来查看一下我们的进程 我们再给一个命令让它一直跑起来每隔一秒查一次 但是我们就发现了为什么进程里面都是S呢答案就是因为我们的代码里面有prinft函数如果进程运行需要1秒的话假设prinft函数运行需要1纳秒那么1秒减去1纳秒剩下的时间进程就在等待IO所以就是S状态所以我们当前这个进程正在运行队列和等待队列来回切换也就是正在阻塞状态 解决方法就是将printf去掉 那么就不用打印到外设上 就不需要等待。 我们再查看进程状态 进程的状态就是R运行了 我们可以看到图中的R后面还有一个 这个 的意思是我们的确这个进程启动是在前台启动的 R (running), /*0 */ 我们可以看到R为0那么我们只需要在PCB当中将当前状态设置为对应的整数就可以保证为R S (sleeping), /*1 */ 同理S为0那么我们也只需要在PCB当中将当前状态设置为对应的整数就可以保证为S其他的几个状态也是如此 2.2 S睡眠状态sleeping) 睡眠状态意味着进程在等待事件完成这⾥的睡眠有时候也叫做可中断睡眠interruptible sleep 在Linux当中操作系统理论里我们的阻塞状态叫做阻塞而在Linux内核当中我们的阻塞状态叫做S我们看到一个进程卡住不动了其实就是这个进程当前没有被调度这个进程正在等待键盘有数据所以这个状态叫做阻塞状态 2.3 D磁盘休眠状态深度睡眠Disk sleep D (disk sleep), /*2 */ 深度睡眠状态有时候也叫不可中断睡眠状态uninterruptible sleep在这个状态的进程通常会等待IO的结束 也叫深度睡眠其实也是一种阻塞状态我们前面的S也叫做浅度睡眠 浅度睡眠状态也叫做可中断休眠状态简单来说就是如果一个进程处于S状态那么我们可以直接把这个进程杀掉这个进程会响应我们杀掉它的动作 深度睡眠其实就是一种不响应操作系统任何请求的状态 一般的阻塞状态 当进程停止等待外设后就会进入运行状态 但是深度睡眠只有当完成了特定的任务 否则不会响应操作系统的任何命令 即便系统关机了 这个进程仍然会自己跑 D状态产生的原因是因为进程向磁盘中写入数据如果我们想要将1G数据写到磁盘中但是对于磁盘来说 磁盘写入数据是有可能失败的磁盘满了或者其他原因 所以对于进程来说 他写入数据就不能将数据交给磁盘后不管了 他要等待磁盘写入的结果。 如果没有写入成功 可以再写入一次 或者写入不成功后想其他办法处理数据 那么进程就将数据交给磁盘但是对于进程来说这个期间等待的时间是非常长的如果这个时候内存满了 操作系统管理内存 就势必要杀掉一部分进程这个过程是必须等 而我们的进程在等待磁盘的过程中会处于闲置的状态 那么就容易被操作系统杀掉而被操作系统杀掉后 磁盘就不会找不到进程 那么他就不会在进程写入数据了数据丢失所以 为了避免这种情况 就出现了深度睡眠——D状态只要进程处于D状态那么这个进程就不可能被杀掉即便操作系统关机 只要电源存在 就可以一直进入想要结束D状态只有关掉电源 D状态其实也是一种阻塞状态 2.4 T/t暂停状态stopped T (stopped), /*4 */
t (tracing stop), /*8 */ 暂停状态stopped可以通过发送 SIGSTOP 信号给进程来暂停T进程。这个被暂停的进程可以通过发送 SIGCONT 信号让进程继续运行 暂停状态属于Linux的一种特有状态 t是有特殊用途的主要是用来做debug的 2.5 X死亡状态dead X (dead), /*16 */ 死亡状态dead这个状态只是⼀个返回状态你不会在任务列表里看到这个状态 死亡状态其实对应的就是我们系统中的结束状态 2.6 Z僵尸状态zombie Z (zombie), /*32 */ 1. 僵死状态Zombies是⼀个⽐较特殊的状态。当进程退出并且⽗进程使⽤wait()系统调⽤,后⾯讲没有读取到⼦进程退出的返回代码时就会产⽣僵死(⼫)进程 2. 僵死进程会以终⽌状态保持在进程表中并且会⼀直在等待⽗进程读取退出状态代码 3. 所以只要⼦进程退出⽗进程还在运⾏但⽗进程没有读取⼦进程状态⼦进程进⼊Z状态 举个例子比如有一天我们在路上走路然后我们看到有一个人躺在路边我们靠近之后发现这个人已经走了好一会了然后我们就报警打110警察来了之后就开始封锁现场警察过来的时候可能还要把法医带过来然后在这个人身上做一些采样拿回去做化验拿几根头发什么的用于判断这个人是自杀还是谋杀还是自然死亡当法医查完之后他把在这个人身上获取了法医想获取的有效信息之后法医就说可以撤了。这个时候呢我们警察才会通知家属啊准备后事然后就把人就拉走了 那么在他死亡之后到被抬走之前这段时间这个人一直在地上躺着那么这个人在这段时间里所处的状态叫做僵尸状态为什么要让这个人处于僵尸状态呢是为了获得这个人死亡退出时的死亡信息自杀还是谋杀还是自然死亡当这个人被警察抬走的时候就变成了X状态 //创建维持30秒的僵死进程例⼦
#include stdio.h
#include stdlib.h
int main()
{pid_t id fork();if (id 0) {perror(fork);return 1;}else if (id 0) { //parentprintf(parent[%d] is sleeping...\n, getpid());sleep(30);}else {printf(child[%d] is begin Z...\n, getpid());sleep(5);exit(EXIT_SUCCESS);}return 0;
} 如何模拟Z状态 我们模拟Z状态的前提条件是我们必须得有父子进程而且要让这个子进程在退的时候父进程什么都不干我们先暂时先不讲父进程怎么解决僵尸状态我们只需要父进程什么都不管然后子进程直接退出如果我们也不获取子进程的退出的信息那么子进程就必须一直把自己维持在Z状态 就好比在路边啊一个人倒下了那么打110没人来获取这个人的退休结果信息那么此时这个人就只能一直在路边躺着所以我要模拟验证Z状态我们就要创建父子进程让Z进程在一定程度上直接退出子进程退出之后我们就可以查到我们子进程的相关信息了 观察上面的两张图片我们发现前面子进程还在正常运行但是后面就只剩下一个父进程了观察我们状态的那张图片我们发现状态里有Z状态 以上这个情况就是说 对于一个进程来说 它在退出的时候 一定要维持一段时间的僵尸进程 而只有当父进程或则其他关系进程子进程的资源将这个进程的情况读取到了 才会去释放这个子进程的资源。 也就是说 对于僵尸进程来说 如果父进程一直不去释放它 那么它就会一直占用着资源也就导致了内存泄漏 僵尸进程危害 1. 进程的退出状态必须被维持下去因为他要告诉关⼼它的进程⽗进程你交给我的任务我办的怎么样了。可⽗进程如果⼀直不读取那⼦进程就⼀直处于Z状态是的 2. 维护退出状态本⾝就是要⽤数据维护也属于进程基本信息所以保存task_struct(PCB)中换句话说Z状态⼀直不退出PCB⼀直都要维护是的 3. 那⼀个⽗进程创建了很多⼦进程就是不回收是不是就会造成内存资源的浪费是的因为数据结构对象本⾝就要占⽤内存想想C中定义⼀个结构体变量对象是要在内存的某个位置进⾏开辟空间 浅谈 我们目前所讲到的6种状态其实都是某一个进程的子进程可能是我们自己进程的子进程也有可能是bash进程的子进程 3. 孤儿进程 如果一个父进程先退出那么子进程就会被操作系统领养子进程的父进程会变成操作系统这个时候子进程就称之为孤儿进程这个过程就叫做领养 为什么需要领养操作答案是一个进程想要被释放 就需要父进程如果没有父进程的话子进程本身是一个进程它也需要被释放 否则就会发生内存泄漏 所以就需要被领养 如果父进程被终止 子进程仍然会运行 完结撒花~