作者:阿波
链接:http://blog.youkuaiyun.com/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模块的配置结构如下,存放配置文件中的核心指令,如deamon,master等。
./src/core/ngx_cycle.h
- 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配置结构。
- 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;
- }
该函数很简单,即将配置结构的各个字段初始化为未设置的值。如下。
- #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定义如下。
- #ifndef NGX_PREFIX
- #define NGX_PREFIX "/usr/local/nginx/"
- #endif
例如,ngx_conf_full_name()被调用前ccf->pid的内容如下。
- (gdb) p ccf->pid
- $2 = {
- len = 14,
- data = 0x4727ff "logs/nginx.pid"
- }
ngx_conf_full_name()被调用后ccf->pid的内容如下。
- (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 */
};
获得的数据如下。
- (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获取其全路径,其全路径如下。
- (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模块的配置结构,如下。
- (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的核心功能代码,我想那将是非常享受的代码之旅。
Reference
# man getpwnam
# man getgrnam