导读:本期聚焦于北京GEO公司创作的《c++如何读取Linux系统的/proc/uptime计算系统运行时间【实战】》,敬请观看详情。想知道一台Linux服务器已经连续运行了多久,最直接的办法就是读取/proc/uptime这个内核提供的虚拟文件。它只包含两个数字,第一个是系统启动至今的总秒数,第二个是各CPU空闲时间的累计值。用C++程序打开这个文件、解析字符串、再做一次简单的数值换算,就能把运行时长精确转换成天时分秒的格式。本文将完整演示从fopen读取、strtod解析到时间换算的完整实现,同时介绍sysinfo函数这一替代方案,并对比两种方式的精度差异和适用场景,最后给出多核环境下CPU空闲率的计算方法,帮助你在系统监控工具开发中选对方案。

在Linux系统上做运维工具或者监控程序时,经常需要知道系统从开机到现在一共运行了多长时间。比如服务器健康检查、日志上报、心跳检测等场景,系统运行时长都是一个很基础但又必不可少的指标。Linux内核其实早就为我们准备好了答案,那就是/proc/uptime这个虚拟文件。本文用C++实战演示如何读取它并计算出可读的时间格式。

c++如何读取Linux系统的/proc/uptime计算系统运行时间【实战】

一、/proc/uptime文件的结构与原理

首先要明白,/proc目录并不是磁盘上真实存在的文件,它是内核在内存中动态生成的一棵虚拟文件树,被称为procfs。每次你用cat命令查看其中的文件,内核都会实时生成内容。所以读取/proc/uptime几乎没有任何磁盘IO开销,性能非常可观,这也是它被大量监控工具采用的原因。

/proc/uptime的内容非常简单,只有两个浮点数,格式如下:

cat /proc/uptime
86423.51 325611.09

第一个数字表示系统自启动以来经过的总秒数,精度可以到小数点后两位。第二个数字是所有CPU核心空闲时间的总和,注意是所有核心的累加值。举个例子,一台4核机器运行了100秒,如果这期间CPU基本处于空闲状态,第二个数理论上最大可以达到400秒左右。理解这一点对后面计算CPU空闲率非常重要。

另外需要说明的是,这里的秒数是系统真实的运行时长,不包含机器休眠挂起的时间差异问题,在绝大多数发行版上它的数值来源是内核的clock_gettime(CLOCK_BOOTTIME)计时,比手动记录开机时间戳更可靠。

二、C++读取与解析的完整实现

实现思路很朴素:用标准的C文件流打开/proc/uptime,读出两个double类型的数值,然后对第一个数做进制换算。下面是完整的可编译代码:

#include <iostream>
#include <fstream>
#include <iomanip>
#include <sstream>

struct UptimeInfo {
    double totalSeconds;   // 系统总运行秒数
    double idleSeconds;    // 所有CPU空闲时间总和
};

bool readUptime(UptimeInfo& info) {
    std::ifstream file("/proc/uptime");
    if (!file.is_open()) {
        std::cerr << "无法打开 /proc/uptime" << std::endl;
        return false;
    }
    file >> info.totalSeconds >> info.idleSeconds;
    return file.good() || !file.eof();
}

int main() {
    UptimeInfo info;
    if (!readUptime(info)) {
        return 1;
    }

    long long total = static_cast<long long>(info.totalSeconds);
    int days    = static_cast<int>(total / 86400);
    int hours   = static_cast<int>((total % 86400) / 3600);
    int minutes = static_cast<int>((total % 3600) / 60);
    int seconds = static_cast<int>(total % 60);

    std::cout << "系统已运行: "
              << days << " 天 "
              << hours << " 小时 "
              << minutes << " 分 "
              << seconds << " 秒" << std::endl;
    return 0;
}

这段代码用了std::ifstream配合流提取运算符,直接把两个数字读进double变量,省去了手动字符串切分的麻烦。换算部分的核心就是86400(一天的秒数)、3600、60这三个进制常量的取模运算。需要注意的是秒数转整型时用了long long,如果机器运行了好几年,秒数会超过20亿,普通int会溢出。

如果你更喜欢传统C风格,也可以用fopenfscanf的写法:

#include <cstdio>

int main() {
    FILE* fp = fopen("/proc/uptime", "r");
    if (fp == nullptr) {
        perror("fopen failed");
        return 1;
    }
    double up, idle;
    if (fscanf(fp, "%lf %lf", &up, &idle) != 2) {
        fclose(fp);
        return 1;
    }
    fclose(fp);
    printf("运行秒数: %.2f\n", up);
    return 0;
}

两种写法效果一致,C++流风格更安全,C风格则少了一层封装,在极端高频采样的场景下略微轻量一点。

三、替代方案:sysinfo函数与两种方式对比

除了读proc文件,Linux还提供了系统调用sysinfo,定义在<sys/sysinfo.h>中,结构体中直接有一个uptime字段,单位是秒:

#include <sys/sysinfo.h>
#include <iostream>

int main() {
    struct sysinfo si;
    if (sysinfo(&si) != 0) {
        perror("sysinfo");
        return 1;
    }
    std::cout << "运行秒数: " << si.uptime << std::endl;
    std::cout << "空闲时间: " << si.idle << std::endl;
    return 0;
}

两种方式的差异主要体现在精度和细节上。sysinfo返回的是整型秒数,没有小数精度;而/proc/uptime保留两位小数,适合需要毫秒级差值计算的场景。此外sysinfo是一次系统调用,不经过VFS文件层,理论上单次调用更快,但一次系统调用的开销本身就远小于一次文件读取的差异,实际项目中两者性能都可以忽略不计。

还有一个隐藏的坑值得提醒:在容器环境中,比如Docker里读取/proc/uptime,得到的是宿主机的运行时长而不是容器的,因为procfs没有被命名空间完全隔离。如果你的程序需要感知容器自身的启动时间,应该改用cgroup或者记录进程自身的启动时间戳来做计算,这一点在云原生场景下尤其容易踩坑。

四、进阶:利用两个数值计算CPU空闲率

既然/proc/uptime给了我们总运行时长和总空闲时长,稍加推导就能算出系统启动以来的平均CPU空闲率,公式为:

#include <iostream>
#include <fstream>

int main() {
    double up, idle;
    {
        std::ifstream f("/proc/uptime");
        f >> up >> idle;
    }

    // 获取CPU核心数
    unsigned int cores = std::thread::hardware_concurrency();
    if (cores == 0) cores = 1;

    // 空闲时间除以(总时长 × 核心数)得到空闲率
    double idleRatio = idle / (up * cores);
    std::cout << "平均CPU空闲率: " << idleRatio * 100.0 << "%" << std::endl;
    return 0;
}

注意分母必须乘以核心数,因为idle是所有核心的累加值。这个比率是自开机以来的历史平均值,如果想要实时CPU使用率,正确做法是间隔几秒采样两次,用两次采样之间的差值来计算,top、htop等工具内部都是这么实现的。

总结一下,读取/proc/uptime是C++获取Linux系统运行时间最通用、跨发行版最稳定的方案,代码简单、无第三方依赖、无磁盘开销。结合sysinfo作为备选,再注意容器环境的特殊性,基本可以覆盖所有实际项目的需求。

/proc/uptimeC++系统编程系统运行时间修改时间:2026-09-07 10:30:42

免责声明:已尽一切努力确保本网站所含信息的准确性。网站作品多为原创整理与精心创作,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们进行处理Email:chomcom@qq.com。
引用或转载本作品时,请注明当前出处:https://www.ipipp.com/html/20260907/52147.html,基于非商业用途的前提下,欢迎转载或二创本作品。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。