nginx学习十二 ngx_cycle_t 和 ngx_init_cycle

本文详细探讨了nginx启动过程中ngx_init_cycle函数的初始化工作,特别是如何处理ngx_cycle_t结构体,包括配置参数、共享内存、监听套接字的设置以及模块初始化。同时分析了ngx_cycle_t在保存启动信息方面的作用。

在nginx的启动过程中,ngx_init_cycle这个函数做了大部分的初始化工作,而初始化的变量都保存在ngx_cycle_t这个结构体中,为了深入了解这个函数都做了那些初始化工作,就化时间研究了一下,并写下来以便以后参考。

1ngx_cycle_t

关于这个结构体前面已经简单介绍过,这里不再赘述。

2ngx_init_cycle

ngx_cycle_t * ngx_init_cycle(ngx_cycle_t *old_cycle);

先看一下这个old_cycle参数从哪里来的:

   ngx_cycle_t      *cycle, init_cycle;
    init_cycle.pool = ngx_create_pool(1024, log);//创建内存池
    if (init_cycle.pool == NULL) {
        return 1;
    }

    ......
    ......

    if (ngx_process_options(&init_cycle) != NGX_OK) {
        return 1;
    }
	
    cycle = ngx_init_cycle(&init_cycle);

可见在调用ngx_int_cycle之前,这个old_cycle已经保存了一些参数,这些参数包括:prefix,conf_prefix,conf_file, conf_para。主要在ngx_process_options这个函数中初始化old_cycle,这个函数比较简单,看一下代码:

static ngx_int_t
ngx_process_options(ngx_cycle_t *cycle)
{
    u_char  *p;
    size_t   len;

    if (ngx_prefix) {
        len = ngx_strlen(ngx_prefix);
        p = ngx_prefix;

        if (!ngx_path_separator(*p)) {
            p = ngx_pnalloc(cycle->pool, len + 1);
            if (p == NULL) {
                return NGX_ERROR;
            }

            ngx_memcpy(p, ngx_prefix, len);
            p[len++] = '/';
        }

        cycle->conf_prefix.len = len;
        cycle->conf_prefix.data = p;
        cycle->prefix.len = len;
        cycle->prefix.data = p;

    } else {

#ifndef NGX_PREFIX

        p = ngx_pnalloc(cycle->pool, NGX_MAX_PATH);
        if (p == NULL) {
            return NGX_ERROR;
        }

        if (ngx_getcwd(p, NGX_MAX_PATH) == 0) {//得到当前的工作目录
            ngx_log_stderr(ngx_errno, "[emerg]: " ngx_getcwd_n " failed");
            return NGX_ERROR;
        }

        len = ngx_strlen(p);

        p[len++] = '/';

        cycle->conf_prefix.len = len;
        cycle->conf_prefix.data = p;//配置目录
        cycle->prefix.len = len;
        cycle->prefix.data = p;//安装目录

#else

#ifdef NGX_CONF_PREFIX
        ngx_str_set(&cycle->conf_prefix, NGX_CONF_PREFIX);//配置文件相对于安装的目录
#else
        ngx_str_set(&cycle->conf_prefix, NGX_PREFIX);
#endif
        ngx_str_set(&cycle->prefix, NGX_PREFIX);

#endif
    }

    if (ngx_conf_file) {
        cycle->conf_file.len = ngx_strlen(ngx_conf_file);
        cycle->conf_file.data = ngx_conf_file;

    } else {
        ngx_str_set(&cycle->conf_file, NGX_CONF_PATH);
    }

    if (ngx_conf_full_name(cycle, &cycle->conf_file, 0) != NGX_OK) {
        return NGX_ERROR;
    }

    for (p = cycle->conf_file.data + cycle->conf_file.len - 1;
         p > cycle->conf_file.data;
         p--)
    {
        if (ngx_path_separator(*p)) {
            cycle->conf_prefix.len = p - ngx_cycle->conf_file.data + 1;
            cycle->conf_prefix.data = ngx_cycle->conf_file.data;
            break;
        }
    }

    if (ngx_conf_params) {
        cycle->conf_param.len = ngx_strlen(ngx_conf_params);
        cycle->conf_param.data = ngx_conf_params;
    }

    if (ngx_test_config) {
        cycle->log->log_level = NGX_LOG_INFO;
    }

    return NGX_OK;
}

现在开始进入关键:ngx_init_cycle,按照执行步骤来进行

2.1调用ngx_timezone_update()、ngx_timeofday() 、ngx_time_update(0,0)做时间校准

 ngx_timezone_update();

    /* force localtime update with a new timezone */

    tp = ngx_timeofday();
    tp->sec = 0;

    ngx_time_update();

