linux内核哈希表一例v1.0
来源:互联网 发布:岳游网络联机捕鱼ol 编辑:程序博客网 时间:2024/04/30 03:42
作者:clusterlee
题记:毕业课题需要,再内核环境下写了个哈希表,和使用C# 、Java 、C++的hash_map相比考虑的东西多了许多,受益匪浅。
要点:
1.内存的分配和回收
2.临界区的互斥、并发控制
代码结构:
hash_example/hash_example.c /*内核模块,使用示例*/
hash_example/hash_table.h /* 结构类型定义、宏以及接口定义*/
hash_example/hash_table.c /* 接口实现*/
hash_example/Makefile
/*
* 以下代码 在2.6.23 下调试通过
*/
//---------------------------------------hash_table.h-----------------------------------------------
#define EXAMPLE_TAB_BITS 16
#define EXAMPLE_TAB_SIZE (1<<EXAMPLE_TAB_BITS)
#define EXAMPLE_TAB_MASK (EXAMPLE_TAB_SIZE-1)
#define EXAMPLE_F_HASHED 0x0001
struct example
{
struct list_head node;
char *s; /*主体 */
spinlock_t lock; /*自旋锁 */
atomic_t refcnt; /*引用计数*/
volatile __u16 flags; /*辅助标记 */
};
extern int example_init(void); /* 内存空间 初始化*/
extern void example_cleanup(void); /* 内存清理回收*/
extern int example_hash(struct example *cp);
extern int example_unhash(struct example *cp);
extern struct example *example_get(char *s); /*查找*/
extern struct example* example_new(char *p); /*构造新项,并加入哈希表 */
extern int example_destroy(struct example *cp); /* 销毁一个哈希表中的项*/
extern inline void example_put(struct example *cp); /*引用计数减一*/
//--------------------------------------hash_example.c---------------------------------------------------
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include "hash_table.h"
static int __init hash_init(void)
{
int ret;
struct example *cp=NULL;
printk(KERN_ALERT "hash mod insert............../n");
ret=example_init();
if(ret<0)
{
printk(KERN_INFO "can't setup conrol./n.");
}
example_new("My girl_1");
example_new("My girl_2");
cp=example_get("My girl_2");
if(NULL!=cp)
printk(KERN_ALERT "cp->s:%s/n",cp->s);
example_put(cp);
example_destroy(cp);
cp=example_get("My girl_2");
if(NULL==cp)
printk(KERN_ALERT "break with girl_2!/n");
return 0;
}
static void __exit hash_exit(void)
{
printk(KERN_ALERT "hash mod remove............../n");
example_cleanup();
}
module_init(hash_init);
module_exit(hash_exit);
//--------------------------------------hash_table.c---------------------------------------------------
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/vmalloc.h>
#include <linux/jhash.h>
#include <linux/random.h>
#include <linux/seq_file.h>
#include <linux/sched.h>
#include "hash_table.h"
/* SLAB 分配器 */
static struct kmem_cache *example_cachep;
/* hash table */
static struct list_head *example_tab;
/* 记录 struct example 总数目,以便回收内存空间 */
static atomic_t example_count=ATOMIC_INIT(0);
/* hash函数使用的随机值 */
static unsigned int example_rnd;
/*
* 一套锁*/
#define CT_LOCKARRAY_BITS 4
#define CT_LOCKARRAY_SIZE (1<<CT_LOCKARRAY_BITS)
#define CT_LOCKARRAY_MASK (CT_LOCKARRAY_SIZE-1)
struct tcp_shift_aligned_lock
{
rwlock_t l;
}__attribute__((__aligned__(SMP_CACHE_BYTES)));
struct tcp_shift_aligned_lock
__example_conntbl_lock_array[CT_LOCKARRAY_SIZE] __cacheline_aligned;
static inline void
ct_read_lock(unsigned key)
{
read_lock(&__example_conntbl_lock_array[key&CT_LOCKARRAY_MASK].l);
}
static inline void
ct_read_unlock(unsigned key)
{
read_unlock(&__example_conntbl_lock_array[key&CT_LOCKARRAY_MASK].l);
}
static inline void
ct_write_lock(unsigned key)
{
write_lock(&__example_conntbl_lock_array[key&CT_LOCKARRAY_MASK].l);
}
static inline void
ct_write_unlock(unsigned key)
{
write_unlock(&__example_conntbl_lock_array[key&CT_LOCKARRAY_MASK].l);
}
static inline void
ct_read_lock_bh(unsigned key)
{
read_lock_bh(&__example_conntbl_lock_array[key&CT_LOCKARRAY_MASK].l);
}
static inline void
ct_read_unlock_bh(unsigned key)
{
read_unlock_bh(&__example_conntbl_lock_array[key&CT_LOCKARRAY_MASK].l);
}
static inline void
ct_write_lock_bh(unsigned key)
{
write_lock_bh(&__example_conntbl_lock_array[key&CT_LOCKARRAY_MASK].l);
}
static inline void
ct_write_unlock_bh(unsigned key)
{
write_unlock_bh(&__example_conntbl_lock_array[key&CT_LOCKARRAY_MASK].l);
}
/* hash 函数 */
static inline unsigned example_hash_key(char *p)
{
int n; /*简单示例*/
n=strlen(p);
return jhash_2words(n,p[0],example_rnd)&EXAMPLE_TAB_MASK;
}
inline void example_put(struct example* cp)
{
atomic_dec(&cp->refcnt);
}
int example_hash(struct example *cp)
{
unsigned hash;
int ret;
hash=example_hash_key(cp->s);
ct_write_lock(hash);
if(!(cp->flags&EXAMPLE_F_HASHED))
{
list_add(&cp->node,&example_tab[hash]);
cp->flags|=EXAMPLE_F_HASHED;
atomic_add(1,&cp->refcnt);
ret=1;
}
else
{
ret=0;
}
ct_write_unlock(hash);
return ret;
}
int example_unhash(struct example *cp)
{
unsigned hash;
int ret;
hash=example_hash_key(cp->s);
ct_write_lock(hash);
if(cp->flags&EXAMPLE_F_HASHED)
{
list_del(&cp->node);
cp->flags &=~EXAMPLE_F_HASHED;
atomic_sub(1,&cp->refcnt);
ret=1;
}
else
{
ret=0;
}
ct_write_unlock(hash);
return ret;
}
struct example *example_get(char *s)
{
struct example *cp;
unsigned hash;
hash=example_hash_key(s);
ct_read_lock(hash);
list_for_each_entry(cp,&example_tab[hash],node)
{
spin_lock(&cp->lock);
if(strncmp(cp->s,s,strlen(cp->s))==0)
{
spin_unlock(&cp->lock);
atomic_inc(&cp->refcnt);
ct_read_unlock(hash);
return cp;
}
spin_unlock(&cp->lock);
}
ct_read_unlock(hash);
return NULL;
}
struct example* example_new(char *p)
{
struct example *cp=NULL;
int n;
cp=kmem_cache_alloc(example_cachep,GFP_ATOMIC);
if(cp==NULL)
{
return NULL;
}
memset(cp,0,sizeof(*cp));
INIT_LIST_HEAD(&cp->node);
spin_lock_init(&cp->lock);
n=strlen(p);
cp->s=(char*)kmalloc(((n+1)*sizeof(char)),GFP_ATOMIC);
memcpy(cp->s,p,(n+1)*sizeof(char));
(cp->s)[n]='/0';
atomic_inc(&example_count);
atomic_set(&cp->refcnt,0);
example_hash(cp);
return cp;
}
int example_destroy( struct example* cp)
{
if (cp==NULL) return 0;
atomic_inc(&cp->refcnt);
if(! example_unhash(cp))
{
example_put(cp);
return 0;
}
if(likely((atomic_read(&cp->refcnt))==1))
{
spin_lock(&cp->lock);
if(cp->s)
kfree(cp->s);
spin_unlock(&cp->lock);
atomic_dec(&example_count);
kmem_cache_free(example_cachep,cp);
return 1;
}
example_hash(cp); //还有人使用此项,hash back!
example_put(cp) ;
return 0;
}
int example_init(void)
{
int idx;
/* allocte hash table*/
if(!(example_tab=vmalloc(EXAMPLE_TAB_SIZE*sizeof(struct list_head))))
return -ENOMEM;
example_cachep=kmem_cache_create("example",
sizeof(struct example),0,
SLAB_HWCACHE_ALIGN,NULL);
if(!example_cachep)
{
vfree(example_tab);
return -ENOMEM;
}
/*init hash tab*/
for(idx=0;idx<EXAMPLE_TAB_SIZE;idx++)
{
INIT_LIST_HEAD(&example_tab[idx]);
}
/*init locking tab*/
for(idx=0;idx<CT_LOCKARRAY_SIZE;idx++)
{
rwlock_init(&__example_conntbl_lock_array[idx].l);
}
/* generate random*/
get_random_bytes(&example_rnd,sizeof(example_rnd));
return 0;
}
static void example_flush(void)
{
int idx;
struct list_head *list=NULL;
struct example *cp=NULL;
flush_again:
for(idx=0;idx<EXAMPLE_TAB_SIZE;idx++)
{
ct_write_lock(idx);
list=&example_tab[idx];
while(!list_empty(list))
{
cp=list_entry(list->next,struct example,node);
ct_write_unlock(idx); // example_destroy 有可能使用了相同的锁,所以先解锁
if(!example_destroy(cp))
{
ct_write_lock(idx);
break;
}
ct_write_lock(idx);
}
ct_write_unlock(idx);
}
if(atomic_read(&example_count)!=0)
{
schedule(); //有些example项,可能正在被使用不能一下被destroy,所以等待下次回收空间
goto flush_again;
}
}
void example_cleanup(void)
{
example_flush();
kmem_cache_destroy(example_cachep);
vfree(example_tab);
}
后记:。。。。。辛苦。。。。
- linux内核哈希表一例v1.0
- Linux内核源代码漫游(code v1.0)
- 编译内核模块Hello World V1.0
- Linux命令行大全 v1.0
- Linux命令行大全 v1.0
- Linux命令行大全 v1.0
- Linux Input drivers v1.0
- Linux移植参考手册v1.0
- Linux字符设备驱动v1.0
- 《深入Linux设备驱动程序内核机制》第2章 字符设备驱动程序 V1.2
- linux内核源码的下载 ------ 各种版本的 v1.x v2.x v3.x
- Linux常用命令大全 Linux Commands Line - v1.0
- V1.0
- linux内核实验0
- SEFS安全透明加密内核V1.02
- logtamper-v1.0 修改linux 日志的工具
- Qt Opencv 在Linux下摄像头简单示例v1.0
- Qt Opencv 在Linux下摄像头简单示例v1.0
- MySQL基本信息
- NFC(Near Field Communication)简介--来自百度百科
- 5分钟搞定内存字节对齐
- c++学习笔记1 2011-02-11
- 过年随笔
- linux内核哈希表一例v1.0
- C语言中结构体在函数中的应用
- linux 统计文件信息 wc
- tcp/ip的time_wait状态
- 加入WP阵营 诺基亚/微软宣布战略合作
- 最大流SAP算法
- [Android] ramdisk.img的生成及解压
- 低价iPhone小心变成摩托罗拉V3
- js监听浏览器退出事件