list_entry宏

list_entry宏

Content #

#define list_entry(ptr, type, member) \
container_of(ptr, type, member)

//container_of()宏的定义在kernel.h头文件中。
#define container_of(ptr, type, member) ({      \
const typeof( ((type *)0)->member ) *__mptr = (ptr);  \
(type *)( (char *)__mptr - offsetof(type,member) );})

#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)

其中offsetof()宏是通过把0地址转换为type类型的指针,然后去获取该结构体中member成员的指针,也就是获取了member在type结构体中的偏移量。最后用指针ptr减去offset,就得到type结构体的真实地址了。

下面是遍历链表的一个例子。

//<drivers/block/osdblk.c>
static LIST_HEAD(osdblkdev_list);
struct osdblk_device {
    int			id;		/* blkdev unique id */
    int			major;		/* blkdev assigned major */
    ...
    struct list_head	node;
    char			osd_path[0];	/* OSD device path */
};

static ssize_t class_osdblk_list(struct class *c,
    struct class_attribute *attr,
    char *data)
{
    int n = 0;
    struct list_head *tmp;
    list_for_each(tmp, &osdblkdev_list) {
        struct osdblk_device *osdev;
        osdev = list_entry(tmp, struct osdblk_device, node);
        n += sprintf(data+n, "%d %d %llu %llu %s\n",
            osdev->id,
            osdev->major,
            osdev->obj.partition,
            osdev->obj.id,
            osdev->osd_path);
    }
    return n;
}

From #

奔跑吧Linux内核——入门篇