Linux c/c++进程之僵尸进程和守护进程

简介: 这篇文章介绍了Linux系统中僵尸进程和守护进程的概念、产生原因、解决方法以及如何创建守护进程。

1. 僵尸进程

1.1 僵尸进程的定义:

   父进程创建了子进程,而子进程先于父进程结束,子进程的资源没有被释放,就会变成僵尸进程,持续占用系统资源

1.2 僵尸进程的解决办法

   子进程在结束之前会向父进程发送SIGCHLD信号,父进程接收到信号之后,先回收子进程资源,然后父进程自己再结束

   想要防止僵尸进程的情况出现,可以在父进程中写一个wait函数(或者waitpid函数)等待子进程发送的SIGCHLD信号

无wait()函数的情况:

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

int main(){
    if(fork()){
        printf("子进程被创建!\n");
    }else{
        for(int i = 0;i<5;i++){
            printf("子进程执行:%d\n",i+1);
            sleep(1);
        }
    }
    printf("父进程结束!\n\n");
    return 0;
}

运行结果:

 从上面的输出结果可以看出,在没有wait()函数的情况下,父进程并不会等待子进程结束之后再执行"父进程结束!"这句话,如果在此时父进程在子进程未结束前被强制结束,那么就会造成僵尸进程的情况出现

有wait()函数的情况:

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

int main(){
    if(fork()){
        printf("子进程被创建!\n");
        wait(0);
    }else{
        for(int i = 0;i<5;i++){
            printf("子进程执行:%d\n",i+1);
            sleep(1);
        }
    }
    printf("父进程结束!\n\n");
    return 0;
}

运行结果:

   当存在wait()函数时,父进程会等待子进程发送的SIGCHLD信号,当父进程接收到信号之后,先回收子进程资源,父进程再结束

2.守护进程

2.1 守护进程概念

独立记录其它进程的情况,记录操作系统日志等

2.2 守护进程的查看方法

ps -axj

TPGID为 -1 的是守护进程

2.3 守护进程的创建

2.3.1 守护进程的功能实现和其它进程一样

2.3.2 将一个进程变为守护进程的步骤

  • 干掉其父进程
  • 摆脱终端控制(关闭0 1 2 文件描述符并重定向当前进程的io操作到 /dev/NULL (黑洞设备))
  • 摆脱原有会话,进程组的控制从而创建新的会话

2.4 创建守护进程编程模型

2.4.1 创建守护进程方式一

  1. 创建新会话 setsid()函数
  2. 改变当前工作目录 chdir()函数
  3. 重设当前文件权限 umask()函数
  4. 关闭文件 close()函数

    2.4.2 创建守护进程方式二

  5. 重设文件权限 umask()函数

  6. 创建子进程 fork()函数
  7. 结束父进程
  8. 创建新会话 setsid()
  9. 防止子进程成为僵尸进程 signal()函数忽略掉SIGCHLD SIGHUP信号
  10. 改变当前工作目录 chdir()函数
  11. 重定向文件描述符号 open()函数 dup2()函数
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <signal.h>
#include <sys/stat.h>
#include <sys/types.h>

int main(){
    // 1. 重设文件权限
    umask(0);
    // 2. 创建子进程
    int ret = fork();
    if(ret < 0) printf("创建进程失败:%m"),exit(-1);
    if(ret > 0) printf("父进程结束:%m\n"),exit(0);     // 3. 让父进程结束
    if(0 == ret){
        printf("pid:%d\n",getpid());
        // 4. 创建新会话
        setsid();
        // 5. 防止子进程成为僵尸进程   忽略掉SIGCHLD SIGHUP信号
        signal(SIGCHLD,SIG_IGN);
        signal(SIGHUP,SIG_IGN);
        // 6. 改变当前工作目录
        chdir("/");
        // 7. 重定向文件描述符号
        int fd = open("/dev/NULL",O_RDWR);
        dup2(fd,0);
        dup2(fd,1);
    }

    while(1){
        //做事情(模拟守护进程工作)
        sleep(1);
    }

    return 0;
}

结果:

