offsetof、container_of、LinuxList

offsetof、container_of

功能介绍及使用注意事项:

/*功能:计算TYPE类中MEMBER成员的偏移量*/
#ifndef offsetof
#define offsetof(TYPE, MEMBER)	((unsigned int) &((TYPE *)0)->MEMBER)
#endif


/*
功能:将类里面的成员指针转为类指针
可以进行类型有效性检测,不是同一个类的会提示错误
( { } ) 与逗号表达式类似,结果为最后一个语句的值
注意事项:需要typeof关键字,gnuc是支持的,其他没支持的都无法使用该宏
参数1:当前成员地址 2:类(结构体)类型(父) 3:当前成员名
*/
#ifndef container_of
#define container_of(ptr,type,member)	\
    ({	const typeof(((type*)0)->member)* __mptr = (ptr);	\
        (type*)((char*)__mptr - offsetof(type,member));		\
    });
#endif

/*
与container_of功能相同,没有typeof关键字,所有编译器都可以使用
但没有类型检测(所有编译器都可以用),使用时要注意两个类型是是同一个类
*/
#ifndef container_of_new
#define container_of_new(ptr,type,member)	(type*)((char*)ptr - offsetof(type,member))
#endif

LinuxList

  Linux内核链表的数据定义
    -带头结点的双向循环链表,且头结点为表中成员
    -头结点的next指针指向首结点
    -头节点的prev指针指向尾结点

struct list_head {
    struct list_head *next, *prev;
};

使用Linux内核中的链表需要自己添加数据,定义结点
下面是其中常用的一些链表操作
注意使用container_of辅助使用

#define prefetch(x) ((void)x)//gnu c里面加速运行速度的,其他编译器没有,所以取消

#define LIST_POISON1  (NULL)//删除后的节点前继指向位置
#define LIST_POISON2  (NULL)//删除后的节点后驱指向位置

//初始化首结点
static void INIT_LIST_HEAD(struct list_head *list)
{
    list->next = list;
    list->prev = list;
}

//在prev与next之间添加结点
static void __list_add(struct list_head *node,
                  struct list_head *prev,
                  struct list_head *next)
{
    next->prev = node;
    node->next = next;
    node->prev = prev;
    prev->next = node;
}

//封装,在首结点后加入结点
static void list_add(struct list_head *node, struct list_head *head)
{
    __list_add(node, head, head->next);
}

//封装,在首结点前加入结点
static void list_add_tail(struct list_head *node, struct list_head *head)
{
    __list_add(node, head->prev, head);
}

//删除prev与next之间的结点,原对象还处在,不在链表里
static void __list_del(struct list_head * prev, struct list_head * next)
{
    next->prev = prev;
    prev->next = next;
}

//正序遍历
#define __list_for_each(pos, head) \
    for (pos = (head)->next; pos != (head); pos = pos->next)

//逆序遍历
#define list_for_each_prev(pos, head) \
    for (pos = (head)->prev; prefetch(pos->prev), pos != (head); \
            pos = pos->prev)
Linux内核中,container_of是一个宏定义,用于获取包含某个成员的结构体变量的地址。它的定义可以在include/linux/kernel.h中找到。该宏的作用是通过给定的成员指针,返回包含该成员的结构体变量的地址。具体的定义如下: ```c #define container_of(ptr, type, member) ({ \ const typeof( ((type *)0)->member ) *__mptr = (ptr); \ (type *)( (char *)__mptr - offsetof(type,member) );}) ``` 这个宏的使用非常方便,可以通过成员指针来获取整个结构体变量的地址。在进行内核驱动开发时,经常会用到这个宏来获取结构体变量的地址,以便进行相关操作。 #### 引用[.reference_title] - *1* [Linux内核:理解container_of宏](https://blog.csdn.net/qq_28877125/article/details/124209504)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* *3* [Linux内核中container_of的原理及其使用详解](https://blog.csdn.net/u010632165/article/details/107523477)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值