网站做301重定向,乌克兰集团网站建设,青海建设工程云网站,广播电台网站建设板块目录 1.进程排队 时间片 时间片的分配 结构体内存对齐 偏移量补充 对齐规则  为什么会有对齐 2.操作系统学科层面对进程状态的理解 2.1进程的状态理解 ①我们说所谓的状态就是一个整型变量#xff0c;是task_struct中的一个整型变量 ②.状态决定了接下来的动作 2.2运行状态 2.… 目录  1.进程排队 时间片 时间片的分配 结构体内存对齐 偏移量补充 对齐规则  为什么会有对齐  2.操作系统学科层面对进程状态的理解 2.1进程的状态理解 ①我们说所谓的状态就是一个整型变量是task_struct中的一个整型变量 ②.状态决定了接下来的动作 2.2运行状态 2.3 阻塞状态  2.4 挂起状态 3.linux下具体的进程状态重要 3.1 R和s  top命令  前后台程序 3.2 休眠状态s 3.3 disk sleep     不可中断睡眠也叫作深度睡眠。 3.4 T状态进程变成暂停状态 3.5 t状态 3.6 z状态僵尸状态 4. 孤儿进程 5.结语   1.进程排队 
狭义上讲进程  task_struct  可执行程序。 
①当一个进程加载到内存的时候首先这个进程不是一直在内存中运行的也不是一直在运行的。我们启动一个软件并不是说我们启动这个软件他就是一直被运行的他可能因为要等待某种资源加载而处于某种等待状态。 等待键盘资源输入所以进程卡住等待我们输入 ②即使进程被cpu调度也不是一直在运行的。 当我们写一个while死循环的程序交给cpu去运行cpu可能被打满如果cpu只是执行我们这个程序那么就意味着这个程序会一直在cpu上运行没有结束就从cpu上下不来其他进程不可能被调度那么其他所有进程跑不了但是事实是可能此时会卡但是其他进程还是正常运行这说明进程不是放在cpu就要等执行完才下来当代计算机都支持一个时间片的概念cpu会给你这个程序一个运行时间你上来就跑这么长时间跑完就走还要让其他进程执行比如这个时间为1毫秒1毫秒就是时间片. 时间片 时间片timeslice又称为“量子quantum”或“处理器片processor slice”是分时操作系统分配给每个正在运行的进程微观上的一段CPU时间在抢占内核中是从进程开始运行直到被抢占的时间。现代操作系统如Windows、Linux、Mac OS X等允许同时运行多个进程 —— 例如你可以在打开音乐播放器听音乐的同时用浏览器浏览网页并下载文件。事实上虽然一台计算机通常可能有多个CPU但是同一个CPU永远不可能真正地同时运行多个任务。在只考虑一个CPU的情况下这些进程“看起来像”同时运行的实则是轮番穿插地运行由于时间片通常很短在Linux上为5ms800ms用户不会感觉到。 时间片由操作系统内核的调度程序分配给每个进程。首先内核会给每个进程分配相等的初始时间片然后每个进程轮番地执行相应的时间当所有进程都处于时间片耗尽的状态时内核会重新为每个进程计算并分配时间片如此往复。 时间片的分配 通常状况下一个系统中所有的进程被分配到的时间片长短并不是相等的尽管初始时间片基本相等在Linux系统中初始时间片也不相等而是各自父进程的一半系统通过测量进程处于“睡眠”和“正在运行”状态的时间长短来计算每个进程的交互性交互性和每个进程预设的静态优先级Nice值的叠加即是动态优先级动态优先级按比例缩放就是要分配给那个进程时间片的长短。一般地为了获得较快的响应速度交互性强的进程即趋向于IO消耗型被分配到的时间片要长于交互性弱的趋向于处理器消耗型进程。引自百度百科 所谓进程排队一定是为了等待某种资可以包括cpu键盘、磁盘、等等........... 
而内存中有很多的进程队列进程排队是经常的进程描述块在排队。就比如我们去找工作时投递简历简历在hr处排队拿到誰的简历了就让相应的人来是简历在排队。而简历就可以说是描述人的工作属性的一个结构体或者类。。所以只要是排队一定是进程的task_struct在排队。 而一个task_struct可以被链入多种数据结构linux中是被链入双链表中的linux实现双链表的方式和我们c语言中是不大一样的 
首先在pcb中定义了这样一个结构体 
struct listnode
{struct listnode *next;
struct listnode *prev;
}; 
在每个进程的pcb中 我们通过链式对象找到listnode对象那么还有很多的属性怎么访问呢。原理 
struct listnode 是 task_struct中的一个变量也是一个地址。现在就相当于我们知道了结构体中一个变量的地址如何知道其他成员的地址呢。 
结构体偏移量补一下结构体偏移 
了解的伙伴可以直接跳过 结构体内存对齐  题型考察结构体的大小我们来看一下例子引入请问如下这段代码输出分别为什么 struct S1
{char c1;int i;char c2;
};
struct S2
{char c1;char c2;int i;
};
int main()
{printf(%d\n, sizeof(struct S1));printf(%d\n, sizeof(struct S2));return 0;
}  明明是两个一样的结构体为什么却不一样大要知道答案我们就要知道结构体的大小是如何计算的结构体大小的计算并不是单单就靠结构体内部元素的类型大小来决定让我们来看一下  偏移量补充    offsetof()    这个宏可以计算结构体某一个成员相较于起始位置的偏移量 头文件stddef.h  需要在宏中传入的是结构体类型和结构体变量名下面我们来计算一下结构体s1中成员的偏移量和S2结构体的偏移量 struct S1
{char c1;int i;char c2;
};
struct S2
{char c1;char c2;int i;
};
int main()
{/*printf(%d\n, sizeof(struct S1));printf(%d\n, sizeof(struct S2));*/printf(%d\n, offsetof(struct S1, c1));printf(%d\n, offsetof(struct S1, i));printf(%d\n, offsetof(struct S1, c2));return 0;
}   对齐规则   1. 第一个成员在与结构体变量偏移量为0的地址处。 2. 其他成员变量要对齐到某个数字对齐数的整数倍的地址处。  对齐数  编译器默认的一个对齐数 与 该成员大小的较小值。 VS中默认的值为8 Linux中没有默认对齐数对齐数就是成员自身的大小  3. 结构体总大小为最大对齐数每个成员变量都有一个对齐数的整数倍。所有成员对齐数的最大值。 4. 如果嵌套了结构体的情况嵌套的结构体对齐到自己的最大对齐数的整数倍处结构体的整 体大小就是所有最大对齐数含嵌套结构体的对齐数的整数倍。  我们来看一下图解S1的对齐   对对齐规则第四条的解释 让我们来看一下结构体嵌套的对齐算法  如果嵌套了结构体的情况嵌套的结构体对齐到自己的最大对齐数的整数倍处结构体的整 体大小就是所有最大对齐数含嵌套结构体的对齐数的整数倍。 看一下这段代码输出风别为多少 struct S3
{double d;char c;int i;
};struct S4
{char c1;struct S3 s3;double d;
};int main()
{printf(%d\n, sizeof(struct S3));printf(%d\n, sizeof(struct S4));return 0;
}    如果出现数组就当做多个同类型数据处理 为什么会有对齐  大部分的参考资料都是如是说的 1. 平台原因(移植原因) 不是所有的硬件平台都能访问任意地址上的任意数据的某些硬件平台只能在某些地址处取某些特定类型的数据否则抛出硬件异常。比如某些平台规定整型必须存放在4的整数倍地址处。 2. 性能原因 数据结构(尤其是栈)应该尽可能地在自然边界上对齐。 原因在于为了访问未对齐的内存处理器需要作两次内存访问而对齐的内存访问仅需要一次访 问。  虽然浪费了一些空间但是换来了访问效率的提升 总体来说 结构体的内存对齐是拿空间来换取时间的做法。 那在设计结构体的时候我们既要满足对齐又要节省空间如何做到 让占用空间小的成员尽量集中在一起。   了解了结构体偏移量就可以利用偏移量计算我们的task_struct的地址了 c  首元素偏移量。结构体中成员越靠后地址越大 一个整型四个字节每个字节一个地址拿到的是最小的因为有类型也就是首地址偏移量拿到4个字节的内容。数组访问结构体成员访问底层都是这个样子。所以这里也是一样我们可以使用偏移量来访问task_struct中所有的的其他属性内容。 task_struct  struct listnode偏移量那么这个偏移零的算法为设我们一个节点为n ((task_struct*)0-n); n-((task_struct*)0-n)  开始 task_struct(n-((task_struct*)0-n) 得到task_struct地址 这既是linux内核的实现会是一个宏的形式这里是介绍会忽略掉一些类型转换。 
那么我们说再全局层面上所有的进程的pcb都要被链接入一个链表方便我们的操作系统进行管理那么当我们的经进程需要排队运行的时候需不要单独将进程从整体的双链表上取下来单独放入排队等待这个队列里面呢答案是不用 
原因誰规定我们的pcb里面只能有一个listnode这种结构体呢没有人规定那么我们的pcb中就可以有多个这种结构体一个用于将这个task_struct链接入整体的双链表中进行操作系统级别的管理其他剩余的可以在不把我们的单个task_struct拿下来的前提下再链接入其他的数据结构比如进程排队的队列等等等等。 这个就叫一个task——struct可以被 链接进入多种数据结构的原因。 
那么当我们的操作系统删除一个进程的时候一定会伴生着将当前的进程从链表、队列中移除但是所有的移除和task_struct没有关系只用移除struct listnode. 
这就是进程排队那么进程排队是去哪里排队呢接下来看进程状态 
2.操作系统学科层面对进程状态的理解 
首先教材删上的表述 对于初学真的不好理解 
2.1进程的状态理解 
①我们说所谓的状态就是一个整型变量是task_struct中的一个整型变量 
#define  NEW 1
#define  READY 2#define  RUNING 3#define  BLOCK 4 1我们进程的task_struct中 
task_struct
{int status;
}; 
也就是说我们未来进程的状态就取决于这个ststus变量里面保持的是数字几。 
②.状态决定了接下来的动作 
今天状态不好今天想摆烂今天状态好库弛库弛的写几套卷子所以状态决定了对象的后续动作。linux中存在很多的进程每一个进程都有一个状态那么就可能存在多个进程都要根据他的状态执行后续的动作而且还必然可能存在多个进程的状态是一样的虽然进程很多状态类型也多所以就需要进程排队 
2.2运行状态 
一个cpu一个运行队列如果电脑中有两个cpu会有两个运行队列操作系统在内核编译的时候识别到两个cpu就会创建两个队列当运行多个进程的时候原则上操作系统是要均衡的将进程负载到两个cpu上这也成为SMP,负载均衡式的给两个cpu平均分配资源但是值得注意的是一个进程这次调度在这个cpu上下一次还是被这个cpu调度。当我们的某个或者某些进程的资源的准备OK了那么就可以进进程放入cpu的运行队列了将进程的task——struct放入运行队列 
关于怎么排在优先级内容里面讲解 只要放在cpu上对应的运行队列中1我们就把该进程当前状态称为运行状态 
(至于运行队列里面保存的是pcb结构体还是只是节点struct listnode ,这和具体的系统和设备有关有些操作系统可能用的指针或者一样的node但是我们只要能够理解要的是链接结构就OK了。) 
解释 一个进程是不是只有在cpu上跑的时候才是运行状态对吗这样的操作系统有不过是在教材的描述里面这样的描述是在教材里面的描述当然在cpu上运行当然是运行状态不过主流的操作系统只要在运行队列里面都可以叫做运行状态。所以所谓的创建和就绪在实际的操作系统中并没有实现要运行就放在运行队列不运行就放在常量队列里面。所以r状态就表明进程已经准备好随时被调度了所以就绪和执行被二合一因为这两个独立的状态看不到。 2.3 阻塞状态  
以硬件为例子 
os对硬件进行管理 
先对硬件的属性进行描述 struct device
{
int tyoe;//1表示键盘2表示网卡3表示磁盘......
//设备的操作方法
//设备的状态
struct listnode n;
:::
:::
:::
}; 在将各个设备使用数据结组织起来 和进程的管理方式一模一样这就是操作系统为了对硬件做出管理做出的数据结构描述对象 
当前假设我们的计算机内部是这个样子 现在比如说我们运行这个程序 当我们程序运行起来是不是就意味着此时进程需要等待键盘输入不能继续往下面执行了除非键盘输入 。所以此时操作系统就来了这个进程在等待什资源就将这个进程的状态从运行状态改为非运行状态我们可以暂时称为阻塞状态然后将这个进程放到我们对应设备资源的队列当中。我们的cpu也是属于设备的只不过是一个跑得快的设备那么cpu可以有进程的运行列表队列我们其他的设备一样的可以有我们的进程队列当我们的进程需要对应的设备资源的时候这个时候要等待这个设备就绪键盘输入才能继续执行进程不能继续执行就从运行队列连入到我们的设备进程队列里面因为可能需要这个设备资源的进程不止这一个。 接下来cpu就不会调度这些连入底层设备调度队列里面的进程了cpu只会调度在运行队列里面的进程所以这个进程后面代码不执行了也就是程序卡在这个地方等待输入。当我们在键盘输入数据了而我们的键盘输入没有数据也就是硬件的就绪状态只有我们的操作系统清楚操作系统可是我们硬件的管理者所有用户按键过后键盘工作OK了操作系统就将这个进程将这个进程移到cpu的运行队列里面将阻塞状态改为运行状态我们操作系统的工作就完成了剩下的就交给cpu去调度。以上对两个进程pcb描述的移动只是形象化的说法我们进程的pcb是不会也不能删除的只不过的是改变pcb里面对应的链接字段也就是listnode 我们不要用人类的感受衡量计算机的速度此时再次执行到输入的话我们的设备状态就绪理解为操作系统已经将数据从外设搬到内存了有数据了就可以继续往下执行。 
结论 当我们的进程在进行等待软硬件资源的资源如果没有就绪我们的进程task_struct只能将自己设置为阻塞状态将自己的pcb连入等待的资源提供的等待队列中。 所以状态的变迁引起的是pcb搬迁到不同的队列中。 2.4 挂起状态 
挂起状态在linux中并不是一个比较常见的状态大部分情况下计算机极少出现这种情况 
挂起状态的前提 计算机资源比较吃紧也就是说计算机的内存资源比较吃紧了并不排除其他情况 进程在阻塞状态的时候我们的程序的代码和数据是不会被执行和访问的那么这个时候这个进程又不会被调度但是进程的代码和数据又占据着内存的空间如果此时计算机内存已经很吃紧了操作系统很大可能就会将这个进程的代码和数据放回磁盘中当这个进程快要被调度的时候再拿回内存。这个我们称之为阻塞挂起。还有运行挂起等等 
进程会等待某种资源此时进程大概率是不会被执行的这种资源如果短期内不会就行进程就在阻塞队列等待如果突然计算机内存资源非常吃紧cpu和整机资源越来越少甚至严重不足已经无法为上层运行分配内存此时对于计算机来说即将面临大量操作的失败操作向上提供好的环境其他就无了操作系统也面临着崩溃问题要么摆烂崩溃要么搞点内存所以操作系统就会对整个机器的每个内存做说明有些内存现在就要用有些现在不用却占着内存比如阻塞状态进程那么就造成资源的浪费所以操作系统就尝试将这个进程的代码和数据交换到磁盘中磁盘有固定的区域是为了在内存紧张的时候用于和操作系统进行数据的换入换出叫做swap分区 真正当内存吃紧操作系统会将很多很多进程的代码和数据换入换出节省空间还有一些为网络预留的空间也会被释放也就是说整个系统中能被释放的都要释放。传出到磁盘叫换出等要用或者即将用到的时候再加载回来叫换入一但对应的进程对应的数据和代码不在内存中就称当前状态为挂起状态。特指阻塞挂起 所以所谓挂起就是将进程的代码和数据写入到外部的磁盘当进程要被调度的时候再放回来这是临时的腾空间这是操作系统在内存不足的情况下进行辗转腾挪想把空间变大一点要是内存分配不足操作系统挂了整个就挂了慢点总比挂了好。 思考换入换出的时候pcb数据结构是不会被换出的因为操作系统就是根据属性知道的进程处于什么状态。 
创建进程是先创建pcb还是先将进程的代码和数据先加载到内存 
如果我们的内存很小比如只有16G,但是我们现在要运行80g的游戏 只会先加载一部分 自己的代码和数据刚开始可能非常大根本加载不完只会先加载一批那么当前进程该不该运行呢先将pcb保存内存里没有代码和数据也不影响未来也可以换入再调度执行所以双击运行的时候会先创建管理字段创建完内存和字段都还不会加载到内存。 
辅助理解例子 
我们高考毕业的时候人还没有到学校但是学校在录取我们的时候就已经将我们的档案拿走了等我们九月份开学的时候我们该在那个班级学号是多少都被排得明明白白就好比进程运行的时候先将pcb建立出来再将数据等加载然后就静等调度了。 
既然数据要换入换出可以将磁盘分区搞大些吗绝对可以操作系统hold得住但是一般在系统设置的时候内存分区的大小一般为内存的一半或者就是内存的大小最多不超过内存的两倍。 
理由整体的换入换出是将数据进行拷贝的过程冯诺依曼体系告诉我们计算机当中本质进行数据访问访问外设速度是比较慢的在阻塞挂起时换入换出使用效率换系统可用性就是运行变慢和系统可用之间选择了系统可用。如果分区设置非常大系统就会很依赖这个swap分区想办法将这个用完那么操作系统和外设的io操作比重就很高效率就会越来越慢。 3.linux下具体的进程状态重要 
具体看看具体操作系统下面什么是运行、什么是阻塞、挂起代码中不是很好看就不展示 
linux内核代码对于进程的描述 
/*
* The task state array is a strange bitmap of
* reasons to sleep. Thus running is zero, and
* you can test for combinations of others with
* simple bit tests.
*/
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 */
};R运行状态running: 并不意味着进程一定在运行中它表明进程要么是在运行中要么在运行队列 里。S睡眠状态sleeping): 意味着进程在等待事件完成这里的睡眠有时候也叫做可中断睡眠 D磁盘休眠状态Disk sleep有时候也叫不可中断睡眠状态uninterruptible sleep在这个状态的 进程通常会等待IO的结束。T停止状态stopped 可以通过发送 SIGSTOP 信号给进程来停止T进程。这个被暂停的进程可 以通过发送 SIGCONT 信号让进程继续运行。X死亡状态dead这个状态只是一个返回状态你不会在任务列表里看到这个状态。Z(zombie)-僵尸进程 僵死状态Zombies是一个比较特殊的状态。当进程退出并且父进程使用wait()系统调用,后面讲 没有读取到子进程退出的返回代码时就会产生僵死(尸)进程 僵死进程会以终止状态保持在进程表中并且会一直在等待父进程读取退出状态代码。 所以只要子进程退出父进程还在运行但父进程没有读取子进程状态子进程进入Z状态  3.1 R和s  
编写一段代码如下执行 查看我们的进程 stat就描述了当前进程的状态  
为什么程序在运行状态却是S,睡眠状态 
因为cpu执行我们这行输出的时间非常快然后我们写了sleep睡眠1秒那么对于cpu来说整个程序很长的时间都是在sleep那么这个状态显示就不奇怪了 
接下来修改一下代码注释掉sleep 代码疯狂运行 状态还是s  
因为我们自己的代码中有printf向显示器打印这个程序在远端服务器跑的当进行执行的时候结果打印在我们的电脑上printf是要访问外设的不论是网络设备还是显示屏都是要访问外设的那么我们想打印的时候我们的设备就绪了吗,cpu可以比其他外设的速度快多了第一次打印了第二次能保证数据已经刷新到设备了吗当执行打印代码将数据执行到缓冲区设备来得及刷新吗不一定所以printf里面就伴生着使得设备处于就绪状态的东西显示是睡眠状态就说明当期进程百分之95的时间都是在等待只有百分之五的时间在运行。 
我们再修改代码 此时就是运行状态了不访问任何外设还是个死循环 
在目前系统里可能有多个进程只有在运行队列里才是运行状态大部分进程等待外设是非运行状态 
top命令 为什么grep总是r 
grep过滤也是一个进程只有被调度时才可以帮我们打印过滤结果把自己过滤出来就相当于自己知道自己是什么状态所以一睁眼就知道自己醒着。 前后台程序 
表示这个程序是前台进程还是后台进程信号文章详细讲解 
一般程序在运行的时候我们将程序称为前台程序 此时的状态为s 我们执行一些指令时没有办法截停这个程序当我们执行ctrc就可以截停 此时我们在执行程序命令后面  我们运行一些指令也是可以的 发现按住ctrls 无法截停 当前进程状态为 就为s没有号这种进程我们就称为后台进程前台进程可以被键盘直接杀掉后台进程不可以只能通过kill -9 进程pid 来杀死 批量化下载等可以在指令后面 
3.2 休眠状态s 
编写代码如下 在等待键盘输入linux中的休眠就等价于操作系统学科中的阻塞状态。 
阻塞描述的是宏观在linux中是s状态但是不仅仅只有上述一种阻塞s状态  
这种进程可以通过ctrlc结束所以我们也将linux中的这种状态称为可中断睡眠也称为浅度睡眠 
3.3 disk sleep     不可中断睡眠也叫作深度睡眠。 
举例来说当我们的进程要将一块很大的数据给我们的磁盘磁盘比较慢进程就一直等待等待那么在内存比较吃紧的时候操作系统也是会移除某些进程的操作系统过来一看你什么也不干还在这里占着内存将移除了这个进程然后此时如果我们磁盘出了异常拷贝的数据找不到来头无法继续拷贝就丢弃了这不行当这个进程一直等待操作系统也不能将他移除就叫深度睡眠。 
3.4 T状态进程变成暂停状态 某个进程要访问某种资源但是呢某种资源又不能被这个进程所访问操作系统又不想杀掉这个进程但是为了不让这个进程做某些非法的操作就将进程设置为暂停状态。 kill -l 命令·可以·查看信号 9号命令可以帮我们杀死一个进程 
19号命令给一个进程发送一个暂停信号 状态变为暂停没有号 进程一但暂停就从前台转变为后台进程了。 18 号信号进程继续启动 3.5 t状态 我们调试这段代码 我们在输入出打上断点过后让程序运行后我们看一下进程的状态 进程会变成t状态也是一种暂停是一种被追踪的状态  等待我们输入或者按下n 等待也是一种阻塞状态。 
3.6 z状态僵尸状态 
进程创建的目的是让进程帮助完成某种任务任务死掉了我们要获取进程的退出数据是正常退出还是遇到异常退出后代码和数据可以直接释放因为进程死掉了后续的代码不会再执行了但是进程pcb不应该立马释放应该缓一下为了未来让系统或者其他进程获取一下他的退出数据只有进程的退出数据被拿走之后这个进程才是正常死亡状态pcb才可以被释放。 
我们将一个进程执行完毕但是当前并没有去获取这个进程的退出数据时我们将这个进程的状态称为僵尸状态。 
通常情况下是由父进程产生子进程当子进程退出父进程就必须去读取一下子进程的退出信息怎么读取不是目前所关心的话题如果父进程不读取这个子进程的代码和数据被释放但是pcb不能被释放其中包含了退出时进程的状态信息。 程序前五秒父进程和子进程一起运行五秒过后子进程退出 就应该看见子进程变成僵尸 defunt就是无用的失效的死亡的意思  
进程退出pcb不能释放保存退出时的状态信息等待父进程读取进程的代码和数据合约先释放 
接下来我们让父进程读一下然后看一下僵尸进程的消失 前五秒父子进程同时运行然后中间五秒子进程变成僵尸十秒后父进程回收子进程 为什么维持僵尸状态 未来我们创建进程是希望这个进程给用户完成某种工作的肯定要求一个结果将子进程创建出来那么子进程必须要有结果数据这个数据是保存在pcb中子进程结束代码和数据可以释放但是pcb还不能被释放 什么是z状态 进程已经退出但是当前进程的状态需要自己维持住供上层读取那么就必须处于z状态 只有当通过我们的方式读取pcb里面的退出信息了才能变成x死亡状态 如果不读取僵尸状态会一直存在是会有影响的一直存在疑问着task_struct会一直存在维护这个对象都是要占据内存的。这块内存得不到释放又不能使用叫做内存泄漏。所以父进程必须等待所有的进程都必须先到z,再到x。bash父进程会自动读取其余父进程不确定可能自己读取可能像我们上面一样要手动读取等待。bash命令行会主动回收子进程状态所以看不到。 那么这张图在我们linux下是适用的 4. 孤儿进程 
修改代码如下 父进程先退出父进程很难查到自己的僵尸状态bash会回收那么父进程先退出了为了子进程变僵尸誰来回收呢  父进程先挂掉子进程会被1号进程领养我们可以理解为操作系统或者说父进程先结束子进程必须被操作系统领养因为无主进程一直僵尸浪费资源我们将这种进程称之为孤儿进程。 还会将自己变成后台进程。 孤儿进程也是可以有子进程的。  
5.结语 
今天的主要内容是进程的排队进程状态在操作系统学科层次的理解和linux操作系统下的观察。扩展了很多内容补充了僵尸进程和孤儿进程后续进程的优先级和进程相关内容欢迎大家关注。创作不易如果大家觉得有所收获欢迎关注一起交流互进。