i write a module about link list with pri as the head node. It’s empty initially.
In pri_init(), I insert 3 nodes into the list and assign value to each of them. Finally, i want to use list_for_each_entry to iterate the list and print out the nodes’ value.
But actually, it just printed out only 1 random value in list_for_each_entry{…} in pri_init().
Instead, if I use container_of within a for() loop to iterate the list, the result is correct.
Can anyone tell me why? Thanks a lot.
#include <linux/init.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/errno.h>
#include <asm/uaccess.h>
#include <linux/list.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/sched.h>
MODULE_LICENSE("GPL");
struct pri_listitem
{
int v;
struct list_head list;
};
LIST_HEAD(pri);
void pri_exit(void)
{
struct pri_listitem *list_p, *next;
list_for_each_entry_safe(list_p, next, &pri, list)
{
list_del(&list_p->list);
kfree(list_p);
}
printk(KERN_ALERT "***** device pri exit() ***** \n");
}
int pri_init(void)
{
int i;
struct pri_listitem *list_p;
printk(KERN_ALERT "***** device pri init() ***** \n");
// Inserting 3 nodes
for(i=1; i<=3; ++i)
{
list_p = kmalloc(sizeof(struct pri_listitem),GFP_KERNEL);
if(!list_p)
{
printk(KERN_DEBUG "Error: alloction memory for list_p\n");
return -ENOMEM;
}
memset(list_p, 0, sizeof(struct pri_listitem));
list_p->v = i;
list_add(&(list_p->list), &pri);
}
printk(KERN_DEBUG "value of the 3 nodes:\n");
list_for_each_entry(list_p, &pri, list);
{
printk(KERN_DEBUG "%d\n",list_p->v); // print nodes' value
}
return 0;
}
module_init(pri_init);
module_exit(pri_exit);
You simply had a semi colon at the end of your list for each entry, this meant your position was set to a garbage value in memory (not really garbage just an offset behind your allocated list_head pri structure in memory) hence you getting random values for the dereference (you unluckily landed in memory you could access so it’s hard to spot the error sometimes.) The single run through the loop should have tipped you off as the following section on the list_for_each_entry simply executed as a scoped block.