内核版本:2.6.24 
list_for_each_entry() 宏用来遍历内核链表,它定义在 include/linux/list.h 中: 
[C++] 纯文本查看 复制代码 /**
 * list_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 list_struct within the struct.
 */
#define list_for_each_entry(pos, head, member)                \
    for (pos = list_entry((head)->next, typeof(*pos), member);    \
         prefetch(pos->member.next), &pos->member != (head);     \
         pos = list_entry(pos->member.next, typeof(*pos), member)) 
由注释知道,pos 参数是 1 个遍历用的指针,第 2 个参数就是链表头,第 3 个参数为链表中元素的一个成员。该宏被定义为一个 for 循环,可以用它从它从第 1 个元素开始(list_entry((head)->next)遍历整个链表。其中 prefetch() 函数用以加快对链表的遍历速度,它实际上是 gcc 内置函数 __builtin_prefetch 的封装,关于 __builtin_prefetch 函数的描述可参考:http://www.groad.net/bbs/read.php?tid-3542.html 。在 2.6.3x 这样的内核中,取消了 prefetch() 函数在此的使用,估计是和后来的 CPU 的缓存机制更为先进的缘故。 
 
下面用这个函数遍历整个模块链表,并打印出各个模块的名字,就如同 lsmod 的精简版: 
[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 void list_module_test(void)
{
        struct module *mod;
        list_for_each_entry(mod, m->list.prev, list)
                printk ("%s\n", mod->name);
}
static int list_module_init (void)
{
        list_module_test();
        return 0;
}
static void list_module_exit (void)
{
        printk ("unload listmodule.ko\n");
}
module_init(list_module_init);
module_exit(list_module_exit); 
因为插入的当前模块会加在表头和原来的第一个模块之间,所以 m->list.prev 参数用以指名从表头开始遍历。 
加载后输出:[root@SLinux listmodule]# dmesg -c 
listmodule 
fuse 
ip6table_filter 
ip6_tables 
xt_CHECKSUM 
iptable_mangle 
ipt_MASQUERADE 
iptable_nat 
... ... 
ata_generic 
pata_acpi 
ata_piix 
dm_mod  |