在Linux中遍历链表会得到所需节点中后向指针成员的地址,而不是节点本身的地址。为了获取节点的地址,linux内核中引入了list_entry这个宏。
#define list_enty(ptr,type,member) container_of(ptr,type,member)
这个宏的作用是通过指向member的指针ptr来获得指向整个节点的指针,member是type结构体的成员。
这个宏里还有另外一个宏container_of,此条宏位于linux/kernel.h中,定义如下:
#define container_of(ptr,type,member) ({const typeof(((type*)0) ->member)*_mptr = (ptr);\
(type*)((char*)_mptr - offsetof(type,member));})
该条宏包含两条语句:
1.const typeof(((type*)0) ->member)*_mptr = (ptr);
其含义为将地址0转换为type类型的指针,然后引用其中的member成员,定义一个指针_mptr其类型与member成员的数据类型一致,并用ptr对它初始化。
2.(type*)((char*)_mptr - offsetof(type,member));
其中offsetof有另一条宏来定义:
#define offsetof(type,member) ((size_t) &(type*)0 ->member)
此条宏作用是取出member成员与节点首地址的偏移量,其精彩之处在于设定一个节点地址为0的结构体,再找出其member成员的地址。
这样成员的地址即为成员地址与首地址的偏移量。
size_t型为unsigned int型。
语句2中将_mptr转换为char*型再与offsetof相减时就是以字节为单位相减。
因此用member成员的地址减去偏移量即为本节点的首地址。
linux内核中的一些有趣的宏
最新推荐文章于 2024-08-19 15:43:01 发布