函数wait、函数waitpid

函数wait

一个进程在终止时会关闭所有文件描述符,释放在用户空间释放的内存,但它的PCB还保留着,内核在其中保存一些信息:如果是正常终止时则保存着退出状态,如果是异常终止则保存着导致该进程终止的信号是哪个,这个进程的父进程可以调用wait或waitpid获取这些信息,然后彻底清除这个进程,我们知道一个进程的退出状态可以在shell用特殊变量$?查看,因为shell是它的父进程,当它终止时shell调用wait或waitpid得到它的退出状态同时彻底清除这个进程。

1. 函数wait:一次只能回收一个子进程

pid_t wait(int *status);   status传出参数

进程终止时,操作系统隐式回收机制会:1. 关闭所有的文件描述符 2. 释放用户空间分配的内存。内核PCB仍存在,其中保存该进程的退出状态。(正常终止--------退出值;异常终止-------终止信号)

 

可使用wait函数传出参数status来保存进程的退出状态,借助宏函数来进一步判断进程终止的具体原因,宏函数可分为三组:

  1. WIFEXITED(status):为非0,进程正常结束;WEXITSTATUS(status) :如上宏为真,使用此宏  获取进程退出状态(exit的参数)
  2. WIFSIGNALED(status):为非0,进程异常终止;WTERMSIG(status):如上宏为真,使用此宏  获取进程终止的那个信号编号
  3. WIFSTOPPED(status) :为非0,进程处于暂停状;WSTOPSIG(status):如上宏为真,使用此宏  获取进程暂停的那个信号编号

 1. 测试代码

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

int main(int argc, const char* argv[])
{
    pid_t pid = fork();

    if (pid > 0)  // 父进程
    {
        printf("parent process, pid = %d, ppid = %d\n", getpid(), getppid());
        int status;
        pid_t wpid = wait(&status);

        if (WIFEXITED(status))
            printf("exit value: %d", WEXITSTATUS(status));
        if (WIFSIGNALED(status))
            printf("exit by signal: %d\n", WTERMSIG(status)); //是否被信号杀死

        printf(" die child pid = %d\n", wpid);
    }
    else if(pid == 0)
    {
        sleep(1);
        printf("child process, pid = %d, ppid = %d\n", getpid(), getppid());
    }
    for (int i = 0; i<5; ++i)
        printf(" i = %d\n", i);
    return 9;
}
 1 #include <stdio.h> 
 2 #include <stdlib.h>
 3 #include <unistd.h>
 4 #include <sys/wait.h>
 5  
 6 int main(void)
 7 {
 8     pid_t pid, wpid;
 9     pid = fork();
10     
11     if(pid == 0) 
12     {
13         printf("---child, my parent = %d, going to sleep 10s\n", getpid());
14         sleep(10);
15         printf("---------child die --------------\n");
16     } 
17     else if(pid > 0) 
18     {
19         wpid = wait(NULL);
20         if(wpid == -1) 
21         {
22             perror("wait error: ");
23             exit(1);
24         }
25         while(1)
26        {
27             printf("I am parent, pid = %d, my son = %d\n", getpid(), pid);
28             sleep(1);
29         }
30     } 
31     else 
32     {
33         perror("fork");
34         return 1;
35     } 
36     return 0;   
37 }
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>

int main(void)
{
    pid_t pid, wpid;
    pid = fork();

    if(pid == 0)
    {
        printf("---child, my parent = %d, going to sleep 10s\n", getpid());
        sleep(10);
        printf("---------child die --------------\n");
    }
    else if(pid > 0)
    {
        wpid = wait(NULL);
        if(wpid == -1)
        {
            perror("wait error: ");
            exit(1);
        }
        while(1)
       {
            printf("I am parent, pid = %d, my son = %d\n", getpid(), pid);
            sleep(1);
        }
    }
    else
    {
        perror("fork");
        return 1;
    }
    return 0;
}

输出结果

 

