僵尸进程

当一个进程终止时,操作系统会释放其资源,不过它位于进程表中的条目还是在的,直到它的父进程调用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之进程管理---孤儿进程和僵尸进程的更多相关文章

  1. 进程——wait与waitpid、僵尸进程与孤儿进程

    僵尸进程:子进程终止了,但是父进程没有回收子进程的资源PCB.使其成为僵尸进程 孤儿进程:父进程先与子进程结束了,使得子进程失去了父进程,这个时候子进程会被1号进程init进程领养,成为孤儿进程 为了 ...

  2. Linux进程实践(4) --wait避免僵尸进程

    Wait的背景 当子进程退出的时候,内核会向父进程发送SIGCHLD信号,子进程的退出是个异步事件(子进程可以在父进程运行的任何时刻终止) 子进程退出时,内核将子进程置为僵尸状态,这个进程称为僵尸进程 ...

  3. [20180312]进程管理其中的SQL Server进程占用内存远远大于SQL server内部统计出来的内存

    sql server 统计出来的内存,不管是这个,还是dbcc memorystatus,和进程管理器中内存差距很大,差不多有70G的差异. 具体原因不止,可能是内存泄漏,目前只能通过重启服务解决   ...

  4. Linux进程管理 lsof命令:列出进程调用或打开的文件信息

    lsof命令 通过 ps 命令查询到系统中所有的进程, 通过lsof 命令可以知道这个进程到底在调用哪些文件.lsof 命令格式如下: [root@localhost ~]# lsof [选项] 选项 ...

  5. python学习笔记—— 多进程中的 孤儿进程和僵尸进程

    1 基本概述 1.1 孤儿进程和僵尸进程 父进程创建子进程后,较为理想状态是子进程结束,父进程回收子进程并释放子进程占有的资源:而实际上,父子进程是异步过程,两者谁先结束是无顺的,一般可以通过父进程调 ...

  6. Python脚本模拟僵尸进程与孤儿进程

    最近一台机器的systemd内存高达30%多,一直不变,后来排查是僵尸进程,什么是僵尸进程呢,只能google,百度等先了解,然后自己总结了一下,虽然这是基础的东西,但是对于我来说就如新大陆一样.花了 ...

  7. day34——僵尸进程和孤儿进程、互斥锁、进程之间的通信

    day34 僵尸进程和孤儿进程 基于unix环境(linux,macOS) 主进程需要等待子进程结束之后,主进程才结束 主进程时刻监测子进程的运行状态,当子进程结束之后,一段时间之内,将子进程进行回收 ...

  8. 僵尸进程 & 孤儿进程

    参考博文 基本概念 僵尸进程:是所有进程都会进入的一种进程状态,子进程退出,而父进程并没有调用 wait() 或 waitpid() 获取子进程的状态信息,那么子进程的 PID 和 进程描述符 等资源 ...

  9. [并发编程 - socketserver模块实现并发、[进程查看父子进程pid、僵尸进程、孤儿进程、守护进程、互斥锁、队列、生产者消费者模型]

    [并发编程 - socketserver模块实现并发.[进程查看父子进程pid.僵尸进程.孤儿进程.守护进程.互斥锁.队列.生产者消费者模型] socketserver模块实现并发 基于tcp的套接字 ...

随机推荐

  1. MetroApp保存UIEment为图片

    写本文的起因是想截取Metro App画面作为图片来使用Win8的共享. 话说自从大MS的客户端UI技术进入XAML时代之后,每次截屏的代码都不太一样,无论silverlight.WPF还是Windo ...

  2. 2018.10.19 NOIP模拟 硬币(矩阵快速幂优化dp)

    传送门 不得不说神仙出题人DZYODZYODZYO出的题是真的妙. f[i][j][k]f[i][j][k]f[i][j][k]表示选的硬币最大面值为iii最小面值不小于jjj,总面值为kkk时的选法 ...

  3. 2018.06.29 NOIP模拟 区间(前缀和差量)

    区间(interval.cpp) 时限:2000ms 空间限制:512MB [问题描述] 给出一个长度为 n 的序列 a[1]-a[n]. 给出 q 组询问,每组询问形如<x,y>< ...

  4. 2018.07.22 bzoj3613: [Heoi2014]南园满地堆轻絮(逆序对结论题)

    传送门 做这道题有一个显然的结论,就是要使这个数列单调不减,就要使所有逆序对保证单调不减,也就是求出所有逆序对的最大差值,然后除以2然后就没了. 代码如下: #include<bits/stdc ...

  5. RHEL6解决无法使用YUM源问题(转)

    RHEL的YUM源需要注册用户才能更新使用,由于CentOS和RHEL基本没有区别,并且CentOS已经被REHL收购.所以将RHEL的YUM源替换为CentOS即可.问题如下:[root@bogon ...

  6. DIV+CSS实战(三)

    一.说明 在上篇博客<DIV+CSS实战(二)>中,实现了头部以及Tab标签卡,下面开始实现内容区域,要实现的效果如下: 二.内容最外层的设计(边框) 给最外层加边框,并且设置高度随着里面 ...

  7. 201709012工作日记--一台电脑创建两个Github账户上传代码

    1. 在一台主机上面使用多个GitHub账号 有时候,我们需要将个人账号和公司账号区分,这时候我们就会需要在一台电脑上使用2个不同的git账号. 2. 上传文件 http://blog.csdn.ne ...

  8. 命令行中开启mySQL数据库服务

    sudo /Applications/XAMPP/xamppfiles/bin/mysql.server start  

  9. (并查集 建立关系)食物链 -- POJ-- 1182

    链接: http://poj.org/problem?id=1182 http://acm.hust.edu.cn/vjudge/contest/view.action?cid=82830#probl ...

  10. hdu 4993

    http://acm.hdu.edu.cn/showproblem.php?pid=4993 满足ax + by = c的x,y对数 水题,暴力 #include <cstdio> #in ...