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

Ubuntu 下 nginx-1.24.0 源码分析 - ngx_monotonic_time函数

声明

在 src\core\ngx_times.c 中:

static ngx_msec_t ngx_monotonic_time(time_t sec, ngx_uint_t msec);

实现 

在 src\core\ngx_times.c 中:

static ngx_msec_t
ngx_monotonic_time(time_t sec, ngx_uint_t msec)
{
#if (NGX_HAVE_CLOCK_MONOTONIC)struct timespec  ts;#if defined(CLOCK_MONOTONIC_FAST)clock_gettime(CLOCK_MONOTONIC_FAST, &ts);
#elseclock_gettime(CLOCK_MONOTONIC, &ts);
#endifsec = ts.tv_sec;msec = ts.tv_nsec / 1000000;#endifreturn (ngx_msec_t) sec * 1000 + msec;
}

通过 gcc -E 处理 预处理指令后

static ngx_msec_t
ngx_monotonic_time(time_t sec, ngx_uint_t msec)
{struct timespec ts;clock_gettime(
# 204 "src/core/ngx_times.c" 3 41
# 204 "src/core/ngx_times.c", &ts);sec = ts.tv_sec;msec = ts.tv_nsec / 1000000;return (ngx_msec_t) sec * 1000 + msec;
}

NGX_HAVE_CLOCK_MONOTONIC 宏

objs/ngx_auto_config.h:287:#define NGX_HAVE_CLOCK_MONOTONIC  1 

在 objs/ngx_auto_config.h 中

#ifndef NGX_HAVE_CLOCK_MONOTONIC
#define NGX_HAVE_CLOCK_MONOTONIC  1
#endif

NGX_HAVE_CLOCK_MONOTONIC 是一个宏定义,

用于指示系统是否支持 clock_gettime() 函数的 CLOCK_MONOTONIC 时钟源

CLOCK_MONOTONIC 是 POSIX 标准中定义的一种时钟类型,表示单调递增的时间。

CLOCK_REALTIME 不同,CLOCK_MONOTONIC 的时间不会因为系统时间的调整(例如用户手动修改系统时间或通过 NTP 同步)而发生跳变。因此,它非常适合用于测量时间间隔或计算超时

NGX_HAVE_CLOCK_MONOTONIC 宏的作用是检查当前系统是否支持 CLOCK_MONOTONIC

如果支持,Nginx 会使用 clock_gettime(CLOCK_MONOTONIC, ...) 来获取高精度的时间戳,从而实现更精确的时间管理

在 Nginx 的构建过程中,通常会通过 configure 脚本来检测系统是否支持 CLOCK_MONOTONIC

  1. 编译时,configure 脚本会尝试编译一段测试代码,调用 clock_gettime() 并传入 CLOCK_MONOTONIC 参数。

  2. 如果编译成功且运行正常,则说明系统支持 CLOCK_MONOTONIC,此时会在生成的配置头文件(如 objs/ngx_auto_config.h)中定义 NGX_HAVE_CLOCK_MONOTONIC 宏。

  3. 如果编译失败或运行异常,则不会定义该宏

CLOCK_MONOTONIC_FAST 宏

未定义

CLOCK_MONOTONIC_FAST 用于替代标准的 CLOCK_MONOTONIC,在保证时间单调递增的前提下,减少时间获取的系统调用开销

  • 在 FreeBSD 等类 Unix 系统中,CLOCK_MONOTONIC_FAST 是系统原生支持的时钟类型(通过 clock_gettime() 使用)。
  • 在 Linux 等不支持该时钟的系统上,Nginx 会通过宏定义将其回退到 CLOCK_MONOTONIC,确保兼容性。

CLOCK_MONOTONIC 表示一种单调递增的时间源,从系统启动(即内核初始化完成)开始计时 

  • 不受系统时间调整的影响 :即使管理员手动修改了系统时间(例如通过 date 命令或 NTP 服务),CLOCK_MONOTONIC 的值也不会受到影响。
  • 单调递增 :该时钟只会随着时间向前推进,不会回退(除非系统重启)。
  • 高分辨率 :通常提供纳秒级别的精度。

所以

clock_gettime(CLOCK_MONOTONIC, &ts);

成立

综上,在我的 Ubuntu 环境下运行的实际代码应该是:

static ngx_msec_t
ngx_monotonic_time(time_t sec, ngx_uint_t msec)
{struct timespec  ts;clock_gettime(CLOCK_MONOTONIC, &ts);sec = ts.tv_sec;msec = ts.tv_nsec / 1000000;return (ngx_msec_t) sec * 1000 + msec;
}

函数的目标是获取一个基于单调时间(monotonic time)的时间戳,以毫秒为单位返回。单调时间的特点是不会受到系统时间调整的影响,适合用于计时和超时检测等场景

定义一个 timespec 结构体变量 ts,用于存储通过 clock_gettime 获取的时间信息

struct timespec 是 POSIX 标准中定义的时间结构体,包含两个字段:

  • tv_sec:秒数部分。
  • tv_nsec:纳秒部分(1 秒 = 10^9 纳秒)。

调用 clock_gettime 函数,获取当前的单调时间,并将结果存储到 ts

CLOCK_MONOTONIC 是一种单调递增的时钟源,不会受到系统时间调整(如手动修改系统时间或 NTP 同步)的影响。

clock_gettime 是 POSIX 标准中的函数,用于获取高精度时间

ts.tv_sec(单调时间的秒数部分)赋值给函数参数 sec

ts.tv_nsec(纳秒部分)转换为毫秒,并赋值给函数参数 msec

将秒数转换为毫秒,并加上毫秒部分,最终返回一个以毫秒为单位的时间戳

clock_gettime 函数

 clock_gettime 是 POSIX 标准中定义的一个函数,用于获取高精度的时间信息。它能够从指定的时钟源(clock source)中读取当前时间,并以纳秒级精度返回结果。

函数原型

#include <time.h>int clock_gettime(clockid_t clk_id, struct timespec *tp);

    clk_id

    指定时钟源(clock source),决定了时间的来源。

    常见的时钟源包括:

    CLOCK_REALTIME :系统实时时间(wall-clock time),可以被手动调整或通过 NTP 同步。

    CLOCK_MONOTONIC :单调递增的时间,从某个固定点开始计时,不受系统时间调整的影响。

    CLOCK_PROCESS_CPUTIME_ID :进程的 CPU 时间。

    CLOCK_THREAD_CPUTIME_ID :线程的 CPU 时间。

    CLOCK_BOOTTIME (Linux 特有):类似于 CLOCK_MONOTONIC,但包括系统休眠时间。

    选择不同的时钟源会影响时间的用途。

    tp

    指向一个 struct timespec 结构体的指针,用于存储获取到的时间信息。

    返回值

    • 成功时返回 0
    • 失败时返回 -1,并设置 errno 表示错误原因。

    http://www.lryc.cn/news/535766.html

    相关文章:

  1. 业务开发 | 基础知识 | Maven 快速入门
  2. 基于 Python(Flask)、JavaScript、HTML 和 CSS 实现前后端交互的详细开发过程
  3. STM32 RCC功能说明 复位和时钟控制RCC
  4. Windows可以永久暂停更新了
  5. 高级 Python Web 开发:基于 FastAPI 构建高效实时聊天系统与并发控制
  6. 深入理解Java虚拟机(JVM)
  7. 笔试面试——逻辑题
  8. 【深度学习入门实战】基于Keras的手写数字识别实战(附完整可视化分析)
  9. 软考高级《系统架构设计师》知识点(一)
  10. 用大模型学大模型01-制定学习计划
  11. lvs的DR模式
  12. mysql读写分离与proxysql的结合
  13. 【C++学习篇】C++11第二期学习
  14. TextWebSocketHandler 和 @ServerEndpoint 各自实现 WebSocket 服务器
  15. 【C++高并发服务器WebServer】-18:事件处理模式与线程池
  16. 23种设计模式的定义和应用场景-02-结构型模式-C#代码
  17. 数据脱敏方案总结
  18. 自然语言处理NLP入门 -- 第二节预处理文本数据
  19. 02.10 TCP之文件传输
  20. 基于STM32的ADS1230驱动例程
  21. Bro想要玩github api
  22. idea插件开发,如何获取idea设置的系统语言
  23. 怎麼使用靜態住宅IP進行多社媒帳號管理
  24. InfiniBand与IP over InfiniBand(IPOIB):实现高性能网络通信的底层机制
  25. 掌握 PHP 单例模式:构建更高效的应用
  26. 实现限制同一个账号最多只能在3个客户端(有电脑、手机等)登录(附关键源码)
  27. Python入门全攻略(四)
  28. Ubuntu 22.04 - OpenLDAP安装使用(服务器+LAM+客户端)
  29. Linux ARM64 将内核虚拟地址转化为物理地址
  30. 使用 Visual Studio Code (VS Code) 开发 Python 图形界面程序