对Linux内核宏container_of的理解
学习Linux驱动的过程中经常会遇到一个这样的宏:container_of,原定义如下
Linux/include/Linux/kernel.h中
486/**
487 * container_of - cast a member of a structure out to the containing structure
488 * @ptr: the pointer to the member.
489 * @type: the type of the container struct this is embedded in.
490 * @member: the name of the member within the struct.
491 *
492 */
493#define container_of(ptr, type, member) ({ \
494 const typeof( ((type *)0)->member ) *__mptr = (ptr); \
495 (type *)( (char *)__mptr - offsetof(type,member) );})
这个宏的作用是获取位置ptr处的包含member成员的,类型为type的struct的指针。
这句话可能比较拗口,我们来看一个具体的例子:
Linux/drivers/gpio/mcp23s08.c
98static int mcp23s08_direction_input(struct gpio_chip *chip, unsigned offset)
99{
100 struct mcp23s08 *mcp = container_of(chip, struct mcp23s08, chip);
101 int status;
102
103 mutex_lock(&mcp->lock);
104 mcp->cache[MCP_IODIR] |= (1 << offset);
105 status = mcp23s08_write(mcp, MCP_IODIR, mcp->cache[MCP_IODIR]);
106 mutex_unlock(&mcp->lock);
107 return status;
108}
/*
上面的函数中执行 container_of后返回的值为一个指向类型为mcp23s08的数据(暂时称这个数据为mcp_data)的指针,并且这个mcp_data数据中包含的成员chip(这个chip为成员名,也就是第三个参数)的数据就是形参*chip(这个chip是形参,是一个指针值,也就是宏中的第一个参数)所指向的数据 ,这里说的“就是”是指他们的位置完全相同,数据理所当然也完全相同。
*/
//类型mcp23s08的定义
39struct mcp23s08 {
40 struct spi_device *spi;
41 u8 addr;
42
43 u8 cache[11];
44 /* lock protects the cached values */
45 struct mutex lock;
46
47 struct gpio_chip chip;
48
49 struct work_struct work;
50};
//上面例子中被调用的写函数
74static int mcp23s08_write(struct mcp23s08 *mcp, unsigned reg, u8 val)
75{
76 u8 tx[3];
77
78 tx[0] = mcp->addr;
79 tx[1] = reg;
80 tx[2] = val;
81 return spi_write_then_read(mcp->spi, tx, sizeof tx, NULL, 0);
82}