前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >L010Linux和androidNDK之linux避免僵尸进程,子进程退出的处理

L010Linux和androidNDK之linux避免僵尸进程,子进程退出的处理

作者头像
上善若水.夏
发布2018-09-28 10:55:04
3.1K0
发布2018-09-28 10:55:04
举报
文章被收录于专栏:上善若水上善若水

L010Linux和androidNDK之linux避免僵尸进程,子进程退出的处理

如果你在程序中fork出一个子进程,没有好好处理子进程退出后的相关事宜,那么就有可能召唤出传说中进程界的僵尸---僵尸进程!!!

什么是僵尸进程

一个进程在调用exit命令结束自己的生命的时候,其实它并没有真正的被 僵尸进程销毁, 而是留下一个称为僵尸进程(Zombie)的数据结构(系统调用exit,它的作用是 使进程退出,但也仅仅限于将一个正常的进程变成一个僵尸进程,并不能将其完全销毁)

僵尸进程是怎么样产生

在Linux进程的状态中,僵尸进程是非常特殊的一种,它已经放弃了几乎所有内存空间,没有任何可执行代码,也不能被调度,仅仅在进程列表中保留一个位置,记载该进程的退出状态等信息供其他进程收集,除此之外,僵尸进程不再占有任何内存空间。它需要它的父进程来为它收尸。

如果他的父进程没安装SIGCHLD信号处理函数调用wait或waitpid()等待子进程结束,又没有显式忽略该信号,那么它就一直保持僵尸状态,如果这时父进程结束了,那么init进程自动会接手这个子进程,为它收尸,它还是能被清除的。

但是如果父进程是一个循环,不会结束,那么子进程就会一直保持僵尸状态,这就是为什么系统中有时会有很多的僵尸进程。系统所能使用的进程号是有限的,如果大量的产生僵死进程,将因为没有可用的进程号而导致系统不能产生新的进程.

异步回收僵尸进程:

fork()之后,子进程从父进程获取了一份拷贝,和父进程分别独立运行,僵尸进程的产生是因为父进程没有给子进程“收尸”造成的,又可以根据危害程度分为下述两类: 总体来说:当子进程结束之后,但父进程未结束之前,子进程将成为僵尸进程。 (1)当子进程结束之后,但父进程未结束之前,子进程将成为僵尸进程,父进程结束后僵尸被init进程回收。 (2)如果子进程结束了,但是父进程始终没有结束,那么这个僵尸将一直存在,而且随着exec,僵尸越来越多。

相关回收进程的函数

代码语言:javascript
复制
#include<sys/types.h>
#include<sys/wait.h>

pid_t waitpid(pid_t pid,int * status,int options);
pid_t wait (int * status);

其中 wait(&status);等价于waitpid(-1, &status, 0);

waitpid()会暂时停止目前进程的执行,直到有信号来到或子进程结束 如果在调用 waitpid()时子进程已经结束,则 waitpid()会立即 返回子进程结束状态值。 子进程的结束状态值会由参数 status 返回, 而子进程的进程识别码也会一起返回。如果不在意结束状态值,则 参数 status 可以设成 NULL。参数 pid 为欲等待的子进程识别码, 其他数值意义如下:

代码语言:javascript
复制
pid<-1 等待进程组识别码为 pid 绝对值的任何子进程。
pid=-1 等待任何子进程,相当于 wait()。
pid=0 等待进程组识别码与目前进程相同的任何子进程。
pid>0 等待任何子进程识别码为 pid 的子进程。

参数options提供了一些额外的选项来控制waitpid,参数 option 可以为 0 或可以用"|"运算符把它们连接起来使用

代码语言:javascript
复制
#include <stdio.h>   
#include <stdlib.h>   
#include <signal.h>   
#include <unistd.h>   
#include <sys/wait.h>   
    
void handler(int num) {   
    //我接受到了SIGCHLD的信号啦   
    int status;   
    int pid = waitpid(-1, &status, WNOHANG);   
    if (WIFEXITED(status)) {   
        printf("The child %d exit with code %d\n", pid, WEXITSTATUS(status));   
    }   
}   
    
int main() {   
    //子进程的pid   
    int c_pid;   
    int pid;   
    
    signal(SIGCHLD, handler);   
    
    if ((pid = fork())) {   
        //父进程   
        c_pid = pid;   
        printf("The child process is %d\n", c_pid);   
    
        //父进程不用等待,做自己的事情吧~   
        int i=0;
        for ( i = 0; i < 16; i++) {   
            printf("Do parent things.\n");   
            sleep(1);   
        } 

        printf("Do parent end\n"); 
    
        exit(0);   
    } else {   
        //子进程   
        printf("I 'm a child.\n");   
        sleep(2);   
        exit(0);   
    }   
} 

子进程的结束状态

代码语言:javascript
复制
WIFEXITED/WEXITSTATUS/WIFSIGNALED
If the exit status value (*note Program Termination::) of the child  
process is zero, then the status value reported by `waitpid' or `wait'  
is also zero. You can test for other kinds of information encoded in  
the returned status value using the following macros. These macros are  
defined in the header file `sys/wait.h'.  
-- Macro: int WIFEXITED (int STATUS)  
     This macro returns a nonzero value if the child process terminated  
     normally with `exit' or `_exit'.  
-- Macro: int WEXITSTATUS (int STATUS)  
     If `WIFEXITED' is true of STATUS, this macro returns the low-order

8 bits of the exit status value from the child process. *Note  
     Exit Status::.  
-- Macro: int WIFSIGNALED (int STATUS)  
     This macro returns a nonzero value if the child process terminated  
     because it received a signal that was not handled. *Note Signal  
     Handling::

子进程的结束状态返回后存于status,如下有几个宏可判别结束情况

代码语言:javascript
复制
WIFEXITED(status)如果子进程正常结束则为非0值。  
WEXITSTATUS(status)取得子进程exit()返回的结束代码,一般会先用WIFEXITED 来判断是否正常结束才能使用此宏。  

WIFSIGNALED(status)如果子进程是因为信号而结束则此宏值为真 

WTERMSIG(status)取得子进程因信号而中止的信号代码,一般会先用WIFSIGNALED 来判断后才使用此宏。  
WIFSTOPPED(status)如果子进程处于暂停执行情况则此宏值为真。一般只有使用WUNTRACED 时才会有此情况。  
WSTOPSIG(status)取得引发子进程暂停的信号代码,一般会先用WIFSTOPPED 来判断后才使用此宏。


kill -STOP 1234 进程暂停。
kill -CONT 1234     进程继续

参考链接

  1. 异步回收fork出的子进程(僵尸进程)
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2016.08.19 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 什么是僵尸进程
  • 僵尸进程是怎么样产生
  • 异步回收僵尸进程:
  • 相关回收进程的函数
  • 子进程的结束状态
  • 参考链接
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档