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

ngx_log_error

声明在 src\core\ngx_log.h 中:

但是通过检索找到了 3 个结果

复制代码
#if (NGX_HAVE_C99_VARIADIC_MACROS)

#define NGX_HAVE_VARIADIC_MACROS  1

#define ngx_log_error(level, log, ...)                                        \
    if ((log)->log_level >= level) ngx_log_error_core(level, log, __VA_ARGS__)

void ngx_log_error_core(ngx_uint_t level, ngx_log_t *log, ngx_err_t err,
    const char *fmt, ...);

#define ngx_log_debug(level, log, ...)                                        \
    if ((log)->log_level & level)                                             \
        ngx_log_error_core(NGX_LOG_DEBUG, log, __VA_ARGS__)

/*********************************/

#elif (NGX_HAVE_GCC_VARIADIC_MACROS)

#define NGX_HAVE_VARIADIC_MACROS  1

#define ngx_log_error(level, log, args...)                                    \
    if ((log)->log_level >= level) ngx_log_error_core(level, log, args)

void ngx_log_error_core(ngx_uint_t level, ngx_log_t *log, ngx_err_t err,
    const char *fmt, ...);

#define ngx_log_debug(level, log, args...)                                    \
    if ((log)->log_level & level)                                             \
        ngx_log_error_core(NGX_LOG_DEBUG, log, args)

/*********************************/

#else /* no variadic macros */

#define NGX_HAVE_VARIADIC_MACROS  0

void ngx_cdecl ngx_log_error(ngx_uint_t level, ngx_log_t *log, ngx_err_t err,
    const char *fmt, ...);
void ngx_log_error_core(ngx_uint_t level, ngx_log_t *log, ngx_err_t err,
    const char *fmt, va_list args);
void ngx_cdecl ngx_log_debug_core(ngx_log_t *log, ngx_err_t err,
    const char *fmt, ...);


#endif /* variadic macros */

通过 gcc -E 先来看一下结果:

复制代码
gcc -E src/event/ngx_event_openssl.c \
	-I src/core \
	-I src/event \
	-I src/event/modules \
	-I src/os/unix \
	-I objs \
	> ngx_event_openssl_preprocessed.c

在输出文件 ngx_event_openssl_preprocessed.c 中查找 ngx_ssl_error

复制代码
void
ngx_ssl_error(ngx_uint_t level, ngx_log_t *log, ngx_err_t err, char *fmt, ...)
{
    int flags;
    u_long n;
    va_list args;
    u_char *p, *last;
    u_char errstr[1024];
    const char *data;

    last = errstr + 1024;

    
# 3623 "src/event/ngx_event_openssl.c" 3 4
   __builtin_va_start(
# 3623 "src/event/ngx_event_openssl.c"
   args
# 3623 "src/event/ngx_event_openssl.c" 3 4
   ,
# 3623 "src/event/ngx_event_openssl.c"
   fmt
# 3623 "src/event/ngx_event_openssl.c" 3 4
   )
# 3623 "src/event/ngx_event_openssl.c"
                      ;
    p = ngx_vslprintf(errstr, last - 1, fmt, args);
    
# 3625 "src/event/ngx_event_openssl.c" 3 4
   __builtin_va_end(
# 3625 "src/event/ngx_event_openssl.c"
   args
# 3625 "src/event/ngx_event_openssl.c" 3 4
   )
# 3625 "src/event/ngx_event_openssl.c"
               ;

    if (ERR_peek_error()) {
        p = ngx_cpystrn(p, (u_char *) " (SSL:", last - p);

        for ( ;; ) {

            n = ERR_peek_error_data(&data, &flags);

            if (n == 0) {
                break;
            }



            if (p >= last - 1) {
                goto next;
            }

            *p++ = ' ';

            ERR_error_string_n(n, (char *) p, last - p);

            while (p < last && *p) {
                p++;
            }

            if (p < last && *data && (flags & 
# 3652 "src/event/ngx_event_openssl.c" 3 4
                                             0x02
# 3652 "src/event/ngx_event_openssl.c"
                                                           )) {
                *p++ = ':';
                p = ngx_cpystrn(p, (u_char *) data, last - p);
            }

        next:

            (void) ERR_get_error();
        }

        if (p < last) {
            *p++ = ')';
        }
    }

    if ((log)->log_level >= level) ngx_log_error_core(level, log, err, "%*s", p - errstr, errstr);
}

原本

复制代码
ngx_log_error(level, log, err, "%*s", p - errstr, errstr);

对应的地方现在是:

复制代码
if ((log)->log_level >= level) ngx_log_error_core(level, log, err, "%*s", p - errstr, errstr);

再回到 src\core\ngx_log.h 中

成立的是这部分

复制代码
#define ngx_log_error(level, log, ...)                                        \
    if ((log)->log_level >= level) ngx_log_error_core(level, log, __VA_ARGS__)

NGX_HAVE_C99_VARIADIC_MACROS

NGX_HAVE_GCC_VARIADIC_MACROS

定义在 objs/ngx_auto_config.h 中:

复制代码
#ifndef NGX_HAVE_C99_VARIADIC_MACROS
#define NGX_HAVE_C99_VARIADIC_MACROS  1
#endif


