对网站建设的建议,网站页面示意图怎么做,广州电信网站备案,长沙点梦网站建设公司怎么样1. 前言
限于作者能力水平#xff0c;本文可能存在谬误#xff0c;因此而给读者带来的损失#xff0c;作者不做任何承诺。
2. 案例
原来的故事是 这样 的#xff0c;感兴趣的读者可以直接前往。我从中截取了一段重现故事中问题的代码#xff08;对原代码做了小小调整本文可能存在谬误因此而给读者带来的损失作者不做任何承诺。
2. 案例
原来的故事是 这样 的感兴趣的读者可以直接前往。我从中截取了一段重现故事中问题的代码对原代码做了小小调整
#include unistd.h
#include stdio.h
#include sys/wait.h#define SLEEP_SCRIPT_PATH /home/bill/Study/qemu-lab/app/issue/1/sleep.shint main(void)
{int pid;if ((pid fork()) 0) {printf(children: %d\n, getpid());/* /bin/bash -c /home/bill/Study/qemu-lab/app/issue/1/sleep.sh */execle(/bin/bash, /bin/bash, -c, SLEEP_SCRIPT_PATH, (char *)0, NULL);}printf(parent: %d\n, getpid());//printf(waitfing for children... );//wait(NULL);//printf(done.\n);while (1)sleep(1);return 0;
}sleep.sh 的内容如下
#!/bin/bashsleep 3编译并运行
$ make zombie_issue$ strace -f -t -e execve ./zombie_issue
16:28:33 execve(./zombie_issue, [./zombie_issue], [/* 69 vars */]) 0
parent: 11128
strace: Process 11129 attached
children: 11129
[pid 11129] 16:28:33 execve(/bin/bash, [/bin/bash, -c, /home/bill/Study/qemu-lab/app/is...], NULL) 0
strace: Process 11130 attached
[pid 11130] 16:28:33 execve(/home/bill/Study/qemu-lab/app/issue/1/sleep.sh, [/home/bill/Study/qemu-lab/app/is...], [/* 3 vars */] unfinished ...
[pid 11129] 16:28:33 exited with 0
[pid 11128] 16:28:33 --- SIGCHLD {si_signoSIGCHLD, si_codeCLD_EXITED, si_pid11129, si_uid1000, si_status0, si_utime0, si_stime0} ---
[pid 11130] 16:28:33 ... execve resumed ) 0
strace: Process 11131 attached
[pid 11131] 16:28:33 execve(/bin/sleep, [sleep, 3], [/* 3 vars */]) 0
[pid 11131] 16:28:36 --- SIGWINCH {si_signoSIGWINCH, si_codeSI_KERNEL} ---
[pid 11128] 16:28:36 --- SIGWINCH {si_signoSIGWINCH, si_codeSI_KERNEL} ---
[pid 11130] 16:28:36 --- SIGWINCH {si_signoSIGWINCH, si_codeSI_KERNEL} ---
[pid 11131] 16:28:36 exited with 0
[pid 11130] 16:28:36 --- SIGCHLD {si_signoSIGCHLD, si_codeCLD_EXITED, si_pid11131, si_uid1000, si_status0, si_utime0, si_stime0} ---
[pid 11130] 16:28:36 exited with 0
16:28:37 --- SIGWINCH {si_signoSIGWINCH, si_codeSI_KERNEL} ---$ ps -ef -o pid,ppid,commPID PPID COMMAND9539 2774 bash11133 9539 \_ ps9439 2774 bash11126 9439 \_ strace11128 11126 \_ zombie_issue11129 11128 \_ bash defunct看看进程 11129 进程变僵尸了defunct 标注表示进程变僵尸了。用 top 可以观察到变 Z 了
top - 16:51:36 up 5:39, 1 user, load average: 0.09, 0.04, 0.01
Tasks: 1 total, 0 running, 0 sleeping, 0 stopped, 1 zombie
%Cpu(s): 0.5 us, 2.1 sy, 0.0 ni, 97.4 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
KiB Mem : 4015908 total, 844272 free, 928832 used, 2242804 buff/cache
KiB Swap: 0 total, 0 free, 0 used. 2735724 avail Mem PID USER PR NI VIRT RES SHR S %CPU %MEM TIME COMMAND 11129 bill 20 0 0 0 0 Z 0.0 0.0 0:00.02 bash开始分析问题之前我们先来了解 bash 是怎么处理 操作符 的
If a command is terminated by the control operator , the shell executes the
command in the background in a subshell. The shell does not wait for the command
to finish, and the return status is 0. 上面是摘自 bash手册 原文翻译下它的意思 从 bash 启动的命令如果尾接 操作符则 bash 启动 子shell 来运行命令而 bash 本身不等待 即不对命令程序发起 wait() 调用命令的结束直接以退出码 0 退出。 我们再来简单了解下什么样的进程会变成 僵尸进程 一个进程退出了其存活的父进程又不对其进行回收(没有对进程发起 wait() 调用)则该进程就会变成 僵尸进程 。 有了上述对 bash 操作符 和 僵尸进程 的基础知识我们就可以来理一理为什么会出现僵尸进程了。 我们不关注用来调试的 strace 进程直接从 zombie_issue 说起。结合 strace 的追踪记录以及程序 zombie_issue 的输出信息我们按 进程 PID 来小结一下出现的几个进程
11128: zombie_issue 进程
11129: zombie_issue 进程 fork 的子进程用来启动程序 /bin/bash
11130: /bin/bash 的子shell用来启动脚本 sleep.sh
11131: 运行脚本 sleep.sh 中 sleep 3 语句的进程上面说了进程变僵尸是因为无人对它进行回收。我们一步步来看为什么 进程 11129 最后变成了僵尸
1. 脚本 sleep.sh 中执行 sleep 3 语句的进程 11131 运行完成后子shell进程 11130 对其进行了回收所以它不会变僵尸
2. 子 shell 进程 11130 等到执行 sleep 3 语句的进程 11131 退出后它自己也退出了。此时因为启动它的父进程程序 /bin/bash 已经退出了它变成了无人理的孤儿那么谁来回收它呢针对这种父进程比子进程先结束的情形Linux内核会将子进程托孤给 始祖进程init由 init进程 负责完成子进程的回收。于是我们的孤儿进程 11130 也被回收了所以它不会变僵尸
3. 而启动程序 /bin/bash 的进程 11129 自从它退出后父程序 zombie_issue 进程 11128 对它不理睬任其曝尸荒野何其惨也但由于父进程 zombie_issue 又没有退出Linux内核也不会将其托孤给 init 进程所以只能变僵尸了。通过上面的分析我们知道了 进程 11129 为什么变僵尸的原因。 上面的测试代码单独拿出来就是一个编程BUG存活的父进程 理应对子进程发起 wait() 。如果放开对代码中的 wait() 调用的注释就不会出现僵尸进程。 这是一个简单的问题但放在复杂的环境下我们确实可能犯这样的错误。其实仅仅是要模拟出现僵尸进程的情形上面的测试代码还可以简化
#include unistd.h
#include sys/wait.hint main(void)
{int pid;if ((pid fork()) 0) {execle(/bin/bash, /bin/bash, -c, /bin/ls, (char *)0, NULL);}//wait(NULL);while (1)sleep(1);return 0;
}3. 参考资料
cron 僵尸进程问题分析 man bash