container_of
是 Linux 内核中一个常用的宏,用于从结构体的成员指针获取包含该成员的整个结构体的指针。
/**
* container_of - cast a member of a structure out to the containing structure
* @ptr: the pointer to the member.
* @type: the type of the container struct this is embedded in.
* @member: the name of the member within the struct.
*
*/
#define container_of(ptr, type, member) ({ \
void *__mptr = (void *)(ptr); \
BUILD_BUG_ON_MSG(!__same_type(*(ptr), ((type *)0)->member) && \
!__same_type(*(ptr), void), \
"pointer type mismatch in container_of()"); \
((type *)(__mptr - offsetof(type, member))); })
ptr:指向结构体中某个成员的指针。
type:结构体的类型。
member:结构体中的成员名。
offsetof: 计算结构体成员member在type这个结构体中的偏移
#define offsetof(type, member) ((size_t)(&((type *)0)->member))
例子:
#include <linux/module.h>
#include <linux/init.h>
#include <linux/kmod.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/list.h>
#define MAX_NAME_LEN 32
#define MAX_ID_LEN 10
struct list_head device_list;
#define I2C_TYPE 1
#define SPI_TYPE 2
char *dev_name[]={
"none",
"I2C",
"SPI"
};
struct device
{
int type;
char name[MAX_NAME_LEN];
struct list_head list;
};
struct i2c_node
{
int data;
unsigned int reg;
struct device dev;
};
struct spi_node
{
unsigned int reg;
struct device dev;
};
void display_i2c_device(struct device *device)
{
struct i2c_node *i2c_device = container_of(device, struct i2c_node, dev);
pr_info("\t i2c_device->data: %d\n", i2c_device->data);
pr_info("\t i2c_device->reg: %#x\n", i2c_device->reg);
}
void display_spi_device(struct device *device)
{
struct spi_node *spi_device = container_of(device, struct spi_node, dev);
pr_info("\t spi_device->reg: %#x\n", spi_device->reg);
}
void display_device(struct device *device)
{
pr_info("\t dev.type: %d\n", device->type);
pr_info("\t dev.type: %s\n", dev_name[device->type]);
pr_info("\t dev.name: %s\n", device->name);
}
void display_list(struct list_head *list_head)
{
int i=0;
struct list_head *p;
struct device *entry;
pr_info("-------list---------\n");
list_for_each(p, list_head)
{
pr_info("node[%d]\n",i++);
entry=list_entry(p, struct device, list);
switch(entry->type)
{
case I2C_TYPE:
display_i2c_device(entry);
break;
case SPI_TYPE:
display_spi_device(entry);
break;
default:
pr_info("unknown device type!\n");
break;
}
display_device(entry);
}
pr_info("-------end----------\n");
}
void i2c_register_device(struct device *device)
{
struct i2c_node *i2c_device = container_of(device, struct i2c_node, dev);
i2c_device->dev.type = I2C_TYPE;
strcpy(i2c_device->dev.name,"yikoulinux");
list_add(&device->list, &device_list);
}
void spi_register_device(struct device *device)
{
struct spi_node *spi_device = container_of(device, struct spi_node, dev);
spi_device->dev.type = SPI_TYPE;
strcpy(spi_device->dev.name,"yikoupeng");
list_add(&device->list, &device_list);
}
void i2c_unregister_device(struct device *device)
{
struct i2c_node *i2c_device = container_of(device, struct i2c_node, dev);
list_del(&device->list);
}
void spi_unregister_device(struct device *device)
{
struct spi_node *spi_device = container_of(device, struct spi_node, dev);
list_del(&device->list);
}
static int hello_init(void)
{
struct i2c_node dev1;
struct spi_node dev2;
INIT_LIST_HEAD(&device_list);
dev1.data = 1;
dev1.reg = 0x40009000;
i2c_register_device(&dev1.dev);
dev2.reg = 0x40008000;
spi_register_device(&dev2.dev);
display_list(&device_list);
i2c_unregister_device(&dev1.dev);
display_list(&device_list);
return 0;
}
static void hello_exit(void)
{
printk(KERN_ALERT "Goodbye, kernel\n");
}
module_init(hello_init);
module_exit(hello_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("xxx");
标签:container,struct,list,dev,device,i2c,type
From: https://www.cnblogs.com/tangshunhui/p/18019515