启动进程 问号_有两个这样的进程:僵尸进程amp;孤儿进程,蓝瘦香菇
进程
先来说下什么是进程:
来看下百度是怎么说的:
光看说的不够形象,在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("%dn",p1);if(p1 > 0){printf("父进程 pid = %d, p1 = %dn", getpid(), p1);}else{printf("子进程 pid = %d , ppid = %d, p1 = %dn", 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] = %dn",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 : %dn" ,getpid());exit(0);} else {printf("我是父进程,我先睡2秒n");printf("父进程 id : %dn" ,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)
总结
本来以为简单的一个问题,没想到这个篇幅其实也不算短,所以感觉程序员真的不能说一个什么知识点就简单,很容易理解啊,一旦你想要深入也是需要一定的时间花费和精力的~
启动进程 问号_有两个这样的进程:僵尸进程amp;孤儿进程,蓝瘦香菇相关推荐
- delphi pid判断进程结束_有两个这样的进程:僵尸进程amp;孤儿进程,蓝瘦香菇
进程 先来说下什么是进程: 来看下百度是怎么说的: 光看说的不够形象,在windows系统中,它长这样: 在Mac系统中,它长这样: Linux中是这样的:(有点长截图一部分好了) [root@iz2 ...
- 有两个这样的进程:僵尸进程孤儿进程,蓝瘦香菇
程序员的成长之路 互联网/程序员/技术/资料共享 关注 阅读本文大概需要 5.8 分钟. 来自:https://juejin.im/post/5f20fbeae51d45348675fa78 那时刚写 ...
- linux基础知识——僵尸进城和孤儿进程
1.什么是孤儿进程? \qquad父进程先于子进程结束,则子进程成为孤儿进程.父进程结束后,子进程的父进程由init进程接替. #include<stdio.h> #include< ...
- 转:Python 主进程被杀死时,如何保证子进程同时退出而不变为孤儿进程
发布于博客园,作者:Tourun <主进程被杀死时,如何保证子进程同时退出,而不变为孤儿进程(一)> <主进程被杀死时,如何保证子进程同时退出,而不变为孤儿进程(二)> < ...
- c++ 进程快照_如何在 Linux 中找出内存消耗最大的进程
很多次,你可能遇见过系统消耗了过多的内存.如果是这种情况,那么最好的办法是识别出 Linux 机器上消耗过多内存的进程. -- Magesh Maruthamuthu(作者) 很多次,你可能遇见过系统 ...
- 如何避免 Go 命令行执行产生“孤儿”进程?
简介: 在 Go 程序当中,如果我们要执行命令时,通常会使用 exec.Command ,也比较好用,通常状况下,可以达到我们的目的,如果我们逻辑当中,需要终止这个进程,则可以快速使用 cmd.Pro ...
- 什么是僵尸进程与孤儿进程
1.什么是僵尸进程和孤儿进程: 在 Unix/Linux 系统中,正常情况下,子进程是通过父进程创建的,且两者的运行是相互独立的,父进程永远无法预测子进程到底什么时候结束.当一个进程调用 exit 命 ...
- 孤儿进程与终端的关系
孤儿进程与终端的关系 孤儿进程 在本篇文章当中主要给大家介绍一下有关孤儿进程和终端之间的关系. 首先我们的需要知道什么是孤儿进程,简单的来说就是当一个程序还在执行,但是他的父进程已经退出了,这种进程叫 ...
- linux进阶14——僵尸进程和孤儿进程
1. 概念 我们知道在unix/linux中,正常情况下,子进程是通过父进程创建的,子进程在创建新的进程.子进程的结束和父进程的运行是一个异步过程,即父进程永远无法预测子进程 到底什么时候结束. 当一 ...
最新文章
- UISearchbar placeholder 文本和icon居左 iOS7
- EL之Boosting之GB(DTR):利用梯度提升法解决回归(对多变量的数据集+实数值评分预测)问题
- 机器学习中的维度灾难
- 分布式事务选型的取舍 | 建议收藏
- 课堂作业:返回一个二维整数组中最大子数组的和
- JSON-B非对称属性绑定
- redisson 大量ping操作,导致 tps过高
- Windows 环境下adb.exe无法启动的解决办法之一
- 2017CCPC哈尔滨 D:X-Men
- CEPH浅析”系列之三——CEPH的设计思想
- presto读取oracle,Presto数据接入方式
- mysql游标 循环_MySQL游标与嵌套循环
- LayaBox1.7.16 TiledMap 销毁的问题,TiledMap销毁后屏幕变灰,不能显示
- 单片机 队列 C语言 OLED 示波器 心率波形 显示 MSP430F5529 pulsesensor ADS1292R
- 如何利用IDM加速下载百度网盘大文件
- 020-机器学习背后的思维-针对入门小白的概念算法及工具的朴素思考
- 公众号开发精品教程(4)——生成带参数的二维码及合成海报
- GET blob:https://172.0.0.1:80/194d39e8-7254-4fc8-b2d9-81109b8ccc94 net::ERR_ACCESS_DENIED 200 (OK)
- 成功路上并不拥挤,因为坚持的人不多
- 科普:维基百科与其创始人
热门文章
- MIT_18.03_微分方程_Laplace_Transform_拉普拉斯变换_Notes
- 使用示例_在Unity中使用ComputeShader示例
- 自己设计java流程审核_关于工作流引擎取回审批的设计方案与实现过程
- 3.10 直观理解反向传播-深度学习-Stanford吴恩达教授
- TCL with SNPS file existsfile rename/copy redirect lsearch split
- 【PC工具】几个提高工作效率的工具素材网站,美化代码,精美图标,logo设计...
- 多用户MIMO系统中的天线选择技术和用户选择技术的MATLAB仿真
- 瞬变电磁法的基本原理与TEM正演技术
- AMDF换成ACF和AMDF合作算法
- C++类的信息隐藏机制