linux删除id为999的进程,linux c 僵尸进程的产生和清除

linuxc僵尸进程的产生和清除

什么是僵尸进程

僵尸进程是指它的父进程已经退出(父进程没有等待(调用wait/waitpid)它),而该进程dead以后没有进程接受,就成为僵尸进程,也就是(zombie)进程。linux

僵尸进程是怎么样产生

一个进程在调用exit命令结束本身的生命的时候,其实它并无真正的被销毁,而是留下一个称为僵尸进程(Zombie)的数据结构(系统调用exit,它的做用是使进程退出,但也仅仅限于将一个正常的进程变成一个僵尸进程,并不能将其彻底销毁)。编程

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

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

可是若是父进程是一个循环,不会结束,那么子进程就会一直保持僵尸状态,这就是为何系统中有时会有不少的僵尸进程。系统所能使用的进程号是有限的,若是大量的产生僵死进程,将由于没有可用的进程号而致使系统不能产生新的进程. 异步

以下代码,子进程先于父进程退出,在父进程执行的5s内,子进程将为僵尸:函数

#include

#include

#include

#include

int main() {

//子进程的pid

int c_pid;

int pid;

if ((pid = fork())) {

//父进程

c_pid = pid;

printf("The child process is %d\n", c_pid);

sleep(5);

exit(0);

} else {

//子进程

printf("I 'm a child.\n");

exit(0);

}

}

如何快速找出僵尸程序

打开终端并输入下面命令:unix

ps aux | grep Zcode

会列出进程表中全部僵尸进程的详细内容。继承

怎么干掉这些僵尸程序

用 SIGCHLD信号来杀死僵尸进程

正常状况下咱们能够用 SIGKILL 信号来杀死进程,可是僵尸进程已经死了, 你不能杀死已经死掉的东西。 所以你须要输入的命令应该是:进程

ps -ef | grep pid 首先查看僵尸进程的父进程pid,输出结果的第三列ppid就是父进程的pid

kill -s SIGCHLD ppid

将这里的 pid 替换成父进程的进程 id,这样父进程就会删除全部以及完成并死掉的子进程了。

程序中避免僵尸进程的产生

父进程调用wait/waitpid。

父进程先于子进程退出,子进程自动托管到init进程。

fork()两次,调用孙子进程。

绑定SIGCHLD信号处理函数,在信号处理函数中调用wait。

绑定SIGCHLD信号处理函数SIG_IGN。(不推荐)

父进程调用wait/waitpid

父进程调用waitpid()等函数来接收子进程退出状态。

#include

#include

#include

#include

#include

int main() {

//子进程的pid

int c_pid;

int pid;

if ((pid = fork())) {

//父进程

c_pid = pid;

printf("The child process is %d\n", c_pid);

//阻塞等待子进程

int status;

if ((pid = wait(&status)) != -1 && pid == c_pid) {

//成功回收子进程

printf("The child exit with %d\n", WEXITSTATUS(status));

fflush(stdin);

}

printf("Now , The child has been exit , and I will sleep.\n");

sleep(20);

exit(0);

} else {

//子进程

printf("I 'm a child.\n");

sleep(5);

exit(0);

}

}

父进程先exit,子进程托管到init进程

父进程先结束,子进程则自动托管到Init进程(pid = 1)。

#include

#include

#include

#include

#include

int main() {

//子进程的pid

int c_pid;

int pid;

if ((pid = fork())) {

//父进程

printf("I'm father id = %d.The child process is %d\n", getpid(), pid);

exit(0);

} else {

//子进程

printf("I 'm a child.\n");

sleep(5);

exit(0);

}

}

fork()两次,调用孙子进程

​ 父进程一次fork()后产生一个子进程随后当即执行waitpid(子进程pid, NULL, 0)来等待子进程结束,而后子进程fork()后产生孙子进程随后当即exit(0)。这样子进程顺利终止(父进程仅仅给子进程收尸,并不须要子进程的返回值),而后父进程继续执行。这时的孙子进程因为失去了它的父进程(便是父进程的子进程),将被转交给Init进程托管。因而父进程与孙子进程无继承关系了,它们的父进程均为Init,Init进程在其子进程结束时会自动收尸,这样也就不会产生僵尸进程了。

#include

#include

#include

#include

#include

int main() {

//子进程的pid

int c_pid;

int pid;

if ((pid = fork())) {

//父进程

c_pid = pid;

printf("I'm father id = %d.The child process is %d\n", getpid(), c_pid);

//阻塞等待子进程

int status;

if ((pid = wait(&status)) != -1 && pid == c_pid) {

//成功回收子进程

printf("The child exit with %d\n", WEXITSTATUS(status));

fflush(stdin);

}

exit(0);

} else {

if ((pid = fork())) {

//子进程

printf("I 'm a child pid = %d. my child pid = %d. exit.\n", getpid(), pid);

exit(0);

} else {

//孙子进程

sleep(20);

printf("I 'm a grandson pid = %d. exit\n", pid);

exit(0);

}

}

}

绑定SIGCHLD信号处理函数,在信号处理函数中调用wait

阻塞等待,那么父进程就没法作其余事;

父进程退出,在建立守护进程时候会有,可是咱们并不想让父进程退出;

fork()两次,孤儿进程不易由咱们程序来管理;

man wait,查看NOTES章节,能够找到:子进程退出的时候,会发送SIGCHLD信号,默认的POSIX不响应

因此设置处理SIGCHLD信号的函数,能够用于异步回收fork子进程。

注意:信号产生触发信号处理函数时,会中断某些函数,例如poll、select、epoll等。

​ 详情见《unix网络编程》5.8小节,POSIX信号处理

#include

#include

#include

#include

#include

void sig_chld(int num) {

pid_t pid;

int stat;

while ( (pid = waitpid(-1, &stat, WNOHANG)) > 0) // 循环处理完全部的信号

printf("child %d terminated\n", pid);

return;

}

int main() {

//子进程的pid

int c_pid;

int pid;

signal(SIGCHLD, sig_chld);

if ((pid = fork())) {

//父进程

c_pid = pid;

printf("The child process is %d\n", c_pid);

//父进程不用等待,作本身的事情吧~

for (int i = 0; i < 10; i++) {

printf("Do parent things.\n");

sleep(1);

}

exit(0);

} else {

//子进程

printf("I 'm a child.\n");

sleep(2);

exit(0);

}

}

绑定SIGCHLD信号处理函数SIG_IGN

不推荐使用,由于POSIX标准中未规定SIG_IGN,会破坏程序的可移植性。

#include

#include

#include

#include

#include

int main() {

//子进程的pid

int c_pid;

int pid;

signal(SIGCHLD,SIG_IGN);

if ((pid = fork())) {

//父进程

c_pid = pid;

printf("The child process is %d\n", c_pid);

//父进程不用等待,作本身的事情吧~

for (int i = 0; i < 10; i++) {

printf("Do parent things.\n");

sleep(1);

}

exit(0);

} else {

//子进程

printf("I 'm a child.\n");

sleep(2);

exit(0);

}

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值