之前一直提到:未看到过任何详细初始化su_log_t结构体变量的代码。可以说,su_default_log.h代码向我们展示了如何详细初始化su_log文件中申明的su_log_default变量。
su_log_t su_log_default[1] = {{
sizeof(su_log_t),
"sofia", /* Log name */
"SOFIA_DEBUG", /* Environment variable controlling logging level */
SOFIA_DEBUG_, /* Default level */
SU_LOG_MAX, /* Maximum log level */
0,
default_logger,
NULL
}};
从上述代码可以看出,su_log_default的名称是“sofia”,可使用的日志等级环境变量是SOFIA_DEBUG,缺省日志等级由SOFIA_DEBUG_宏决定。更关键一点是,日志输出函数确定是default_logger。可惜这里还是没看到指定stream。
static void default_logger(void *stream, char const *fmt, va_list ap)
{
FILE *f = stream ? (FILE *)stream : stderr;
vfprintf(f, fmt, ap);
}
由日志输出函数定义可看出,缺省会使用stderr作为输出流。
su_global_log.c文件内主要内容如下:
extern char const SU_DEBUG[];
#endif
#ifdef SU_DEBUG
#define SU_DEBUG_ SU_DEBUG
#else
#define SU_DEBUG_ 3
#endif
/**Debug log for @b su module.
*
* The su_log_global is the log object used by @b su module. The level of
* #su_log_global is set using #SU_DEBUG environment variable.
*/
su_log_t su_log_global[1] = {{
sizeof(su_log_t),
"su",
"SU_DEBUG",
SU_DEBUG_,
SU_LOG_MAX,
0,
NULL,
NULL
}};
如上述代码所示,su_log_global的目的是让缺省日志输出有个出口,虽然这个出口没任何作用:因为它没有实际的输出函数。
至此,终于搞明白了su提供的基础日志服务中su_log_default和su_log_global两个变量何时被详细初始化。同时,也搞明白了c库向上层应用提供基础服务时该采用什么样的设计策略。
简单总结下:
1、su_log文件提供日志基础构件;
2、su_debug.h文件提供各个模块自身使用日志服务所需的SU_DEBUG_0至SU_DEBUG_9宏;
3、su_module_debug文件提供su模块自身使用基础日志服务所需的宏;
4、su_default_log和su_global_log文件初始化su_log_default和su_log_global变量;
5、其他模块使用日志基础服务,必须首先用自身的su_log_t结构体变量重定义SU_LOG,然后再包括su_debug.h头文件。