if (ngx_save_argv(&init_cycle, argc, argv) != NGX_OK) {
return 1;
}
接着上次的解读,接下来应该是ngx_save_argv了,该函数就定义在core文件夹当中的nginx.c文件当中
//该函数的含义就是应该将用户输入的参数放在cycle当中
static ngx_int_t
ngx_save_argv(ngx_cycle_t *cycle, int argc, char *const *argv)
{
#if (NGX_FREEBSD)
ngx_os_argv = (char **) argv;
ngx_argc = argc;
ngx_argv = (char **) argv;
#else
size_t len;
ngx_int_t i;
ngx_os_argv = (char **) argv;
ngx_argc = argc;
//以上就是将参数保存在本函数的局部变量当中,而现在看看,使用ngx_alloc函数,开辟空间,ngx_argv是二维数组,
//我们开辟了参数个数加1个存放地址的空间,失败返回ERROR,ngx_argv是定义在os文件夹当中的unix文件夹当中的ngx_process.c文件当中的全局变量
ngx_argv = ngx_alloc((argc + 1) * sizeof(char *), cycle->log);
if (ngx_argv == NULL) {
return NGX_ERROR;
}
for (i = 0; i < argc; i++) {
//计算每个具体参数的长度,并为其开辟空间
len = ngx_strlen(argv[i]) + 1;
//为某个具体参数开辟空间
ngx_argv[i] = ngx_alloc(len, cycle->log);
if (ngx_argv[i] == NULL) {
return NGX_ERROR;
}
//将每一个参数复制到ngx_argv当中去,兵进行保存
(void) ngx_cpystrn((u_char *) ngx_argv[i], (u_char *) argv[i], len);
}
//最后一个作为标记,记为NULL
ngx_argv[i] = NULL;
#endif
ngx_os_environ = environ;//ngx_os_environ是定义在nginx.c文件当中的全局变量
return NGX_OK;
}
上述函数的主要作用就是将用户输入的参数放在全局变量ngx_argv当中。该变量位于os/unix/ngx_process.c文件当中
现在我们看下该函数中使用到的ngx_alloc函数,该函数的定义是在os文件夹当中的unix当中的ngx_alloc.c文件当中
void *
ngx_alloc(size_t size, ngx_log_t *log)
{
void *p;
//首先开辟size大小的内存空间
p = malloc(size);
if (p == NULL) {
//如果开辟空间失败,则进行日志记录
ngx_log_error(NGX_LOG_EMERG, log, ngx_errno,
"malloc(%uz) failed", size);
}
//进行日志记录,该函数定义在 /src/core/ngx_log.h 文件中
ngx_log_debug2(NGX_LOG_DEBUG_ALLOC, log, 0, "malloc: %p:%uz", p, size);
return p;
}
可以看到,ngx_alloc就是封装了malloc函数以及对该操作的日志记录,并且返回开辟空间的地址,其中NGX_LOG_EMERG(其值是1)变量的作用是,日志记录等级,
还有就是ngx_errono,
#define ngx_errno errno//os文件夹下的ngx_errno.h文件当中
现在看下日志记录模块ngx_log_error函数定义在core文件夹下的ngx_log.c文件当中
void ngx_cdecl
ngx_log_error(ngx_uint_t level, ngx_log_t *log, ngx_err_t err,
const char *fmt, ...)
{
va_list args;
if (log->log_level >= level) {
va_start(args, fmt);
ngx_log_error_core(level, log, err, fmt, args);
va_end(args);
}
}
可以看到该函数就是组合了一下传递进来的参数,根据最后将参数,传给ngx_log_error_core函数,该函数也是定义在ngx_log.c文件当中
void
ngx_log_error_core(ngx_uint_t level, ngx_log_t *log, ngx_err_t err,
const char *fmt, ...)
#else
void
ngx_log_error_core(ngx_uint_t level, ngx_log_t *log, ngx_err_t err,
const char *fmt, va_list args)
#endif
{
#if (NGX_HAVE_VARIADIC_MACROS)
va_list args;
#endif
u_char *p, *last, *msg;
u_char errstr[NGX_MAX_ERROR_STR];
//首先查看日志记录文件是否成功打开
if (log->file->fd == NGX_INVALID_FILE) {
return;
}
//日志记录的结束为止
last = errstr + NGX_MAX_ERROR_STR;
//日志记录的内容首先是时间
ngx_memcpy(errstr, ngx_cached_err_log_time.data,
ngx_cached_err_log_time.len);
//p是当前日志记录字符串的可写位置
p = errstr + ngx_cached_err_log_time.len;
//接下来就是将该要记录的日志等级进行输出,level是日志等级的数组索引
p = ngx_slprintf(p, last, " [%V] ", &err_levels[level]);
/* pid#tid *开始记录日志的进程ID*/
p = ngx_slprintf(p, last, "%P#" NGX_TID_T_FMT ": ",
ngx_log_pid, ngx_log_tid);
//看看该日志文件是否可写connection锁
if (log->connection) {
p = ngx_slprintf(p, last, "*%uA ", log->connection);
}
msg = p;
#if (NGX_HAVE_VARIADIC_MACROS)
va_start(args, fmt);
p = ngx_vslprintf(p, last, fmt, args);
va_end(args);
#else
//将传入的参数进行字符串化,方便我们写入日志文件
p = ngx_vslprintf(p, last, fmt, args);
#endif
//err是错误代码,如果不是0则是系统内置的错误,获得错误信息
if (err) {
p = ngx_log_errno(p, last, err);
}
if (level != NGX_LOG_DEBUG && log->handler) {
//这里进行了操作,但是是何种操作就不得而知了,
p = log->handler(log, p, last - p);
}
if (p > last - NGX_LINEFEED_SIZE) {
p = last - NGX_LINEFEED_SIZE;
}
//进行换行操作
ngx_linefeed(p);
//进行文件写入操作
(void) ngx_write_fd(log->file->fd, errstr, p - errstr);
if (!ngx_use_stderr
|| level > NGX_LOG_WARN
|| log->file->fd == ngx_stderr)
{
return;
}
msg -= (7 + err_levels[level].len + 3);
(void) ngx_sprintf(msg, "nginx: [%V] ", &err_levels[level]);
//显示在屏幕上的就是日志等级和错误信息
(void) ngx_write_console(ngx_stderr, msg, p - msg);
}
接下来就是
if (ngx_process_options(&init_cycle) != NGX_OK) {
return 1;
}
未完,待续...