欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 文旅 > 艺术 > Ubuntu 下 nginx-1.24.0 源码分析 - ngx_monotonic_time函数

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

2025/2/13 19:46:23 来源:https://blog.csdn.net/weixin_41812346/article/details/145592446  浏览:    关键词: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 表示错误原因。

    版权声明:

    本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

    我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com