OS之进程管理---孤儿进程和僵尸进程
僵尸进程
当一个进程终止时,操作系统会释放其资源,不过它位于进程表中的条目还是在的,直到它的父进程调用wait();这是因为进程表中包含了进程的退出状态。当进程已经终止,但是其父进尚未调用wait(),这样的进程叫做僵尸进程(zombie prpcess)。
所有进程终止时都会过度到这种状态,但是一般而言僵尸只是短暂存在。一旦父进程调用了wait(),僵尸进程的进程标示符和它在进程表中的条目就会释放。
这里需要注意:僵尸进程不能通过kill来进行杀死,因为kill是用来终止进程的,僵尸进程已经是终止的。
设计一个僵尸进程:
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <signal.h>
#include <errno.h>
#include <signal.h>
//僵尸进程
int main(void) {
pid_t pid;
printf("before fork pid:%d\n", getpid());
int abc = 10;
pid = fork();
if(pid < 0) {
fprintf(stderr, "fork failed");
return 1;
}
else if(pid == 0) {
abc++;
printf("child:%d, parent:%d\n",getpid(), getppid());
printf("abc:%d", abc);
exit(0);
}
else {
abc++;
printf("parent:pid:%d \n", getpid());
printf("abc:%d \n", abc);
sleep(20);
}
printf("fork after ... \n");
}
执行结果:
shanlei@shanlei-Lenovo-ideapad-110-15ISK:/var/www/c_code/操作系统$ ./2
before fork pid:7203
parent:pid:7203
abc:11
child:7204, parent:7203
abc:11fork after ...
shanlei@shanlei-Lenovo-ideapad-110-15ISK:/var/www/c_code/操作系统$
查看运行时的进程表:
F S UID PID PPID C PRI NI ADDR SZ WCHAN TTY TIME CMD
0 S 1000 7203 5576 0 80 0 - 1127 hrtime pts/0 00:00:00 2
1 Z 1000 7204 7203 0 80 0 - 0 - pts/0 00:00:00 0
4 R 1000 7205 7084 0 80 0 - 9006 - pts/1 00:00:00 ps
注意:在进程表中进程状态位于列S,状态位为Z的是僵尸进程,子进程的进程标识符(pid)位于列PID,而父进程的标识符则位于列PPID。
僵尸进程的危害:
如果不调用wait / waitpid的话,保留的那段信息可能会一直存在,那么将会一直占用着进程号,如果系统中存在大量的僵尸进程,将会造成进程号短缺而无法产生新进程。并且很可能造成资源泄露。
如何避免僵尸进程
1.通过信号机制,子进程退出时向父进程发送SIGCHILD信号,父进程处理SIGCHILD信号。在信号处理函数中调用wait/waitpid进行处理僵尸进程。代码如下:
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <signal.h>
#include <errno.h>
#include <signal.h>
static void sig_child(int signo);
//僵尸进程
int main(void) {
pid_t pid;
printf("before fork pid:%d\n", getpid());
//采用信号量机制
signal(SIGCHLD, sig_child);
int abc = 10;
pid = fork();
if(pid < 0) {
fprintf(stderr, "fork failed");
return 1;
}
else if(pid == 0) {
abc++;
printf("child:%d, parent:%d\n",getpid(), getppid());
printf("abc:%d", abc);
exit(0);
}
else {
abc++;
printf("parent:pid:%d \n", getpid());
printf("abc:%d \n", abc);
sleep(20);
}
printf("fork after ... \n");
}
static void sig_child(int signo) {
pid_t pid;
int stat;
while((pid = waitpid(-1, &stat, WNOHANG)) > 0)
printf("child pid=%d terminated.\n", pid);
}
2.或者fork两次,原理是将子进程成为孤儿进程,从而其的父进程变为init进程,通过init进程可以处理僵尸进程。(这种方法不是很理解,所以没有代码…哪位好心人能给我讲一讲吗?)
孤儿进程
如果父进程没有调用wait()就终止了,那么对于该父进程的子进程将会成为孤儿进程(orphan process)。Linux/Unix对这种情况的处理是:将init进程作为孤儿进程的父进程,进程init定期调用wait(),以便收集任何孤儿进程的退出状态,并释放孤儿进程标识符和进程表条目。
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
//孤儿进程
int main(void) {
pid_t pid;
pid = fork();
if(pid < 0) {
fprintf(stderr, "fork failed");
return 1;
}
else if(pid == 0) {
printf("I am Child, pid=%d, ppid=%d\n", getpid(), getppid());
sleep(10);
printf("I am Child, pid=%d, ppid=%d\n", getpid(), getppid());
}
else {
sleep(1);
printf("I am Parent, pid=%d\n", getpid());
}
return 0;
}
执行结果:
shanlei@shanlei-Lenovo-ideapad-110-15ISK:/var/www/c_code/操作系统$ ./3
I am Child, pid=8300, ppid=8299
I am Parent, pid=8299
shanlei@shanlei-Lenovo-ideapad-110-15ISK:/var/www/c_code/操作系统$ I am Child, pid=8300, ppid=1
进程表条目:
F S UID PID PPID C PRI NI ADDR SZ WCHAN TTY TIME CMD
4 S 0 1 0 0 80 0 - 56380 - ? 00:00:09 systemd
....
1 S 1000 8300 1 0 80 0 - 1127 hrtime pts/0 00:00:00 3
4 R 1000 8301 7084 0 80 0 - 9006 - pts/1 00:00:00 ps
由于子进程sleep了10s,所以父进程终止时,子进程还没有结束,此时将会该子进程成为孤儿进程,可以看到这个时候该孤儿进程的父进程PID为1,也就是所谓的systemd(init)进程。
init进程就好像是一个民政局,专门负责处理孤儿进程的善后工作。每当出现一个孤儿进程的时候,内核就把孤 儿进程的父进程设置为init,而init进程会循环地wait()它的已经退出的子进程。这样,当一个孤儿进程凄凉地结束了其生命周期的时候,init进程就会代表党和政府出面处理它的一切善后工作。因此孤儿进程并不会有什么危害。
OS之进程管理---孤儿进程和僵尸进程的更多相关文章
- 进程——wait与waitpid、僵尸进程与孤儿进程
僵尸进程:子进程终止了,但是父进程没有回收子进程的资源PCB.使其成为僵尸进程 孤儿进程:父进程先与子进程结束了,使得子进程失去了父进程,这个时候子进程会被1号进程init进程领养,成为孤儿进程 为了 ...
- Linux进程实践(4) --wait避免僵尸进程
Wait的背景 当子进程退出的时候,内核会向父进程发送SIGCHLD信号,子进程的退出是个异步事件(子进程可以在父进程运行的任何时刻终止) 子进程退出时,内核将子进程置为僵尸状态,这个进程称为僵尸进程 ...
- [20180312]进程管理其中的SQL Server进程占用内存远远大于SQL server内部统计出来的内存
sql server 统计出来的内存,不管是这个,还是dbcc memorystatus,和进程管理器中内存差距很大,差不多有70G的差异. 具体原因不止,可能是内存泄漏,目前只能通过重启服务解决 ...
- Linux进程管理 lsof命令:列出进程调用或打开的文件信息
lsof命令 通过 ps 命令查询到系统中所有的进程, 通过lsof 命令可以知道这个进程到底在调用哪些文件.lsof 命令格式如下: [root@localhost ~]# lsof [选项] 选项 ...
- python学习笔记—— 多进程中的 孤儿进程和僵尸进程
1 基本概述 1.1 孤儿进程和僵尸进程 父进程创建子进程后,较为理想状态是子进程结束,父进程回收子进程并释放子进程占有的资源:而实际上,父子进程是异步过程,两者谁先结束是无顺的,一般可以通过父进程调 ...
- Python脚本模拟僵尸进程与孤儿进程
最近一台机器的systemd内存高达30%多,一直不变,后来排查是僵尸进程,什么是僵尸进程呢,只能google,百度等先了解,然后自己总结了一下,虽然这是基础的东西,但是对于我来说就如新大陆一样.花了 ...
- day34——僵尸进程和孤儿进程、互斥锁、进程之间的通信
day34 僵尸进程和孤儿进程 基于unix环境(linux,macOS) 主进程需要等待子进程结束之后,主进程才结束 主进程时刻监测子进程的运行状态,当子进程结束之后,一段时间之内,将子进程进行回收 ...
- 僵尸进程 & 孤儿进程
参考博文 基本概念 僵尸进程:是所有进程都会进入的一种进程状态,子进程退出,而父进程并没有调用 wait() 或 waitpid() 获取子进程的状态信息,那么子进程的 PID 和 进程描述符 等资源 ...
- [并发编程 - socketserver模块实现并发、[进程查看父子进程pid、僵尸进程、孤儿进程、守护进程、互斥锁、队列、生产者消费者模型]
[并发编程 - socketserver模块实现并发.[进程查看父子进程pid.僵尸进程.孤儿进程.守护进程.互斥锁.队列.生产者消费者模型] socketserver模块实现并发 基于tcp的套接字 ...
随机推荐
- 【JDBC】jdbc原理总结
1 什么是JDBC JDBC(Java DataBase Connectivity)就是Java数据库连接,说白了就是用Java语言来操作数据库.原来我们操作数据库是在控制台使用SQL语句来操作数据库 ...
- 二进制搭建kubernetes多master集群【一、使用TLS证书搭建etcd集群】
上一篇我们介绍了kubernetes集群架构以及系统参数配置,参考:二进制搭建kubernetes多master集群[开篇.集群环境和功能介绍] 下面本文etcd集群才用三台centos7.5搭建完成 ...
- 将Tomcat设置为自动启动的服务最快捷方法
将Tomcat设置为自动启动的服务: 最近遇到了个问题,服务器上的项目突然访问不了,就上服务器去重启了tomcat服务,谁知道到最后tomcat的服务报错了,重新启动服务的选项 也没有,之前这个项目也 ...
- js限制上传图片类型和大小
<script type="text/javascript"> function checkFile(brandLogo){ var file=brandLogo.va ...
- 创建template模板
创建一个自己常用的快捷键的模板. 1.选择window-->preferrence--搜索temp--java 2.点击new 3.根据自己的习惯起一个名字 4.比如syso 5.语法不会,就找 ...
- org.eclipse.ui.PartInitException: Unable to open editor, unknown editor ID: org.xmen.ui.text.XMLTextEditor
无法打开struts模式的编译xml的编译器,然后打开.project文件,编辑最后一行,找到<natures>结点,增加一条<nature>com.genuitec.ecli ...
- 完美解决VC++6.0与Visio/office不兼容问题!!!
话说电脑上如果装有VC++6.0编程软件和Visio或office办公软件,那么经常编程的人就会遇到下面的问题:VC打不开文件和工程,总是提示读取内存错误,点“确定”后vc自动关闭,但vc却能新建文件 ...
- hdu 1348 凸包模板
http://acm.hdu.edu.cn/showproblem.php?pid=1348 造城墙问题,求出凸包加上一圈圆的周长即可 凸包模板题 #include <cstdio> #i ...
- 分离 桂林电子科技大学第三届ACM程序设计竞赛
链接:https://ac.nowcoder.com/acm/contest/558/H 来源:牛客网 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 262144K,其他语言5242 ...
- Delphi Dll 动态调用例子(1)
http://blog.sina.com.cn/s/blog_62c46c3701010q7h.html 一.编写dll library TestDllByD2007; uses SysUtils, ...