Linux进程等待(上)

举报
跳动的bit 发表于 2022/08/30 07:58:08 2022/08/30
【摘要】 💦 进程等待的必要性之前讲过,子进程退出,父进程如果不管不顾,就可能造成 “ 僵尸进程 ” 的问题,进而造成内存泄漏。另外,进程一旦变成僵尸状态,那就刀枪不入,“ 杀人不眨眼 ” 的kill -9也无能为力,因为谁也没有办法杀死一个已经死去的进程。 最后,父进程派给子进程的任务完成的如何,我们需要知道。如,子进程运行完成,结果对还是不对,或者是否正常退出。父进程通过进程等待的方式,回收子...
💦 进程等待的必要性

之前讲过,子进程退出,父进程如果不管不顾,就可能造成 “ 僵尸进程 ” 的问题,进而造成内存泄漏。另外,进程一旦变成僵尸状态,那就刀枪不入,“ 杀人不眨眼 ” 的kill -9也无能为力,因为谁也没有办法杀死一个已经死去的进程。 最后,父进程派给子进程的任务完成的如何,我们需要知道。如,子进程运行完成,结果对还是不对,或者是否正常退出。父进程通过进程等待的方式,回收子进程资源,获取子进程退出信息。

  • 回收僵尸进程,避免内存泄漏。

  • 需要获取子进程的运行结束状态、结果。

    结束状态和结果不是必须的。注意区分运行状态和运行结果,两者是有区别的。

  • 尽量保证父进程要晚于子进程退出,可以规范化进行资源回收。

    将来我们写代码时,所有要做的事情都交给子进程,子进程把事办完了,由父进程统一回收。这点其实是与编码相关的策略,而并非属于系统级别的要求。

其实信号部分结束我们就可以知道有一种方案可以让父进程既不等子进程又没有内存泄漏。

💦 进程等待的方法
1、wait方法
#include<sys/types.h>
#include<sys/wait.h>

pid_t wait(int* status);

返回值:
	成功则返回被等待进程的pid,失败则返回-1。
参数:
	输出型参数,获取子进程退出状态,不关心则可以设置为NULL。wait 的参数 int* status 会重点在下面的 waitpid 学习。

✔ 测试用例一:

父进程等待子进程退出后,wait 取子进程的 pid。

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

int main()
{
    pid_t id = fork();
    if(id < 0)
    {
        perror("fork");
        return 1;
    }
    else if(id == 0)
    {
        int count = 5;
        while(count)
        {
            printf("child is running: %d, ppid: %d, pid: %d\n", count--, getppid(), getpid());
            sleep(1);
        }                                                                                     
        printf("child quit...\n");
        exit(0);
    }
    else
    {
        printf("father is waiting...\n");
        pid_t ret = wait(NULL);
        printf("father is wait done, ret: %d\n", ret);
    }
    return 0;
} 

💨运行结果:

请添加图片描述

✔ 测试用例二:

相比测试用例一,更直观的等待,进程从无到有,从有到无。

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

int main()
{
    pid_t id = fork();
    if(id < 0)
    {
        perror("fork");
        return 1;
    }
    else if(id == 0)
    {
        int count = 5;
        while(count)
        {
            printf("child is running: %d, ppid: %d, pid: %d\n", count--, getppid(), getpid());
            sleep(1);
        }                                                                                     
        printf("child quit...\n");
        exit(0);
    }
    else
    {
        printf("father is waiting...\n");
        sleep(10);
        pid_t ret = wait(NULL);
        printf("father is wait done, ret: %d\n", ret);
        sleep(3);
        printf("father quit...\n");
    }
    return 0;
} 

💨运行结果:

  监控脚本:while :; do ps ajx | head -1 && ps ajx | grep process | grep -v grep; sleep 1; echo "####################"; done

请添加图片描述

✔ 测试用例三:

fork 5 个子进程后,父进程依次等待,并回收僵尸进程。

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

int main()
{
    int i = 0;
    while(i < 5)
    {    
        pid_t id = fork();
        if(id < 0)
        {
            perror("fork");
            return 1;
        } 
        if(id == 0)
        {
            int count = 5;
            while(count)
            {
                printf("child is running: %d, ppid: %d, pid: %d\n", count--, getppid(), getpid());
                sleep(1);
            }                                                                                     
            printf("child quit...\n");
            exit(0);        
        }
        i++;
    }
    for(i = 0; i < 5; i++)
    { 
        printf("father is waiting...\n");
        sleep(10);
        pid_t ret = wait(NULL);
        printf("father is wait done, ret: %d\n", ret);
        sleep(3);
        printf("father quit...\n");
    } 
    return 0;
}                                                                                                      

💨运行结果:

请添加图片描述

子进程僵尸了,父进程也退出了 ❓

  此时 ps ajx 能否看到僵尸进程是不确定的。因为父进程退出,子进程会被操作系统领养。那么这个僵尸进程是在被操作系统领养后立马回收,还是积累到一定的僵尸进程再回收,这是由操作系统的策略决定的,同时也跟当前操作系统的状态有关系,如果操作系统发现内存资源已经很紧张了,就会提前回收。

父进程是如何知道子进程的退出结果呢 ❓

  

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。