[C++]sylar高性能服务器框架学习记录:daemon模块

记录一下最近这学期学习的sylar服务器框架项目,输出整理一下项目的结构,用到的知识和自己的体会

项目仓库地址

https://github.com/sylar-yin/sylar/

整理博客过程中参考的大佬资料链接:

============================================

基础介绍

守护进程模块可以将进程与终端解绑,在后台运行,父进程还可以检测子进程是正常结束还是异常崩溃,如果是异常崩溃可以重新拉起子进程

ProcessInfo结构体

用于存储进程信息,采用单例模式,提供字符串方法

// 进程信息结构体
struct ProcessInfo {
    pid_t parent_id = 0;                // 父进程ID
    pid_t main_id = 0;                  // 主进程ID
    uint64_t parent_start_time = 0;     // 父进程启动时间
    uint64_t main_start_time = 0;       // 主进程启动时间
    uint32_t restart_count = 0;         // 主进程重启次数

    std::string toString() const;
};

typedef sylar::Singleton
<ProcessInfo> ProcessInfoMgr;

std::string ProcessInfo::toString() const {
    std::stringstream ss;
    ss << "[ProcessInfo parent_id=" << parent_id
       << " main_id="               << main_id
       << " parent_start_time="     << sylar::Time2Str(parent_start_time)
       << " main_start_time="       << sylar::Time2Str(main_start_time)
       << " restart_count="         << restart_count << "]";
    return ss.str();
}

start_deamon函数

当第三个参数为true的时候才开启deamon模式,从循环的开始位置fork子进程,子进程执行main函数,父进程检测子进程返回值

使用daemon(1, 0)开启daemon

int start_daemon(int argc, char** argv
                , std::function<int(int argc, char** argv)> main_cb
                , bool is_daemon) {
    if(!is_daemon) {
        return real_start(argc, argv, main_cb);
    }
    return real_daemon(argc, argv, main_cb);
}

static int real_start(int argc, char** argv
                , std::function<int(int argc, char** argv)> main_cb) {
    return main_cb(argc, argv);
}

static int real_daemon(int argc, char** argv
                , std::function<int(int argc, char** argv)> main_cb) {
    int rt = daemon(1, 0);
    if(rt != 0) {
        SYLAR_LOG_ERROR(g_logger) << "deamon() error rt=" << rt
            << " errno=" << errno << " errstr=" << strerror(errno);
    }

    ProcessInfoMgr::GetInstance()->main_id = getpid();
    ProcessInfoMgr::GetInstance()->main_start_time = time(0);
    while(true) {
        pid_t pid = fork();
        if(pid == 0) {      // 子进程返回
            ProcessInfoMgr::GetInstance()->main_id = getpid();
            ProcessInfoMgr::GetInstance()->main_start_time = time(0);
            SYLAR_LOG_INFO(g_logger) << "process start pid=" << getpid()
                << " errno=" << errno << " errstr=" << strerror(errno);
            return real_start(argc, argv, main_cb);
        } else if(pid < 0) {
            SYLAR_LOG_ERROR(g_logger) << "fork fail return=" << pid
                << " errno=" << errno << " errstr=" << strerror(errno);
            return  -1;
        } else {            // 父进程返回
            int status = 0;
            waitpid(pid, &status, 0);
            if(status) {
                SYLAR_LOG_ERROR(g_logger) << "child crash pid=" << pid
                    << " status=" << status;;
            } else {
                SYLAR_LOG_INFO(g_logger) << "child finished pid=" << pid;
                break;
            }
            ProcessInfoMgr::GetInstance()->restart_count++;
            sleep(g_daemon_restart_interval->getValue());
        }
    }
    return 0;
}

子进程重启时间间隔

注册了一个配置项

static sylar::ConfigVar
<uint32_t>::ptr g_daemon_restart_interval 
    = sylar::Config::Lookup("daemon.restart_interval", (uint32_t)5, "daemon restart interval");

测试

模拟服务进程为一个循环5次的1s定时器,第5次超时之后手动调用abort()模拟崩溃

#include "sylar/daemon.h"
#include "sylar/iomanager.h"
#include "sylar/log.h"

static sylar::Logger::ptr g_logger = SYLAR_LOG_ROOT();

sylar::Timer::ptr timer;

int server_main(int argc, char** argv) {
    SYLAR_LOG_INFO(g_logger) << sylar::ProcessInfoMgr::GetInstance()->toString();
    sylar::IOManager iom(1);
    timer =
    iom.addTimer(1000, [](){
        SYLAR_LOG_INFO(g_logger) << "on Timer";
        static int count = 0;
        if(++count > 5) {
            abort();    // 手动崩溃
            timer->cancel();
        }
    }, true);
    return 0;
}

int main(int argc, char** argv) {
    return sylar::start_daemon(argc, argv, server_main, argc != 1);
}

使用非守护进程模式运行,可以看到5次超时之后程序崩溃

image-20260311142406496

使用守护进程模式运行,在btop命令行工具中可以看到fork了一个子进程,子进程崩溃之后5s被拉回重新运行

image-20260311142533432

image-20260311142631748

image-20260311142604568

image-20260311142653704

总结

为服务器稳定性提供保障

评论

  1. sankkooos
    Android Chrome 142.0.7444.173
    2 周前
    2026-3-11 18:34:30

    严肃责怪中……(这么高产,不要命啦啊喂?

    • Re1
      sankkooos
      Windows Firefox 146.0
      2 周前
      2026-3-11 18:49:08

      水课写的

      • sankkooos
        Re1
        Android Chrome 142.0.7444.173
        2 周前
        2026-3-13 14:54:49

        那很勤奋了( ,,´・ω・)ノ”(´っω・`。)

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