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

Linux time function in C/C++【2】

Linux 时间与定时机制设计思想的核心


一、时间函数的分类与作用

Linux 的时间函数大体分为两类:

(1)计时函数(获取当前时间)

这些函数用于读取当前的系统时间或高精度时间戳,区别在于时间单位与精度不同:

函数返回结构精度说明
time()time_t(整型秒)秒级最简单、最老的API
ftime()struct timeb毫秒级已被废弃
gettimeofday()struct timeval微秒级常用,用户态实现,高效
clock_gettime()struct timespec纳秒级最精确,但调用代价略高

(2)定时函数(控制程序等待或定时触发)

这些函数用于让程序等待一定时间或设置定时器,常用于超时控制、周期任务等:

函数类型是否线程安全是否基于信号是否可与 I/O 复用机制结合
sleep()秒级休眠是(SIGALRM)
usleep()微秒级休眠是(SIGALRM)
nanosleep()纳秒级休眠
alarm()设置闹钟信号是(SIGALRM)
getitimer() / setitimer()定时器信号
timer_create() / timer_settime()POSIX 定时器可选信号
timerfd_create() / timerfd_settime()文件描述符定时器可与 epoll/poll 集成

timerfd_* 系列,能直接与 Reactor 模型兼容。


二、为何选择 gettimeofday() 而不是 clock_gettime()

原因 1:精度与开销平衡

  • time() 只能到秒,不够;
  • ftime() 已被淘汰;
  • clock_gettime() 虽能到纳秒,但调用属于系统调用,会陷入内核,开销较高
  • gettimeofday() 精度达微秒,且 在 x86-64 平台是纯用户态实现(无系统调用陷入),因此速度极快。

也就是说:
clock_gettime() 追求极致精度;
gettimeofday() 追求低开销和足够的精度(微秒级即可满足绝大多数需求)。


原因 2:实现机制优越

在 x86-64 平台上,gettimeofday() 的实现利用了 VDSO(Virtual Dynamic Shared Object)机制,让用户态程序可直接访问内核的共享时间数据结构,无需切换上下文。



三、为何选择 timerfd_* 而非其他定时函数

原因 1:避免信号混乱

  • sleep()usleep()alarm()getitimer()setitimer() 等函数都依赖 SIGALRM 信号

  • 多线程程序中,信号机制非常危险:

    • 不确定信号由哪个线程处理;
    • 信号处理函数受限(不可调用大部分系统API);
    • 若主程序与第三方库都用 SIGALRM,极易发生冲突。

强调:多线程程序应尽量避免信号驱动定时。

  • 不确定信号由哪个线程处理:

    • 由于信号处理是异步且不可预测的,操作系统可能将信号随机分配给任意线程
    • 主线程和工作线程都可能成为信号处理者,导致程序行为不可控
    • 例如在Web服务器中,SIGTERM信号可能被处理请求的工作线程捕获,而非主线程
    • POSIX标准规定信号的处理线程是未指定的,不同实现表现各异
  • 信号处理会中断线程的正常执行流:

    • 信号处理函数可能在任何时刻抢占线程执行
    • 若信号发生在临界区内,可能破坏共享数据的一致性
    • 比如数据库写入操作被信号中断,导致数据损坏
  • 线程安全信号处理难度大:

    • 信号处理函数中只能使用异步信号安全函数
    • 常规的锁机制在信号处理中不可用
    • 需要复杂的线程间协调机制来保证安全
  • 信号处理与线程取消的交互问题:

    • 信号可能意外触发线程取消点
    • 导致资源清理和状态恢复更加困难
    • 在实时系统中这类问题尤为突出

原因 2:非阻塞编程要求“事件驱动”

  • nanosleep() 是线程安全的,但会让线程挂起
  • 会造成事件循环停滞
  • 正确做法:用定时器注册回调函数,让事件循环继续执行。

