DoubleLi

qq: 517712484 wx: ldbgliet

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::
  4737 随笔 :: 2 文章 :: 542 评论 :: 1615万 阅读
< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

Intro

当我们编写服务器代码时,为了让自己的服务器在意外崩溃时能够及时的重启,软件看门狗就显示出它的作用了,该看门狗进程是通过fork一个子进程(业务进程),父进程一旦捕获到了子进程的结束信号就重新再fork一个子进程来实现的,下面将完整代码贴上。


/************************************************
 * 该例程讲解Linux软件看门狗的优雅编写方法
 *
 * 编写WatchDog有很多种方式:
 * a.一个WatchDog.sh脚本程序
 * b.一个WatchDog.exe可执行程序
 * c.一个可执行程序里面包含WatchDog
 *
 * 本例程就是使用的c方式,通过父进程监控子进程的运行状态来实现的
 * 其中父进程就是子进程(具体的任务进程)的WatchDog
************************************************/
#include <unistd.h>
#include <signal.h>
#include <sys/wait.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>

void childProcessFunc()
{
    int i = 0;
    while (true)
    {
        ++i;
        printf("i: %d, pid: %d, ppid: %d\n", i, getpid(), getppid());
        if (i == 10)
        {
            // 子进程主动结束
            //exit(0);
            char* p = NULL;
            *p = 1;
        }
        sleep(1);
    }
}

void forkChildProcess(int)
{
    int status = 0;
    // 等待子进程中断或终止,释放子进程资源
    // 否则死掉的子进程会变成僵尸进程
    int pid = wait(&status);
    if (pid < 0)
    {
        printf("error: %s\n", strerror(errno));
        return;
    }

    // 如果子进程是由于某种信号退出的,捕获该信号
    if (WIFSIGNALED(status))
    {
        int signalNum = WTERMSIG(status);
        printf("Child process was killed by signal num: %d\n", signalNum);
    }

    // 检测是否生成了core文件
    if (WCOREDUMP(status))
    {
        printf("Child process core dump file generated\n");
    }

    // 等待3秒钟重新启动子进程
    sleep(3);

    pid = fork();
    if (pid == 0)
    {
        printf("Fork new child process\n");
        childProcessFunc();
    }
}

bool initWatchDog()
{
    int pid = fork();
    if (pid)
    {
        // 父进程一直监视子进程的运行状态
        while (true)
        {
            // 捕获子进程结束信号
            assert(signal(SIGCHLD, forkChildProcess) != SIG_ERR);
            // 父进程挂起,当有信号来时被唤醒
            pause();
        }
    }
    else if (pid < 0)
    {
        return false;
    }

    return true;
}

int main()
{
    printf("Main pid: %d\n", getpid());

    // 初始化看门狗进程
    bool ret = initWatchDog();
    if (!ret)
    {
        printf("Init watch dog failed\n");
        return 1;
    }

    printf("Init watch dog success...\n");

    // 运行子进程代码
    childProcessFunc(); 

    return 0;
}

该例子的github地址:https://github.com/chxuan/samples/blob/master/WatchDog/WatchDog.cpp

posted on   DoubleLi  阅读(1407)  评论(0编辑  收藏  举报
编辑推荐:
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
历史上的今天:
2013-11-19 CDialogSK - A Skinnable Dialog Class
2013-11-19 Dialog with HTML skin using CDHtmlDialog and SetWindowRgn
2013-11-19 Using SetWindowRgn
2012-11-19 C++中MessageBox()的详细用法
点击右上角即可分享
微信分享提示