哈希表&哈希算法

简单用如下的例子介绍哈希表数据结构,以及相关操作。

1、数据结构

/*哈希头节点*/
typedef struct _hash_head
{
	unsigned  elem;     /* The number of elements currently in the table */
	unsigned  size;     /* The size of the hash table */

	struct hlist_head *head;    /* The hash table */
	
	spinlock_t lock ;
} hash_head_t;

hash_head_t *g_hash_head = NULL;

/*存储的数据结构:源IP+目的IP*/
typedef  struct ip_addr_pair
{
	__be32 src_ip;
	__be32 dst_ip;
	atomic_t count;

	struct hlist_node hash_list;
} ip_addr_pair_t;

2、初始化

主要是分配哈希头节点存储空间,以及每个哈希节点的空间分配及初始化。

int hash_init(void)
{
	struct hlist_head *hash = NULL;
	unsigned int i, hash_size = nf_conntrack_max;

	g_hash_head = kmalloc(sizeof(hash_head_t), GFP_KERNEL);
	if (NULL  == g_hash_head)
	{
		printk("Failed to malloc hash head in hash init.\n");
		return ERROR;
	}

	hash = vmalloc(hash_size * sizeof(struct hlist_head));
	if (NULL == hash)
	{
		kfree(g_hash_head);
		printk("Failed to malloc hash table in hash init.\n");
		return ERROR;
	}

	if (NULL != hash)
	{
		for (i = 0; i < hash_size; i++)
		{
			INIT_HLIST_HEAD(&hash[i]);
		}
	}

	g_hash_head->head = hash;
	g_hash_head->elem = 0;
	g_hash_head->size = hash_size;

	spin_lock_init(&g_hash_head->lock);

	return OK;
}

3、卸载清空

void hash_exit(void)
{
	unsigned i = 0;
	ip_addr_pair_t *entry = NULL;
	hash_head_t *head = g_hash_head;
	struct hlist_node *node, *next;

	spin_lock_bh(&head->lock);
	for(i = 0; i < head->size; i++)
	{
		hlist_for_each_entry_safe(entry, node, next, &head->head[i], hash_list)
		{
			__hlist_del(&entry->hash_list);

			head->elem--;
			kfree(entry);
			entry = NULL;
		}
	}
	spin_unlock_bh(&head->lock);

	if (g_hash_head)
	{
		vfree(g_hash_head->head);
		g_hash_head->head = NULL;

		kfree(g_hash_head);
		g_hash_head = NULL;
	}
}

4、哈希函数

static unsigned hash_fn(const void *key_param, int key_len)
{
	unsigned a = 0;
	unsigned b = 0;
	unsigned len;
	uint8_t *key = (uint8_t *) key_param;

	/* Set up the internal state */
	len = (unsigned) key_len;
	a = len;

	if (len >= 4)
	{
		b = key[0] + (key[1] << 8) + (key[2] << 16) + (key[3] << 24);
	}

	while (len >= 8)
	{
		a += b;
		key += 4;
		a += ~(a << 15);
		len -= 4;
		a ^=  (a >> 10);
		b = key[0];
		a +=  (a << 3);
		b += key[1] << 8;
		a ^=  (a >> 6);
		b += key[2] << 16;
		a += ~(a << 11);
		b += key[3] << 24;
		a ^=  (a >> 16);
	}

	if (len >= 4)
	{
		a += b;
		a += ~(a << 15);
		len -= 4;
		a ^=  (a >> 10);
		a +=  (a << 3);
		a ^=  (a >> 6);
		a += ~(a << 11);
		a ^=  (a >> 16);
	}


	/* All the case statements fall through */
	switch (len)
	{
	case 3 :
		a += key[2] << 16;
	case 2 :
		a ^= key[1] << 8;
	case 1 :
		a += key[0];
	default:
		break;
	}

	return a;
}

5、元素比较函数

static bool addrPair_hash_cmp(ip_addr_pair_t *pAddrPair, ip_addr_pair_key_t *key)
{
	return ((pAddrPair->src_ip == key->src_ip) && (pAddrPair->dst_ip == key->dst_ip));
}

