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
的参数)