nginx源码分析—core模块callback

作者:阿波
链接:http://blog.csdn.net/livelylittlefish/article/details/7262750

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

0. 序

<nginx源码分析—全局变量ngx_cycle的初始化>中,简单介绍了如何调用core模块的callback,并简单列出其定义及其初始化,本文将重点阐述callback做什么。

1. Core模块的配置结构

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

./src/core/ngx_cycle.h

[cpp]  view plain copy
  1. typedef struct {  
  2.      ngx_flag_t               daemon;  
  3.      ngx_flag_t               master;  
  4.   
  5.      ngx_msec_t               timer_resolution;  
  6.   
  7.      ngx_int_t                worker_processes;  
  8.      ngx_int_t                debug_points;  
  9.   
  10.      ngx_int_t                rlimit_nofile;  
  11.      ngx_int_t                rlimit_sigpending;  
  12.      off_t                    rlimit_core;  
  13.   
  14.      int                      priority;  
  15.   
  16.      ngx_uint_t               cpu_affinity_n;  
  17.      u_long                  *cpu_affinity;  
  18.   
  19.      char                    *username;            /* 用户名 */  
  20.      ngx_uid_t                user;                /* user ID */  
  21.      ngx_gid_t                group;               /* group ID*/  
  22.   
  23.      ngx_str_t                working_directory;   /*  */  
  24.      ngx_str_t                lock_file;           /* 用户名 */  
  25.   
  26.      ngx_str_t                pid;  
  27.      ngx_str_t                oldpid;              /* 以'.oldbin'结尾 */  
  28.   
  29.      ngx_array_t              env;  
  30.      char                   **environment;  
  31.   
  32. #if (NGX_THREADS)  
  33.      ngx_int_t                worker_threads;  
  34.      size_t                   thread_stack_size;  
  35. #endif  
  36.   
  37. } ngx_core_conf_t;  

2. create_conf分析

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

[cpp]  view plain copy
  1. static void *  
  2. ngx_core_module_create_conf(ngx_cycle_t *cycle)  
  3. {  
  4.     ngx_core_conf_t  *ccf;  
  5.   
  6.     ccf = ngx_pcalloc(cycle->pool, sizeof(ngx_core_conf_t));  
  7.     if (ccf == NULL) {  
  8.         return NULL;  
  9.     }  
  10.   
  11.     /* 
  12.      * set by ngx_pcalloc() 
  13.      * 
  14.      *     ccf->pid = NULL; 
  15.      *     ccf->oldpid = NULL; 
  16.      *     ccf->priority = 0; 
  17.      *     ccf->cpu_affinity_n = 0; 
  18.      *     ccf->cpu_affinity = NULL; 
  19.      */  
  20.   
  21.     ccf->daemon = NGX_CONF_UNSET;  
  22.     ccf->master = NGX_CONF_UNSET;  
  23.     ccf->timer_resolution = NGX_CONF_UNSET_MSEC;  
  24.   
  25.     ccf->worker_processes = NGX_CONF_UNSET;  
  26.     ccf->debug_points = NGX_CONF_UNSET;  
  27.   
  28.     ccf->rlimit_nofile = NGX_CONF_UNSET;  
  29.     ccf->rlimit_core = NGX_CONF_UNSET;  
  30.     ccf->rlimit_sigpending = NGX_CONF_UNSET;  
  31.   
  32.     ccf->user = (ngx_uid_t) NGX_CONF_UNSET_UINT;  
  33.     ccf->group = (ngx_gid_t) NGX_CONF_UNSET_UINT;  
  34.   
  35. #if (NGX_THREADS)  
  36.     ccf->worker_threads = NGX_CONF_UNSET;  
  37.     ccf->thread_stack_size = NGX_CONF_UNSET_SIZE;  
  38. #endif  
  39.   
  40.     if (ngx_array_init(&ccf->env, cycle->pool, 1, sizeof(ngx_str_t))  
  41.         != NGX_OK)  
  42.     {  
  43.         return NULL;  
  44.     }  
  45.   
  46.     return ccf;  
  47. }  

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

[cpp]  view plain copy
  1. #define NGX_CONF_UNSET       -1  
  2. #define NGX_CONF_UNSET_UINT  (ngx_uint_t) -1  
  3. #define NGX_CONF_UNSET_PTR   (void *) -1  
  4. #define NGX_CONF_UNSET_SIZE  (size_t) -1  
  5. #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]  view plain copy
  1. #ifndef NGX_PREFIX  
  2. #define NGX_PREFIX  "/usr/local/nginx/"  
  3. #endif  

例如,ngx_conf_full_name()被调用前ccf->pid的内容如下。

[plain]  view plain copy
  1. (gdb) p ccf->pid   
  2. $2 = {  
  3.   len = 14,   
  4.   data = 0x4727ff "logs/nginx.pid"  
  5. }  

ngx_conf_full_name()被调用后ccf->pid的内容如下。

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

(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]  view plain copy
  1. (gdb) p *pwd  
  2. $5 = {  
  3.   pw_name = 0x6b82a0 "nobody",   
  4.   pw_passwd = 0x6b82a7 "x",   
  5.   pw_uid = 99,   
  6.   pw_gid = 99,   
  7.   pw_gecos = 0x6b82af "Nobody",   
  8.   pw_dir = 0x6b82b6 "/",   
  9.   pw_shell = 0x6b82b8 "/sbin/nologin"  
  10. }  
  11.   
  12. (gdb) p *grp  
  13. $6 = {  
  14.   gr_name = 0x6c3bf0 "nobody",   
  15.   gr_passwd = 0x6c3bf7 "x",   
  16.   gr_gid = 99,   
  17.   gr_mem = 0x6c3c00  
  18. }  

(4) 初始化lock_file

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

[plain]  view plain copy
  1. (gdb) p ccf->lock_file   
  2. $6 = {  
  3.   len = 32,   
  4.   data = 0x6ccebf "/usr/local/nginx/logs/nginx.lock"  
  5. }  

(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]  view plain copy
  1. (gdb) p *ccf  
  2. $12 = {  
  3.   daemon = 1,   
  4.   master = 1,   
  5.   timer_resolution = 0,   
  6.   worker_processes = 1,   
  7.   debug_points = 0,   
  8.   rlimit_nofile = -1,   
  9.   rlimit_sigpending = -1,   
  10.   rlimit_core = -1,   
  11.   priority = 0,   
  12.   cpu_affinity_n = 0,   
  13.   cpu_affinity = 0x0,   
  14.   username = 0x47280e "nobody",   
  15.   user = 99,   
  16.   group = 99,   
  17.   working_directory = {  
  18.     len = 0,   
  19.     data = 0x0  
  20.   },   
  21.   lock_file = {  
  22.     len = 32,   
  23.     data = 0x6ccebf "/usr/local/nginx/logs/nginx.lock"  
  24.   },   
  25.   pid = {  
  26.     len = 31,   
  27.     data = 0x6cce78 "/usr/local/nginx/logs/nginx.pid"  
  28.   },   
  29.   oldpid = {  
  30.     len = 39,   
  31.     data = 0x6cce98 "/usr/local/nginx/logs/nginx.pid.oldbin"  
  32.   },   
  33.   env = {  
  34.     elts = 0x6b12a0,   
  35.     nelts = 0,   
  36.     size = 16,   
  37.     nalloc = 1,   
  38.     pool = 0x6b0280  
  39.   },   
  40.   environment = 0x0  
  41. }  

4. 小结

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

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

 

Reference

# man getpwnam

# man getgrnam

你可能感兴趣的:(nginx,Module,File,callback,DST,structure)