1 定义ngx_hash_find 函数 定义在 ./nginx-1.24.0/src/core/ngx_hash.cvoid*ngx_hash_find(ngx_hash_t*hash,ngx_uint_tkey,u_char*name,size_tlen){ngx_uint_ti;ngx_hash_elt_t*elt;#if0ngx_log_error(NGX_LOG_ALERT,ngx_cycle-log,0,hf:\%*s\,len,name);#endifelthash-buckets[key%hash-size];if(eltNULL){returnNULL;}while(elt-value){if(len!(size_t)elt-len){gotonext;}for(i0;ilen;i){if(name[i]!elt-name[i]){gotonext;}}returnelt-value;next:elt(ngx_hash_elt_t*)ngx_align_ptr(elt-name[0]elt-len,sizeof(void*));continue;}returnNULL;}ngx_hash_find 函数 用于在 Nginx 的静态哈希表中 根据预先计算的哈希键值、键字符串及其长度查找并返回对应的数据指针。 它通过取模定位桶然后在该桶的连续内存区域中遍历元素 依次比较长度和字符内容 直至找到匹配项或返回 NULL 表示未命中。2 详解1 函数签名void*ngx_hash_find(ngx_hash_t*hash,ngx_uint_tkey,u_char*name,size_tlen)返回值 返回一个无类型指针指向哈希表中存储的“值”参数1 ngx_hash_t *hash 要查找的静态哈希表参数2 ngx_uint_t key 已预先计算好的哈希键值用于确定键所在的桶参数3 u_char *name 指向待查找的键字符串或称键名参数4 size_t len 表示 name 指向的字节序列的长度2 逻辑流程1 局部变量 2 定位桶元素 3 遍历桶内元素 4 返回 NULL1 局部变量{ngx_uint_ti;ngx_hash_elt_t*elt;#if0ngx_log_error(NGX_LOG_ALERT,ngx_cycle-log,0,hf:\%*s\,len,name);#endif2 定位桶元素elthash-buckets[key%hash-size];if(eltNULL){returnNULL;}3 遍历桶内元素while(elt-value){if(len!(size_t)elt-len){gotonext;}for(i0;ilen;i){if(name[i]!elt-name[i]){gotonext;}}returnelt-value;next:elt(ngx_hash_elt_t*)ngx_align_ptr(elt-name[0]elt-len,sizeof(void*));continue;}开始遍历桶内元素 检查当前元素的 value 字段是否非 NULL。 在 Nginx 哈希实现中每个 ngx_hash_elt_t 元素存储一个键值对 且规定有效的 value 一定是一个非空指针。 当元素序列到达结束时会有一个特殊的“哨兵”元素 其 value 字段被置为 NULL即0作为链尾标记。 因此 while (elt-value) 即“当未到达桶内元素链尾时循环”。长度快速比较 若待查键的长度与元素键长度不同两者必然不匹配。 通过 goto next 直接跳到“移动到下一元素”的处理代码逐字符比较 从索引 0 到 len-1依次比较 name 和 elt-name 中的每个字节。 name[i] ! elt-name[i]一旦发现任何字节不同说明当前元素键不匹配 立即跳转到 next 处理下一个元素。 全部相等若循环执行完毕仍未跳转说明所有字节完全匹配表示找到了目标元素。匹配成功返回数据 当执行到这一行时表示长度一致且所有字符匹配键值对已找到。 直接返回当前元素的 value 字段即存储的数据指针。调用者获得所需的结构体地址。标签 next用于从上面的 goto next 语句跳转至此 统一处理“移动到下一个元素”的操作。 计算下一个元素地址 elt-name[0]取当前元素的 name 数组首地址 elt-name[0] elt-len指针向后移动 elt-len 字节 到达当前键字符串数据的尾后地址 即当前元素实际占用的内存末尾不包括可能为对齐而填充的额外字节 ngx_align_ptr(ptr, sizeof(void *)) 这是一个宏用于将指针 ptr 按 sizeof(void *) 指针大小32位系统为464位系统为8向上对齐 由于下一个 ngx_hash_elt_t 结构体必须满足内存对齐要求 所以从当前元素尾部开始需要向上取整到指针大小的倍数才能作为下一个元素的起始地址。 continue 使程序跳转回 while 循环的起始处 检查新 elt 的 value 是否为非 NULL即开始处理下一个元素。 配合上面的地址计算形成隐式链表遍历。4 返回 NULLreturnNULL;}当 while 循环因 elt-value NULL 而退出时 说明已经遍历完桶内所有有效元素 没有找到匹配的键。返回 NULL 表示查找失败。
ngx_hash_find
发布时间:2026/5/26 7:56:08
1 定义ngx_hash_find 函数 定义在 ./nginx-1.24.0/src/core/ngx_hash.cvoid*ngx_hash_find(ngx_hash_t*hash,ngx_uint_tkey,u_char*name,size_tlen){ngx_uint_ti;ngx_hash_elt_t*elt;#if0ngx_log_error(NGX_LOG_ALERT,ngx_cycle-log,0,hf:\%*s\,len,name);#endifelthash-buckets[key%hash-size];if(eltNULL){returnNULL;}while(elt-value){if(len!(size_t)elt-len){gotonext;}for(i0;ilen;i){if(name[i]!elt-name[i]){gotonext;}}returnelt-value;next:elt(ngx_hash_elt_t*)ngx_align_ptr(elt-name[0]elt-len,sizeof(void*));continue;}returnNULL;}ngx_hash_find 函数 用于在 Nginx 的静态哈希表中 根据预先计算的哈希键值、键字符串及其长度查找并返回对应的数据指针。 它通过取模定位桶然后在该桶的连续内存区域中遍历元素 依次比较长度和字符内容 直至找到匹配项或返回 NULL 表示未命中。2 详解1 函数签名void*ngx_hash_find(ngx_hash_t*hash,ngx_uint_tkey,u_char*name,size_tlen)返回值 返回一个无类型指针指向哈希表中存储的“值”参数1 ngx_hash_t *hash 要查找的静态哈希表参数2 ngx_uint_t key 已预先计算好的哈希键值用于确定键所在的桶参数3 u_char *name 指向待查找的键字符串或称键名参数4 size_t len 表示 name 指向的字节序列的长度2 逻辑流程1 局部变量 2 定位桶元素 3 遍历桶内元素 4 返回 NULL1 局部变量{ngx_uint_ti;ngx_hash_elt_t*elt;#if0ngx_log_error(NGX_LOG_ALERT,ngx_cycle-log,0,hf:\%*s\,len,name);#endif2 定位桶元素elthash-buckets[key%hash-size];if(eltNULL){returnNULL;}3 遍历桶内元素while(elt-value){if(len!(size_t)elt-len){gotonext;}for(i0;ilen;i){if(name[i]!elt-name[i]){gotonext;}}returnelt-value;next:elt(ngx_hash_elt_t*)ngx_align_ptr(elt-name[0]elt-len,sizeof(void*));continue;}开始遍历桶内元素 检查当前元素的 value 字段是否非 NULL。 在 Nginx 哈希实现中每个 ngx_hash_elt_t 元素存储一个键值对 且规定有效的 value 一定是一个非空指针。 当元素序列到达结束时会有一个特殊的“哨兵”元素 其 value 字段被置为 NULL即0作为链尾标记。 因此 while (elt-value) 即“当未到达桶内元素链尾时循环”。长度快速比较 若待查键的长度与元素键长度不同两者必然不匹配。 通过 goto next 直接跳到“移动到下一元素”的处理代码逐字符比较 从索引 0 到 len-1依次比较 name 和 elt-name 中的每个字节。 name[i] ! elt-name[i]一旦发现任何字节不同说明当前元素键不匹配 立即跳转到 next 处理下一个元素。 全部相等若循环执行完毕仍未跳转说明所有字节完全匹配表示找到了目标元素。匹配成功返回数据 当执行到这一行时表示长度一致且所有字符匹配键值对已找到。 直接返回当前元素的 value 字段即存储的数据指针。调用者获得所需的结构体地址。标签 next用于从上面的 goto next 语句跳转至此 统一处理“移动到下一个元素”的操作。 计算下一个元素地址 elt-name[0]取当前元素的 name 数组首地址 elt-name[0] elt-len指针向后移动 elt-len 字节 到达当前键字符串数据的尾后地址 即当前元素实际占用的内存末尾不包括可能为对齐而填充的额外字节 ngx_align_ptr(ptr, sizeof(void *)) 这是一个宏用于将指针 ptr 按 sizeof(void *) 指针大小32位系统为464位系统为8向上对齐 由于下一个 ngx_hash_elt_t 结构体必须满足内存对齐要求 所以从当前元素尾部开始需要向上取整到指针大小的倍数才能作为下一个元素的起始地址。 continue 使程序跳转回 while 循环的起始处 检查新 elt 的 value 是否为非 NULL即开始处理下一个元素。 配合上面的地址计算形成隐式链表遍历。4 返回 NULLreturnNULL;}当 while 循环因 elt-value NULL 而退出时 说明已经遍历完桶内所有有效元素 没有找到匹配的键。返回 NULL 表示查找失败。