有两个这样的进程:僵尸进程&孤儿进程,蓝瘦香菇
liebian365 2024-10-17 14:05 35 浏览 0 评论
作者:Java小咖秀
链接:https://juejin.im/post/5f20fbeae51d45348675fa78
进程
先来说下什么是进程:
来看下百度是怎么说的:
光看说的不够形象,在windows系统中,它长这样:
在Mac系统中,它长这样:
Linux中是这样的:(有点长截图一部分好了)
[root@iz2ze76ybn73dvwmdij06zz ~]# ps -ef
UID PID PPID C STIME TTY TIME CMD
root 1 0 0 5月20 ? 00:00:33 /usr/lib/systemd/systemd --system --deserialize 21
root 2 0 0 5月20 ? 00:00:00 [kthreadd]
root 3 2 0 5月20 ? 00:00:06 [ksoftirqd/0]
root 5 2 0 5月20 ? 00:00:00 [kworker/0:0H]
root 7 2 0 5月20 ? 00:00:02 [migration/0]
root 8 2 0 5月20 ? 00:00:00 [rcu_bh]
root 9 2 0 5月20 ? 00:30:40 [rcu_sched]
root 10 2 0 5月20 ? 00:00:17 [watchdog/0]
root 11 2 0 5月20 ? 00:00:16 [watchdog/1]
root 12 2 0 5月20 ? 00:00:02 [migration/1]
root 13 2 0 5月20 ? 00:00:03 [ksoftirqd/1]
root 15 2 0 5月20 ? 00:00:00 [kworker/1:0H]
root 17 2 0 5月20 ? 00:00:00 [kdevtmpfs]
root 18 2 0 5月20 ? 00:00:00 [netns]
root 19 2 0 5月20 ? 00:00:01 [khungtaskd]
root 20 2 0 5月20 ? 00:00:00 [writeback]
root 21 2 0 5月20 ? 00:00:00 [kintegrityd]
root 22 2 0 5月20 ? 00:00:00 [bioset]
root 23 2 0 5月20 ? 00:00:00 [kblockd]
复制代码
OK,以上每一行都是对一个进程的描述,来具体看一下每个参数的含义:
标示 描述 UID 用户ID PID 进程ID PPID 父进程ID C 进程占cpu百分比 STIME 进程启动的时间 TTY 终端机位置 TIME 实际使用cpu的时间 CMD 命令以及参数
我们现在知道了每个参数的含义,既然讲到进程嘛,首先,进程ID是唯一的并且是非负数的,但是进程ID是可以复用的,毕竟进程也会终止。
可以看到没有进程PID是0的,这是为什么呢? 黑人问号脸?
0一般来说是系统进程,属于内核的一部分,不执行任何磁盘上的程序。
fork
一个进程可以通过调用fork函数创建新的进程,被创建出来的这个进程就叫子进程。
这里需要注意一下,fork函数的返回值父子进程区别。
- 子进程 : 返回值是0,返回0的理由是子进程的父进程是可以唯一确定的,通过getppid方法可以获取到父进程id。
- 父进程 : 返回的是新创建的子进程的id,因为父进程可以有多个子进程,也没有这样的函数可以获取该线程的子线程的所有id。
下边的话我们来验证一下上说的这一段话。准备好脚本。
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
int main(int argc, char const *argv[])
{
pid_t p1 = fork();
printf("%d\n",p1);
if(p1 > 0)
{
printf("父进程 pid = %d, p1 = %d\n", getpid(), p1);
}
else
{
printf("子进程 pid = %d , ppid = %d, p1 = %d\n", getpid(), getppid(), p1);
}
return 0;
}
复制代码
运行看结果:
[root@iz2ze76ybn73dvwmdij06zz ~]# ./fork2
10213
父进程 pid = 10212, p1 = 10213
0
子进程 pid = 10213 , ppid = 10212, p1 = 0
复制代码
通过上面的小例子我们可以看到父进程的返回值是子进程的ID,子进程的返回是0。
孤儿进程
孤儿我们都懂就是。。。
是的,没错孤儿进程也是这样的,就是没有父进程的进程。当然创建的时候肯定是要先创建父进程了,当父进程退出时,它的子进程们(一个或者多个)就成了孤儿进程了。
接下来在继续做一个小测试,让父进程现退出。准备好脚本。
[root@iz2ze76ybn73dvwmdij06zz ~]# cat guer.c
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
int main()
{
pid_t pid = fork();
if (pid < 0) {
perror("fork error;");
exit(1);
} else if (pid == 0) {
sleep(5);
printf ("子进程 : [ pid] = %d , 父进程 [ppid] = %d\n",getpid(),getppid());
exit(0);
} else if (pid > 0) {
printf("我是父线程,我先退出一步~\n");
exit(0);
}
return 0;
}
复制代码
执行并看结果:
到这里估计很多童鞋估计已经看懂了,父进程退出后,子进程被一个进程ID为1的进程领养的。还挺好这个结果,至少还是有人管的,被暖到了~ 进程id为1的进程是init进程,每当有孤儿进程出现时,init进程就会收养它并成为它的父进程 ,来照顾它以孤儿进程以后的生活。
危害
因为孤儿进程会被init进程接管,所以孤儿进程是没有危害的。
僵尸进程
和孤儿进程相反的是,这次是子进程先退出,而父进程又没有去处理回收释放子进程的资源,这个时候子进程就成了僵尸进程。
先准备好代码:
[root@iz2ze76ybn73dvwmdij06zz ~]# cat zombie.c
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <stdlib.h>
int main()
{
pid_t pid;
pid = fork();
if (pid < 0)
{
perror("fork error:");
exit(1);
}
else if (pid == 0)
{
printf("我是子进程,我要先退出一步了.\n");
printf("子进程 id : %d\n" ,getpid());
exit(0);
} else {
printf("我是父进程,我先睡2秒\n");
printf("父进程 id : %d\n" ,getpid());
sleep(2);
while(2); //来个死循环,不退出的那种
}
return 0;
}
复制代码
运行看下结果:
再来开一个终端看下进程结果:
大家可以看到,子进程并没有完全退出,释放资源,而是变成了僵尸进程。
危害
资源上是占用不了什么资源。但是通常系统的进程数量都是有限制的,如果有大量的僵尸进程占用进程号,导致新的进程无法创建,这个危害类似于占个坑,不办事,别人也办不了事。
处理
1.干掉父进程
干掉父进程后,让剩下的子进程成为孤儿进程,成为孤儿进程后就和我们上面说的一样了,由init进程来领养这些进程,并且来处理这些进程的资源释放等工作。
2.父进程调用wait或waitpid
等函数等待子进程结束,这会导致父进程挂起。 执行wait()或 waitpid()系统调用,则子进程在终止后会立即把它在进程表中的数据返回给父进程,此时系统会立即删除该进入点。在这种情形下就不会产生defunct进程。
3.fork两次
第一次 fork : 父进程fork一个子进程
第二次 fork : 子进程fork一个孙进程后退出
那么孙进程被init接管,当孙进程结束后,init会回收。
但子进程的回收还要自己做。
4.signal函数
父进程来处理:用signal函数为SIGCHLD安装handler,在子进程结束后,父进程会收到该信号,可以在handler中调用wait回收。
内核来处理: 如果父进程不关心子进程什么时候结束,可以通过以下两个函数通知内核自己不感兴趣子进程的结束,此时,子进程结束后,内核会回收并不再给你父进程发信号。
- signal(SIGCLD, SIG_IGN)
- signal(SIGCHLD, SIG_IGN)
总结
本来以为简单的一个问题,没想到这个篇幅其实也不算短,所以感觉程序员真的不能说一个什么知识点就简单,很容易理解啊,一旦你想要深入也是需要一定的时间花费和精力的~
相关推荐
- “版本末期”了?下周平衡补丁!国服最强5套牌!上分首选
-
明天,酒馆战棋就将迎来大更新,也聊了很多天战棋相关的内容了,趁此机会,给兄弟们穿插一篇构筑模式的卡组推荐!老规矩,我们先来看10职业胜率。目前10职业胜率排名与一周前基本类似,没有太多的变化。平衡补丁...
- VS2017 C++ 程序报错“error C2065:“M_PI”: 未声明的标识符"
-
首先,程序中头文件的选择,要选择头文件,在文件中是没有对M_PI的定义的。选择:项目——>”XXX属性"——>配置属性——>C/C++——>预处理器——>预处理器定义,...
- 东营交警实名曝光一批酒驾人员名单 88人受处罚
-
齐鲁网·闪电新闻5月24日讯酒后驾驶是对自己和他人生命安全极不负责的行为,为守护大家的平安出行路,东营交警一直将酒驾作为重点打击对象。5月23日,东营交警公布最新一批饮酒、醉酒名单。对以下驾驶人醉酒...
- Qt界面——搭配QCustomPlot(qt platform)
-
这是我第一个使用QCustomPlot控件的上位机,通过串口精确的5ms发送一次数据,再将读取的数据绘制到图表中。界面方面,尝试卡片式设计,外加QSS简单的配了个色。QCustomPlot官网:Qt...
- 大话西游2分享赢取种族坐骑手办!PK趣闻录由你书写
-
老友相聚,仗剑江湖!《大话西游2》2021全民PK季4月激燃打响,各PK玩法鏖战齐开,零门槛参与热情高涨。PK季期间,不仅各种玩法奖励丰厚,参与PK趣闻录活动,投稿自己在PK季遇到的趣事,还有机会带走...
- 测试谷歌VS Code AI 编程插件 Gemini Code Assist
-
用ClaudeSonnet3.7的天气测试编码,让谷歌VSCodeAI编程插件GeminiCodeAssist自动编程。生成的文件在浏览器中的效果如下:(附源代码)VSCode...
- 顾爷想知道第4.5期 国服便利性到底需优化啥?
-
前段时间DNF国服推出了名为“阿拉德B计划”的系列改版计划,截至目前我们已经看到了两项实装。不过关于便利性上,国服似乎还有很多路要走。自从顾爷回归DNF以来,几乎每天都在跟我抱怨关于DNF里面各种各样...
- 掌握Visual Studio项目配置【基础篇】
-
1.前言VisualStudio是Windows上最常用的C++集成开发环境之一,简称VS。VS功能十分强大,对应的,其配置系统较为复杂。不管是对于初学者还是有一定开发经验的开发者来说,捋清楚VS...
- 还嫌LED驱动设计套路深?那就来看看这篇文章吧
-
随着LED在各个领域的不同应用需求,LED驱动电路也在不断进步和发展。本文从LED的特性入手,推导出适合LED的电源驱动类型,再进一步介绍各类LED驱动设计。设计必读:LED四个关键特性特性一:非线...
- Visual Studio Community 2022(VS2022)安装图文方法
-
直接上步骤:1,首先可以下载安装一个VisualStudio安装器,叫做VisualStudioinstaller。这个安装文件很小,很快就安装完成了。2,打开VisualStudioins...
- Qt添加MSVC构建套件的方法(qt添加c++11)
-
前言有些时候,在Windows下因为某些需求需要使用MSVC编译器对程序进行编译,假设我们安装Qt的时候又只是安装了MingW构建套件,那么此时我们该如何给现有的Qt添加一个MSVC构建套件呢?本文以...
- Qt为什么站稳c++GUI的top1(qt c)
-
为什么现在QT越来越成为c++界面编程的第一选择,从事QT编程多年,在这之前做C++界面都是基于MFC。当时为什么会从MFC转到QT?主要原因是MFC开发界面想做得好看一些十分困难,引用第三方基于MF...
- qt开发IDE应该选择VS还是qt creator
-
如果一个公司选择了qt来开发自己的产品,在面临IDE的选择时会出现vs或者qtcreator,选择qt的IDE需要结合产品需求、部署平台、项目定位、程序猿本身和公司战略,因为大的软件产品需要明确IDE...
- Qt 5.14.2超详细安装教程,不会来打我
-
Qt简介Qt(官方发音[kju:t],音同cute)是一个跨平台的C++开库,主要用来开发图形用户界面(GraphicalUserInterface,GUI)程序。Qt是纯C++开...
- Cygwin配置与使用(四)——VI字体和颜色的配置
-
简介:VI的操作模式,基本上VI可以分为三种状态,分别是命令模式(commandmode)、插入模式(Insertmode)和底行模式(lastlinemode),各模式的功能区分如下:1)...
你 发表评论:
欢迎- 一周热门
- 最近发表
-
- “版本末期”了?下周平衡补丁!国服最强5套牌!上分首选
- VS2017 C++ 程序报错“error C2065:“M_PI”: 未声明的标识符"
- 东营交警实名曝光一批酒驾人员名单 88人受处罚
- Qt界面——搭配QCustomPlot(qt platform)
- 大话西游2分享赢取种族坐骑手办!PK趣闻录由你书写
- 测试谷歌VS Code AI 编程插件 Gemini Code Assist
- 顾爷想知道第4.5期 国服便利性到底需优化啥?
- 掌握Visual Studio项目配置【基础篇】
- 还嫌LED驱动设计套路深?那就来看看这篇文章吧
- Visual Studio Community 2022(VS2022)安装图文方法
- 标签列表
-
- wireshark怎么抓包 (75)
- qt sleep (64)
- cs1.6指令代码大全 (55)
- factory-method (60)
- sqlite3_bind_blob (52)
- hibernate update (63)
- c++ base64 (70)
- nc 命令 (52)
- wm_close (51)
- epollin (51)
- sqlca.sqlcode (57)
- lua ipairs (60)
- tv_usec (64)
- 命令行进入文件夹 (53)
- postgresql array (57)
- statfs函数 (57)
- .project文件 (54)
- lua require (56)
- for_each (67)
- c#工厂模式 (57)
- wxsqlite3 (66)
- dmesg -c (58)
- fopen参数 (53)
- tar -zxvf -c (55)
- 速递查询 (52)