原因 3:timerfd 与 epoll完美结合

  • timerfd_create() 创建的定时器表现为一个文件描述符(fd)
  • 当定时到期,该 fd 就会“变得可读”;
  • 因此它能直接与 select()poll()epoll() 结合;
  • 统一处理网络I/O事件与定时事件,形成优雅一致的事件循环机制

原因 4:精度更高

  • epoll_wait()poll() 的 timeout 参数是毫秒级;
  • timerfd_settime() 可达 纳秒级 精度。

因此,timerfd 提供了高精度、统一接口、线程安全的定时解决方案。


四、Linux 定时与计时的现实限制

在非实时 Linux 系统中,不可能做到“绝对精确”的计时。

原因是:

  • Linux 是非实时调度系统
  • 任意时刻,内核可能把当前任务换出;
  • 尤其在 CPU 负载高时,误差更明显。

因此我们能做的只是提高“时间精度的可靠性”
比如:

  • 控制 CPU 负载;
  • 使用合适的优先级;
  • 利用高精度 timerfd;
  • 保证程序在“99.99% 的情况下”按预期执行。

五、精度 vs 分辨率

最后两者区别:

  • Resolution(分辨率):时间函数能“分出多细的时间单位”,比如微秒或纳秒;
  • Accuracy(准确度):返回值与真实时间的偏差;

举例:

你可能有一个 1 微秒分辨率的时钟,但在高负载时偏差达 100 微秒,这意味着分辨率高但准确度低。


六、总结对比表

功能类别典型函数精度是否阻塞线程是否依赖信号是否线程安全是否适合Reactor
计时gettimeofday()微秒
定时sleep()
定时nanosleep()纳秒
定时getitimer()微秒
定时timer_create()纳秒✅可控
定时timerfd_create()纳秒

七、核心理念总结

  • 获取时间:gettimeofday() —— 快、够精、用户态;
  • 定时任务:timerfd_* —— 精度高、无信号干扰、易于与 epoll 集成;
  • Reactor 统一事件模型:IO 与定时都用“fd”驱动;
  • 非实时系统中追求高可靠时间精度而非“绝对精确”。

http://www.dtcms.com/a/557236.html

相关文章:

  • 人工智能学习中深度学习之python基础之迭代器、生成器、文件处理和模块等
  • wordpress显示评论数福建企业seo推广
  • 12.C++:模版进阶
  • 大模型训练评估中的交叉验证详解
  • 变更股东怎样在工商网站做公示做网站的收费标准
  • (142页PPT)立白MES解决方案1Wonderware运营管理平台(附下载方式)
  • 机器学习日报10
  • Linux 2.6.10 调度器负载均衡机制深度解析:从理论到实现
  • 访链家网网站开发嘉定房地产网站建设
  • 多商户商城APP源码开发的未来方向:云原生、电商中台与智能客服
  • Liunx线程安全
  • 基于数据增强与对抗学习的门诊电子病历(EMR)文本分类python编程
  • 企业网站seo推广技巧建设视频网站设计意义
  • VSCode的插件配置同步到gitee
  • 短剧广告联盟 APP 用户画像:基于观看行为的广告精准投放模型
  • 找快照网站查询网站建设博采
  • [论文阅读] AI+ | AI如何重塑审计行业?从“手工筛查”到“智能决策”:AI审计的核心逻辑与未来路径
  • 论文精读:A review on multi-view learning(多视图学习综述)
  • 长宁制作网站网站建设属于会计哪个科目
  • 波动率建模(三)Heston模型及其Python实现
  • 左侧 导航 网站泰安信誉好的网络推广公司
  • python 初学2
  • 51单片机基础-LCD12864液晶显示
  • 在openSUSE-Leap-15.6-DVD-x86_64-Media自制应用软件离线包——备份91个视频解码器的rpm包
  • 《云原生基础设施》
  • dedecms手机网站开发怎么在网站底部添加备案号
  • 2019个人建网站利用关键词进网站后台
  • 物联网技术与应用传感器学习笔记
  • 云架构设计与实践:从基础到未来趋势
  • 【SDIO】【SDMMC】硬件层