僵尸进程
Posted leo_wl
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了僵尸进程相关的知识,希望对你有一定的参考价值。
1. 关于fork
fork()函数:
用于创建一个进程,所创建的进程复制父进程的代码段/数据段/BSS段/堆/栈等所有用户空间信息;在内核中操作系统重新为其申请了一个PCB,并使用父进程的PCB进行初始化;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
#include <iostream> #include <unistd.h> using namespace std; int val = 10; int main( int argc, char *argv[])
pid_t pid; int lval = 20; ? pid = fork(); ? if (pid == 0) val += 2; lval += 5;
else
val -= 2; lval += 5;
? if (pid == 0) cout << "val:" << val << ", lval = " << lval << endl;
else
cout << "val:" << val << ", lval = " << lval << endl;
return 0;
|
对于父进程而言,fork()函数返回子进程的ID(子进程的PID);而对于子进程而言,fork函数返回0。
僵尸进程
父进程创建子进程后,子进程运行到终止时刻(例如,调用
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
int main() pid_t pid = fork(); if (pid == 0) cout << "I am a Child Process." <<endl;
else
cout << "I am a Father Process and Child Process is " << pid << endl; sleep(30); //让父进程休眠30秒,此时便于观察子进程的状态
if (pid == 0) cout << " Child Process exits " << endl;
else
cout << "Father Process exits " << endl;
return 0;
|
此时,运行该程序,查看后台进程可知(test16是该测试程序的名称,defunct表示僵尸进程):
[email protected]:~$ ps -au USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND root 923 0.6 0.9 480840 159824 tty7 Ssl+ 4月09 36:07 /usr/lib/xorg/ root 1351 0.0 0.0 17676 1768 tty1 Ss+ 4月09 0:00 /sbin/agetty - ... gqx 24856 0.0 0.0 0 0 pts/11 Z+ 11:03 0:00 [tes16] <defunct> gqx 24859 0.0 0.0 39104 3300 pts/3 R+ 11:03 0:00 ps -au
僵尸进程的消除
方法一:调用wait()
函数:
/* Wait for a child to die. When one does, put its status in *STAT_LOC and return its process ID. For errors, return (pid_t) -1. ? This function is a cancellation point and therefore not marked with __THROW. */ extern __pid_t wait (__WAIT_STATUS __stat_loc);
成功返回终止的进程ID,失败返回-1;子进程的最终返回值将指向该函数参数所指向的内存空间,但函数所指向的内存单元总还含有其他的信息,需要使用宏进行分离。
# define WIFEXITED(status) __WIFEXITED (__WAIT_INT (status)) //子进程正常终止返回"true" # define WEXITSTATUS(status) __WEXITSTATUS (__WAIT_INT (status)) //返回子进程的返回值
要注意的是:如果没有已终止的子进程,那么程序将被阻塞,直到有子进程终止。
方法二:调用waitpid()
函数
/* Wait for a child matching PID to die. If PID is greater than 0, match any process whose process ID is PID. If PID is (pid_t) -1, match any process. If PID is (pid_t) 0, match any process with the same process group as the current process. If PID is less than -1, match any process whose process group is the absolute value of PID. If the WNOHANG bit is set in OPTIONS, and that child is not already dead, return (pid_t) 0. If successful, return PID and store the dead child‘s status in STAT_LOC. Return (pid_t) -1 for errors. If the WUNTRACED bit is set in OPTIONS, return status for stopped children; otherwise don‘t. ? This function is a cancellation point and therefore not marked with __THROW. */ extern __pid_t waitpid (__pid_t __pid, int *__stat_loc, int __options);
第一个参数:如果__pid
的值是-1,则与wait()
函数相同,可以等待任意的子程序终止;如果是0,则等待进程组识别码与目前进程相同的任何子进程;如果pid>0,则等待任何子进程识别码为 pid 的子进程。
第二个参数:与前一个函数wait()
的参数意义相同。
第三个参数:常用WNOHANG——若pid指定的子进程没有结束,则waitpid()函数返回0,不予以等待。若结束,则返回该子进程的ID。
示例程序如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
|
#include <iostream> #include <stdlib.h> #include <unistd.h> #include <signal.h> #include <sys/wait.h> using namespace std; ? void read_childproc( int sig) int status; pid_t id = waitpid(-1, &status, WNOHANG); if (WIFEXITED(status)) printf ( "Remove proc id: %d \n" , id); printf ( "Child send: %d \n" , WEXITSTATUS(status));
? int main() pid_t pid; struct sigaction act; act.sa_handler = read_childproc; sigemptyset(&act.sa_mask); act.sa_flags = 0; sigaction(SIGCHLD, &act, 0); ? pid = fork(); ? if (pid == 0) puts ( "Hi, I am a child process!" ); sleep(6); return 12;
else
printf ( "Child proc id: %d \n" , pid); pid = fork(); if (pid == 0) puts ( "Hi, I am a child process!" ); sleep(13); exit (24);
else
int i; printf ( "Child proc id: %d \n" , pid); for (i = 0; i < 4; i++) puts ( "wait..." ); sleep(5);
return 0;
|