【Linux系统编程】僵尸进程与孤儿进程

张开发
2026/5/3 20:31:34 15 分钟阅读
【Linux系统编程】僵尸进程与孤儿进程
文章目录1. 僵尸进程2. 僵尸进程的危害3. 孤儿进程1. 僵尸进程上一篇文章进程的状态中最后我们提出了僵尸状态为了方便子进程退出后父进程或操作系统获取该进程的退出结果Linux进程退出时进程一般不会立即死亡而是要维持一个Z状态即——僵尸状态。那处在僵尸状态的进程即僵尸进程那首先我们就要来重点理解一下僵尸进程。那我们来给大家讲一个故事假如你呢是一名非常自律上进的大学生每天早晨都有到外面跑步的好习惯。今天早上呢你正在跑步的时候忽然后面来了一个程序员也在跑步但他跑的非常快边跑边掉头发很快就超过你跑到前面去了你依然在后面慢慢的跑着。突然这个程序员跑到在你前面100M左右的地方口吐白沫一阵抽搐就倒下了。后面不远处的你看到了这个情况非常慌张赶紧打了120并报了警。然后警察很快就到了到了之后发现这个人已经不行了。然后请问大家警察会怎么做会不会直接把这个人弄走通知它的家属然后销毁现场。那正常情况呢应该是不会这样的。警察应该会封锁现场然后刚好120的人过来了警察说你帮我们确认了这个人是不是已经不行了120的医务人员说确实不行了。然后呢警察可能会通知法医来确认这个人的死因是自己死亡还是被谋杀了啥的然后进行一些相关的调查啥的。假设最后发现这个人是自己发病死亡了那然后警察就通知家属让它们把人带走然后就可以撤离现场了。那上述的故事中警察发现这个人死亡后应不应该立即把这个人弄走然后销毁现场。不应该而是要维护好现场便于调查它的死因啥的…那其实这就对应了我们上面提到的一个进程退出后不会立即死亡而是维持一个僵尸状态便于父进程或者操作系统获取该进程的退出结果。那么简单总结一下僵尸状态Zombies是一种比较特殊的状态。当进程退出并且其父进程没有读取到该进程退出的返回代码时就会产生僵死(尸)进程。僵尸进程会以终止状态保持在进程表中并且会一直在等待父进程读取退出状态代码处于僵尸状态的进程会被释放掉对应的代码和数据但是会保留task_structtask_struct就包含了进程退出的状态码。所以只要子进程退出但父进程还在运行且父进程没有读取子进程退出的返回代码子进程就会进入僵尸状态。那我们写个代码给大家演示一下代码就不解释了都是之前讲过的内容我们运行一下那我们用ps命令查看一下进程我们看到现在父子进程两个的状态都是S。那按我们上面讲的子进程退出父进程还在运行且没有回收子进程获取返回码我们现在也不会那么子进程就会进入僵尸状态那我们现在干掉子进程然后我们再来查看子进程就变成了僵尸进程2. 僵尸进程的危害进程的退出状态必须被维持下去因为他要告诉关心它的进程父进程你交给我的任务我办的怎么样了。可父进程如果一直不读取那子进程就一直处于Z状态是的维护退出状态本身就是要用数据维护也属于进程基本信息所以保存在task_struct(PCB)中换句话说Z状态一直不退出PCB一直都要维护是的那一个父进程创建了很多子进程就是不回收是不是就会造成内存泄漏是的因为数据结构对象本身就要占用内存如果一直不释放那就内存泄漏了。如何避免后面讲等这个进程真正被回收了它的状态才会变成X死亡状态此时该进程的所有资源才会被释放。至此值得关注的进程状态全部讲解完成下面来认识另一种进程3. 孤儿进程首先我们给出孤儿进程的概念孤儿进程指的是在其父进程执行完成退出或被终止后仍继续运行的一类进程。即如果父进程先退出子进程继续还在运行那么该子进程就被称为孤儿进程。那下面我们还是写写代码来帮助大家理解这里我们写这样一个程序子进程循环打印运行父进程打印10次退出写个Makefile然后这里给大家解释一下这两个之前没见过的符号$就代表左边的目标文件$^代表右边的所有的依赖文件所以后续如果我们开发的时候这个依赖文件列表里面有多个文件我们不用一个个都列在后面直接用这个符号就行了。那下面我们就运行这个程序并观察一下对应的现象那这里呢我们要用到一条shell语句while :; do ps axj | head -1ps axj | grep mytest|grep -v grep; sleep 1;echo --------; done大家看不懂没关系它的作用其实就是每个1秒去显示一下对应搜索的进程信息并打印了一个“----------”的分割线那现在我们把程序跑起来那我们发现呢运行一段时间之后父进程就结束退出了后面就只剩子进程在运行了。但是呢这里有些问题值得我们去思考和探索首先第一个问题父进程也是一个进程啊那按照我们前面学的内容一个进程退出时并不会立即变为X死亡状态而是要维持一个僵尸状态但是这里这个父进程退出之后为啥我们没有看到Z状态呢它直接就没了那大家想一下僵尸状态存在的意义是啥其实我们前面已经说了是为了方便子进程退出后父进程或操作系统获取该进程的退出结果。所以如果子进程一直没有被回收的话那么它就会一直处在僵尸进程那它就会一直占据资源进而导致内存泄漏这都是我们前面讲过的。那这里为什么没有看到父进程处于僵尸状态是不是因为它退出后就被回收了呢是的大家说这里的这个父进程它的父进程是谁啊是不是bash啊这也是我们前面讲过的内容——命令行启动的所有程序最后变成进程其对应的父进程都是bash。所以我们这里之所以没有看到父进程处于僵尸状态就是它的父进程bash把它直接回收了。然后第二个问题我们发现原来这个子进程的父进程的PID是2618但是它的父进程退出后它的父进程的PID变成了1它被一个新的爹领养了那这里我们得出一个结论如果一个进程的父进程退出了而这个进程自己还在运行那么它将会被1号进程init进程自动领养那么这个被领养的进程即孤儿进程。那大家想一下为什么为什么操作系统要领养孤儿进程或者大家思考一下如果不领养孤儿进程会发生什么那其实这个问题可以说我们前面已经讲过了。如果孤儿进程不被领养那它就没有父进程了嘛那这样的话未来这个孤儿进程退出的时候谁来回收它给它收尸呢那退出后没有人回收它它就会一直处于僵尸状态等待回收而没有人回收那么就导致内存泄漏。那再来总结一下在操作系统领域中孤儿进程指的是在其父进程执行完成或被终止后仍继续运行的一类进程。这些孤儿进程将被init进程(进程号为1)所收养并由init进程对它们完成状态收集工作。除此之外还有一个细节也提一下我们还可以发现它的父进程退出后它的状态由S变成了S没了。那进程状态里面的这个其实我们前面也提过带的是前台进程不带的是后台进程。那他变成后台进程后呢我们CTRLc就终止不掉它了这个我们前面也演示过而且它在后台运行我们还可以正常执行命令但是这样很影响我们的使用。所以我们可以使用kill命令把它杀掉这也是之前讲过的那这里我们再补充一个方法killall进程名称就可以杀掉指定名称的进程。那以上就是关于僵尸进程和孤儿进程的相关内容…

更多文章