监听连接数组、复用连接队列、模块配置上下文初始化

2014-12-31 13:40:32   最后更新: 2014-12-31 13:40:32   访问数量:2157




// 监听链接数组初始化 n = old_cycle->listening.nelts ? old_cycle->listening.nelts : 10; cycle->listening.elts = ngx_pcalloc(pool, n * sizeof(ngx_listening_t)); if (cycle->listening.elts == NULL) { ngx_destroy_pool(pool); return NULL; } cycle->listening.nelts = 0; cycle->listening.size = sizeof(ngx_listening_t); cycle->listening.nalloc = n; cycle->listening.pool = pool;

 

这段代码比较简单,主要是数组的创建和初始化操作

// nginx 复用连接队列初始化 ngx_queue_init(&cycle->reusable_connections_queue);

 

循环双向链表结构 -- ngx_queue_t

复用连接队列是一个循环双向链表结构 ngx_queue_t

typedef struct ngx_queue_s ngx_queue_t; struct ngx_queue_s { ngx_queue_t *prev; ngx_queue_t *next; };

 

这里有一点不明白,这样的结构,只有指针域,究竟是用来做什么的呢?

随着我们继续深入的研究源码,应该可以逐步解答这个问题

循环双向链表初始化 -- ngx_queue_init

#define ngx_queue_init(q) \ (q)->prev = q; \ (q)->next = q

 

这个宏函数很简单,就是让节点的前后指针都指向自己,这是一个典型的双向链表初始化方式

// struct ngx_module_s // nginx 模块结构 {{{ struct ngx_module_s { ngx_uint_t ctx_index; ngx_uint_t index; ngx_uint_t spare0; ngx_uint_t spare1; ngx_uint_t spare2; ngx_uint_t spare3; ngx_uint_t version; void *ctx; ngx_command_t *commands; ngx_uint_t type; ngx_int_t (*init_master)(ngx_log_t *log); ngx_int_t (*init_module)(ngx_cycle_t *cycle); ngx_int_t (*init_process)(ngx_cycle_t *cycle); ngx_int_t (*init_thread)(ngx_cycle_t *cycle); void (*exit_thread)(ngx_cycle_t *cycle); void (*exit_process)(ngx_cycle_t *cycle); void (*exit_master)(ngx_cycle_t *cycle); uintptr_t spare_hook0; uintptr_t spare_hook1; uintptr_t spare_hook2; uintptr_t spare_hook3; uintptr_t spare_hook4; uintptr_t spare_hook5; uintptr_t spare_hook6; uintptr_t spare_hook7; }; // }}} // 创建所有模块的配置上下文数组 cycle->conf_ctx = ngx_pcalloc(pool, ngx_max_module * sizeof(void *)); if (cycle->conf_ctx == NULL) { ngx_destroy_pool(pool); return NULL; } for (i = 0; ngx_modules[i]; i++) { if (ngx_modules[i]->type != NGX_CORE_MODULE) { continue; } module = ngx_modules[i]->ctx; if (module->create_conf) { // 创建模块配置 rv = module->create_conf(cycle); if (rv == NULL) { ngx_destroy_pool(pool); return NULL; } cycle->conf_ctx[ngx_modules[i]->index] = rv; } } // 初始化所有模块 for (i = 0; ngx_modules[i]; i++) { if (ngx_modules[i]->type != NGX_CORE_MODULE) { continue; } module = ngx_modules[i]->ctx; if (module->init_conf) { if (module->init_conf(cycle, cycle->conf_ctx[ngx_modules[i]->index]) == NGX_CONF_ERROR) { environ = senv; ngx_destroy_cycle_pools(&conf); return NULL; } } }

 

在内存池中分配了空间,用来存储所有模块的配置上下文数组的首地址

// 获取主机名 if (gethostname(hostname, NGX_MAXHOSTNAMELEN) == -1) { ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, "gethostname() failed"); ngx_destroy_pool(pool); return NULL; } /* on Linux gethostname() silently truncates name that does not fit */ hostname[NGX_MAXHOSTNAMELEN - 1] = '\0'; cycle->hostname.len = ngx_strlen(hostname); cycle->hostname.data = ngx_pnalloc(pool, cycle->hostname.len); if (cycle->hostname.data == NULL) { ngx_destroy_pool(pool); return NULL; } ngx_strlow(cycle->hostname.data, (u_char *) hostname, cycle->hostname.len);

 

这里使用系统调用 gethostname 将当前主机的 hostname 保存在局部变量 hostname 中,并赋值到 cycle->hostname 中

字符串拷贝并转换为小写 -- ngx_strlow

// void ngx_strlow(u_char *dst, u_char *src, size_t n) // 内存拷贝,并转换成小写 {{{ void ngx_strlow(u_char *dst, u_char *src, size_t n) { while (n) { *dst = ngx_tolower(*src); dst++; src++; n--; } } // }}}

 

这是一个非常常用的函数,在nginx中这个函数实现的非常简洁漂亮,值得学习

 

欢迎关注微信公众号,以技术为主,涉及历史、人文等多领域的学习与感悟,每周三到七篇推文,只有全部原创,只有干货没有鸡汤

 






技术帖      龙潭书斋      nginx      opensource      cycle      ngx_array_t      ngx_cycle_t      ngx_strlow      ngx_string_t      gethostname      ngx_module_s      ngx_queue_init      ngx_queue_s      ngx_queue_t     


京ICP备2021035038号