2.2创建一个新的ngx_cycl
Nginx 中的 `ngx_hash_t` 是一个高效且轻量级的数据结构,用于实现哈希表。它主要用于处理字符串键值对,适用于 Nginx 内部的各种配置运行时数据管理场景[^3]。 ### 基本用途 `ngx_hash_t` 通常用于存储静态或动态生成的键值对,例如在处理 HTTP 请求时,用于快速查找配置信息、变量映射等。它的设计目标是提供高效的查找性能,并支持并发访问。 ### 实现细节 #### 结构定义 `ngx_hash_t` 的核心结构如下: ```c typedef struct { ngx_hash_elt_t **buckets; // 指向桶数组的指针 ngx_uint_t size; // 哈希表的大小(桶的数量) } ngx_hash_t; ``` 每个桶是一个指向 `ngx_hash_elt_t` 类型的指针,表示哈希冲突链表的头节点。 #### 元素结构 `ngx_hash_elt_t` 是哈希表中存储元素的基本单元,其定义如下: ```c typedef struct { uintptr_t value; // 存储对应的值 u_short len; // 键的长度 u_char name[1]; // 键的实际内容(柔性数组) } ngx_hash_elt_t; ``` 该结构允许存储任意长度的字符串键及其对应的值。键的长度通过 `len` 字段指定,而 `name[1]` 则用于存储实际的字符串内容。 #### 初始化与销毁 `ngx_hash_t` 的初始化通常通过 `ngx_hash_init` 函数完成,该函数会根据提供的键值对集合分配足够的内存并构建哈希表。销毁操作则通过 `ngx_hash_destroy` 完成,释放所有相关的内存资源。 #### 插入与查找 插入操作通过 `ngx_hash_add_key` 函数完成,该函数会计算键的哈希值,并将其插入到相应的桶中。如果发生哈希冲突,则使用链表的方式将新元素添加到现有元素之后。 查找操作通过 `ngx_hash_find` 函数完成,该函数根据给定的键计算哈希值,并遍历对应的桶中的链表以找到匹配的元素。 #### 性能优化 Nginx 的 `ngx_hash_t` 实现采用了多种优化策略: - **预分配内存**:为了减少内存碎片提高性能,`ngx_hash_t` 使用了内存池 (`ngx_pool_t`) 来管理内存分配。 - **负载因子控制**:通过合理设置哈希表的大小,确保负载因子保持在一个较低的水平,从而减少哈希冲突的发生。 - **线程安全**:虽然 Nginx 主要采用单线程异步事件驱动模型,但在多线程环境中,`ngx_hash_t` 的实现也考虑到了线程安全性,避免并发访问导致的数据竞争问题。 ### 示例代码 以下是一个简单的示例,展示如何使用 `ngx_hash_t` 进行哈希表的初始化、插入查找操作: ```c #include <ngx_config.h> #include <ngx_core.h> #include <ngx_http.h> static ngx_int_t init_hash(ngx_conf_t *cf, ngx_hash_t *hash) { ngx_str_t keys[] = { ngx_string("key1"), ngx_string("key2"), ngx_null_string }; ngx_uint_t i; ngx_array_t *array; array = ngx_array_create(cf->pool, 4, sizeof(ngx_hash_key_t)); if (array == NULL) { return NGX_ERROR; } for (i = 0; !ngx_is_null(&keys[i]); i++) { ngx_hash_key_t *key = ngx_array_push(array); if (key == NULL) { return NGX_ERROR; } key->key = keys[i]; key->key_hash = ngx_hash_key_lc(keys[i].data, keys[i].len); key->value = (void *)123456; } if (ngx_hash_init(hash, array->elts, array->nelts, cf->size, cf->name) != NGX_OK) { return NGX_ERROR; } return NGX_OK; } static void find_in_hash(ngx_hash_t *hash, ngx_str_t *key) { ngx_uint_t hash_value = ngx_hash_key_lc(key->data, key->len); ngx_hash_elt_t *elt = ngx_hash_find(hash, hash_value, key->data, key->len); if (elt != NULL) { ngx_log_error(NGX_LOG_INFO, ngx_cycle->log, 0, "Found value: %p", elt->value); } else { ngx_log_error(NGX_LOG_INFO, ngx_cycle->log, 0, "Key not found"); } } ``` 在这个示例中,首先通过 `init_hash` 函数初始化了一个哈希表,并插入了一些键值对。然后通过 `find_in_hash` 函数进行查找操作,输出对应的值。 ### 总结 `ngx_hash_t` 是 Nginx 中一个非常重要的数据结构,广泛应用于各种需要高效查找的场景。它的设计兼顾了性能与内存使用的平衡,能够很好地适应 Nginx 的高并发、低延迟需求。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值