当前位置: 首页 > news >正文

localtime和gmtime获取的时间不可靠

多线程中使用localtimegmtime的风险

引言

在嵌入式设备管理中,我们经常会遇到设备需要在特定时间自动开关机的场景。然而,一个设备在预定关机后,意外地提前开机然后再次关机,这引起了我们的注意。本文将探讨这一现象背后的原因,并提供解决方案。

核心发现

我们发现,在多线程环境中,使用localtimegmtime函数 可能会导致不可预测的结果。具体来说,localtime的返回值可能会被gmtime的结果篡改,这是一个严重的线程安全问题。

问题分析与解决
1. 代码审查与日志分析

通过代码审查和日志分析,我们发现设备在定时检测到当前时间符合条件后,会执行关机操作。然而,日志显示云服务返回的时间与预期存在8小时的差异。

2. 增加日志与挂测

为了进一步诊断问题,我们在代码中增加了打印时间戳的日志,并进行了长时间的挂测。结果发现,时间戳偶尔会出现异常跳动,与实际时间相差8小时。

3. 函数替换与挂测

考虑到localtime是非线程安全的,我们将其替换为线程安全的localtime_r,并继续进行挂测。这次,时间戳显示正常,没有出现之前的异常。

根因探究

尽管localtime是非线程安全的,但时间相差8小时的现象仍然令人费解。我们考虑了以下可能的原因:

  1. 时区变更:我们首先怀疑时区被意外改变,但日志中没有发现任何修改痕迹。
  2. 返回值被修改:我们检查了业务,没有发现有地方使用了localtime的返回值并进行了修改。
  3. uClibc库问题:我们分析了uClibc库中localtime的实现,并发现localtimelocaltime_r在时区处理上是一致的。但官网下载的uClibc版本与AX平台的不一致,我们怀疑是实现上的差异。
深入分析

进一步分析发现,localtime不仅使用全局指针(这是非线程安全的表现),而且与gmtime共享同一个指针。这与glibc的行为不同,可能是问题的关键所在。

struct tm __time_tm; /* Global shared by gmtime() and localtime(). */
实验 验证

为了验证我们的结论,我们设计了一个多线程实验:

  1. 创建多个线程,其中一部分线程使用localtime获取时间,并打印小时数。
  2. 另一部分线程使用gmtime获取时间。
  3. 观察localtime获取的小时数是否为本地时间,结果显示localtime获取的小时数出现了UTC时间。

以下是实验的 代码示例 :

#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <pthread.h> #include <time.h> void* thread_localtime(void* arg) { while(1) { time_t rawtime; struct tm* timeinfo; time(&rawtime); timeinfo = localtime(&rawtime); printf("Local tm_hour:%d\n", timeinfo->tm_hour); usleep(200*1000); } return NULL; } void* thread_gmtime(void* arg) { while(1) { time_t rawtime; struct tm* utc_info; time(&rawtime); utc_info = gmtime(&rawtime); printf("UTC tm_hour:%d\n", utc_info->tm_hour); usleep(200*1000); } return NULL; } int main() { pthread_t threads[10]; for (int i = 0; i < 10; i++) { if (i < 5) { pthread_create(&threads[i], NULL, thread_localtime, NULL); } else { pthread_create(&threads[i], NULL, thread_gmtime, NULL); } } // 等待所有线程完成 for (int i = 0; i < 10; i++) { pthread_join(threads[i], NULL); } return 0; }
结论

在多线程环境中,为了避免全局指针被篡改的风险,建议使用线程安全的函数,如localtime_r。这不仅可以避免潜在的线程安全问题,还可以确保程序的健壮性和可靠性。

localtime和gmtime获取的时间不可靠_localtime多线程-CSDN博客

http://www.jsqmd.com/news/786484/

相关文章:

  • 从简单夹爪到灵巧手的运动映射:原理、实现与机器人抓取技能迁移
  • 助睿ETL入门实验指导
  • 跨境电商提效必看:6款指纹浏览器RPA功能深度对比
  • OpenClaw(小龙虾 AI)完整安装使用教程
  • 用专业微光,吸引技术实习生主动奔赴
  • Portage开源项目:构建跨平台AI技能市场,实现技能一次编写处处运行
  • 如何获取最完整的 AVC 日志?
  • TopicGPT:大语言模型驱动的交互式主题建模框架
  • 长时间AEC(回声信号)录制需求
  • Python 爬虫高级实战:爬虫监控告警系统搭建
  • CANN/GE 流分配特性分析
  • Go语言微服务开发必备:gomcp核心工具集的设计哲学与实战应用
  • 基于Gemini大语言模型的自动化研究工具:从Agent原理到工程实践
  • Decantr:AI生成UI的设计智能治理工具,解决前端一致性难题
  • 复合工程:构建可组合系统的架构方法论与云原生实践
  • 空间智能筑基,领航世界级智慧强港
  • 大模型驱动的网络攻击:AI对抗AI,智能WAF的进化之路
  • 读论文前先画文献地图,别一上来就硬啃 30 篇
  • 基于LangChain与Streamlit的六合一聊天机器人项目实战解析
  • 当BMI遮住了警报:男性正常体重肥胖的深度科学综述
  • 无标无感定位,重构超级港口感知体系
  • 【新手流畅上手指南】2026 OpenClaw 安装指南 Windows 系统零代码部署
  • CANN/pto-isa PTO汇编规范
  • 基于MCP协议构建Cursor团队数据AI助手:从原理到实战部署
  • 从LIME到反事实解释:可解释AI的核心技术路径与应用实战
  • 告别熬夜改稿!百考通AI带你一步步通关本科毕业论文
  • Origin:本地优先AI知识伴侣,构建可编辑记忆与知识图谱
  • Helm-GCS:构建高并发安全的私有Helm仓库实战指南
  • Windows驱动存储清理完全指南:DriverStore Explorer新手快速入门
  • 硬件IP隐私保护验证:BlindMarket框架与SAT求解优化