原理
子进程先于父进程退出,父进程还在继续运行,且没有调用wait函数。
实验代码
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <errno.h>
#define _DEBUG_INFO
#ifdef _DEBUG_INFO
#define DEBUG_INFO(format, ...) printf("%s:%s:%d -- "format"\n" \
,__FILE__,__func__,__LINE__ \
, ##__VA_ARGS__)
#else
#define DEBUG_INFO(format, ...)
#endif
int main(int argc, char *argv[])
{
int pid = fork();
if(pid == 0){
DEBUG_INFO("i'm a child process %d",getpid());
return 0;
}
DEBUG_INFO("i'm a parent process %d",getpid());
pause();
DEBUG_INFO("BYEBYE");
return 0;
}
执行结果:
此时程序父进程处于pause状态。子进程的PID是21964, 搜索该进程:ps aux | grep fork,如下所示,
看到PID号为21964的进程,就是截图中间那个。它的最后是<defunct>,没错它就是僵尸进程了。
wait函数
#include <sys/types.h>
#include <sys/wait.h>
pid_t wait(int *status);
测试代码:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/wait.h>
#define _DEBUG_INFO
#ifdef _DEBUG_INFO
#define DEBUG_INFO(format, ...) printf("%s:%s:%d -- "format"\n" \
,__FILE__,__func__,__LINE__ \
, ##__VA_ARGS__)
#else
#define DEBUG_INFO(format, ...)
#endif
int main(int argc, char *argv[])
{
int pid = fork();
if(pid == 0){
DEBUG_INFO("i'm a child process %d",getpid());
return 0;
}
DEBUG_INFO("i'm a parent process %d",getpid());
int status = 0;
int res = wait(&status);
DEBUG_INFO("wait res = %d status = %d",res,status);
pause();
DEBUG_INFO("BYEBYE");
return 0;
}
实验结果:
实验解析
此时,子进程22302已经安息了,它的PID通过wait函数的返回值传递给了父进程,返回值通过status传递给了父进程。
为了获取有效的返回值,修改代码如下所示:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/wait.h>
#define _DEBUG_INFO
#ifdef _DEBUG_INFO
#define DEBUG_INFO(format, ...) printf("%s:%s:%d -- "format"\n" \
,__FILE__,__func__,__LINE__ \
, ##__VA_ARGS__)
#else
#define DEBUG_INFO(format, ...)
#endif
void pr_exit(int status)
{
if (WIFEXITED(status))
printf("normal termination, exit status = %d\n",
WEXITSTATUS(status));
else if (WIFSIGNALED(status))
printf("abnormal termination, signal number = %d%s\n",
WTERMSIG(status),
#ifdef WCOREDUMP
WCOREDUMP(status) ? " (core file generated)" : "");
#else
"");
#endif
else if (WIFSTOPPED(status))
printf("child stopped, signal number = %d\n",
WSTOPSIG(status));
}
int main(int argc, char *argv[])
{
int pid = fork();
if(pid == 0){
DEBUG_INFO("i'm a child process %d",getpid());
return -2;
}
DEBUG_INFO("i'm a parent process %d",getpid());
int status = 0;
int res = wait(&status);
DEBUG_INFO("wait res = %d status = %d",res,status);
pr_exit(status);
pause();
DEBUG_INFO("BYEBYE");
return 0;
}
执行结果:
实验解析
当进程返回-1时,红色框中的值是255,当前返回值是-2,红框中的值是254.
waitpid函数
#include <sys/types.h>
#include <sys/wait.h>
pid_t wait(int *status);
pid_t waitpid(pid_t pid, int *status, int options);
int waitid(idtype_t idtype, id_t id, siginfo_t *infop, int options);