您的位置:首页 > 运维架构 > Nginx

nginx之main函数的解读(七)

2014-10-15 10:27 2695 查看
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_H***E_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_H***E_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;
    }


未完,待续...
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: