ngx_time_sigsafe_update
1 定义ngx_time_sigsafe_update 函数 定义在 ./nginx-1.24.0/src/core/ngx_times.cvoidngx_time_sigsafe_update(void){u_char*p,*p2;ngx_tm_ttm;time_tsec;ngx_time_t*tp;structtimevaltv;if(!ngx_trylock(ngx_time_lock)){return;}ngx_gettimeofday(tv);sectv.tv_sec;tpcached_time[slot];if(tp-secsec){ngx_unlock(ngx_time_lock);return;}if(slotNGX_TIME_SLOTS-1){slot0;}else{slot;}tpcached_time[slot];tp-sec0;ngx_gmtime(seccached_gmtoff*60,tm);pcached_err_log_time[slot][0];(void)ngx_sprintf(p,%4d/%02d/%02d %02d:%02d:%02d,tm.ngx_tm_year,tm.ngx_tm_mon,tm.ngx_tm_mday,tm.ngx_tm_hour,tm.ngx_tm_min,tm.ngx_tm_sec);p2cached_syslog_time[slot][0];(void)ngx_sprintf(p2,%s %2d %02d:%02d:%02d,months[tm.ngx_tm_mon-1],tm.ngx_tm_mday,tm.ngx_tm_hour,tm.ngx_tm_min,tm.ngx_tm_sec);ngx_memory_barrier();ngx_cached_err_log_time.datap;ngx_cached_syslog_time.datap2;ngx_unlock(ngx_time_lock);}ngx_time_sigsafe_update 函数的核心作用是 在信号处理上下文中安全且高效地刷新 Nginx 的全局时间缓存与预格式化时间字符串。2 详解1 函数签名voidngx_time_sigsafe_update(void)返回值 无返回值 该函数执行一个副作用操作 更新全局时间缓存数组、刷新日志时间字符串指针。 调用者无需获取任何返回值因为所有更新结果都直接写入全局变量参数 不需要参数2 逻辑流程1 局部变量 2 获取锁 3 更新时间 4 更新格式化时间字符串 5 释放锁1 局部变量{u_char*p,*p2;ngx_tm_ttm;time_tsec;ngx_time_t*tp;structtimevaltv;2 获取锁if(!ngx_trylock(ngx_time_lock)){return;}ngx_time_lock 全局的自旋锁变量 ngx_trylock 尝试获取 ngx_time_lock 成功 → 返回 1真!1 为假跳过 if 块继续执行后续更新逻辑。 失败锁已被占用→ 返回 0假!0 为真进入 if 块。 放弃更新 函数立即终止返回调用者3 更新时间ngx_gettimeofday(tv);sectv.tv_sec;tpcached_time[slot];#1 获取当前系统时间填充到 tv #2 将 tv.tv_sec 的值存入 sec sec 作为当前时间的秒级标识 #3 获取当前环形缓冲区槽位对应的 ngx_time_t 结构体指针 并赋值给局部指针变量 tpif(tp-secsec){ngx_unlock(ngx_time_lock);return;}检查当前槽位中时间的秒数 两者相等说明缓存已经是最新值。 一秒只更新一次同一秒 表示缓存未过期无需更新 释放已获取的锁 立即终止函数执行if(slotNGX_TIME_SLOTS-1){slot0;}else{slot;}时间缓存已经过期 更新 slot 指向下一个槽位 如果索引已经到达末尾将其重置为 0tpcached_time[slot];tp 指向新的槽位tp-sec0;赋值为零这是一个无效的秒数值 标记 当前这个槽位的时间缓存是 无效的ngx_gmtime(seccached_gmtoff*60,tm);将 UTC 时间戳转换为本地时间的年、月、日、时、分、秒并存入 tm 结构体。 sec当前 UTC 秒数 cached_gmtoff预缓存的时区偏移量单位分钟如东八区为 480 * 60将分钟转为秒与 sec 相加得到本地时间戳 ngx_gmtimeNginx 自实现的日历分解函数将本地时间戳拆解为 ngx_tm_t 结构的各字段4 更新格式化时间字符串pcached_err_log_time[slot][0];(void)ngx_sprintf(p,%4d/%02d/%02d %02d:%02d:%02d,tm.ngx_tm_year,tm.ngx_tm_mon,tm.ngx_tm_mday,tm.ngx_tm_hour,tm.ngx_tm_min,tm.ngx_tm_sec);p2cached_syslog_time[slot][0];(void)ngx_sprintf(p2,%s %2d %02d:%02d:%02d,months[tm.ngx_tm_mon-1],tm.ngx_tm_mday,tm.ngx_tm_hour,tm.ngx_tm_min,tm.ngx_tm_sec);ngx_memory_barrier();ngx_cached_err_log_time.datap;ngx_cached_syslog_time.datap2;ngx_memory_barrier() 插入编译器与 CPU 级别的内存屏障 保证在此之前的对 内存的写操作 对于其他 CPU 核心或执行流完全可见 且不会被编译器或 CPU 重排序到屏障之后。5 释放锁ngx_unlock(ngx_time_lock);}