Linux进程等待

目录

一、进程等待的原因

二、进程等待的方法

(一)wait方法

1. 定义

2. 进程等待能回收子进程的僵尸状态(wait方法验证)

3. 子进程没退出时,父进程在wait上进行阻塞等待,直到子进程僵尸,wait自动回收(wait) 

(二)waitpid方法

(三)获取子进程status

1. status结构

2. 我们不能对status整体使用

3. 正确使用

(四)图示说明父进程等待子进程的方式


一、进程等待的原因

  • 解决子进程僵尸问题带来的内存泄露的问题
  • 父进程为什么要创建子进程?要让子进程来完成任务。子进程任务完成的如何,父进程要不要知道?要知道(需要通过进程等待的方式),获取子进程退出的信息----两个数字(退出信号和退出码)----不是必须,但是系统需要提供这样的基础功能

二、进程等待的方法

(一)wait方法

1. 定义

#include
#include
pid_t wait(int*status);
返回值:
成功返回被等待进程pid,失败返回-1。
参数:
输出型参数,获取子进程退出状态,不关心则可以设置成为NULL

2. 进程等待能回收子进程的僵尸状态(wait方法验证)

#include    
#include//exit的头文件    
#include//fork头文件    
#include//pid_t类型的头文件    
#include//wait头文件    
    
void Worker()    
{    
    int cnt = 3;    
    while(cnt)    
    {    
        printf("I am child process, pid: %d, ppid: %d, cnt: %d\n",getpid(),getppid(),cnt--);    
        sleep(1);    
    }    
}    
int main()    
{    
    pid_t id = fork();    
    if(id == 0)//子进程    
    {    
        Worker();    
        exit(0);    
    }    
    else    
    {//父进程    
        sleep(5);    
        pid_t rid = wait(NULL);    
        if(rid == id)    
        {    
            printf("wait a process,pid: %d\n",getpid());    
        }    
        sleep(5);    
    }    
    return 0;    
} 

Linux进程等待_第1张图片

3. 子进程没退出时,父进程在wait上进行阻塞等待,直到子进程僵尸,wait自动回收(wait) 

#include    
#include//exit的头文件    
#include//fork头文件    
#include//pid_t类型的头文件    
#include//wait头文件    
    
void Worker()    
{    
    int cnt = 3;    
    while(cnt)    
    {    
        printf("I am child process, pid: %d, ppid: %d, cnt: %d\n",getpid(),getppid(),cnt--);    
        sleep(1);    
    }    
}    
int main()    
{    
    pid_t id = fork();    
    if(id == 0)//子进程    
    {    
        Worker();    
        exit(0);    
    }    
    else    
    {//父进程    
        printf("wait before!\n");//回收之前    
        pid_t rid = wait(NULL);    
        printf("wait after!\n");//回收之后    
        if(rid == id)    
        {    
            printf("wait a process,pid: %d\n",getpid());    
        }    
        sleep(5);    
    }    
    return 0;    
} 

Linux进程等待_第2张图片

(二)waitpid方法

pid_ t waitpid(pid_t pid, int *status, int options);
  • 返回值:当正常返回的时候waitpid返回收集到的子进程的进程ID;如果设置了选项WNOHANG,而调用中waitpid发现没有已退出的子进程可收集,则返回0;如果调用中出错,则返回-1,这时errno会被设置成相应的值以指示错误所在; 
  • pid 参数指定了要等待的子进程的进程ID。它可以取以下几个值:
    • -1:等待任意一个子进程,类似于 wait 函数。
    • 大于 0:等待指定进程ID的子进程。
  • status 是一个指向整型的指针,用于接收子进程的退出状态信息。如果子进程正常结束,会将退出状态信息存放在这个指针指向的位置。
  • status 的内容会被填充为一个整数,其中包含了子进程的退出状态信息。可以通过宏来解析这个整数,比如:
    • WIFEXITED(status):若为正常终止子进程返回的状态,则为真。(查看进程是否是正常退出)
    • WEXITSTATUS(status):若WIFEXITED非零,提取子进程退出码。(查看进程的退出码)
  • options 是一个整型参数,可以用来指定一些选项,比如 WNOHANG 可以使 waitpid 变为非阻塞调用。
  1. 如果子进程已经退出,调用wait/waitpid时,wait/waitpid会立即返回,并且释放资源,获得子进程退出信息。
  2. 如果在任意时刻调用wait/waitpid,子进程存在且正常运行,则进程可能阻塞。
  3. 如果不存在该子进程,则立即出错返回。

(三)获取子进程status

1. status结构

  • wait和waitpid,都有一个status参数,该参数是一个输出型参数由操作系统填充
  • 如果传递NULL,表示不关心子进程的退出状态信息
  • 否则,操作系统会根据该参数,将子进程的退出信息反馈给父进程。
  • status不能简单的当作整形来看待,可以当作位图来看待,具体细节如下图 

Linux进程等待_第3张图片

2. 我们不能对status整体使用

#include
#include//exit的头文件
#include//fork头文件
#include//pid_t类型的头文件
#include//wait头文件

void Worker()
{
    int cnt = 3;
    while(cnt)
    {
        printf("I am child process, pid: %d, ppid: %d, cnt: %d\n",getpid(),getppid(),cnt--);
        sleep(1);
    }
}
int main()
{
    pid_t id = fork();
    if(id == 0)//子进程
    {
        Worker();
        exit(10);
    }
    else
    {//父进程
        printf("wait before!\n");//回收之前
        int status;
        pid_t rid = waitpid(id, &status,0);
        printf("wait after!\n");//回收之后
        if(rid == id)
        {                                                                                                     
            printf("wait a process,pid: %d, status: %d\n",getpid(),status);
        }
        sleep(5);
    }
    return 0;
}

Linux进程等待_第4张图片

3. 正确使用

#include    
#include//exit的头文件    
#include//fork头文件    
#include//pid_t类型的头文件    
#include//wait头文件    
    
void Worker()    
{    
    int cnt = 3;    
    while(cnt)    
    {    
        printf("I am child process, pid: %d, ppid: %d, cnt: %d\n",getpid(),getppid(),cnt--);    
        sleep(1);    
    }    
}    
int main()    
{    
    pid_t id = fork();    
    if(id == 0)//子进程    
    {    
        Worker();    
        exit(10);    
    }    
    else    
    {//父进程    
        printf("wait before!\n");//回收之前    
        int status;    
        pid_t rid = waitpid(id, &status,0);    
        printf("wait after!\n");//回收之后    
        if(rid == id)    
        {//我们不能对status整体使用    
            printf("wait a process,pid: %d, rpid: %d, exit sig: %d, exit code: %d\n",getpid(),rid, status&0x7F, (status>>8)&0xFF);    
        }    
        sleep(5);    
    }    
    return 0;    
}   

Linux进程等待_第5张图片

(四)图示说明父进程等待子进程的方式

Linux进程等待_第6张图片

Linux进程等待_第7张图片

你可能感兴趣的:(Linux,linux,算法,运维)