等待进程结束wait

41 篇文章 0 订阅

等待进程结束(p133)

孤儿进程

  • 父进程先于子进程结束,此时子进程成为孤儿进程,但操作系统会将子进程的父进程设为init进程

僵尸(死)进程(zombie)

  • 子进程终止,父进程没有回收子进程,子进程残留资源pcb存放于内核中,变成僵死进程。
  • 僵死进程不能用kill命令清除,因为kill命令是用来终止进程的。

wait函数

  • 一个进程在终止时会关闭所有文件描述符,释放在用户空间分配的内存,但它的PCB还保留着,内核在其中保存了一些信息:如果是正常终止则保存着退出状态,如果是异常终止则保存着导致该进程终止的信号是哪个。
  • 这个进程的父进程可以调用wait 或 waitpid获取这些信息,然后彻底清除掉这个进程。我们知道一个进程的退出状态可
    以在Shell中用特殊变量$?查看,因为Shell是它的父进程,当它终止时Shell 调用wait 或waitpid.得到它的退出状态,同时彻底清除掉这个进程。
  • 父进程调用wait函数可以回收子进程终止信息。该函数有三个功能:
    阻塞等待子进程退出
    ②回收子进程残留资源
    ③获取子进程结束状态(退出原因)
  • 父进程执行wait函数之后,父进程会被阻塞在此处,如果子进程状态发生变化,则wait函数会立即返回结果;否则wait函数会一直阻塞直到子进程状态发生变化。
#include<sys/types.h>
#include<sys/wait.h>
pid_t wait(int *status);

status:子进程结束时返回的终止状态(子进程是怎么结束的)
status是一个传出参数
如果父进程不关心子进程的状态,向wait中传入NULL
功能:等待子进程结束(阻塞等待)
成功:返回子进程的pid,失败:返回-1

扩展:使用一次wait只回收一个子进程,循环使用wait可回收多个子进程
  • status:子进程结束时返回的终止状态,这个状态值为一个整数,可以通过宏获取进程的终止状态信息,如下:
    1.WIFEXITED[wifexited] (status):如果子进程正常终止,返回true
    2.WEXITSTATUS[wexitstatus] (status):如果1为真,返回子进程的退出状态(exit的参数)
    3.WIFSIGNALED[wifsignaled] (status):如果子进程被某个信号终止(异常终止),返回true
    4.WTERMSIG[wtermsig] (status):如果3为真,返回终止进程的那个信号的编号
  1 #include<stdio.h>
  2 #include<unistd.h>
  3 #include<stdlib.h>
  4 #include<sys/wait.h>
  5 
  6 void main()
  7 {
  8         int status;
  9         pid_t pid = fork();
 10         if(pid == -1)
 11         {
 12                 perror("fork error:");
 13                 exit(1);
 14         }
 15         else if(pid == 0)
 16         {
 17                 printf("我是子进程!!!听歌\n");
 18                 sleep(40);
 19                 printf("chilrd is died\n");
 20         }
 21         else if(pid >0)
 22         {
 23                 printf("I am father,waitting for child\n");
 24                 pid_t wpid = wait(&status);
 25                 if(wpid == -1)
 26                 {
 27                         perror("wait error:");
 28                         exit(1);
 29                 }
 30                 else if(WIFEXITED(status))
 31                 {
 32                         printf("child process is normally stop    ed:%d\n",WEXITSTATUS(status));
 33                 }
 34                 else if(WIFSIGNALED(status))
 35                 {
 36                         printf("child process is abnormally st    oped:%d\n",WTERMSIG(status));
 37                 }
 38         }
 39 
 40 }

waitpid函数

#include<sys/types.h>
#include<sys/wait.h>
pid_t waitpid(pid_t pid,int *status,int options);

功能:等待指定的子进程结束
pid:要等待子进程的pid
status:子进程结束时返回的终止状态(同wait函数中的介绍)
options:等待方式
返回值:结束子进程的pid

if pid>0,等待进程id为要等待的子进程的pid
if pid==0,回收本组的子进程
if pid==-1,与wait等效
if pid<-1,回收指定组的子进程

options的取值:
1.WNOHANG:非阻塞式,如果子进程没有退出,waitpid返回0
如果子进程退出,则回收子进程
2.WUNTRACED:,用于调试,子进程退出时返回。
3.0:阻塞,waitpid(-1,&status,0) == wait(&status);
  • 当进程终止时,操作系统的隐式回收机制会:1.关闭所有文件描述符2.释放用户空间分配的内存。内核的PCB仍存在。其中保存该进程的退出状态。(正常终止一退出值;异常终止一终止信号)
这个程序有问题
#include<sys/types.h>
#include<unistd.h>
#include<stdlib.h>
#include<sys/wait.h>
#include<stdio.h>
#include<math.h>

int main()
{
        int n = 5,i,status;
        pid_t wpid;
        for(i = 0;i < 5;i++)
        {
                pid_t pid = fork();
                if(pid == 0)
                {
                        break;
                }

        }
        if(i != n)
        {
                sleep(i);
                printf("i am [%d]child,my pid is:%d\n",i,getpid());
        }
        else
        {
                sleep(n);
                printf("i am father,my pid is:%d\n",getpid());

        }
        do{
                wpid = waitpid(-1,&status,WNOHANG);
                printf("wpid = %d\n",wpid);
                if(wpid == -1)
                {
                        perror("waitpid error:");
                        exit(1);
                }
                if(wpid>0)
                {
                        printf("[%d]child is over,mypid is:%d\n",abs(n-5),getpid());问题在这里,为什么输出的pid是父进程的?
                        n--;
                        if(WIFEXITED(status))
                        {
                                printf("normal end:%d\n",WEXITSTATUS(status));
                        }
                        else if(WIFSIGNALED(status))
                        {
                                printf("abnormal end:%d\n",WTERMSIG(status));
                        }
                }
                else
                {
                        printf("[%d]child is not over\n",abs(n-5));
                        if(WIFEXITED(status))
                        {
                                printf("normal end:%d\n",WEXITSTATUS(status));
                        }
                        else if(WIFSIGNALED(status))
                        {
                                printf("abnormal end:%d\n",WTERMSIG(status));
                        }
                }

                sleep(1);
        }while(n>0);
        return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值