进程控制 wait() waitpid()演示 避免/消除僵尸进程 退出码

什么是进程等待?  进程等待函数介绍int wait(int *status);  int waitpid(pid_ t pid, int *status, int option);  代码演示


什么是进程等待?  

进程等待 : 等待子进程退出获取子进程的退出码释放子进程资源

为什么要进行进程等待避免子进程成为僵尸进程,僵尸进程会占用系统资源。如有很多,会严重影响服务器的性能;

僵尸进程 :子进程先于父进程退出,为了保存退出码,没有完全释放资源

进程等待分类 : 

        阻塞等待 : 为了完成一个功能,我们发起了一个调用,如果功能不能立即完成则一直等待

        非阻塞等待 : 为了完成一个功能,我们发起了一个调用,如果功能不能立即完成则函数立即报错返回。



进程等待函数介绍

int wait(int *status);

功能 : 阻塞等待任意一个子进程的退出。意味着如果当前有子进程且都没有退出就会阻塞进程一直等待。

参数 : int *status 指针 status 指向的空间用于存放退出码

返回值 : 成功则返回处理的退出的子进程的pid (>0) , 失败则返回 -1 (比如没有子进程)
 


int waitpid(pid_ t pid, int *status, int option);

功能 : 也是等待子进程退出,但是可以等待指定的子进程,可以进行阻塞 / 非阻塞等待

参数 : pid_ t pid :指定等待的子进程pid , 若为 -1则表示等待任意一个子进程

          int *status 整形空间地址用于获取退出码

          option 设置阻塞标志  0 表示阻塞等待  WNOHANG 表示非阻塞等待

返回值 : 大于0表示处理的退出子进程pid ; 等于0表示当前没有子进程退出(非阻塞) ; 小于0表示出错了;



代码演示

示例一

#include <stdio.h>
#include <sys/wait.h> //wait() waitpid()
int main()
{
   printf("wait start ----------\n");
   int status;
   int ret = wait(&status);
   //成功返回0 失败返回-1
   if(ret<0){
     perror("wait error"); 
     //perror函数输出 “括号中字符串:上一个程序执行失败的原因”
     return -1;
   }
   printf("wait end ----------\n");
   return 0;
}

执行结果: 

此时,由于父进程并没有属于自己的子进程,所以无法进行进程等待,返回 -1


示例二

#include <stdio.h>
#include<stdlib.h> //exit()                                                                                                                              
#include <unistd.h> //sleep() exit() fork()
#include <sys/wait.h> //wait() waitpid()
int main()
{
  pid_t pid = fork();
  if(pid < 0){
    perror("fork error"); //打印fork执行失败的原因
    return -1;
  }else if (pid == 0){
    sleep(3);
    exit(99); //3秒后子进程退出
  }
  //能走下来的只有父进程
  printf("wait start ----------\n");
  int status;
  int ret = wait(&status);//成功返回0 失败返回-1
  //int ret = waitpid(-1,&status,0);与上行代码等价
  if(ret < 0){
    perror("wait error");
    return -1;
  }
  printf("wait end ----------\n");
  return 0;
}

程序立刻输出:

三秒后执行结果为 :

 

 语句执行到wait( )处,开始进行进程阻塞等待,直到三秒后,子进程退出,等待退出。


示例三

#include<stdio.h>
#include<stdlib.h> //exit()
#include<unistd.h> //sleep() fork()
#include<sys/wait.h>
int main()
{
  pid_t pid = fork(); //创建一个子进程
  if(pid<0){
    perror("fork error");
    return -1;
  }else if(pid == 0){
    sleep(3);
    exit(99);
  }
  printf("wait start ----------\n");
  int status;
  //当子进程存在,但并未退出时,
  while(waitpid(-1,&status,WNOHANG) == 0){
    printf("have child ,have not exited ,waiting...\n");
    sleep(1);
  }                                                                      
  printf("wait end ----------\n");
}

运行结果


while中语句表示,当子进程存在但并未退出时,程序休眠一秒,一秒后再进行进程等待,直到子进程退出后,循环结束,进程等待也结束。

但如果子进程在休眠一秒中间退出,就意味着在下一次进程等待开始前,子进程成为了僵尸进程

因此,我们可以得出结论:
wait / waitpid 并不是仅处理刚好退出的子进程,也会处理已经成为僵尸进程的子进程
 

Status&退出码&异常信号

status是int类型,占四个字节,我们只用到后面两个字节,实际有效的也就是后两个字节

进程正常退出时,只用到后两个字节的高8位

 进程异常退出时,只用到后两个字节的低8位,其中第八位是coredump标志位(核心转储,表示程序异常退出前将自己的运行信息保存起来,便于事后调试),低7位表示进程收到的终止信号。

程序崩溃的本质:程序运行的过程中发生异常,系统内核检测到后会给进程发送一个异常信号,程序崩溃异常退出。

只有进程的异常信号为0时,表示程序正常退出;否则就表示异常退出。

    if (( status&0x7f) == 0){
      printf("child exit code:%d\n",(status>>8) & 0xff);
    }else{
      printf("signal code:%d\n",status & 0x7f );
    }

status & 0x7f 获取异常退出信号值

(status >> 8) & 0xff 获取退出码

实用接口
 

if( WIFEXITED(status) ){
   printf("child exit code : %d\n", WEXITSTATUS(status));
}

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值