Linux僵尸进程

Linux僵尸进程

一个进程使用fork系统调用创建子进程,如果子进程退出,而父进程并没有调用wait或waitpid获取子进程的状态信息,那么子进程的进程描述符仍然保存在系统中,这种进程称之为僵尸进程。

为什么会存在僵尸进程?

Unix提供了一种机制可以保证只要父进程想知道子进程结束时的状态信息,就可以得到。这种机制就是,在每个进程退出的时候,内核释放该进程所有的资源,包括打开的文件,占用的内存等。但是仍然为其保留一定的信息(包括进程号pid,退出状态、运行时间等)。直到父进程通过wait/waitpid来取时才释放。但这样就导致了问题,如果进程一直不调用wait/waitpid的话,那么保留的那段信息就不会释放,其进程号就会一直被占用,但是系统所能使用的进程号是有限的,如果大量的产生僵尸进程,将因为没有可用的进程号而导致系统不能产生新的进程。

假设子进程结束时父进程仍存在,而父进程fork()前既没有安装SIGCHLD信号处理函数调用waitpid()等待子进程结束,又没有显式忽略该信号,则子进程成为僵尸进程,无法正常结束,此时即使是root身份kill -9也不能杀死僵尸进程。而杀死僵尸进程的方法之一就是杀死僵尸进程的父进程,使僵尸进程成为“孤儿进程”,过继给1号进程init,init进程始终会负责清理僵尸进程。进程表越大,init进程清理僵尸进程就越慢。应该尽量避免产生僵尸进程,因为在init清理它们之前,它们将一直消耗系统的资源。

wait函数

可以通过wait函数让父进程等待子进程结束。

#include 
#include 

pid_t wait(int *stat_loc);

wait系统调用将暂停父进程直到它的子进程结束为止。这个调用返回子进程的PID,它通常是已经结束运行的子进程的PID。状态信息允许父进程了解子进程的退出状态,即子进程的main函数返回的值或子进程中exit函数的退出码。如果stat_loc不是空指针,状态信息将被写入它指向的位置。

状态码的意义:

状态名 意义
WIFEXITED(stat_val) 如果子进程正常结束,它就取一个非零值
WEXITSTATUS(stat_val) 如果WIFEXITED非零,它返回子进程的退出码
WIFSIGNALED(stat_val) 如果子进程因为一个未捕获的信号而终止,它就取一个非零值
WTERMSIG(stat_val) 如果WIFSIGNALED非零,它返回一个信号代码
WIFSTOPPED(stat_val) 如果子进程意外终止,它就取一个非零值
WSTOPSIG(stat_val) 如果WIFSTOPPED非零,它返回一个信号代码

waitpid函数

除了wait函数,waitpid函数也可以用来等待子进程结束。

#include 
#include 

pid_t waitpid(pid_t pid, int *stat_loc, int options);

参数说明:

  • pid:指定需要等待的子进程的PID。如果值为-1,这waitpid将返回任一子进程的信息。
  • stat_loc:若不为空指针,waitpid将把状态信息写到它所指向的位置。
  • options:用来改变waitpid的行为。例如WNOHANG选项可以防止waitpid调用将调用者挂起。

你可能感兴趣的:(Linux,linux,操作系统)