C++如何获取系统启动时间 _ GetTickCount与uptime方法【实战】
C++如何获取系统启动时间:GetTickCount与uptime方法实战

免费影视、动漫、音乐、游戏、小说资源长期稳定更新! 👉 点此立即查看 👈
在跨平台开发中,获取系统启动时间是个看似简单、实则暗藏玄机的任务。Windows下的GetTickCount64和Linux下的/proc/uptime,这两者提供的“启动时间”在语义上有着本质区别,直接互换使用,往往是线上监控告警误触发的罪魁祸首。
Windows用GetTickCount64获取开机后毫秒数(不含休眠),Linux用/proc/uptime读取实际运行总秒数(含休眠),二者语义不同不可互换;GetTickCount因32位溢出(约49.7天)已被淘汰。
Windows:为什么不用 GetTickCount 而必须用 GetTickCount64
先说说Windows平台。老牌的GetTickCount函数返回一个32位无符号整数,这意味着它在大约49.7天后就会溢出归零。对于需要长期稳定运行的服务或嵌入式设备来说,这无疑是个定时冲击波——系统明明没重启,程序却可能误判为刚刚启动。
所以,答案很明确:必须使用它的64位升级版——GetTickCount64。它返回ULONGLONG类型,理论溢出周期长达约584年,足以应对绝大多数场景。
- 链接与单位:函数位于
kernel32.lib中(MSVC编译器通常默认已链接)。其返回值单位是毫秒,除以1000.0即可转换为秒级浮点数。 - 关键语义:这里有个至关重要的细节:
GetTickCount64的值从系统启动开始累计,但不计入系统进入睡眠或休眠状态的时间。换句话说,如果机器休眠了两小时再唤醒,这个计时器的数值并不会增加那两小时。 - 示例代码:
ULONGLONG uptime_ms = GetTickCount64();
Linux:读 /proc/uptime 的正确姿势
转到Linux世界,获取启动时间的标准姿势是读取/proc/uptime这个虚拟文件。它比uptime命令更底层、更轻量,尤其适合嵌入式或需要高频采样的场景。
这个文件通常包含两个以空格分隔的浮点数:第一个字段是系统启动以来的实际运行总秒数(这个“实际”包含了系统休眠的时间);第二个字段则是总的空闲时间。
- 读取方法:用C++的
std::ifstream打开文件,直接读取第一个double值即可,简单高效。 - 权限与精度:普通用户就有读取权限,无需root。其精度对于秒级应用完全足够;如果追求纳秒级精度,则应考虑结合
clock_gettime(CLOCK_BOOTTIME, ...)。 - 示例代码:
std::ifstream f(“/proc/uptime”); double up_sec; f >> up_sec;
跨平台封装时最常踩的坑
到了封装跨平台接口这一步,才是真正考验理解深度的时候。最常见的错误,就是试图用一个宏或函数名统一两者,然后返回一个uint64_t类型的毫秒数。这忽略了最根本的语义差异:Windows不计休眠,Linux计入休眠。一旦机器进入休眠,两个平台返回的时间增量就会产生巨大分歧,直接导致依赖于此的监控、调度逻辑出错。
那么,正确的设计思路是什么?
- 明确接口语义:在设计上,最好明确区分“系统运行时间”和“系统启动时刻”这两个概念。对于运行时间,各自使用原生方法获取。若需要计算启动的绝对时刻,Windows推荐用
GetSystemTimeAsFileTime获取当前时间后反推,Linux则可用clock_gettime(CLOCK_BOOTTIME, ...)。 - 避开时间陷阱:千万不要用
time(NULL) - boot_time这种方式来估算运行时间。系统时间可能被NTP校准或手动修改,这样计算的结果毫无可靠性可言。 - 容器环境特例:在Docker等容器环境中,
/proc/uptime反映的是宿主机的运行时间,而非容器自身的。如果需要容器的启动时间,需要另辟蹊径,例如通过检查/proc/1/stat来获取容器内第一个进程的启动时间戳。
立即学习“C++免费学习笔记(深入)”;
说到底,真正的难点不在于调用哪个API或读取哪个文件,而在于精确理解“系统启动时间”在你当前的上下文里究竟指代什么:是内核加载完成的那一刻?是第一个用户进程启动的瞬间?还是上次从休眠中恢复的时刻?选错了语义基准,后续的所有计算和判断都将失之毫厘,谬以千里。
相关攻略
C++如何解析MPEG-TS流中的PAT与PMT节目表【深度】 PAT表是解析MPEG-TS流的关键起点,它固定位于PID为0x0000的TS包中。解析时需通过payload_unit_start_indicator标志定位新表起始,正确处理adaptation field以找到payload,校验
C++ std::identity用法详解:函数对象占位符与ranges算法核心指南 std::identity 核心概念与应用场景解析 在C++20标准库中,std::identity绝非简单的语法糖,而是std::ranges算法体系中表达“元素原样透传”意图的唯一标准函数对象。当你调用std:
std::is_base_of编译期报错解析:非法类型、不完整类型与非类类型传入的应对方案 std::is_base_of 编译期报错的根本原因 许多C++开发者在首次使用 std::is_base_of 模板时,常对其在编译阶段直接报错感到困惑。这源于其作为类型特征(type trait)的本质—
Linux下birth time仅能通过statx()读取且不可设置,需内核≥4 11、支持的文件系统及正确挂载选项;glibc未暴露该字段,stat()等传统接口无法获取。 Linux 下用 stat 和 utimensat 读取 设置 birth time(创建时间) 在Linux的世界里,文件
cista 实现微秒级序列化的核心原理:零开销内存拷贝与偏移重定位 cista 微秒级序列化的技术实现解析 cista 之所以能够实现微秒甚至纳秒级的序列化性能,源于其颠覆性的设计理念。与传统的序列化方案不同,cista 彻底摒弃了运行时类型识别(RTTI)、动态反射和堆内存分配等重型操作。它采用了
热门专题
热门推荐
荣耀400 Pro正确关机全指南:从常规操作到故障应对详解 需要关闭您的荣耀400 Pro手机?日常操作其实非常简便。只需长按位于机身右侧的电源键约3秒钟,屏幕上便会浮现一个简洁的半透明菜单,其中明确列出了“关机”、“重启”以及“紧急呼叫”选项。直接点击“关机”,系统将启动一次10秒的安全倒计时,随
红米K30 Pro后盖拆解教程:专业工具与细致手法的完美结合 红米K30 Pro的后盖采用了高强度背胶配合隐藏式螺丝的双重固定设计,想要实现无损拆解,绝非依靠蛮力可以完成。整个操作流程对加热温度、撬启手法以及清洁标准都有严格要求,任何环节的疏忽都可能导致部件损伤。具体而言,其后盖边缘使用了耐高温的工
无需Root权限:三星Galaxy Z Flip系列电量数字显示设置全解析 很多三星折叠屏手机用户都想知道,如何在状态栏直接查看精确的电池百分比数字,是否必须获取Root权限才能实现?实际上完全不需要。三星自Galaxy Z Flip 5、Z Flip 4等主流机型开始,已在系统层面内置了这一实用功
笔记本开机自检信息虽不直接标注“DDR3”或“DDR4”,但联想、戴尔、华硕等品牌BIOS画面常以“PC3-”或“PC4-”编码间接揭示内存代际。UEFI自检显示的内存频率(如2400MHz 3200MHz)结合JEDEC规范可辅助推断:PC3对应DDR3,PC4对应DDR4。更高精度的识别方案包括
空调制冷不足怎么办?先别急着维修压缩机,这些问题更常见 夏天开空调却感觉不够凉爽?很多朋友的第一反应是压缩机坏了,其实压缩机故障的概率相对较低。根据维修行业的大数据统计,绝大多数制冷效果不佳的情况,源于几个容易被忽略的日常维护与环境因素。滤网积尘、制冷剂泄漏、外机散热不良才是真正的高发原因。盲目更换





