list_for_each_entry
Rev.2を表示中。最新版はこちら。
list_for_each_entryは以下の様に展開されて、ちょっと引いてしまいそうですが、リスト処理でlist_for_eachとlist_entryの機能をもたせたものです。#define list_for_each_entry(pos, head, member) \ for (pos = list_entry((head)->next, typeof(*pos), member); \ &pos->member != (head); \ pos = list_entry(pos->member.next, typeof(*pos), member))
#define list_for_each(pos, head) \ for (pos = (head)->next; pos != (head); pos = pos->next) #define list_entry(ptr, type, member) \ container_of(ptr, type, member)以下は、list_for_each_entryとlist_for_eachでリストを走査するサンプルです。
#include <linux/kernel.h> #include <linux/module.h> #include <linux/list.h> #include <linux/slab.h> MODULE_DESCRIPTION("list_for_each_entry"); MODULE_AUTHOR("y.kitamura"); static LIST_HEAD(head); struct my_object { struct list_head list; int sec; }; void set_data(void) { struct my_object *myobj; int i; for (i = 0; i < 10; ++i) { myobj = (struct my_object*)kmalloc(sizeof(struct my_object), GFP_KERNEL); myobj->sec = i; list_add_tail(&myobj->list, &head); } } void for_each(void) { struct list_head *p; struct my_object *myobj; list_for_each(p, &head) { myobj = list_entry(p, struct my_object, list); printk("%d:", myobj->sec); } printk("\n"); } void for_each_entry(void) { struct my_object *myobj; list_for_each_entry(myobj, &head, list) { printk("%d:", myobj->sec); } printk("\n"); } int init_module(void) { set_data(); for_each(); for_each_entry(); return 0; } void cleanup_module(void) { struct my_object *myobj; while(!list_empty(&head)) { myobj = list_entry(head.next, struct my_object, list); list_del(&myobj->list); kfree(myobj); } }
[root@localhost lkm]# insmod list_head.ko [root@localhost lkm]# dmesg : : [11090.009091] pcnet32 0000:02:01.0: eth0: link up [11092.004380] pcnet32 0000:02:01.0: eth0: link down [11102.008055] pcnet32 0000:02:01.0: eth0: link up [21452.459410] 0:1:2:3:4:5:6:7:8:9: [21452.459423] 0:1:2:3:4:5:6:7:8:9: