模拟linux内核哈希表

原创作品,敬请转载,转载时请务必以超链接形式标明出处。欢迎讨论。

一.linux源码中,提供了方便哈希表创建和使用的结构体和API。他们在源码中的位置和定义如下:
   1./include/linux/types.h文件中有两个结构体:
    

点击(此处)折叠或打开

  1. struct hlist_head {
  2.         struct hlist_node *first;
  3.  };
  4.  struct hlist_node {
  5.        struct hlist_node *next, **pprev;
  6.  };
   2./include/linux/list.h文件中实现了操作哈希表的API。这里不予以列举。有需要看源码哦。
二.一个哈希表的实例(相信大家在数据结构书中都遇见过)。
   1.问题描述:将关键字 {19, 14, 23, 01, 68, 20, 84, 27, 55, 11, 10, 79},用H(x)=x % P,散列到
哈希表中,使用链地址法处理冲突。
   2.hash.h文件中描述了这一实例。
     

点击(此处)折叠或打开

  1. #include <linux/types.h>
  2. /*H(k) = k%p
  3.  *@ p<=m,m哈希表的长度
  4. */
  5. #define NR_HASH 13 /*m*/
  6. #define P 13 /*p*/
  7. #define NR_KEYS 12 /*keys number*/

  8. #define hashfn(x) ((x)%(P)) /*hashfn*/

  9. int keys[NR_KEYS] = {19, 14, 23, 01, 68, 20, 84, 27, 55, 11, 10, 79}; /*关键字
  10. */

  11. struct hash_term /*哈希表项*/
  12. {
  13.         int key;
  14.         struct hlist_node list;
  15. };
  16. struct hlist_head hash[NR_HASH]; /*哈希表*/

   3.hash.c是一个内核模块程序,实现了哈希表的创建,散列和遍历。
     

点击(此处)折叠或打开

  1. #include <linux/types.h>

  2. #include <linux/module.h>
  3. #include <linux/kernel.h>
  4. #include <linux/init.h>

  5. #include "hash.h"
  6. static int __init lkp_init(void)
  7. {
  8.         int i;
  9.         int addr;
  10.         struct hash_term *p;
  11.         struct hash_term *tpos;
  12.         struct hlist_node *pos;

  13.         for(i=0; i<NR_HASH; i++)
  14.         {
  15.                 INIT_HLIST_HEAD( &hash[i] ); /*初始化哈希表*/
  16.         }

  17.         for(i=0; i<NR_KEYS; i++)
  18.         {
  19.                 addr = hashfn(keys[i]); /*由哈希函数获得地址*/

  20.                 p = (struct hash_term *)kmalloc(sizeof(struct hash_term), GFP_KERNEL); /*动态申请内核内存*/
  21.                 p->key = keys[i];
  22.                 hlist_add_head(&p->list, &hash[addr]); /*头插法存放关键字节点*/
  23.         }
  24.         
  25.         for(i=0; i<NR_HASH; i++) /*输出哈希表*/
  26.         {
  27.                 printk("print hash table:\n");
  28.                 printk("%d\t",i);
  29.                 hlist_for_each_entry(tpos, pos, &hash[i], list){
  30.                         printk("%d\t",tpos->key);
  31.                 }
  32.                 printk("^\n");
  33. }

  34.         return 0;
  35. }

  36. static void __exit lkp_cleanup(void)
  37. {
  38.         struct hlist_node *pos;
  39.         struct hlist_node *n;
  40.         int i;

  41.         printk("destroy hash table...."); /*释放内存*/
  42.         for(i=0; i<NR_HASH; i++)
  43.         {
  44.                 hlist_for_each_safe(pos, n, &hash[i]){
  45.                         kfree(pos);
  46.                 }
  47.         }
  48. }
  49. module_init(lkp_init);
  50. module_exit(lkp_cleanup);
  51. MODULE_LICENSE("GPL");
4.接下来就是编写Makefile文件,执行make命令,插入模块并观察运行结果等等。
  
     
<script type=text/javascript charset=utf-8 src="http://static.bshare.cn/b/buttonLite.js#style=-1&uuid=&pophcol=3&lang=zh"></script> <script type=text/javascript charset=utf-8 src="http://static.bshare.cn/b/bshareC0.js"></script>
阅读(211) | 评论(0) | 转发(0) |
0

上一篇:linux模块编程

下一篇:Linux进程内核栈

给主人留下些什么吧!~~
评论热议
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值