在LINUX中内核中有很多C语言的奇技淫巧,比如container_of()这个宏, 在很多地方会用到,比如在定义宏to_i2c_driver, to_spi_driver时都用到这个,有些就直接在函数中调用 container_of宏。
1. 作用
这个宏的作用就是通过一个结构体的某个成员的指针,反推出这个结构体的首地址。
这种操作非常有用,尤其在C语言中写面向对象的程序时,相当模拟了C++多态的效果。以LINUX内核中I2C子系统为例, i2c驱动结构体如下:
struct i2c_driver {
unsigned int class;
/* Standard driver model interfaces */
int (*probe)(struct i2c_client *client, const struct i2c_device_id *id);
void (*remove)(struct i2c_client *client);
/* New driver model interface to aid the seamless removal of the
* current probe()'s, more commonly unused than used second parameter.
*/
int (*probe_new)(struct i2c_client *client);
/* driver model interfaces that don't relate to enumeration */
void (*shutdown)(struct i2c_client *client);
/* Alert callback, for example for the SMBus alert protocol.
* The format and meaning of the data value depends on the protocol.
* For the SMBus alert protocol, there is a single bit of data passed
* as the alert response's low bit ("event flag").
* For the SMBus Host Notify protocol, the data corresponds to the
* 16-bit payload data reported by the slave device acting as master.
*/
void (*alert)(struct i2c_client *client, enum i2c_alert_protocol protocol,
unsigned int data);
/* a ioctl like command that can be used to perform specific functions
* with the device.
*/
int (*command)(struct i2c_client *client, unsigned int cmd, void *arg);
struct device_driver driver;
const struct i2c_device_id *id_table;
/* Device detection callback for automatic device creation */
int (*detect)(struct i2c_client *client, struct i2c_board_info *info);
const unsigned short *address_list;
struct list_head clients;
u32 flags;
};
在struct i2c_driver 中有一个成员struct device_driver driver, 这相当于“is-a”的关系,即 i2c_driver 是一种 device_driver. 这种操作实际就是继承。
紧接着定义了一个i2c专用宏