Chinaunix首页 | 论坛 | 博客
  • 博客访问: 2316415
  • 博文数量: 252
  • 博客积分: 5472
  • 博客等级: 大校
  • 技术积分: 3107
  • 用 户 组: 普通用户
  • 注册时间: 2011-09-17 18:39
文章分类

全部博文(252)

文章存档

2012年(96)

2011年(156)

分类: LINUX

2012-03-16 10:01:15

ngx_hash

ngx_hash.{c|h} 实现了nginx里面比较重要的一个hash结构, 这个在模块配置解析里经常被用到。该 hash 结构是只读的,即仅在初始创建时可以给出保存在其中的 key-val 对,其后就只能查询而不能进行增删改操作了。

下面是简单 hash 结构的内存布局:


虽然代码理解起来比较混乱,但是使用还是比较简单的,常用的有创建 hash 和在 hash 中进行查找两个操作,对于创建hash的操作,过程一般为:

  1. 构造一个 ngx_hash_key_t 为成员的数组, 包含 key, value 和 使用key计算出的一个hash值
  2. 构建一个 ngx_hash_init_t结构体的变量, 其中包含了ngx_hash_t 的成员, 为hash的结构体, 还包括一些其他初始设置,如bucket的大小,内存池等
  3. 调用 ngx_hash_init 传入 ngx_hash_init_t 结构, ngx_hash_key_t 的数组,和数组的长度, 进行初始化,这样 ngx_hash_init_t的hash成员就是我们要的hash结构

查找的过程很简单

  1. 计算 key 的hash值
  2. 使用 ngx_hash_find 进行查找,需要同时传入 hash值和key ,返回的就是value的指针

需要注意的是,nginx 的 hash 在查找时使用的是分桶后线性查找法,因此当分桶数确定时查找效率同其中的总 key-val 对数量成反比。

下面是一些demo代码(可以从svn中找到)


  1. #include <stdio.h>
  2. #include "ngx_config.h"
  3. #include "ngx_conf_file.h"
  4. #include "nginx.h"
  5. #include "ngx_core.h"
  6. #include "ngx_string.h"
  7. #include "ngx_palloc.h"
  8. #include "ngx_array.h"
  9. #include "ngx_hash.h"
  10. volatile ngx_cycle_t *ngx_cycle;
  11. void ngx_log_error_core(ngx_uint_t level, ngx_log_t *log, ngx_err_t err, const char *fmt, ...) { }


  12. static ngx_str_t names[] = {ngx_string("rainx"),
  13.                             ngx_string("xiaozhe"),
  14.                             ngx_string("zhoujian")};
  15. static char* descs[] = {"rainx's id is 1","xiaozhe's id is 2","zhoujian's id is 3"};

  16. // hash table的一些基本操作
  17. int main()
  18. {
  19.     ngx_uint_t k; //, p, h;
  20.     ngx_pool_t* pool;
  21.     ngx_hash_init_t hash_init;
  22.     ngx_hash_t* hash;
  23.     ngx_array_t* elements;
  24.     ngx_hash_key_t* arr_node;
  25.     char* find;
  26.     int i;

  27.     ngx_cacheline_size = 32;
  28.     // hash key cal start
  29.     ngx_str_t str = ngx_string("hello, world");
  30.     k = ngx_hash_key_lc( str.data, str.len);
  31.     pool = ngx_create_pool(1024*10, NULL);
  32.     printf("caculated key is %u \n", k);
  33.     // hask key cal end
  34.     //
  35.     hash = (ngx_hash_t*) ngx_pcalloc(pool, sizeof(hash));
  36.     hash_init.hash = hash; // hash结构
  37.     hash_init.key = &ngx_hash_key_lc; // hash算法函数
  38.     hash_init.max_size = 1024*10; // max_size
  39.     hash_init.bucket_size = 64; // ngx_align(64, ngx_cacheline_size);
  40.     hash_init.name = "yahoo_guy_hash"; // 在log里会用到
  41.     hash_init.pool = pool; // 内存池
  42.     hash_init.temp_pool = NULL;

  43.     // 创建数组

  44.     elements = ngx_array_create(pool, 32, sizeof(ngx_hash_key_t));
  45.     for(i = 0; i < 3; i++) {
  46.         arr_node = (ngx_hash_key_t*) ngx_array_push(elements);
  47.         arr_node->key = (names[i]);
  48.         arr_node->key_hash = ngx_hash_key_lc(arr_node->key.data, arr_node->key.len);
  49.         arr_node->value = (void*) descs[i];
  50.         //
  51.         printf("key: %s , key_hash: %u\n", arr_node->key.data, arr_node->key_hash);
  52.     }

  53.     if (ngx_hash_init(&hash_init, (ngx_hash_key_t*) elements->elts, elements->nelts)!=NGX_OK){
  54.         return 1;
  55.     }

  56.     // 查找
  57.     k = ngx_hash_key_lc(names[0].data, names[0].len);
  58.     printf("%s key is %d\n", names[0].data, k);
  59.     find = (char*)
  60.         ngx_hash_find(hash, k, (u_char*) names[0].data, names[0].len);

  61.     if (find) {
  62.         printf("get desc of rainx: %s\n", (char*) find);
  63.     }

  64.     ngx_array_destroy(elements);
  65.     ngx_destroy_pool(pool);

  66.     return 0;
  67. }

按照前面的方法编译运行:
hash_op.c

运行结果


  1. caculated key is 3654358412
  2. key: rainx , key_hash: 108275556
  3. key: xiaozhe , key_hash: 2225329080
  4. key: zhoujian , key_hash: 3269715264
  5. rainx key is 108275556
  6. get desc of rainx: rainx's id is 1

阅读(3172) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~