一个zombie进程也成过渡进程,是指已结束运行,但尚未被清除的进程。当使用fork建立子进程时,由于子进程有可能会比父进程晚结束,子进程有可能会成为zombie进程。为避免这种情况发生可以在父进程中调用wait()函数或waitpid()函数使子进程先结束,而让父进程有机会了解子进程结束时的状态,并自动清除zombie进程。
wait(等待子进程中断或结束) 相关函数 waitpid,fork 表头文件 #include<sys/types.h> #include<sys/wait.h> 定义函数 pid_t wait (int * status); 函数说明 wait()会暂时停止目前进程的执行,直到有信号来到或子进程结束。如果在调用wait()时子进程已经结束,则wait()会立即返回子进程结束状态值。子进程的结束状态值会由参数status 返回,而子进程的进程识别码也会一起返回。如果不在意结束状态值,则参数status 可以设成NULL。子进程的结束状态值请参考下面的waitpid()。 返回值 如果执行成功则返回子进程识别码(PID),如果有错误发生则返回-1。失败原因存于errno 中。
WIFEXITED(status)如果子进程正常结束则为非0值。
WEXITSTATUS(status)取得子进程exit()返回的结束代码,一般会先用WIFEXITED 来判断是否正常结束才能使用此宏。
WIFSIGNALED(status)如果子进程是因为信号而结束则此宏值为真
WTERMSIG(status)取得子进程因信号而中止的信号代码,一般会先用WIFSIGNALED 来判断后才使用此宏。
WIFSTOPPED(status)如果子进程处于暂停执行情况则此宏值为真。一般只有使用WUNTRACED 时才会有此情况。
WSTOPSIG(status)取得引发子进程暂停的信号代码,
waitpid(等待子进程中断或结束)
相关函数 wait,fork
表头文件
#include<sys/types.h>
#include<sys/wait.h>
定义函数 pid_t waitpid(pid_t pid,int * status,int options);
函数说明
waitpid()会暂时停止目前进程的执行,直到有信号来到或子进程结束。如果在调用waitpid()时子进程已经结束,则waitpid()会立即返回子进程结束状态值。子进程的结束状态值会由参数status 返回,而子进程的进程识别码也会一快返回。如果不在意结束状态值,则参数status 可以设成NULL。参数pid 为欲等待的子进程识别码,其他数值意义如下:
pid<-1 等待进程组识别码为pid 绝对值的任何子进程。
pid=-1 等待任何子进程,相当于wait()。
pid=0 等待进程组识别码与目前进程相同的任何子进程。
pid>0 等待任何子进程识别码为pid 的子进程。
参数option 可以为0 或下面的OR 组合:
WNOHANG 如果没有任何已经结束的子进程则马上返回,不予以等待。WUNTRACED 如果子进程进入暂停执行情况则马上返回,但结束状态不予以理会。
子进程的结束状态返回后存于status,底下有几个宏可判别结束情
况:
WIFEXITED(status)如果子进程正常结束则为非0 值。
WEXITSTATUS(status)取得子进程exit()返回的结束代码,一
般会先用WIFEXITED 来判断是否正常结束才能使用此宏。
WIFSIGNALED(status)如果子进程是因为信号而结束则此宏值为
真
WTERMSIG(status) 取得子进程因信号而中止的信号代码,一般
会先用WIFSIGNALED 来判断后才使用此宏。
WIFSTOPPED(status) 如果子进程处于暂停执行情况则此宏值为
真。一般只有使用WUNTRACED 时才会有此情况。
WSTOPSIG(status) 取得引发子进程暂停的信号代码,一般会先
用WIFSTOPPED 来判断后才使用此宏。
返回值
如果执行成功则返回子进程识别码(PID),如果有错误发生则返回
-1。失败原因存于errno 中。
#include<stdio.h>
#include<stdlib.h>
#include<sys/wait.h>
#include<sys/types.h>
void disp0();
void disp1();
void disp2();
int mymax(int ,int);
int main(void)
{
pid_t child;
int status,ans;
void (*fun[3])();
int (*pm)(int x,int y);
int num1,num2,num3,max_num;
fun[0]=disp0;
fun[1]=disp1;
fun[2]=disp2;
pm=mymax;
printf("是否复制进程?(1: yes,2:No)");
scanf("%d",&ans);
if(ans==1)
{
child=fork();
if(child==-1)
{
perror("fork error");
exit(1);
}
}
if(child==0)
{
puts("这是子进程...");
printf("\t 子进程 pid=%d\n",getpid());
printf("\t 子进程ppid=%d \n",getppid());
printf("要购买哪一种产品?(0:计算机 1:电视: 2:音箱)");
scanf("%d",&num3);
if(num3>=0&&num3<=2)
{
(*fun[num3])();
} exit(0);
}
else
{
waitpid(child,&status,0);
puts("这是父进程....");
printf(" \t 父进程 pid=%d\n",getpid());
printf("\t 父进程 ppid=%d \n",getppid());
printf("\t 子进程离开的状态: %d \n",WIFEXITED(status));
printf("输入第一个数值:");
scanf("%d",&num1);
printf("输入第二个数值:");
scanf("%d",&num2);
printf("输入第三个数值:");
scanf("%d",&num3);
max_num=(*pm)(num1,num2);
printf("最大值为 %d \n",max_num);
exit(0);
}
return 0;
}
int mymax(int x, int y)
{
if(x>y)
return x;
else
return y;
}
void disp0()
{
printf("您购买了计算机\n");
}
void disp1()
{
printf("您购买了电视\n");
}
void disp2()
{
printf("您购买了音箱\n");
}