#ifndef NGX_HAVE_GCC_VARIADIC_MACROS
#define NGX_HAVE_GCC_VARIADIC_MACROS  1
#endif

NGX_HAVE_C99_VARIADIC_MACROS 和 NGX_HAVE_GCC_VARIADIC_MACROS 是 Nginx 源码中用于检测编译器是否支持 **可变参数宏(Variadic Macros)**的两个宏。

它们的作用是帮助 Nginx 在不同编译器和标准下选择合适的实现方式,以确保代码的兼容性和正确性。


什么是可变参数宏?

在 C 语言中,可变参数宏 是一种允许宏定义接受可变数量参数的功能。它的语法类似于函数的可变参数(...),但用于预处理器宏。


C99 标准中的可变参数宏

C99 标准引入了对可变参数宏的支持,语法如下:

复制代码
#define LOG_ERROR(fmt, ...) printf(fmt, ##__VA_ARGS__)

__VA_ARGS__: 表示宏调用时传递的所有额外参数

##__VA_ARGS__: 在某些编译器中(如 GCC),可以用来处理空参数的情况,避免多余的逗号


GCC 扩展中的可变参数宏

在 C99 标准之前,GCC 编译器已经通过扩展支持了可变参数宏,语法与 C99 类似,但在某些细节上可能有所不同。

GCC 风格的可变参数宏使用 args... 来表示可变参数部分,而不是 C99 标准中的 __VA_ARGS__

其基本语法如下:

复制代码
#define MACRO_NAME(fixed_args, args...) implementation_using_args
  • fixed_args: 宏的固定参数。
  • args... : 表示可变参数部分,类似于函数中的 ...。
  • ##args : 在 GCC 扩展中,可以使用 ## 来处理空参数的情况,避免多余的逗号。

NGX_HAVE_C99_VARIADIC_MACROS
  • 含义 : 表示当前编译环境是否支持 C99 标准的可变参数宏。
  • 检测方式: 通常通过检查编译器是否支持 C99 标准来定义该宏。
  • 用途: 如果定义了该宏,Nginx 可以使用 C99 风格的可变参数宏。
NGX_HAVE_GCC_VARIADIC_MACROS
  • 含义 : 表示当前编译环境是否支持 GCC 扩展的可变参数宏。
  • 检测方式: 通常通过检查编译器是否为 GCC 或兼容 GCC 的编译器来定义该宏。
  • 用途: 如果定义了该宏,Nginx 可以使用 GCC 风格的可变参数宏。

  • 如果支持 C99 标准,则使用 __VA_ARGS__
  • 如果仅支持 GCC 扩展,则使用 args...

回到 ngx_log_error 的定义中来:

复制代码
#define ngx_log_error(level, log, ...)                                        \
    if ((log)->log_level >= level) ngx_log_error_core(level, log, __VA_ARGS__)
(log)->log_level

表示当前日志对象允许记录的最低日志级别


level

指定当前日志消息的级别


(log)->log_level >= level

比较当前日志对象的配置级别和日志消息的级别

  • 如果 log->log_level 大于或等于 level,表示当前日志消息的严重程度足够高,应该被记录。
  • 否则,跳过日志记录,避免不必要的性能开销

ngx_log_error_core(level, log, __VA_ARGS__)

调用核心日志函数,实际执行日志记录操作

  • level: 当前日志消息的级别。
  • log: 日志对象,包含日志的输出目标(如文件、标准错误等)。
  • __VA_ARGS__: 可变参数,表示格式化字符串及其参数(类似于 printf 的参数)

下面的 问题是 ngx_log_error_core

声明在 src\core\ngx_log.h 中:

复制代码
void ngx_log_error_core(ngx_uint_t level, ngx_log_t *log, ngx_err_t err,
    const char *fmt, ...);

Ubuntu 下 nginx-1.24.0 源码分析 - ngx_log_error_core 函数-CSDN博客

相关推荐
KIDULT°5 小时前
MySQL系列 (1):数据库原理
运维·数据库·mysql·云计算
wewowilling8 小时前
认识微服务
java·运维·微服务·springcloud
玖石书8 小时前
Ubuntu 24.04 UFW 全命令攻略:从入门到端口开放实战
linux·运维·ubuntu
weifont10 小时前
自动化抓取和上架商品:能不动手,就少动手
运维·前端·自动化
拂拉氏10 小时前
【知识讲解】 Linux之动静态库的了解
linux·运维·服务器·动静态库
Mikko711 小时前
Linux 重启后日志没了?进程被 OOM 杀了去哪看?logrotate 之后日志还往旧文件写?三台真机实测日志与性能排查
linux·运维·centos
光依旧11 小时前
发版就掉请求?Spring Boot优雅停机的四步
运维·spring boot·nginx·高可用·优雅停机·mcp server
yichengerp13 小时前
电子行业常用erp系统有哪些?推荐适合中小电子厂的易呈erp软件,操作简单,易落地
大数据·运维·人工智能·云计算·制造
天国梦13 小时前
国密门禁品牌怎么选?2026年最新3个避坑要点
运维·服务器·数据库·python
信可维14 小时前
自动化操作多平台账号:登录态、双会话与 User Data 的 3 个坑
运维·自动化