发布日期:2013-03-25 09:55 来源:未知 标签: Nginx 模块
 

Content
0. 序
1. Core模块的配置结构
2. create_conf分析
3. init_conf分析
4. 小结


0. 序

在<Nginx源码分析—全局变量ngx_cycle的初始化>(见 http://www.codesky.net/Linux/2012-02/54739.htm )中,简单介绍了如何调用core模块的callback,并简单列出其定义及其初始化,本文将重点阐述callback做什么。


1. Core模块的配置结构

如前文所述,core模块的callback有两个create_conf()和init_conf(),从名字就可以看出,一个创建配置结构,另一个初始化该配置结构。core模块的配置结构如下,存放配置文件中的核心指令,如deamon,master等。

./src/core/ngx_cycle.h

[cpp]
typedef struct { 
     ngx_flag_t               daemon; 
     ngx_flag_t               master; 
 
     ngx_msec_t               timer_resolution; 
 
     ngx_int_t                worker_processes; 
     ngx_int_t                debug_points; 
 
     ngx_int_t                rlimit_nofile; 
     ngx_int_t                rlimit_sigpending; 
     off_t                    rlimit_core; 
 
     int                      priority; 
 
     ngx_uint_t               cpu_affinity_n; 
     u_long                  *cpu_affinity; 
 
     char                    *username;            /* 用户名 */ 
     ngx_uid_t                user;                /* user ID */ 
     ngx_gid_t                group;               /* group ID*/ 
 
     ngx_str_t                working_directory;   /*  */ 
     ngx_str_t                lock_file;           /* 用户名 */ 
 
     ngx_str_t                pid; 
     ngx_str_t                oldpid;              /* 以'.oldbin'结尾 */ 
 
     ngx_array_t              env; 
     char                   **environment; 
 
#if (NGX_THREADS)  
     ngx_int_t                worker_threads; 
     size_t                   thread_stack_size; 
#endif  
 
} ngx_core_conf_t; 

2. create_conf分析

create_conf只是指针,CORE模块的create_conf指向ngx_core_module_init_conf()函数,该函数创建ngx_core_conf_t配置结构。

[cpp]
static void * 
ngx_core_module_create_conf(ngx_cycle_t *cycle) 

    ngx_core_conf_t  *ccf; 
 
    ccf = ngx_pcalloc(cycle->pool, sizeof(ngx_core_conf_t)); 
    if (ccf == NULL) { 
        return NULL; 
    } 
 
    /*
     * set by ngx_pcalloc()
     *
     *     ccf->pid = NULL;
     *     ccf->oldpid = NULL;
     *     ccf->priority = 0;
     *     ccf->cpu_affinity_n = 0;
     *     ccf->cpu_affinity = NULL;
     */ 
 
    ccf->daemon = NGX_CONF_UNSET; 
    ccf->master = NGX_CONF_UNSET; 
    ccf->timer_resolution = NGX_CONF_UNSET_MSEC; 
 
    ccf->worker_processes = NGX_CONF_UNSET; 
    ccf->debug_points = NGX_CONF_UNSET; 
 
    ccf->rlimit_nofile = NGX_CONF_UNSET; 
    ccf->rlimit_core = NGX_CONF_UNSET; 
    ccf->rlimit_sigpending = NGX_CONF_UNSET; 
 
    ccf->user = (ngx_uid_t) NGX_CONF_UNSET_UINT; 
    ccf->group = (ngx_gid_t) NGX_CONF_UNSET_UINT; 
 
#if (NGX_THREADS)  
    ccf->worker_threads = NGX_CONF_UNSET; 
    ccf->thread_stack_size = NGX_CONF_UNSET_SIZE; 
#endif  
 
    if (ngx_array_init(&ccf->env, cycle->pool, 1, sizeof(ngx_str_t)) 
        != NGX_OK) 
    { 
        return NULL; 
    } 
 
    return ccf; 

该函数很简单,即将配置结构的各个字段初始化为未设置的值。如下。

[cpp]
#define NGX_CONF_UNSET       -1  
#define NGX_CONF_UNSET_UINT  (ngx_uint_t) -1  
#define NGX_CONF_UNSET_PTR   (void *) -1  
#define NGX_CONF_UNSET_SIZE  (size_t) -1  
#define NGX_CONF_UNSET_MSEC  (ngx_msec_t) -1 

3. init_conf分析

init_conf才是真正的初始化该结构。

(1) 初始化daemon、master等

直接赋值。

(2) 初始化pid、oldpid

调用ngx_conf_full_name()函数初始化pid,实际上就是在pid字符串前加上NGX_PREFIX获取pid全路径,NGX_PREFIX定义如下。

[cpp]
#ifndef NGX_PREFIX  
#define NGX_PREFIX  "/usr/local/nginx/"  
#endif 
例如,ngx_conf_full_name()被调用前ccf->pid的内容如下。

[plain]
(gdb) p ccf->pid  
$2 = { 
  len = 14,  
  data = 0x4727ff "logs/nginx.pid" 

(gdb) p ccf->pid
$2 = {
  len = 14,
  data = 0x4727ff "logs/nginx.pid"
}
ngx_conf_full_name()被调用后ccf->pid的内容如下。

[plain]
(gdb) p ccf->pid  
$3 = { 
  len = 31,  
  data = 0x6cce78 "/usr/local/nginx/logs/nginx.pid" 

(3)初始化username,user,group

该初始化通过调用系统函数getpwnam()和getgrnam()完成。相关数据结构如下。

The getpwnam() function returns a pointer to a structure containing the broken-out fields of the record in the password database (e.g., the local password file /etc/passwd, NIS, and LDAP) that matches the username name.
       The passwd structure is defined in <pwd.h> as follows:
           struct passwd {
               char   *pw_name;       /* username */
               char   *pw_passwd;     /* user password */
               uid_t   pw_uid;        /* user ID */
               gid_t   pw_gid;        /* group ID */
               char   *pw_gecos;      /* user information */
               char   *pw_dir;        /* home directory */
               char   *pw_shell;      /* shell program */
           };

The getgrnam() function returns a pointer to a structure containing the broken-out fields of the record in the group database (e.g., the local group file /etc/group, NIS, and LDAP) that matches the group name name.
      The group structure is defined in <grp.h> as follows:
           struct group {
               char   *gr_name;       /* group name */
               char   *gr_passwd;     /* group password */
               gid_t   gr_gid;        /* group ID */
               char  **gr_mem;        /* group members */
           };

获得的数据如下。

[plain]
(gdb) p *pwd 
$5 = { 
  pw_name = 0x6b82a0 "nobody",  
  pw_passwd = 0x6b82a7 "x",  
  pw_uid = 99,  
  pw_gid = 99,  
  pw_gecos = 0x6b82af "Nobody",  
  pw_dir = 0x6b82b6 "/",  
  pw_shell = 0x6b82b8 "/sbin/nologin" 

 
(gdb) p *grp 
$6 = { 
  gr_name = 0x6c3bf0 "nobody",  
  gr_passwd = 0x6c3bf7 "x",  
  gr_gid = 99,  
  gr_mem = 0x6c3c00 

(4) 初始化lock_file

同初始化pid,调用ngx_conf_full_name()函数初始化lock_file,即在lock_file字符串前加上NGX_PREFIX获取其全路径,其全路径如下。

[plain]
(gdb) p ccf->lock_file  
$6 = { 
  len = 32,  
  data = 0x6ccebf "/usr/local/nginx/logs/nginx.lock" 
}
 
(5) 初始化ngx_cycle->lock_file

ngx_cycle->lock_file的初始化是复制ccf->lock_file的内容并在其后链接".accept"。

(6) ngx_cpymem与ngx_memcpy

ngx_cpymem(dst,src,n):将src内容拷贝n个到dst,且返回地址dst+n

ngx_memcpy(dst,src,n):将src内容拷贝n个到dst

(7) 配置结构初始化后的内容

跟踪调试即可获得ngx_core_module这个CORE模块的配置结构,如下。

[plain]
(gdb) p *ccf 
$12 = { 
  daemon = 1,  
  master = 1,  
  timer_resolution = 0,  
  worker_processes = 1,  
  debug_points = 0,  
  rlimit_nofile = -1,  
  rlimit_sigpending = -1,  
  rlimit_core = -1,  
  priority = 0,  
  cpu_affinity_n = 0,  
  cpu_affinity = 0x0,  
  username = 0x47280e "nobody",  
  user = 99,  
  group = 99,  
  working_directory = { 
    len = 0,  
    data = 0x0 
  },  
  lock_file = { 
    len = 32,  
    data = 0x6ccebf "/usr/local/nginx/logs/nginx.lock" 
  },  
  pid = { 
    len = 31,  
    data = 0x6cce78 "/usr/local/nginx/logs/nginx.pid" 
  },  
  oldpid = { 
    len = 39,  
    data = 0x6cce98 "/usr/local/nginx/logs/nginx.pid.oldbin" 
  },  
  env = { 
    elts = 0x6b12a0,  
    nelts = 0,  
    size = 16,  
    nalloc = 1,  
    pool = 0x6b0280 
  },  
  environment = 0x0 

4. 小结

本文主要分析core模块的callback,后文继续分析配置文件解析等。

阅读、分析优秀的开源代码,一定要亲自操刀运行、调试,才能深刻理解调用路径,数据流向。当然笔者还没有开始分析nginx的核心功能代码,我想那将是非常享受的代码之旅。

 

相关评论

专题信息
    Nginx ("engine x") 是一个高性能的 HTTP 和 反向代理 服务器,也是一个 IMAP/POP3/SMTP 代理服务器。 Nginx 是由 Igor Sysoev 为俄罗斯访问量第二的 Rambler.ru 站点开发的,第一个公开版本0.1.0发布于2004年10月4日。其将源代码以类BSD许可证的形式发布,因它的稳定性、丰富的功能集、示例配置文件和低系统资源的消耗而闻名。2011年6月1日,nginx 1.0.4发布。