You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C++守护进程无限间隔循环优化咨询:CPU占用过高及代码等价性验证

问题:守护进程定时任务CPU占用过高及代码等价性疑问

我正在开发一个以守护进程(daemon)运行的应用程序,需按固定间隔执行代码,当前代码如下:

#include <iostream>
#include <thread>
using namespace std;
int main() {
    thread([=]() {
        while (true) {
            try {
                cout << "log" << endl;
                this_thread::sleep_for(chrono::milliseconds(3000));
            } catch (...) {
                cout << "Some errors here :/" << endl;
            }
        }
    }).detach();
    while (true);
}

通过top命令观察到该程序CPU占用率约80%,我担心代码并非最优实现,请问该如何优化?另外,我的这段代码是否与StackOverflow某篇回答中的代码等价?


解答

一、CPU占用过高的优化方案

兄弟,你这CPU飙高的核心原因太明显了——主函数里的while(true);是个空循环!CPU会拼尽全力一直执行这个空循环,完全得不到休息,占用率自然居高不下。

优化的思路很简单,让主线程不要空转,而是进入等待状态,具体有几种方案:

方案1:让主线程进入休眠(最简单)

把主函数的空循环替换成无限休眠,这样主线程不会占用CPU资源:

#include <iostream>
#include <thread>
#include <chrono>
using namespace std;
int main() {
    thread([=]() {
        while (true) {
            try {
                cout << "log" << endl;
                this_thread::sleep_for(chrono::milliseconds(3000));
            } catch (...) {
                cout << "Some errors here :/" << endl;
            }
        }
    }).detach();
    
    // 替换空循环,让主线程无限休眠
    while (true) {
        this_thread::sleep_for(chrono::hours(1));
    }
}

方案2:用条件变量让主线程等待(更优雅)

如果后续需要给主线程添加退出逻辑,用条件变量会更灵活:

#include <iostream>
#include <thread>
#include <chrono>
#include <mutex>
#include <condition_variable>
using namespace std;

mutex mtx;
condition_variable cv;
bool should_exit = false;

int main() {
    thread([=]() {
        while (!should_exit) {
            try {
                cout << "log" << endl;
                this_thread::sleep_for(chrono::milliseconds(3000));
            } catch (...) {
                cout << "Some errors here :/" << endl;
            }
        }
    }).detach();
    
    // 主线程等待条件变量,直到收到退出信号
    unique_lock<mutex> lock(mtx);
    cv.wait(lock, []{ return should_exit; });
}

方案3:实现真正的守护进程(符合你的需求)

你提到要做守护进程,但当前代码根本不是真正的daemon——它还和终端关联,没有脱离会话,也没有处理后台运行的必要步骤。真正的daemon需要完成这些操作:

  • 调用fork()创建子进程,父进程退出
  • 子进程调用setsid()创建新会话,脱离终端
  • 再次fork()避免成为会话组长
  • 切换工作目录到/,避免占用挂载点
  • 关闭所有文件描述符,重定向标准输入输出到/dev/null

结合定时任务的完整daemon示例大概是这样:

#include <iostream>
#include <thread>
#include <chrono>
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>

void daemonize() {
    // 第一步:fork子进程,父进程退出
    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);

    // 第四步:切换工作目录到根目录
    chdir("/");

    // 第五步:设置文件权限掩码
    umask(0);

    // 第六步:关闭所有文件描述符
    for (int i = sysconf(_SC_OPEN_MAX); i >= 0; --i) {
        close(i);
    }

    // 第七步:重定向标准输入输出到/dev/null
    open("/dev/null", O_RDONLY);
    open("/dev/null", O_WRONLY);
    open("/dev/null", O_RDWR);
}

int main() {
    // 先把程序转成真正的守护进程
    daemonize();

    // 执行定时任务
    while (true) {
        try {
            // 这里写你的定时逻辑,比如写入日志文件
            int fd = open("/var/log/daemon_example.log", O_WRONLY | O_APPEND | O_CREAT, 0644);
            if (fd >= 0) {
                const char* log = "daemon running\n";
                write(fd, log, strlen(log));
                close(fd);
            }
            std::this_thread::sleep_for(std::chrono::milliseconds(3000));
        } catch (...) {
            // 错误处理,同样写入日志
            int fd = open("/var/log/daemon_example.log", O_WRONLY | O_APPEND | O_CREAT, 0644);
            if (fd >= 0) {
                const char* err = "some error occurred\n";
                write(fd, err, strlen(err));
                close(fd);
            }
            std::this_thread::sleep_for(std::chrono::milliseconds(3000));
        }
    }
}

二、与目标代码的等价性对比

完全不等价!那篇回答的代码是标准的守护进程创建流程,包含了我上面提到的fork、setsid、关闭文件描述符等核心步骤,目的是让程序脱离终端,在后台独立运行,成为真正的daemon。

而你的代码只是在主进程里创建了一个detach的后台线程,然后主进程空循环——这本质上还是一个前台程序,只要终端关闭,你的程序大概率会跟着退出,完全没有实现daemon的核心特性,和那篇回答的代码差得很远。


内容的提问来源于stack exchange,提问作者sal-k

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 06:37:13