可靠获取系统重启时间需查Windows事件日志ID 12或Linux journalctl --list-boots;Windows用EvtQuery(EvtQueryReverseDirection)查System日志中Event[System[(EventID=12)]],解析TimeCreated为FILETIME再转system_clock::time_point;Linux优先解析journalctl输出,fallback到/proc/uptime粗算。

Windows上用GetTickCount64不够,得查事件日志
单纯调用GetTickCount64只能拿到系统已运行时长,不是重启时间。真正可靠的来源是 Windows 事件日志里的系统启动事件(ID 12 或 1074),对应System日志中Event ID 12(内核启动完成)或Event ID 1074(用户发起关机/重启)。需要使用 Windows API 的EvtQuery和EvtNext系列函数。
用EvtQuery查最近一次 Event ID 12 的时间
关键步骤是构造 XPath 查询表达式,按时间倒序取第一条匹配记录:
- 查询字符串必须用
Event[System[(EventID=12)]],注意括号嵌套和大小写 - 必须指定
EvtQueryReverseDirection标志,否则默认从最早开始遍历 -
EvtFormatMessage对EventRecordId或TimeCreated字段格式化时,需传入EvtFormatMessageTime并确保缓冲区足够(至少 32 字节) - 返回的
FILETIME需用FileTimeToSystemTime转为可读结构,别直接当成秒数处理
// 示例片段:获取最近一次 Event ID 12 的 TimeCreated
DWORD status = EvtQuery(NULL, L"System", L"*[System[(EventID=12)]]",
EvtQueryReverseDirection | EvtQueryTolerateQueryErrors, NULL);
// 后续用 EvtNext 获取首条事件,再用 EvtRender 提取 TimeCreated 字段Linux下读/proc/sys/kernel/random/boot_id不行,得看uptime或journalctl
/proc/sys/kernel/random/boot_id每次启动生成新 UUID,但不带时间戳;真正可用的是:
-
cat /proc/uptime返回秒数,用time(NULL) - uptime_sec粗略算出启动时间(注意时区和系统时间是否准确) - 更可靠的是
journalctl --list-boots输出的 boot ID 列表,最后一行第一列是 boot index,第二列是启动时间(ISO 格式),可用system()+popen()捕获输出 - 若系统没启用 journald(如某些嵌入式或 minimal 安装),
/proc/uptime是唯一选项,但无法区分休眠唤醒和真正重启
跨平台封装要注意时区和权限问题
Windows 查询事件日志需要管理员权限(否则EvtQuery返回ERROR_ACCESS_DENIED);Linux 上journalctl --list-boots普通用户可执行,但journalctl -b -1查前一次启动可能受限于日志保留策略。
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
立即学习“C++免费学习笔记(深入)”;
统一返回std::chrono::system_clock::time_point时,务必确认:FILETIME转time_t要减去 11644473600LL 秒(Windows 时间纪元偏移);Linux 用strtoll()解析journalctl输出的时间字符串时,得跳过带时区的+0800部分,或用strptime配合%Y-%m-%d %H:%M:%S格式。
实际部署时,别指望一次调用就覆盖所有边缘情况——比如 Windows 系统日志被清空、Linux journal 被轮转、或者容器环境里/proc/uptime反映的是宿主而非容器启动时间。

















