• 【Linux】浅谈进程等待


    前言

    前面我们说明了进程等待的必要性,父进程通过进程等待,来回收子进程的资源,并且得知子进程的运行状态,下面我们接着谈谈wait和waitpid


    我们先看看wait和waitpid的函数声明

    1. #include /* 提供类型pid_t的定义*/
    2. #include
    3. int wait(int *status)
    1. #include
    2. #include
    3. 定义函数 pid_t waitpid(pid_t pid,int * status,int options);

    这两个函数有相似的功能,我们以waitpid来举例说明

    waitpid一共有三个参数

    第一参数pid,它通常有两种赋值方式,-1,和pid > 0

    -1就是等待该进程的任意一个子进程

    > 0就是等待特定的进程,这个特定的进程也就是我们所要填入的pid值

    第二个参数是status,它是一个输出型参数,主要是用来获取子进程的状态信息

    如果子进程是正常跑完了它的代码,那么它的退出码是有意义的

    如果子进程遇到了崩溃等其它情况,使它的代码没有跑完,那么它的退出码就没有意义,这时我们要看它的退出信号

    上一篇文章已经说明过一种获取进程退出码和退出信号的方法了

    接下来我们再说明另一种更加优雅的方式获取进程状态信息

    使用两个宏函数来解决

    WIFEXITED(status)
    

    这个是用来检测子进程是否正常退出的,如果为true证明子进程是正常退出的,反之就没有正常退出

    另一个宏函数是

    WEXITSTATUS(status)

    这个宏是用来获取子进程的退出码的

    第三个参数options它也有两种赋值方式,0和WNOHANG

    它默认是0,0代表着父进程阻塞式的等待子进程

    换句话说是父进程不能再执行其它代码直到等待子进程退出

    在操作系统上说是父进程被操作系统从运行队列上换下,放到阻塞队列或者等待被操作系统调度

    这种方法是十分的不好的,创建子进程就没有什么意义了

    另一种赋值方式就是WNOHANG这种方法就十分的好

    它会检测子进程的退出状态,如果返回的是子进程的pid证明子进程已经退出

    返回值是0证明子进程没有退出,还在运行

    返回值是-1证明出错了

    根据上面的解释也就是说,如果waitpid填入的是WNOHANG父进程调用一次检测一次子进程的状态,所以我们要不停的检测直到子进程退出或者其它情况。

    在下一次调用waitpid的间隙,我们可以让父进程进行其他任务

    下面有一个小例子

    1. #include
    2. #include
    3. #include
    4. #include
    5. #include
    6. #include
    7. using namespace std;
    8. typedef void (*handler_t)();
    9. std::vector<handler_t> handlers;
    10. void func_one()
    11. {
    12. std::cout << "这是临时任务1" << std::endl;
    13. }
    14. void func_two()
    15. {
    16. std::cout << "这是临时任务2" << std::endl;
    17. }
    18. void Load()
    19. {
    20. handlers.push_back(func_one);
    21. handlers.push_back(func_two);
    22. }
    23. int main()
    24. {
    25. pid_t id = fork();
    26. if(id < 0)
    27. {
    28. perror("fork");
    29. exit(1);
    30. }
    31. }
    32. else if(id == 0)
    33. {
    34. int cnt = 5;
    35. while(cnt--)
    36. {
    37. cout << "我是子进程" << cnt << getpid() << endl;
    38. sleep(1);
    39. }
    40. }
    41. else
    42. {
    43. int status = 0;
    44. int quit = 0;
    45. cout << "我是父进程" << endl;
    46. while(!quit)
    47. {
    48. cout << "父进程等待子进程中" << endl;
    49. pid_t res = waitpid(-1, &status, WNOHANG);
    50. if(res > 0)
    51. {
    52. cout << "等待子进程成功" << endl;
    53. cout << "子进程退出码为" << WEXITSTATUS(status) << endl;
    54. quit = 1;
    55. }
    56. else if(res == 0)
    57. {
    58. cout << "子进程还在运行" << endl;
    59. if(handlers.empty())
    60. {
    61. Load();
    62. }
    63. for(auto iter : handlers)
    64. {
    65. iter();
    66. }
    67. }
    68. else
    69. {
    70. cout << "出错了" << endl;
    71. quit = 1;
    72. exit(1);
    73. }
    74. sleep(1);
    75. }
    76. }
    77. return 0;
    78. }


     

    总结


    以上就是今天要讲的内容,本文仅仅简单介绍了waitpid的使用。

  • 相关阅读:
    热重分析(TGA)真空试验中的真空度精密控制解决方案
    如何写一份全面、易读的交互说明文档
    Vim实用技巧_7.模式匹配和查找
    html 笔记:CSS
    Java(98)Java执行时,报错Unsupported major.minor version 52.0
    高等数学教材啃书汇总重难点(二)导数与微分
    Learning an Animatable Detailed 3D Face Model from In-The-Wild Images论文笔记
    美团悄悄上线社群团购“团买买”
    三显智能氮气柜温度、湿度和氧含量控制介绍
    【算法模板】图论:最近公共祖先(LCA)
  • 原文地址:https://blog.csdn.net/m0_62179366/article/details/126955364