list_head双向链表的删除问题

来源:互联网 发布:linux ftp 端口设置 编辑:程序博客网 时间:2024/06/05 14:38

下面的程序,目的是遍历一条链表,逐条的删除没一个节点。

[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]

原创粉丝点击