• 函数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. 测试代码

     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
    ", getpid());
    14         sleep(10);
    15         printf("---------child die --------------
    ");
    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
    ", getpid(), pid);
    28             sleep(1);
    29         }
    30     } 
    31     else 
    32     {
    33         perror("fork");
    34         return 1;
    35     } 
    36     return 0;   
    37 }

    输出结果

    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
    ", 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
    ", WTERMSIG(status)); //是否被信号杀死
    19         
    20         printf(" die child pid = %d
    ", wpid);
    21     }
    22     else if(pid == 0) 
    23     {
    24         sleep(1);
    25         printf("child process, pid = %d, ppid = %d
    ", getpid(), getppid());    
    26     }
    27     for (int i = 0; i<5; ++i) 
    28         printf(" i = %d
    ", i);
    29     return 9;
    30 }

    输出结果:

    3. 测试代码:

     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
    ", 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
    ", WTERMSIG(status)); //是否被信号杀
    19  
    20         printf(" die child pid = %d
    ", wpid);
    21     }
    22     else if (pid == 0) 
    23     {
    24         while(1) 
    25         {
    26            sleep(1);
    27            printf("child process, pid = %d, ppid = %d
    ", getpid(), getppid()); 
    28         }        
    29     }
    30     for (int i = 0; i<5; ++i) 
    31         printf(" i = %d
    ", 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:函数阻塞。
  • 相关阅读:
    软件开发流程
    开心一笑 项目的开发和升级(转载知乎)
    转载编程之美
    etc/hosts文件详解
    自己centos7成功的修改了主机名(记录了该改哪些文件)
    CentOS7修改主机名的三种方法
    /etc/hosts文件修改后如何生效
    如何在Linux中显示和设置主机名(适用ubantu、centos等版本)
    Linux centos7 shell 介绍、 命令历史、命令补全和别名、通配符、输入输出重定向
    hadoop学习笔记(四):HDFS文件权限,安全模式,以及整体注意点总结
  • 原文地址:https://www.cnblogs.com/sunbines/p/10263614.html
Copyright © 2020-2023  润新知