子进程得回收

子进程的回收:
#include<sys/wait.h>
pid_t wait(int *status)
功能:(阻塞函数)等待并回收任意子进程
参数:status 用于输出子进程的终止状态,可置NULL
返回值:成功返回所回收的子进程的PID,失败返回-1

父进程在创建若干自己进程以后调用wait函数:
A.若所有子进程都在进行,则阻塞,知道有子进程终止才返回
B.若有一个子进程已终止,则返回该子进程的PID并通过status参数输出其终止状态
C.若没有任何可被等待并回收的子进程,则返回-1,置erroe为ECHILD

wait函数主要完成三个任务
1.阻塞父进程的运行,直到子进程终止在继续,停等同步
2.获取子进程的PID和终止状态,令父进程得知谁因何而死
3.为子进程收尸,防止大量僵尸进程耗费系统资源
以上三个任务中,即使前两个与具体需求无关,仅仅第三个也足以
凸显wait哈桑农户的重要性,尤其是对那些多进程服务器型的应用而言

子进程的终止状态通过wait函数的status参数输出给该函数调用者。<sys/wait.h>头文件提供了
几个辅助分析进程终止状态的工具宏
WIFEXITED(status)
真:正常终止  WEXITSTATUS(status)->进程退出码
假:异常终止  WTERMSIG(status)->终止进程的信号
WIFSIGNALED(status)
真:异常终止  WTERMSIG(status)->终止进程的信号
假:正常终止  WEXITSTATUS(status)->进程退出码
 

#include<stdio.h>
#include<sys/wait.h>
#include<unistd.h>
#include<stdlib.h>

int main()
{
    pid_t pid =fork();
    if(pid == -1)
    {
        perror("fork");
        return -1;
    }

    if(pid == 0)
    {
        printf("子进程%d\n",getpid());
        //sleep(4);
        //return 330;//正常终止
        //exit(300);
        //_exit(300);
        //_EXIT(300);
        abort();//异常终止
    }

    int status;//输出回收的子进程的终止状态
    pid_t wait_pid = wait(&status);
    if(wait_pid == -1)
    {
        perror("wait");
        return -1;
    }
    printf("status = %d\n",status);
    printf("父进程%d\n",getpid());
    if(WIFEXITED(status))
    {
        printf("正常终止 退出码:%d\n",WEXITSTATUS(status));
    }
    else
    {
        printf("异常终止 信号:%d\n",WTERMSIG(status));
    }
    return 0;
}


子进程90815
status = 18944
父进程90814
正常终止 退出码:74

子进程90835
status = 6
父进程90834
异常终止 信号:6

//创建多个子进程  父进程回收
#include<stdio.h>
#include<stdlib.h>
#include<sys/wait.h>
#include<unistd.h>
#include<errno.h>
int main()
{
    //创建多个子进程
    for(int i =0;i<5;i++)
    {
        pid_t pid = fork();
        if(pid ==-1)
        {
            perror("fork");
            return -1;
        }
        if(pid ==0)
        {
            printf("子进程:%d\n",getpid());
            sleep(i+1);
            return i;
        }
    }
    //父进程回收多个子进程
    while(1)
    {
        int status;
        pid_t wait_pid =wait(&status);
        if(wait_pid ==-1)
        {
            if(errno == ECHILD)
            {
                printf("没有子进程\n");
                break;
            }
            else
            {
                perror("wait");
                return -1;
            }
        }
        printf("%d回收%d进程的僵尸\n",getpid(),wait_pid);
        if(WIFEXITED(status))
        {
            printf("正常终止 退出码:%d\n",WEXITSTATUS(status));
        }
        else
        {
            printf("异常终止 信号:%d\n",WTERMSIG(status));
        }
    }
    
    return 0;
}

子进程:90972
子进程:90971
子进程:90975
子进程:90973
子进程:90974
90970回收90971进程的僵尸
正常终止 退出码:0
90970回收90972进程的僵尸
正常终止 退出码:1
90970回收90973进程的僵尸
正常终止 退出码:2
90970回收90974进程的僵尸
正常终止 退出码:3
90970回收90975进程的僵尸
正常终止 退出码:4
没有子进程
//回收特定子进程
#include<stdio.h>
#include<sys/wait.h>
#include<unistd.h>