1. 测试代码:

 1 #include <stdio.h>
 2 #include <unistd.h>
 3 #include<sys/wait.h>
 4  
 5 int main(int argc, const char* argv[])
 6 {
 7     pid_t pid = fork();
 8  
 9     if (pid > 0)  // 父进程
10     {   
11         printf("parent process, pid = %d, ppid = %d\n", getpid(), getppid());
12         int status;
13         pid_t wpid = wait(&status);
14  
15         if (WIFEXITED(status))
16             printf("exit value: %d", WEXITSTATUS(status));
17         if (WIFSIGNALED(status)) 
18             printf("exit by signal: %d\n", WTERMSIG(status)); //是否被信号杀死
19         
20         printf(" die child pid = %d\n", wpid);
21     }
22     else if(pid == 0) 
23     {
24         sleep(1);
25         printf("child process, pid = %d, ppid = %d\n", getpid(), getppid());    
26     }
27     for (int i = 0; i<5; ++i) 
28         printf(" i = %d\n", i);
29     return 9;
30 }

输出结果:

 

3. 测试代码:

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

int main(int argc, const char* argv[])
{
    pid_t pid = fork();

    if (pid > 0)  //父进程
    {
        printf("parent process, pid = %d, ppid = %d\n", getpid(), getppid());
        int status;
        pid_t wpid = wait(&status);

        if (WIFEXITED(status))
            printf("exit value: %d", WEXITSTATUS(status));
        if (WIFSIGNALED(status))
            printf("exit by signal: %d\n", WTERMSIG(status)); //是否被信号杀

        printf(" die child pid = %d\n", wpid);
    }
    else if (pid == 0)
    {
        while(1)
        {
           sleep(1);
           printf("child process, pid = %d, ppid = %d\n", getpid(), getppid());
        }
    }
    for (int i = 0; i<5; ++i)
        printf(" i = %d\n", i);
    return 9;
}
 1 #include <stdio.h>
 2 #include <unistd.h>
 3 #include<sys/wait.h>
 4  
 5 int main(int argc, const char* argv[])
 6 {
 7     pid_t pid = fork();
 8  
 9     if (pid > 0)  //父进程
10     {
11         printf("parent process, pid = %d, ppid = %d\n", getpid(), getppid());
12         int status;
13         pid_t wpid = wait(&status);
14  
15         if (WIFEXITED(status)) 
16             printf("exit value: %d", WEXITSTATUS(status));
17         if (WIFSIGNALED(status)) 
18             printf("exit by signal: %d\n", WTERMSIG(status)); //是否被信号杀
19  
20         printf(" die child pid = %d\n", wpid);
21     }
22     else if (pid == 0) 
23     {
24         while(1) 
25         {
26            sleep(1);
27            printf("child process, pid = %d, ppid = %d\n", getpid(), getppid()); 
28         }        
29     }
30     for (int i = 0; i<5; ++i) 
31         printf(" i = %d\n", i);
32     return 9;
33 }

采取操作:

 54270  54286  54286  54270 pts/18    54286 S+    1000   0:00 ./test
 54286  54287  54286  54270 pts/18    54286 S+    1000   0:00 ./test
 54256  54288  54288  54256 pts/4     54288 R+    1000   0:00 ps ajx
sunbin@sunbin:~$ kill -9 54287

输出结果:

 

 

函数waitpid

函数waitpid原型:作用同wait,但可指定pid进程清理,可以不阻塞( 一次只能回收一个子进程)

pid_t wait(pid_t pid, int *staloc, int options);

1. 参数pid:

  • pid == -1:回收任一子进程
  • pid  >  0 :回收指定pid的进程
  • pid == 0 :回收与父进程同一个进程组的任一个子进程
  • pid < -1  :回收指定进程组内的任意子进程

2. 参数options:

  • 设置为WNOHANG:函数不阻塞;
  • 设置为0:函数阻塞。

 

posted @ 2019-01-13 19:08  苏格拉底的落泪  阅读(362)  评论(0编辑  收藏  举报