news 2026/4/23 14:57:14

C++:守护进程(附带源码)

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
C++:守护进程(附带源码)

项目背景详细介绍

在 Linux / Unix 系统中,守护进程(Daemon Process)是系统运行的基础组成部分之一。

几乎所有重要的系统服务,都是以守护进程形式存在的,例如:

  • sshd—— 远程登录服务

  • cron—— 定时任务服务

  • nginx—— Web 服务

  • mysqld—— 数据库服务

  • systemd—— 系统服务管理器

这些进程都有几个显著特点:

  • 不依附于任何终端

  • 后台长期运行

  • 系统启动或用户登录后自动运行

  • 稳定、可靠、可恢复

在真实工程中,你会频繁遇到需要编写守护进程的场景,例如:

  • 后台监控程序

  • 日志采集服务

  • 心跳检测进程

  • 自动化运维工具

  • 内网代理与转发服务

  • 长时间运行的算法服务

然而,很多初学者对“守护进程”的理解仅停留在:

“把程序丢到后台跑 & 就算守护进程了”

这在工程上是完全错误的

真正合格的守护进程,需要满足一整套严格的系统级规范,包括:

  • 正确脱离控制终端

  • 正确处理父子进程关系

  • 正确设置会话与进程组

  • 正确重定向标准 IO

  • 正确处理信号

  • 正确管理 PID 与日志

因此,本项目的目标是:

使用 C++,完整、规范地实现一个 Linux 标准守护进程模板

该示例可以直接作为你今后所有后台服务程序的工程起点,非常适合:

  • Linux 系统编程教学

  • 运维 / 后台开发课程

  • 博客深度技术文章

  • 面试系统编程考察


项目需求详细介绍

1. 功能需求

  1. 使用 C++ 创建标准 Linux 守护进程

  2. 正确脱离终端并在后台运行

  3. 支持写入日志文件

  4. 支持信号处理(优雅退出)

  5. 模拟长期运行服务

2. 技术要求

  1. 基于 POSIX API

  2. 使用fork / setsid / umask

  3. 正确关闭与重定向文件描述符

  4. 支持 Linux / Unix 系统

3. 教学与工程要求

  1. 严格遵循守护进程创建流程

  2. 每一步操作解释清晰

  3. 代码结构可复用

  4. 可扩展为真实后台服务


相关技术详细介绍

1. 什么是守护进程(Daemon)

守护进程是一种特殊进程,特点是:

  • 在后台运行

  • 不与终端关联

  • 生命周期通常与系统一致

从系统角度看,守护进程是:

为其他进程或用户提供服务的长期后台程序


2. 守护进程的标准创建步骤

经典的守护进程创建流程包括:

  1. fork(),父进程退出

  2. setsid(),创建新会话

  3. 再次fork(),防止重新获得终端

  4. 修改工作目录

  5. 重设文件权限掩码

  6. 关闭 / 重定向标准 IO

  7. 安装信号处理器

这是Linux 系统编程中的标准模板


3. setsid 的作用

setsid()用于:

  • 创建新会话(Session)

  • 使进程成为会话首进程

  • 脱离控制终端

这是守护进程的核心步骤之一


实现思路详细介绍

本项目采用完全标准化的守护进程实现流程

  1. main中调用daemonize()

  2. daemonize()内完成所有系统级操作

  3. 主逻辑进入无限循环,模拟服务行为

  4. 使用信号处理实现优雅退出

  5. 所有运行信息写入日志文件

该结构:

  • 可直接复制到实际项目

  • 与系统服务规范完全一致

  • 易于维护与扩展


完整实现代码

/**************************************************** * File: Daemon.h ****************************************************/ #pragma once #include <string> class Daemon { public: static void daemonize(); static void run(); private: static void handleSignal(int sig); }; /**************************************************** * File: Daemon.cpp ****************************************************/ #include "Daemon.h" #include <unistd.h> #include <sys/stat.h> #include <sys/types.h> #include <signal.h> #include <fcntl.h> #include <fstream> #include <ctime> static bool g_running = true; void Daemon::daemonize() { pid_t pid = fork(); if (pid < 0) _exit(EXIT_FAILURE); if (pid > 0) _exit(EXIT_SUCCESS); // 创建新会话 if (setsid() < 0) _exit(EXIT_FAILURE); // 第二次 fork,防止重新获得终端 pid = fork(); if (pid < 0) _exit(EXIT_FAILURE); if (pid > 0) _exit(EXIT_SUCCESS); // 设置文件权限掩码 umask(0); // 切换工作目录 chdir("/"); // 关闭标准文件描述符 close(STDIN_FILENO); close(STDOUT_FILENO); close(STDERR_FILENO); // 重定向到 /dev/null open("/dev/null", O_RDONLY); open("/dev/null", O_RDWR); open("/dev/null", O_RDWR); // 注册信号处理 signal(SIGTERM, handleSignal); signal(SIGINT, handleSignal); } void Daemon::handleSignal(int sig) { g_running = false; } void Daemon::run() { std::ofstream log("/tmp/daemon.log", std::ios::app); while (g_running) { std::time_t now = std::time(nullptr); log << "Daemon running at " << std::ctime(&now); log.flush(); sleep(5); } log << "Daemon exiting gracefully\n"; log.close(); } /**************************************************** * File: main.cpp ****************************************************/ #include "Daemon.h" int main() { Daemon::daemonize(); Daemon::run(); return 0; }