int main()
{
    printf("父进程:%d\n",getpid());
    int pid_arr[5] ={};
    for(int i= 0;i < 5;i++)
    {
        pid_arr[i] = fork();
        if(pid_arr[i] ==-1)
        {
            perror("fork");
            return -1;
        }
        if(pid_arr[i] == 0)
        {
            printf("子进程:%d\n",getpid());
            sleep(i+1);
            return 0;
        }
    }
    //父进程回收子进程
    for(int i =4;i>=0;i--)
    {
        printf("我是%d父进程,我要回收%d子进程\n",getpid(),pid_arr[i]);
        //阻塞方式回收子进程
        pid_t wait_pid = waitpid(pid_arr[i],NULL,0);
        if(wait_pid == -1)
        {
            perror("waitpid");
            return -1;
        }
        printf("%d父进程回收%d子进程\n",getpid(),wait_pid);

    }
    return 0;
}

父进程:91906
子进程:91907
子进程:91908
子进程:91910
我是91906父进程,我要回收91911子进程
子进程:91909
子进程:91911
91906父进程回收91911子进程
我是91906父进程,我要回收91910子进程
91906父进程回收91910子进程
我是91906父进程,我要回收91909子进程
91906父进程回收91909子进程
我是91906父进程,我要回收91908子进程
91906父进程回收91908子进程
我是91906父进程,我要回收91907子进程
91906父进程回收91907子进程
//非阻塞方式回收子进程
#include<stdio.h>
#include<errno.h>
#include<sys/wait.h>
#include<stdlib.h>
#include<unistd.h>

int main()
{
    pid_t pid = fork();
    if(pid == -1)
    {
        perror("fork");
        return -1;
    }
    if(pid == 0)
    {
        printf("子进程%d\n",getpid());
        sleep(5);
        return 0;
    }

    while(1)
    {
        pid_t pid = waitpid(-1,NULL,WNOHANG);
        if(pid == -1)
        {
            if(errno == ECHILD)
            {
                printf("没有子进程了\n");
                break;
            }
            else
            {
                perror("waitpid");
                return -1;
            }
        }
        else if(pid == 0)//非阻塞回收时,要回收的子进程在运行
        {
            printf("子进程正在运行,一会再来回收\n");
        }
        else
        {
            printf("回收了%d进程的僵尸\n",pid);
        }
    }

    
    return 0;
}

子进程正在运行,一会再来回收
子进程正在运行,一会再来回收
子进程正在运行,一会再来回收
子进程正在运行,一会再来回收
子进程正在运行,一会再来回收
子进程正在运行,一会再来回收
子进程正在运行,一会再来回收
子进程正在运行,一会再来回收
子进程正在运行,一会再来回收
回收了91875进程的僵尸
没有子进程了

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
SIGCHLD信号是在一个子进程结束运行后,向其父进程发送的一个信号。这个信号可以让父进程知道子进程已经结束,从而可以回收子进程的资源。 当一个子进程结束时,操作系统会向其父进程发送SIGCHLD信号。父进程可以通过调用wait()或waitpid()函数来回收子进程的资源。在父进程中,可以通过设置一个信号处理函数来处理SIGCHLD信号,以便在子进程结束时自动回收资源。 下面是一个使用waitpid()函数来回收子进程资源的示例代码: ```c #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/wait.h> int main() { pid_t pid = fork(); if (pid == 0) { // 子进程 printf("child process\n"); exit(0); } else if (pid > 0) { // 父进程 printf("parent process\n"); int status; waitpid(pid, &status, 0); // 回收子进程资源 if (WIFEXITED(status)) { printf("child process exited with code %d\n", WEXITSTATUS(status)); } } else { // fork失败 perror("fork"); exit(1); } return 0; } ``` 在上面的代码中,父进程调用waitpid()函数来等待子进程结束,并回收子进程的资源。如果子进程正常结束,父进程就可以通过WIFEXITED(status)函数判断子进程是否正常结束,并通过WEXITSTATUS(status)函数获取子进程的退出码。 需要注意的是,如果父进程没有调用wait()或waitpid()函数来回收子进程的资源,那么子进程就会成为一个僵尸进程,占用系统资源。因此,在父进程中一定要及时回收子进程的资源。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值