6、哈希添加

int hash_add(ip_addr_pair_key_t *key, uint32_t mark)
{
	unsigned hash = 0;
	unsigned hash_index = 0;
	ip_addr_pair_t *entry, *pAddrPair = NULL;
	hash_head_t *head = g_hash_head;
	struct hlist_node *node = NULL;

	if(elem_up_limit())
		return OVER_MAX;

	hash = hash_fn((void *)key, sizeof(ip_addr_pair_key_t));
	hash_index = hash % head->size;

	spin_lock_bh(&head->lock);
	hlist_for_each_entry(entry, node, &head->head[hash_index], hash_list)
	{
		if (addrPair_hash_cmp(entry, key))
		{
			atomic_inc(&entry->count);
			spin_unlock_bh(&head->lock);

			return OK;
		}
	}

	pAddrPair = kmalloc(sizeof(ip_addr_pair_t), GFP_KERNEL);
	if(NULL == pAddrPair)
	{
		spin_unlock_bh(&head->lock);
		printk("Failed kmalloc pAddrPair.\n");
		return ALLOC_FAIL;
	}

	pAddrPair->src_ip = key->src_ip;
	pAddrPair->dst_ip = key->dst_ip;

	atomic_set(&pAddrPair->count, 1);

	hlist_add_head(&pAddrPair->hash_list, &head->head[hash_index]);
	head->elem++;

	spin_unlock_bh(&head->lock);

	return OK;
}

7、哈希查询

ip_addr_pair_t *hash_get(ip_addr_pair_key_t *key)
{
	unsigned hash = 0;
	unsigned hash_index = 0;
	struct hlist_node *node = NULL;
	ip_addr_pair_t *entry = NULL;
	hash_head_t *head = g_hash_head;

	hash = hash_fn((void *)key, sizeof(ip_addr_pair_key_t));
	hash_index = hash % head->size;

	spin_lock_bh(&head->lock);
	hlist_for_each_entry(entry, node, &head->head[hash_index], hash_list)
	{
		if (addrPair_hash_cmp(entry, key))
		{
			spin_unlock_bh(&head->lock);
			return entry;
		}
	}
	spin_unlock_bh(&head->lock);

	return NULL;
}

8、哈希删除

int hash_remove(ip_addr_pair_key_t *key)
{
	unsigned hash = 0;
	unsigned hash_index = 0;
	struct hlist_node *node = NULL;
	ip_addr_pair_t *entry = NULL;
	hash_head_t *head = g_hash_head;

	hash = hash_fn((void *)key, sizeof(ip_addr_pair_key_t));
	hash_index = hash % head->size;

	spin_lock_bh(&head->lock);
	hlist_for_each_entry(entry, node, &head->head[hash_index], hash_list)
	{
		if (addrPair_hash_cmp(entry, key))
		{
			if(atomic_read(&entry->count) > 1)
			{
				atomic_dec(&entry->count);

				spin_unlock_bh(&head->lock);
				return COUNT_NOZERO;
			}
			else
			{
				__hlist_del(&entry->hash_list);
				head->elem--;
				
				spin_unlock_bh(&head->lock);
				return OK;
			}
		}
	}
	spin_unlock_bh(&head->lock);

	return NO_EXIST;
}