关闭守护进程:

由此可知上方创建的pid为3469的守护进程已经被关闭

2.5 进程的组织形式

多个进程组成一个进程组

多个进程组组成一个会话

注: 进程组的组长 session进程

2.6 守护进程的关闭

直接使用kill 2 pid 将指定进程干掉即可

2.7 终端标准输入输出设备

  • 0 标准输入设备
  • 1 标准输出设备
  • 2 标准错误输出设备
相关文章
|
15天前
|
算法 Linux 调度
深入理解Linux操作系统的进程管理
本文旨在探讨Linux操作系统中的进程管理机制,包括进程的创建、执行、调度和终止等环节。通过对Linux内核中相关模块的分析,揭示其高效的进程管理策略,为开发者提供优化程序性能和资源利用率的参考。
40 1
|
4天前
|
存储 监控 Linux
嵌入式Linux系统编程 — 5.3 times、clock函数获取进程时间
在嵌入式Linux系统编程中,`times`和 `clock`函数是获取进程时间的两个重要工具。`times`函数提供了更详细的进程和子进程时间信息,而 `clock`函数则提供了更简单的处理器时间获取方法。根据具体需求选择合适的函数,可以更有效地进行性能分析和资源管理。通过本文的介绍,希望能帮助您更好地理解和使用这两个函数,提高嵌入式系统编程的效率和效果。
40 13
|
10天前
|
SQL 运维 监控
南大通用GBase 8a MPP Cluster Linux端SQL进程监控工具
南大通用GBase 8a MPP Cluster Linux端SQL进程监控工具
|
18天前
|
运维 监控 Linux
Linux操作系统的守护进程与服务管理深度剖析####
本文作为一篇技术性文章,旨在深入探讨Linux操作系统中守护进程与服务管理的机制、工具及实践策略。不同于传统的摘要概述,本文将以“守护进程的生命周期”为核心线索,串联起Linux服务管理的各个方面,从守护进程的定义与特性出发,逐步深入到Systemd的工作原理、服务单元文件编写、服务状态管理以及故障排查技巧,为读者呈现一幅Linux服务管理的全景图。 ####
|
24天前
|
缓存 算法 Linux
Linux内核的心脏:深入理解进程调度器
本文探讨了Linux操作系统中至关重要的组成部分——进程调度器。通过分析其工作原理、调度算法以及在不同场景下的表现,揭示它是如何高效管理CPU资源,确保系统响应性和公平性的。本文旨在为读者提供一个清晰的视图,了解在多任务环境下,Linux是如何智能地分配处理器时间给各个进程的。
|
7月前
|
存储 Linux 编译器
Linux C/C++ 编程 内存管理之道:探寻编程世界中的思维乐趣
Linux C/C++ 编程 内存管理之道:探寻编程世界中的思维乐趣
133 0
|
7月前
|
关系型数据库 MySQL 数据库
Linux C/C++ 开发(学习笔记七):Mysql数据库C/C++编程实现 插入/读取/删除
Linux C/C++ 开发(学习笔记七):Mysql数据库C/C++编程实现 插入/读取/删除
153 0
|
7月前
|
Shell Linux C++
Linux C/C++ 开发(学习笔记二):Shell脚本编程案例
Linux C/C++ 开发(学习笔记二):Shell脚本编程案例
113 0
|
Linux C语言 C++
Linux ICMP协议实现:C/C++编程指南
ICMP(Internet Control Message Protocol)是网络通信中的重要协议,用于在IP网络中传递错误消息和诊断信息。在Linux系统中,我们可以使用C/C++编程语言来实现基本的ICMP功能,例如发送ICMP回显请求(Ping)和解析ICMP消息。本文将带您深入了解C/C++实现的ICMP协议,包括套接字编程、构造ICMP报文、发送和接收ICMP消息等,以及提供实际的代码示例。
932 1
|
7月前
|
算法 Linux Shell
Linux C/C++ 开发(学习笔记三):Linux C编程案例
Linux C/C++ 开发(学习笔记三):Linux C编程案例
53 0
下一篇
DataWorks