对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}

相关推荐