|
| 1 | +#include <linux/hashtable.h> |
| 2 | +#include <linux/types.h> |
| 3 | +#include <linux/module.h> |
| 4 | +#include <linux/slab.h> // kmalloc() |
| 5 | +MODULE_LICENSE("GPL"); |
| 6 | + |
| 7 | +#define LENGTH 11 |
| 8 | + |
| 9 | +typedef struct num_node { |
| 10 | + char data[LENGTH]; |
| 11 | + struct hlist_node node; |
| 12 | +} num_node; |
| 13 | + |
| 14 | +DECLARE_HASHTABLE(tbl, 3); |
| 15 | + |
| 16 | +// Just to demonstrate the behavior when two keys are equal. |
| 17 | +static u32 myhash(const char *s) |
| 18 | +{ |
| 19 | + u32 key = 0; |
| 20 | + char c; |
| 21 | + |
| 22 | + //pr_err("Calculating the key of %s....", s); |
| 23 | + |
| 24 | + while ((c = *s++)) { |
| 25 | + key += c; |
| 26 | + //pr_err("key = %u\n", key); |
| 27 | + } |
| 28 | + |
| 29 | + return key; |
| 30 | +} |
| 31 | + |
| 32 | +static u32 add_num(char * num) |
| 33 | +{ |
| 34 | + u32 key; |
| 35 | + struct num_node *a = kmalloc(sizeof(num_node), GFP_KERNEL); |
| 36 | + strcpy(a->data, num); |
| 37 | + key = myhash(a->data); |
| 38 | + hash_add(tbl, &a->node, key); |
| 39 | + pr_err("Phone num %s added!\n", a->data); |
| 40 | + return key; |
| 41 | +}; |
| 42 | + |
| 43 | +static int __init myhashtable_init(void) |
| 44 | +{ |
| 45 | + struct num_node *cur; |
| 46 | + unsigned bkt; |
| 47 | + u32 key; |
| 48 | + |
| 49 | + pr_info("myhashtable: module loaded\n"); |
| 50 | + |
| 51 | + // Initialize the hashtable. |
| 52 | + hash_init(tbl); |
| 53 | + |
| 54 | + key = add_num("01157133430"); |
| 55 | + add_num("01157133403"); |
| 56 | + add_num("01157134303"); |
| 57 | + add_num("01157122403"); |
| 58 | + add_num("01157166403"); |
| 59 | + |
| 60 | + |
| 61 | + add_num("01111111111"); |
| 62 | + add_num("01122222222"); |
| 63 | + add_num("01133333333"); |
| 64 | + add_num("01144444444"); |
| 65 | + add_num("01155555555"); |
| 66 | + |
| 67 | + // List all elements in the table. |
| 68 | + pr_cont("List all elements in the table"); |
| 69 | + hash_for_each(tbl, bkt, cur, node) { |
| 70 | + pr_info("myhashtable: Phone num = %s\n", |
| 71 | + cur->data); |
| 72 | + } |
| 73 | + |
| 74 | + // Get the element = "01157133430". |
| 75 | + pr_cont("Get the phone number = \"01157133430\""); |
| 76 | + hash_for_each_possible(tbl, cur, node, key) { |
| 77 | + pr_info("myhashtable: match for key %u: Phone = %s\n", |
| 78 | + key, cur->data); |
| 79 | + |
| 80 | + // Check the value |
| 81 | + if (!strcmp(cur->data, "01157133430")) { |
| 82 | + pr_err("myhashtable: \"01157133430\" found!\n"); |
| 83 | + break; |
| 84 | + } |
| 85 | + } |
| 86 | + |
| 87 | + return 0; |
| 88 | +} |
| 89 | + |
| 90 | +static void myhashtable_exit(void) |
| 91 | +{ |
| 92 | + |
| 93 | + struct num_node *cur; |
| 94 | + unsigned bkt; |
| 95 | + |
| 96 | + // Remove elements. |
| 97 | + hash_for_each(tbl, bkt, cur, node) { |
| 98 | + hash_del_rcu(&cur->node); |
| 99 | + } |
| 100 | + |
| 101 | + hash_for_each(tbl, bkt, cur, node) { |
| 102 | + pr_info("myhashtable: Phone num = %s\n", |
| 103 | + cur->data); |
| 104 | + } |
| 105 | + |
| 106 | + pr_info("myhashtable: module unloaded\n"); |
| 107 | +} |
| 108 | + |
| 109 | +module_init(myhashtable_init); |
| 110 | +module_exit(myhashtable_exit); |
0 commit comments