下面的程序,目的是遍历一条链表,逐条的删除没一个节点。
[code]
struct list_head *listp;
struct arethe* arethep;
list_for_each(listp, arethe_list)
{
arethep = list_entry(listp, struct arethe, list_entry);
list_del(listp);
kfree(arethep);
}
[/code]
但是,在执行时,会出现内存引用出错的问题. 在分析list_del与list_for_each后,发现在list_del之后,list_for_each以无法再遍历剩下的链表。因为listp->next与listp->prev与链表都以没有关联。此时,采用list_for_each_safe(pos,n,head)宏可解决问题。该宏与前者的区别主要是采用了另外一个指针n来存储pos的下一个节点的位置,因此在删除某个节点以后,保存了剩下的节点的信息。相应代码应修改为如下:
[code]
struct list_head *listp;
struct list_head *listn;
struct arethe* arethep;
list_for_each_safe(listp, listn, arethe_list)
{
arethep = list_entry(listp, struct arethe, list_entry);
list_del(listp);
kfree(arethep);
}
arethep = list_entry(listp, struct arethe, list_entry);
printk("arethe_list->arethe_ip: %d/n", arethep->arethe_ip);
[/code]
有一点需要注意的是,无论是list_for_each还是list_for_each_safe,都遍历不到头结点.
另附上一段list_head的操作范例:
[code]
#include <linux/module.h>
#include <linux/kernel.h>
#include <arethe_dbg.h>
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Arethe");
struct arethe{
struct list_head list_entry;
int arethe_ip;
};
int arethe_ip = 0;
struct list_head *arethe_list;
int list_head_init(void)
{
struct list_head *listp;
struct arethe *arethep;
int arethe_num = 10;
int i = 0;
for(i=0; i < arethe_num; i++)
{
arethep = kzalloc(sizeof(*arethep), GFP_KERNEL);
arethe_ip++;
arethep->arethe_ip = arethe_ip;
printk(KERN_ALERT"arethe_ip: %d/n", arethe_ip);
INIT_LIST_HEAD(&arethep->list_entry);
if(!arethe_list)
arethe_list = &arethep->list_entry;
else
list_add(arethep, arethe_list);
}
list_for_each(listp, arethe_list)
{
arethep = list_entry(listp, struct arethe, list_entry);
printk(KERN_ALERT"arethe->arethe_ip: %d/n", arethep->arethe_ip);
}
arethep = list_entry(listp, struct arethe, list_entry);
printk(KERN_ALERT"arethe->arethe_ip: %d/n", arethep->arethe_ip);
return 0;
}
void list_head_exit(void)
{
struct list_head *listp;
struct list_head *listn;
struct arethe* arethep;
list_for_each_safe(listp, listn, arethe_list)
{
arethep = list_entry(listp, struct arethe, list_entry);
printk(KERN_ALERT"Del: arethep->ip: %d/n", arethep->arethe_ip);
//if(listp->next != listp && listp->prev != listp)
list_del(listp);
kfree(arethep);
}
arethep = list_entry(listp, struct arethe, list_entry);
printk("arethe_list->arethe_ip: %d/n", arethep->arethe_ip);
}
module_init(list_head_init);
module_exit(list_head_exit);
[/code]
运行结果为:
[code]
arethe_ip: 1
arethe_ip: 2
arethe_ip: 3
arethe_ip: 4
arethe_ip: 5
arethe_ip: 6
arethe_ip: 7
arethe_ip: 8
arethe_ip: 9
arethe_ip: 10
arethe->arethe_ip: 10
arethe->arethe_ip: 9
arethe->arethe_ip: 8
arethe->arethe_ip: 7
arethe->arethe_ip: 6
arethe->arethe_ip: 5
arethe->arethe_ip: 4
arethe->arethe_ip: 3
arethe->arethe_ip: 2
arethe->arethe_ip: 1
Del: arethep->ip: 10
Del: arethep->ip: 9
Del: arethep->ip: 8
Del: arethep->ip: 7
Del: arethep->ip: 6
Del: arethep->ip: 5
Del: arethep->ip: 4
Del: arethep->ip: 3
Del: arethep->ip: 2
arethe_list->arethe_ip: 1
[/code]