代码详细解读(仅解读方法作用)

daemonize

完成守护进程创建的所有系统级操作,是守护进程的核心函数。

fork

创建子进程,使父进程退出,保证进程不再是前台进程。

setsid

创建新会话并脱离控制终端。

umask

重设文件权限掩码,保证守护进程可控的文件权限。

重定向标准 IO

避免守护进程意外向终端输出数据。

handleSignal

用于处理退出信号,实现优雅关闭。

run

守护进程的主循环,模拟后台服务逻辑。


项目详细总结

通过本项目,你可以系统掌握:

  • Linux 守护进程的标准实现流程

  • POSIX 系统调用在工程中的真实用途

  • 后台服务程序的设计规范

  • 从“写程序”到“写系统服务”的能力跃迁

这是Linux 系统编程中必学、必会、必用的经典项目


项目常见问题及解答

Q1:为什么要 fork 两次?
A:防止守护进程重新获得控制终端。

Q2:一定要关闭标准 IO 吗?
A:是,避免资源泄漏和不可控输出。

Q3:如何用 systemd 管理?
A:可在此基础上编写.service文件。


扩展方向与性能优化

  1. PID 文件(防止多实例)

  2. systemd / init.d 集成

  3. 日志轮转(logrotate)

  4. 配置文件支持

  5. 多线程 / epoll 服务模型

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/23 14:41:46

BooruDatasetTagManager:从图片标注小白到高手的进阶指南

BooruDatasetTagManager&#xff1a;从图片标注小白到高手的进阶指南 【免费下载链接】BooruDatasetTagManager 项目地址: https://gitcode.com/gh_mirrors/bo/BooruDatasetTagManager 还在为海量图片标注而头疼吗&#xff1f;传统手工标注不仅效率低下&#xff0c;还容…

作者头像 李华
网站建设 2026/4/16 15:28:39

2025零基础实战:三步搞定视频字幕智能提取

2025零基础实战&#xff1a;三步搞定视频字幕智能提取 【免费下载链接】video-subtitle-extractor 视频硬字幕提取&#xff0c;生成srt文件。无需申请第三方API&#xff0c;本地实现文本识别。基于深度学习的视频字幕提取框架&#xff0c;包含字幕区域检测、字幕内容提取。A GU…

作者头像 李华
网站建设 2026/4/23 14:48:13

从零实现基于电路仿真circuits网页版的稳压电源项目应用

用指尖搭建电源&#xff1a;在电路仿真网页版中从零实现一个稳压电源系统你有没有过这样的经历&#xff1f;想做个单片机小项目&#xff0c;却卡在“怎么给它稳定供电”这一步。买模块太贵&#xff0c;自己搭又怕烧板子——别急&#xff0c;今天我们不焊一根线、不插一块芯片&a…

作者头像 李华
网站建设 2026/4/16 17:44:42

StructBERT模型比较:选择最佳分类方案

StructBERT模型比较&#xff1a;选择最佳分类方案 1. 引言&#xff1a;AI 万能分类器的时代来临 在自然语言处理&#xff08;NLP&#xff09;领域&#xff0c;文本分类是构建智能系统的核心能力之一。无论是客服工单自动归类、用户意图识别&#xff0c;还是舆情监控与新闻分类…

作者头像 李华
网站建设 2026/4/23 12:21:51

6个超实用内容解锁技巧:轻松实现付费墙绕过的方法详解

6个超实用内容解锁技巧&#xff1a;轻松实现付费墙绕过的方法详解 【免费下载链接】bypass-paywalls-chrome-clean 项目地址: https://gitcode.com/GitHub_Trending/by/bypass-paywalls-chrome-clean 你是否曾经遇到这样的情况&#xff1a;一篇看似精彩的文章&#xff…

作者头像 李华
网站建设 2026/4/16 14:21:23

mermaid ER图终极指南:从零绘制专业级实体关系图

mermaid ER图终极指南&#xff1a;从零绘制专业级实体关系图 【免费下载链接】mermaid 项目地址: https://gitcode.com/gh_mirrors/mer/mermaid 本文教你如何使用mermaid快速创建清晰易懂的实体关系图&#xff0c;适合数据库设计者和系统分析师。无论你是初学者还是有经…

作者头像 李华