前情提要
上文 给了一个打印hlist的demo,遍历函数是自己随便实现的,本文会给出一个使用正经的Linux kernel API来遍历的例子API
/**
* hash_for_each - iterate over a hashtable
* @name: hashtable to iterate
* @bkt: integer to use as bucket loop cursor
* @obj: the type * to use as a loop cursor for each entry
* @member: the name of the hlist_node within the struct
*/
#define hash_for_each(name, bkt, obj, member) \
for ((bkt) = 0, obj = NULL; obj == NULL && (bkt) < HASH_SIZE(name);\
(bkt)++)\
hlist_for_each_entry(obj, &name[bkt], member)
/**
* hlist_for_each_entry - iterate over list of given type
* @pos: the type * to use as a loop cursor.
* @head: the head for your list.
* @member: the name of the hlist_node within the struct.
*/
#define hlist_for_each_entry(pos, head, member) \
for (pos = hlist_entry_safe((head)->first, typeof(*(pos)), member);\
pos; \
pos = hlist_entry_safe((pos)->member.next, typeof(*(pos)), member))
#define hlist_entry_safe(ptr, type, member) \
({ typeof(ptr) ____ptr = (ptr); \
____ptr ? hlist_entry(____ptr, type, member) : NULL; \
})
- code
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/hashtable.h>
#include <linux/vmalloc.h>
#define HBITS 2
DEFINE_HASHTABLE(planet_htable, HBITS);
struct planet {
int mass;
char name[16];
struct hlist_node node;
};
struct planet *create_planet(int mass, char *name);
void destroy_planet(struct planet *p);
void hlist_print(void);
void hlist_test(void);
void create_planet(int mass, char *name){
struct planet *p;
p = vmalloc(sizeof(struct planet));
if(!p){
pr_err("[!] Create planet failed.\n");
return NULL;
}
memset(p, 0, sizeof(struct planet));
p->mass = mass;
strcpy(p->name, name);
hash_add_rcu(planet_htable, &p->node, p->mass);
return p;
}
void destroy_planet(struct planet *p){
hash_del_rcu(&p->node);
vfree(p);
}
void hlist_print(void){
struct planet *p;
int i = 0;
hash_for_each_rcu(planet_htable, i, p, node){
pr_info("i: %d, p: %px, p->name: %s\n", i, p, p->name);
}
}
void hlist_test(void){
struct planet * earth;
struct planet * mars;
struct planet * venus;
struct planet * jupiter;
earth = create_planet(0, "Earth");
mars = create_planet(1, "Mars ");
venus = create_planet(1, "Venus");
jupiter = create_planet(1, "Jupiter");
hlist_print();
destroy_planet(earth);
destroy_planet(mars);
destroy_planet(venus);
destroy_planet(jupiter);
}
static int __init hlist_t_init(void)
{
printk(KERN_INFO "Hello hlist_t\n");
hlist_test();
return 0;
}
static void __exit hlist_t_exit(void)
{
printk(KERN_INFO "Goodbye hlist_t\n");
}
module_init(hlist_t_init);
module_exit(hlist_t_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("X++0");
MODULE_DESCRIPTION("Kernel xxx Module.");
MODULE_VERSION("0.1");
- output
[10447.917434] Earth, 0 created
[10447.918381] Mars , 1 created
[10447.919051] Venus, 1 created
[10447.919860] Jupiter, 1 created
[10447.920673] i: 0, p: ffffc9000009f000, p->name: Earth
[10447.921676] i: 1, p: ffffc900000fb000, p->name: Jupiter
[10447.922523] i: 1, p: ffffc900000a3000, p->name: Venus
[10447.923336] i: 1, p: ffffc900000a1000, p->name: Mars