Linux进程等待(上)
💦 进程等待的必要性
之前讲过,子进程退出,父进程如果不管不顾,就可能造成 “ 僵尸进程 ” 的问题,进而造成内存泄漏。另外,进程一旦变成僵尸状态,那就刀枪不入,“ 杀人不眨眼 ” 的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 能否看到僵尸进程是不确定的。因为父进程退出,子进程会被操作系统领养。那么这个僵尸进程是在被操作系统领养后立马回收,还是积累到一定的僵尸进程再回收,这是由操作系统的策略决定的,同时也跟当前操作系统的状态有关系,如果操作系统发现内存资源已经很紧张了,就会提前回收。
父进程是如何知道子进程的退出结果呢 ❓
- 点赞
 - 收藏
 - 关注作者
 
            
           
评论(0)