学习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;102103 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}