嵌入式C语言系列---container_of的定义与使用

前言

container_of 是一个宏函数,它被称为内核第一宏。反正就是牛逼。
作用:根据一个结构体成员的名称和地址以及,结构体的类型,可以计算出结构体变量的地址。
网上大多数文章都是在分析这个宏的原理,但是对于如何使用这个宏讲的非常少,其实笔者认为,对于container_of的理解固然重要,
但是正真实践中还是要掌握他的使用方法。

1. container_of 的定义

#define offsetof(TYPE, MEMBER) ({ (size_t)(&((TYPE *)0->MEMBER))})
#define container_of(ptr, type, member) ({	\
		const typeof((type *)0 -> member) * mptr = (ptr);	\
		(type *)((char *)mptr - offsetof(type, member));	})

上面是我自己写的。其实这个宏不难理解,这里不展开讲,因为网上讲这个宏的文章 多且棒,
你只需要理解他,然后每天写一遍,每天写得都不一样,但是在进步就够了。
还有,很多嵌入式开发岗位都会让你默写一个container_of出来,所以对于这个定义除了锻炼你的思维能力之外
可能最大的用处就是应付面试了。

2. container_of 的使用

应用广泛

本节是我写这篇文章的目的,应为他太重要了,一个linux 内核源码中就包含了数不清的container_of。 看下图我搜了一下,这个数字多吧!
在这里插入图片描述

第一个参数的使用最重要

它有三个参数,一定要搞清楚搞明白,这个三个参数
container_of(ptr, type, member)
member: 他是一个结构体成员变量的名称,注意这里是名称,它既不是普通含义的变量,也不是像听起来是个字符串。
type:它是结构体的类型
ptr 这是最容易搞混淆的一个参数,他是结构体成员的地址。不是结构体的地址

例子:下面iomd_request_dma函数是参考来自/arch/arm/mach-rpc/dma.c的内核源代码

struct dma_struct;
typedef struct dma_struct dma_t;
///
struct iomd_dma {
	struct dma_struct	dma;
	void __iomem		*base;		/* Controller base address */
	int			irq;		/* Controller IRQ */
	unsigned int		state;
	dma_addr_t		cur_addr;
	unsigned int		cur_len;
	dma_addr_t		dma_addr;
	unsigned int		dma_len;
};
/
static int iomd_request_dma(unsigned int chan, dma_t *dma)
{
	struct iomd_dma *idma = container_of(dma, struct iomd_dma, dma);

	return request_irq(idma->irq, iomd_dma_handle,
			   0, idma->dma.device_id, idma);
}

函数iomd_request_dma中的 container_of(dma, struct iomd_dma, dma)
第三个参数: 结构体成员的名称: dma(此dma表示的是结构体struct iomd_dma 的成员dma的名称 )
第二个参数: 结构体类型:struct iomd_dma
第一个参数:结构体成员的地址:dma(此dma是指结构体成员dma的地址,它是作为函数的形参从函数调用位置传入的,他和成员名称dma不是一回事)

因此该宏得到的结构体是指向结构体struct iomd_dma的一个指针struct iomd_dma *idma

那么这个结构体指针idma就是指向第三个参数所表示那个结构体成员idma处于的结构体的指针

总结

因此在实际使用中container_of的第一个参数,往往来自于该宏所处的函数的形式参数,其中形参的类型就是指向结构体成员同类型的指针,下图画出来了:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值