曲径通幽论坛

标题: 获得链表中第一个结构的指针 |list_first_entry() [打印本页]

作者: beyes    时间: 2011-5-18 15:31
标题: 获得链表中第一个结构的指针 |list_first_entry()
list_first_entry() 宏用来获取链表中第一个结构的指针。当然了,如果你将此函数用在一个模块中,当你插入这个模块后,那么链表中原来第一个模块结构就会退变为第 2 个。链表的插入原理见:http://www.groad.net/bbs/read.php?tid-3181.html

该宏定义在 include/linux/list.h 中:
[C++] 纯文本查看 复制代码
/**
* list_first_entry - get the first element from a list
* @ptr:    the list head to take the element from.
* @type:    the type of the struct this is embedded in.
* @member:    the name of the list_struct within the struct.
*
* Note, that list is expected to be not empty.
*/
#define list_first_entry(ptr, type, member) \
    list_entry((ptr)->next, type, member)

实际上,它被定义为 list_entry() 宏,对该宏的描述见:http://www.groad.net/bbs/read.php?tid-3539.html

下面用具体实例说明:
[C++] 纯文本查看 复制代码

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/version.h>
#include <linux/list.h>

MODULE_LICENSE("Dual BSD/GPL");

struct module *m = &__this_module;
static int list_module_init (void)
{
        printk ("---------------------------\n");
        printk ("the first module name is: %s\n", (list_first_entry(&(m->list), struct module, list))->name);
        printk ("---------------------------\n");
        return 0;
}

static void list_module_exit (void)
{
        printk ("unload listmodule.ko\n");
}

module_init(list_module_init);
module_exit(list_module_exit);

在插入该宏之前,我们使用 lsmod 命令列出了内核中已经插入的模块列表,从中发现 fuse 模块是排在第 1 个的。那么可以想象,当插入该模块后,打印出的信息也应该标明第 1 个模块的名称是 fuse 。然后再运行一遍 lsmod 命令时,同样会发现第 1 个模块已经变成上面这个。

插入模块前运行 lsmod 命令:
[root@SLinux listmodule]# lsmod
Module                  Size  Used by
fuse                   56128  0
ip6table_filter         2219  0
... ...

插入模块后观察输出:
---------------------------
the first module name is: fuse
---------------------------

再运行一次 lsmod 命令:
[root@SLinux listmodule]# lsmod
Module                  Size  Used by
listmodule               728  0
fuse                   56128  0
... ...
从输出结果发现设想是对的。

因为插入自后自己变成第 1 个元素,那么为了获得自身,可以修改 list_first_entry() 中的 ptr 指针为 m->list.prev 。




欢迎光临 曲径通幽论坛 (http://www.groad.net/bbs/) Powered by Discuz! X3.2