当前位置: 首页 > 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 表示错误原因。

    相关文章:

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

    声明 在 src\core\ngx_times.c 中&#xff1a; static ngx_msec_t ngx_monotonic_time(time_t sec, ngx_uint_t msec); 实现 在 src\core\ngx_times.c 中&#xff1a; static ngx_msec_t ngx_monotonic_time(time_t sec, ngx_uint_t msec) { #if (NGX_HAVE_CLOCK_MONOTONIC)st…...

    业务开发 | 基础知识 | Maven 快速入门

    Maven 快速入门 1.Maven 全面概述 Apache Maven 是一种软件项目管理和理解工具。基于项目对象模型的概念&#xff08;POM&#xff09;&#xff0c;Maven 可以从中央信息中管理项目的构建&#xff0c;报告和文档。 2.Maven 基本功能 因此实际上 Maven 的基本功能就是作为 Ja…...

    基于 Python(Flask)、JavaScript、HTML 和 CSS 实现前后端交互的详细开发过程

    以下是一个基于 Python&#xff08;Flask&#xff09;、JavaScript、HTML 和 CSS 实现前后端交互的详细开发过程&#xff1a; --- ### 一、技术选型 1. **后端**&#xff1a;Python Flask&#xff08;轻量级Web框架&#xff09; 2. **前端**&#xff1a;HTML/CSS JavaScript&…...

    STM32 RCC功能说明 复位和时钟控制RCC

    目录 背景 RCC配置时钟主要涉及两方面 程序 第1步、RCC默认初始化 第2步、等待HSE工作稳定 第3步、设置PLL时钟源以及倍频数 第4步、设置AHB总线时钟&#xff08;HCLK&#xff09; 第5步、设置PCLK1(APB1总线) 第6步、设置PCLK2(APB2总线) 第7步、FLASH存储器的配置 …...

    Windows可以永久暂停更新了

    最终效果图&#xff1a; 第一步&#xff1a; winR组合键打开运行对话框&#xff0c;输入“regedit”&#xff0c;点击“确定”或回车&#xff1a; 第二步&#xff1a; 注册表定位到“\HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\WindowsUpdate\UX\Settings”&#xff0c;新建DWO…...

    高级 Python Web 开发:基于 FastAPI 构建高效实时聊天系统与并发控制

    高级 Python Web 开发&#xff1a;基于 FastAPI 构建高效实时聊天系统与并发控制 目录 &#x1f310; WebSocket 实时通讯概述&#x1f4ac; FastAPI 中实现 WebSocket 聊天系统&#x1f527; WebSocket 并发控制与性能优化&#x1f512; WebSocket 安全性与认证机制&#x1…...

    深入理解Java虚拟机(JVM)

    JVM概述 JVM作用 java虚拟机负责装载字节码到其内部&#xff0c;解释/编译为对应平台上的机器码指令执行&#xff0c;通俗说就是将字节码转换为机器码 JVM内部构造 1、类加载部分&#xff1a;负责把硬盘上的字节码加载到内存中&#xff08;运行时数据区&#xff09; 2、运…...

    笔试面试——逻辑题

    1.n从1开始&#xff0c;每个操作可以选择对n加1或者对n加倍&#xff0c;若想获得整数2014&#xff0c;最少需要多少个操作。 2.一个池塘&#xff0c;养龙虾若干&#xff0c;请想一个办法尽量准确的估算其中有多少龙虾? 3. S先生&#xff0c;P先生&#xff0c;Q先生他们知道桌子…...

    【深度学习入门实战】基于Keras的手写数字识别实战(附完整可视化分析)

    ​ 本人主页:机器学习司猫白 ok,话不多说,我们进入正题吧 项目概述 本案例使用经典的MNIST手写数字数据集,通过Keras构建全连接神经网络,实现0-9数字的分类识别。文章将包含: 关键概念图解完整实现代码训练过程可视化模型效果深度分析环境准备 import numpy as np impo…...

    软考高级《系统架构设计师》知识点(一)

    计算机硬件 校验码 码距&#xff1a;就单个编码A:00而言&#xff0c;其码距为1&#xff0c;因为其只需要改变一位就变成另一个编码。在两个编码中&#xff0c;从A码到B码转换所需要改变的位数称为码距&#xff0c;如A:00要转换为B:11&#xff0c;码距为2。一般来说&#xff0c;…...

    用大模型学大模型01-制定学习计划

    提示词&#xff1a;我想学习大模型&#xff0c;需要AI制定一个完整的学习计划&#xff0c;并给出学习路径和学习资料。以教科书目录的方式给出学习路线 第1章&#xff1a;数学与编程基础&#xff08;4-6周&#xff09; 1.1 数学基础 线性代数&#xff08;矩阵运算、特征值分…...

    lvs的DR模式

    基于Linux的负载均衡集群软件 LVS 全称为Linux Virtual Server,是一款开源的四层(传输层)负载均衡软件 Nginx 支持四层和七层(应用层)负载均衡 HAProxy 和Nginx一样,也可同时支持四层和七层(应用层)负载均衡 基于Linux的高可用集群软件 Keepalived Keepalived是Linux…...

    mysql读写分离与proxysql的结合

    上一篇文章介绍了mysql如何设置成主从复制模式&#xff0c;而主从复制的目的&#xff0c;是为了读写分离。 读写分离&#xff0c;拿spring boot项目来说&#xff0c;可以有2种方式&#xff1a; 1&#xff09;设置2个数据源&#xff0c;读和写分开使用 2&#xff09;使用中间件…...

    【C++学习篇】C++11第二期学习

    目录 1. 可变参数模板 1.1 基本语法及原理 1.2 包扩展 1.3empalce系列接⼝ 2. lamba 2.1 lambda的语法表达式 2.2 捕捉列表 2.3 lamba的原理 1. 可变参数模板 1.1 基本语法及原理 1. C11⽀持可变参数模板&#xff0c;也就是说⽀持可变数量参数的函数模板和类模板&…...

    TextWebSocketHandler 和 @ServerEndpoint 各自实现 WebSocket 服务器

    TextWebSocketHandler 和 ServerEndpoint 都可以用于实现 WebSocket 服务器&#xff0c;但它们属于不同的技术栈&#xff0c;使用方式和功能有一些区别。以下是它们的对比&#xff1a; 1. 技术栈对比 特性TextWebSocketHandler (Spring)ServerEndpoint (Java EE/JSR-356)所属框…...

    【C++高并发服务器WebServer】-18:事件处理模式与线程池

    本文目录 一、事件处理模式1.1 Reactor模式1.2 Proactor模式1.3 同步IO模拟Proactor模式 二、线程池 一、事件处理模式 服务器程序通常需要处理三类事件&#xff1a;I/O事件、信号、定时事件。 对应的有两种高效的事件处理模式&#xff1a;Reactor和Proactor&#xff0c;同步…...

    23种设计模式的定义和应用场景-02-结构型模式-C#代码

    23种设计模式的定义和应用场景&#xff1a; 1. 创建型模式&#xff08;共5种&#xff09;&#xff1a; 单例模式&#xff08;Singleton&#xff09;、工厂方法模式&#xff08;Factory Method&#xff09;、抽象工厂模式&#xff08;Abstract Factory&#xff09;、建造者模式…...

    数据脱敏方案总结

    什么是数据脱敏 数据脱敏的定义 数据脱敏百度百科中是这样定义的&#xff1a; 数据脱敏&#xff0c;指对某些敏感信息通过脱敏规则进行数据的变形&#xff0c;实现敏感隐私数据的可靠保护。这样就可以在开发、测试和其它非生产环境以及外包环境中安全地使用脱敏后的真实数据集…...

    自然语言处理NLP入门 -- 第二节预处理文本数据

    在自然语言处理&#xff08;NLP&#xff09;中&#xff0c;数据的质量直接影响模型的表现。文本预处理的目标是清理和标准化文本数据&#xff0c;使其适合机器学习或深度学习模型处理。本章介绍几种常见的文本预处理方法&#xff0c;并通过 Python 代码进行示例。 2.1 文本清理…...

    02.10 TCP之文件传输

    1.思维导图 2.作业 服务器代码&#xff1a; #include <stdio.h> #include <string.h> #include <unistd.h> #include <stdlib.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <pthread.h> …...

    FFmpeg 低延迟同屏方案

    引言 在实时互动需求激增的当下&#xff0c;无论是在线教育中的师生同屏演示、远程办公的屏幕共享协作&#xff0c;还是游戏直播的画面实时传输&#xff0c;低延迟同屏已成为保障用户体验的核心指标。FFmpeg 作为一款功能强大的多媒体框架&#xff0c;凭借其灵活的编解码、数据…...

    CRMEB 框架中 PHP 上传扩展开发:涵盖本地上传及阿里云 OSS、腾讯云 COS、七牛云

    目前已有本地上传、阿里云OSS上传、腾讯云COS上传、七牛云上传扩展 扩展入口文件 文件目录 crmeb\services\upload\Upload.php namespace crmeb\services\upload;use crmeb\basic\BaseManager; use think\facade\Config;/*** Class Upload* package crmeb\services\upload* …...

    Spring AI与Spring Modulith核心技术解析

    Spring AI核心架构解析 Spring AI&#xff08;https://spring.io/projects/spring-ai&#xff09;作为Spring生态中的AI集成框架&#xff0c;其核心设计理念是通过模块化架构降低AI应用的开发复杂度。与Python生态中的LangChain/LlamaIndex等工具类似&#xff0c;但特别为多语…...

    CMake控制VS2022项目文件分组

    我们可以通过 CMake 控制源文件的组织结构,使它们在 VS 解决方案资源管理器中以“组”(Filter)的形式进行分类展示。 🎯 目标 通过 CMake 脚本将 .cpp、.h 等源文件分组显示在 Visual Studio 2022 的解决方案资源管理器中。 ✅ 支持的方法汇总(共4种) 方法描述是否推荐…...

    【C++特殊工具与技术】优化内存分配(一):C++中的内存分配

    目录 一、C 内存的基本概念​ 1.1 内存的物理与逻辑结构​ 1.2 C 程序的内存区域划分​ 二、栈内存分配​ 2.1 栈内存的特点​ 2.2 栈内存分配示例​ 三、堆内存分配​ 3.1 new和delete操作符​ 4.2 内存泄漏与悬空指针问题​ 4.3 new和delete的重载​ 四、智能指针…...

    Vite中定义@软链接

    在webpack中可以直接通过符号表示src路径&#xff0c;但是vite中默认不可以。 如何实现&#xff1a; vite中提供了resolve.alias&#xff1a;通过别名在指向一个具体的路径 在vite.config.js中 import { join } from pathexport default defineConfig({plugins: [vue()],//…...

    tauri项目,如何在rust端读取电脑环境变量

    如果想在前端通过调用来获取环境变量的值&#xff0c;可以通过标准的依赖&#xff1a; std::env::var(name).ok() 想在前端通过调用来获取&#xff0c;可以写一个command函数&#xff1a; #[tauri::command] pub fn get_env_var(name: String) -> Result<String, Stri…...

    GraphQL 实战篇:Apollo Client 配置与缓存

    GraphQL 实战篇&#xff1a;Apollo Client 配置与缓存 上一篇&#xff1a;GraphQL 入门篇&#xff1a;基础查询语法 依旧和上一篇的笔记一样&#xff0c;主实操&#xff0c;没啥过多的细节讲解&#xff0c;代码具体在&#xff1a; https://github.com/GoldenaArcher/graphql…...

    2025年低延迟业务DDoS防护全攻略:高可用架构与实战方案

    一、延迟敏感行业面临的DDoS攻击新挑战 2025年&#xff0c;金融交易、实时竞技游戏、工业物联网等低延迟业务成为DDoS攻击的首要目标。攻击呈现三大特征&#xff1a; AI驱动的自适应攻击&#xff1a;攻击流量模拟真实用户行为&#xff0c;差异率低至0.5%&#xff0c;传统规则引…...

    字符串哈希+KMP

    P10468 兔子与兔子 #include<bits/stdc.h> using namespace std; typedef unsigned long long ull; const int N 1000010; ull a[N], pw[N]; int n; ull gethash(int l, int r){return a[r] - a[l - 1] * pw[r - l 1]; } signed main(){ios::sync_with_stdio(false), …...