list_entry()

macro :

#define list_entry(ptr,type,member)  \

    ((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member)))

功能  从一个结构的成员指针找到其容器的指针

原理:   ptr是指向type结构体member成员的指针

    &((type *)0)->member

    把0强制转化为指针类型,即0是一个地址,为段基址。取以0为结构体基址的结构体的域变量member的地址,那么这个地址就等于member域到结构体基地址的偏移字节数。

    ((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member)))

    ptr是指向类型为type的某结构体中的成员member的指针,减去该member在结构体中的偏移量,即得到该结构体的起始地址。

list.h中定义了下面三个宏

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

#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)

list_entry(),布布扣,bubuko.com

时间: 2024-10-10 13:58:53

list_entry()的相关文章

linux 链表之:初始化(INIT_HEAD)、添加(list_add)、遍历(list_for_each)及取节点list_entry

这里是最为简单的链表测试代码,使用如下接口: 初始化(INIT_HEAD).添加(list_add).遍历(list_for_each)及取节点list_entry 功能待丰富,目前代码如下: #include "list.h" struct stListUse { char *name; int index; struct list_head list; }; LIST_HEAD(list_use_head); struct stListUse *pstListNode; int m

LIST_ENTRY链表学习

链表是驱动开发中经常遇到的一个数据结构,主要是双向循环链表:要使用链表,需要用到一个LIST_ENTRY的结构,其定义如下: typedef struct _LIST_ENTRY { struct _LIST_ENTRY *Flink; // 指向下一个节点 struct _LIST_ENTRY *Blink; // 指向前一个节点 } LIST_ENTRY, *PLIST_ENTRY; 每个双向链表都是一个以链表头作为链表第一个元素,初次使用时需要进行初始化,主要讲链表头的Flink,Blin

驱动链表(LIST_ENTRY)

DDK提供了两种链表的数据结构,双向链表和单向链表,其定义如下: typedef struct _LIST_ENTRY { struct _LIST_ENTRY *Flink; struct _LIST_ENTRY *Blink; } LIST_ENTRY,*PLIST_ENTRY; typedef struct _SINGLE_LIST_ENTRY { struct _SINGLE_LIST_ENTRY *Next;} SINGLE_LIST_ENTRY, *PSINGLE_LIST_ENTR

由结构体成员地址计算结构体地址——list_entry()原理详解

#define list_entry(ptr, type, member) container_of(ptr, type, member) 在进行编程的时候,我们经常在知道结构体地址的情况下,寻找其中某个成员的地址:但是知道了成员的地址,如果找到这个结构体对应的地址呢? Linux内核中,获取节点地址的函数是list_entry(),它的宏定义如上所示. 我们再来查找container_of(ptr, type, member)的定义,发现它依然是一个宏定义: #define container

第33课 双向循环链表的实现

1. DTLib中双向链表的设计思路 (1)数据结点之间在逻辑上构成双向循环,这有别于Linux内核链表的实现. (2)头结点仅用于结点的定位,而Linux内核链表是将头结点作为循环的一部分. 2. 实现思路 (1)通过模板定义DualCircleList类,继承自DualLinkList类 (2)在DualCircleList内部使用Linux内核链表进行实现(另类实现) (3)使用struct list_head定义DualCircleList的头结点 (4)特殊处理:循环遍历时忽略头结点

list_for_each_entry

内核里面用list_for_each_entry实在太多了,定义在linux-3.10/include/linux/list.h: 1 /** 2 * list_for_each_entry - iterate over list of given type 3 * @pos: the type * to use as a loop cursor. 4 * @head: the head for your list. 5 * @member: the name of the list_struc

Linux内核数据结构——链表

目录 目录 简介 单向链表 双向链表 环形链表 Linux内核中的链表实现 offsetof container_of container_of 第一部分 container_of 第二部分 链表初始化 向链表中增加一个节点 删除节点 移动节点 判断链表是否为空 遍历链表 Demo测试 mlisth mlistc 执行结果 简介 最近在学习Android Binder驱动程序实现的时候,发现里面的数据结构用到了struct list_head.而我google发现struct list_head

Process Kill Technology && Process Protection Against In Linux

目录 0. 引言 1. Kill Process By Kill Command 2. Kill Process By Resource Limits 3. Kill Process By Code Injection Into Running Process Via GDB 4. Kill Process By Using Cross Process Virtual Memory Modify 5. Kill Process By Using ptrace To Inject .so 6. P

list链表之:从链表删除一个节点list_del

从链表删除一个节点使用接口list_del,使用list_del时要非常注意. list_del的实现如下: static inline void list_del(struct list_head *entry) { __list_del(entry->prev, entry->next); entry->next = LIST_POISON1; entry->prev = LIST_POISON2; } static inline void __list_del(struct