&lt;think&gt;好的,用户想了解哈希算法的相关信息,包括介绍、原理和应用。首先,我需要回顾已有的引用内容,确保信息准确并正确标注引用。 首先,引用[3]提到哈希算法是将任意长度输入映射为固定长度输出的算法,输出称为哈希值、散列值或摘要。这可以作为哈希算法的基础定义。同时,应用领域包括数据存储、完整性校验、密码学等,需要分点说明。 接下来,原理部分需要详细解释哈希算法的核心机制。引用[3]指出哈希算法通过特定数学函数处理输入,生成唯一或近乎唯一的哈希值。确定性、高效性、抗碰撞性、雪崩效应和不可逆性是关键特性。需要逐一解释这些特性,例如确定性指相同输入必然相同输出,抗碰撞性指不同输入产生相同哈希值的概率极低,雪崩效应指输入微小变化导致输出巨大差异。 在应用场景方面,引用[1]和[3]提到数据完整性验证、密码学存储、数据快速检索(如哈希表)、负载均衡和分布式系统(一致性哈希)。需要结合引用[2]中的分布式缓存案例,说明普通哈希算法在分布式场景中的问题,例如节点增减导致大量缓存失效,而一致性哈希通过环形结构减少影响,这里可以引用[2]的具体描述。 另外,引用[4]提到模糊哈希算法,用于相似性比较,如恶意软件检测。这部分可以作为特殊类型的哈希算法补充,说明其分片、强弱哈希结合的特点,以及应用场景。 需要确保所有技术术语解释清晰,避免用户混淆。同时,按照用户要求,行内公式用$...$,独立公式用$$...$$,例如哈希函数的数学表示。例如,哈希函数可以表示为$H: \{0,1\}^* \rightarrow \{0,1\}^n$,其中输入为任意长度二进制字符串,输出为固定长度n的哈希值。 在生成相关问题部分,需围绕哈希算法的特性、类型、应用场景、安全性及优化方法展开,确保问题具有针对性和延伸性,帮助用户进一步探索。 最后,检查引用标注是否正确,每个引用来源的信息是否准确对应到回答中的相应部分,避免错误引用。例如,引用[2]在讨论一致性哈希时,需正确关联分布式缓存的应用场景。 总结回答结构:定义、原理、核心特性、应用场景、特殊类型(模糊哈希),最后生成相关问题。确保每个部分逻辑连贯,信息准确,引用恰当。&lt;/think&gt;### 哈希算法介绍、原理及应用 #### 一、哈希算法定义 哈希算法(Hash Algorithm)是一种将任意长度的输入数据(如文本、文件)通过特定数学函数转换为**固定长度输出**的算法,输出结果称为哈希值(Hash Value)或摘要(Digest)。例如,输入字符串&ldquo;Hello&rdquo;通过SHA-256算法生成的哈希值为: $$ \text{SHA-256(&quot;Hello&quot;)} = 185f8db32271... $$ #### 二、核心原理 1. **确定性** 相同输入必定生成相同哈希值,即 $H(x) = H(x)$[^3]。 2. **高效性** 无论输入规模多大,哈希值的计算时间接近常数复杂度 $O(1)$。 3. **抗碰撞性** 找到两个不同输入 $x \neq y$ 但满足 $H(x) = H(y)$ 的概率极低[^3]。 4. **雪崩效应** 输入微小变化(如改动1比特)会导致输出剧烈变化,例如: - $H(\text{&quot;apple&quot;}) = 1f3...$ - $H(\text{&quot;applE&quot;}) = a9d...$ 5. **不可逆性** 无法从哈希值反向推导原始输入,确保数据安全性[^1]。 #### 三、典型应用场景 1. **数据完整性验证** 文件下载后对比哈希值,确认未被篡改。 2. **密码存储** 用户密码以哈希值形式存储(如SHA-256 +盐值),避免明文泄露风险[^1]。 3. **哈希表(快速检索)** 通过键的哈希值直接定位存储位置,时间复杂度 $O(1)$。 4. **分布式系统一致性哈希** 解决传统哈希算法在节点增减时导致的缓存大规模失效问题[^2]。例如,将数据映射到环形空间,节点负责相邻区间的数据,增减节点仅影响局部数据。 5. **区块链与数字签名** 区块哈希确保链的不可篡改性;私钥对哈希值签名实现身份认证。 #### 四、特殊类型:模糊哈希算法 模糊哈希(Fuzzy Hashing)通过分片和组合哈希值,实现相似文件检测(如恶意软件变体识别)[^4]。例如: 1. **分片处理**:将文件分割为多个片段。 2. **强弱哈希结合**:每片段分别计算弱哈希(捕捉局部特征)和强哈希(精确匹配)。 3. **相似度比较**:通过模糊哈希值计算相似程度。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值