wait和waitpid都可用来处理僵死进程(注:僵死进程(zombie),一个已经终止、但是其父进程尚未对其进行善后处理(获得终止子进程的有关信息,释放它仍占用的资)的进程被称为僵死进程。)
wait函数原型:pid_t wait (int * status);
返回值:成功则返回子进程的ID,失败则返回-1;
wait会出现阻塞状态:子进程还在进行,父进程中的wait会一直等子进程结束将其回收,等到海枯石烂;
wait函数只能解决一个僵死进程,若存在多个正在运行的子进程,wait只接收第一个结束的子进程并立即返回;
如若程序没有子进程则立即出错返回;
wait函数的参数 statu:获取子进程的终止状态
有4个互斥的宏可以用来获取进程终止的原因:
WIFEXITED(status)
若子进程正常终止,该宏返回true。
此时,可以通过WEXITSTATUS(status)获取子进程的退出状态(exit status)。
WIFSIGNALED(status)
若子进程由信号杀死,该宏返回true。
此时,可以通过WTERMSIG(status)获取使子进程终止的信号值。
WIFSTOPPED(status)
若子进程被信号暂停(stopped),该宏返回true。
此时,可以通过WSTOPSIG(status)获取使子进程暂停的信号值。
WIFCONTINUED(status)
若子进程通过SIGCONT恢复,该宏返回true。
实例:
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
#include <sys/wait.h>
int main()
{
pid_t pid = fork();
switch (pid)
{
case -1://发生错误
perror("fork");
return -1;
case 0://子进程
printf ("我是子进程,ID:%d\n", getpid());
while(1);//让子进程不退出,可用第二个终端杀死进程
default://父进程
printf("等待子进程GG\n");
int status;
pid_t childID = wait(&status);//处理僵尸进程
printf("成功处理一个子进程,ID:%d\n", childID);
if (WIFEXITED(status))
{
printf ("进程正常终止\n");//现在程序有死循环,没有正常终止
}
else
{
printf ("外部终端结束进程\n");
}
break;
}
return 0;
}
waitpid函数原型:pid_t waitpid (pid_t pid, int *status, int options);
功能:会暂时停止目前进程的执行,直到有信号来到或子进程结束
返回值:如果执行成功则返回子进程识别码(PID),如果有错误发生则返回-1。失败原因存于errno中。
参数:如果不在意结束状态值,则参数status可以设成NULL。
参数pid为欲等待的子进程识别码:
pid<-1 等待进程组识别码为pid绝对值的任何子进程。
pid=-1 等待任何子进程,相当于wait()。
pid=0 等待进程组识别码与目前进程相同的任何子进程。
pid>0 等待任何子进程识别码为pid的子进程。
参数option可以为0 或下面的OR 组合
WNOHANG: 如果没有任何已经结束的子进程则马上返回,不予以等待。
WUNTRACED :如果子进程进入暂停执行情况则马上返回,但结束状态不予以理会。
waitpid并不等待在其调用之后的第一个终止的子进程。它有若干个选项,可以控制它所等待的进程。
实例:
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
#include <sys/wait.h>
int main()
{
pid_t pid = fork();
switch (pid)
{
case -1:
perror ("fork");
break;
case 0:
printf ("我是子进程,ID:%d\n", getpid());
while(1);//不让子进程结束
exit(0);
default:
printf ("等待子进程GG\n");
int status;
pid_t childID = waitpid(pid, NULL, WNOHANG);//(等待特定的识别符为pid的子进程结束,不关注结束状态,不阻塞:子进程已结束就处理,未结束就不予处理,立即返回)
printf ("成功处理一个子进程,ID:%d\n", childID);
break;
}
return 0;
}