• 父进程循环创建三个子进程, 并用sigchld完成对子进程的回收


    1. #include <stdio.h>
    2. #include <stdlib.h>
    3. #include <string.h>
    4. #include <unistd.h>
    5. #include <sys/types.h>
    6. #include <sys/wait.h>
    7. #include <signal.h>
    8. //父进程循环创建三个子进程, 并用sigchld完成对子进程的回收
    9. /*
    10. 1. fork 循环3if()
    11. 2. 在父进程中注册信号处理函数,在子进程中睡眠,然后不同时间段退出
    12. 3. 设置未决信号集 , 阻塞信号集 , 将sigchld添加到阻塞信号集合中, 在完成信号注册后,解除对sigchld信号的阻塞. 这一步的目的是 : 为了防止父进程还没有完成对sigchld信号的注册, 子进程就结束了, 没有利用到sigchld回收子进程, 子进程就变成了僵尸进程
    13. sigset_t mask;
    14. sigemptyset(&mask);
    15. sigaddset(&mask , SIGCHLD);
    16. sigprocmask(SIG_BLOCK , &mask , NULL);
    17. //注册
    18. sigprocmask(SIG_UNBLOCK , &mask , NULL);
    19. 4. 注册信号处理函数的过程: 利用sigaction(SIGCHLD , )
    20. struct sigaction act;
    21. act.sa_handler = chld;
    22. sigemptyset(&act.sa_mask); //清空信号集中的信号
    23. act.sa_flags = 0;
    24. sigaction(SIGINT , &act , NULL);
    25. */
    26. void chld(int signo)
    27. {
    28. pid_t wpid;
    29. while(1)
    30. {
    31. wpid = waitpid(-1 , NULL , WNOHANG);
    32. if(wpid == 0 && wpid < 0) //子进程还活着 没子进程活着了
    33. {
    34. break;
    35. }else if(wpid>0) //子进程退出 返回子进程pid
    36. {
    37. printf("exit . child sig = [%d]\n" , wpid);
    38. }
    39. }
    40. }
    41. int main()
    42. {
    43. int i;
    44. sigset_t mask;
    45. sigemptyset(&mask);
    46. sigaddset(&mask ,SIGCHLD);
    47. sigprocmask(SIG_BLOCK , &mask , NULL);
    48. for(i=0; i<3; i++)
    49. {
    50. int pid = fork();
    51. if(pid < 0)
    52. {
    53. perror("fork error");
    54. }
    55. else if(pid > 0)
    56. {
    57. printf("father pid=[%d]\n", getpid());
    58. }
    59. else
    60. {
    61. printf("son pid = [%d]\n",getpid());
    62. break; //1. err1 这里应该break ,防止子进程创建子进程
    63. }
    64. }
    65. if(i==0)
    66. {
    67. printf("i==[%d], son pid = [%d]\n",i, getpid());
    68. sleep(1);
    69. }
    70. if(i==1)
    71. {
    72. printf("i==[%d], son pid = [%d]\n",i, getpid());
    73. sleep(2);
    74. }
    75. if(i==2)
    76. {
    77. printf("i==[%d], son pid = [%d]\n",i, getpid());
    78. sleep(1);
    79. }
    80. else if(i==3)
    81. {
    82. struct sigaction act;
    83. act.sa_handler = chld;
    84. sigemptyset(&act.sa_mask);
    85. act.sa_flags = 0;
    86. //这里加延时 是为了模拟: 父进程还没来得及注册信号处理函数 , 子进程就全部退出了的情形!
    87. sigaction(SIGCHLD , &act , NULL);
    88. sigprocmask(SIG_UNBLOCK , &mask ,NULL);
    89. while(1)
    90. {
    91. sleep(1); //sleep(1) 是为了防止空转速度过快
    92. }
    93. }
    94. return 0;
    95. }

    holo@holo:~/fwq$ ./sigchld
    father pid=[33860]
    son pid = [33861]
    i==[0], son pid = [33861]
    father pid=[33860]
    son pid = [33862]
    i==[1], son pid = [33862]
    father pid=[33860]
    son pid = [33863]
    i==[2], son pid = [33863]


    exit . child sig = [33861]
    exit . child sig = [33863]


    exit . child sig = [33862]

    ^C
     

  • 相关阅读:
    《流畅的python》阅读笔记 - 第五章:一等函数
    Linux——Xshell、Xftp实现Linux远程登录与应用
    CachedThreadPool
    3. 使用PyTorch深度学习库训练第一个卷积神经网络CNN
    IntelliJ IDEA一站式配置【全】(提高开发效率)
    vmpalyer虚拟机的使用教程,小白也能看懂
    17. 电话号码的字母组合
    C++ 输入N本书,查找并且显示书相关信息
    学习Java的第十一天
    [Linux]Git
  • 原文地址:https://blog.csdn.net/holoyh/article/details/133845061