zoukankan      html  css  js  c++  java
  • 二十三、Linux 进程与信号---进程链和进程扇、守护进程和孤儿进程以及僵尸进程

    23.1 进程链和进程扇

    23.1.1 概念

      进程链:一个父进程构建出一个子进程,子进程再构建出子子进程,子子进程构建出子子子进程。。。。 这种就为进程链

      进程扇:一个父进程构建出多个子进程,子进程都是由同一个父进程构建出来

      

    23.1.2 进程链的构建

      process_link.c

     1 /* 创建5个进程(包括父进程) */
     2 #include <stdio.h>
     3 #include <stdlib.h>
     4 #include <unistd.h>
     5 
     6 int main(int argc, char *argv[])
     7 {
     8     int counter = 0;
     9 
    10     if(argc < 2) {
    11         counter = 2;
    12     } else {
    13         counter = atoi(argv[1]);
    14     }
    15 
    16     int i = 1;
    17     pid_t pid;
    18 
    19     //循环变量从1开始,要减去父进程,即创建4个子进程
    20     //需要保证父进程要跳出循环,子进程去创建子子进程
    21     for(; i < counter; i++) {
    22         pid = fork();
    23         if(pid < 0) {
    24             perror("fork error");
    25             exit(1);
    26         } else if(pid > 0) {
    27             break;    //父进程退出循环,子进程继续做循环
    28         }
    29     }
    30 
    31     printf("pid : %d, ppid: %d
    ", getpid(), getppid());
    32     while(1) {
    33         sleep(1);
    34     }
    35 
    36     return 0;
    37 }

      运行:

      

      执行 ps -ef | grep process_link 查看进程:

      

      注意 8468 进程编号并不是 process_link 进程,它为 shell 的进程,运行的 process_link 的进程的父进程就是shell终端

    23.1.3 进程扇的构建

     1 /* 创建5个进程(包括父进程) */
     2 #include <stdio.h>
     3 #include <stdlib.h>
     4 #include <unistd.h>
     5 
     6 int main(int argc, char *argv[])
     7 {
     8     int counter = 0;
     9 
    10     if(argc < 2) {
    11         counter = 2;
    12     } else {
    13         counter = atoi(argv[1]);
    14     }
    15 
    16     int i = 1;
    17     pid_t pid;
    18 
    19     //循环变量从1开始,要减去父进程,即创建4个子进程
    20     //需要保证父进程要跳出循环,子进程去创建子子进程
    21     for(; i < counter; i++) {
    22         pid = fork();
    23         if(pid < 0) {
    24             perror("fork error");
    25             exit(1);
    26         } else if(pid == 0) {
    27             break;    //子进程退出循环,父进程继续做循环
    28         }
    29     }
    30 
    31     printf("pid : %d, ppid: %d
    ", getpid(), getppid());
    32     while(1) {
    33         sleep(1);
    34     }
    35 
    36     return 0;
    37 }

      编译运行如下,

      

      子进程对应的父进程都为 113892

    23.2 守护进程和孤儿进程

      进程在操作系统中根据功能分为各种各样的进程。

    23.2.1 守护进程

    • 守护进程(daemon)是生存期长的一种进程。它们常常在系统引导装入时启动,在系统关闭时终止。
    • 所有守护进程都以超级用户(用户 ID 为0)的优先权运行
    • 守护进程没有控制终端
    • 守护进程的父进程都是 init 进程

    23.2.2 孤儿进程

    • 父进程结束,子进程就成为孤儿进程,会由 1 号进程(init 进程)领养

      process_orphen.c

     1 #include <stdio.h>
     2 #include <stdlib.h>
     3 #include <unistd.h>
     4 
     5 int main(void)
     6 {
     7     pid_t pid;
     8 
     9     pid = fork();
    10     if(pid < 0) {
    11         perror("fork error");
    12         exit(1);
    13     } else if(pid > 0) {
    14         printf("%d deaded
    ", getpid());
    15         exit(0);
    16     } else {
    17         sleep(4);
    18         printf("pid : %d, ppid : %d
    ", getpid(), getppid());
    19     }
    20 
    21     return 0;
    22 }

      编译运行:

      

      这里由些奇怪的地方是孤儿进程被进程 2323领养,查看下这个进程:

      

      这个进程的作用是:用于linux开机自动启动某些后台服务,同时还承担监控这些服务运行状态的功能。

      这个进程代替了 1 号进程的一些特性,如果作死想试下关闭掉这个进程,可以进入下面的链接尝试:

      https://www.cnblogs.com/chilumanxi/p/5136102.html

    23.2.3 僵尸进程

    • 子进程结束,但是没有完全释放内存(在内核中的  task_struct 没有释放),该进程就成为僵尸进程。
    • 当僵尸进程的父进程结束后,就会被 init 进程领养,最终被回收
    • 避免僵尸进程
      • 让僵尸进程的父进程来回收,父进程每隔一段时间来查询子进程是否结束并回收,调用 wait() 或者 waitpid() ,通知内核释放僵尸进程
      • 采用信号 SIGCHLD 通知处理,并在信号处理程序中调用 wait 函数
      • 让僵尸进程成为孤儿进程,由 init 进程回收

    (1)构建僵尸进程

      process_zombie.c

     1 #include <stdio.h>
     2 #include <stdlib.h>
     3 #include <unistd.h>
     4 
     5 int main(void)
     6 {
     7     pid_t pid;
     8 
     9     pid = fork();
    10     if(pid < 0) {
    11         perror("fork error");
    12         exit(1);
    13     } else if(pid == 0) {
    14         printf("pid : %d, ppid: %d
    ", getpid(), getppid());
    15         exit(0); //子进程结束成为僵尸进程
    16     }
    17 
    18     while(1) {//父进程继续循环
    19         sleep(1);
    20     }
    21 
    22     exit(0);
    23 }

      编译运行:

      

      另开一终端,查看进程

      114707 为父进程,为S+,即可中断运行状态

      子进程为 114708,状态为 Z+,Z即代表是僵尸进程,或者看进程名的 defunct ,有这个名字也为僵尸进程

  • 相关阅读:
    绑定方法和非绑定方法
    property属性
    面向对象的三大特征之一:封装
    asp:GridView控件的使用
    javaWeb中struts开发——Logic标签
    javaWeb中struts开发——Bean标签
    大话数据结构(十二)java程序——KMP算法及改进的KMP算法实现
    大话数据结构(十一)java程序——串
    大话数据结构(七)——单链表的整表创建与删除
    大话数据结构(十)java程序——队列
  • 原文地址:https://www.cnblogs.com/kele-dad/p/9142206.html
Copyright © 2011-2022 走看看