在设备驱动中经常看见container_of,根据结构体中某个成员变量的指针找到该结构体的指针,这样在指针传递时可以只传递结构体中某个变量的指针,使用container_of就能找到该结构体的指针
使用container_of宏需要包含linux/kernel.h头文件,container_of宏的定义如下所示:
#define container_of(ptr, type, member) ({ \
const typeof( ((type *)0)->member ) *__mptr = (ptr); \
(type *)( (char *)__mptr - offsetof(type,member) );})
container_of宏分为两部分,
第一部分:
const typeof( ((type *)0)->member ) *__mptr = (ptr);
通过typeof定义一个member指针类型的指针变量__mptr,(即__mptr是指向member类型的指针),并将__mptr赋值为ptr。
第二部分:
(type *)( (char *)__mptr - offsetof(type,member) )
通过offsetof宏计算出member在type中的偏移,然后用member的实际地址__mptr减去偏移,得到type的起始地址,即指向type类型的指针。
示例程序如下:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <linux/kernel.h>
#define NAME_STR_LEN 128
typedef struct student_info {
int id;
char name[NAME_STR_LEN];
int age;
} student_info;
static int get_info_from_id(int *ptr_id);
int main(void)
{
int ret;
size_t off_set = 0;
off_set = offsetof(student_info, id);//成员age相对student_info的偏移地址
printf("id offset = %u\n", off_set);
off_set = offsetof(student_info, name);
printf("name offset = %u\n", off_set);
off_set = offsetof(student_info, age);
printf("age offset = %u\n", off_set);
student_info *stu = (student_info *)malloc(sizeof(student_info));
stu->age = 24;
stu->id = 0;
strcpy(stu->name, "yangguang");
if (ret = get_info_from_id(&stu->id)) {
printf("OK\n");
}
return ret;
}
static int get_info_from_id(int *ptr_id)
{
student_info *stu = container_of(ptr_id, student_info, id);
if (stu == NULL) {
printf("get info from id error!\n");
return -1;
}
else {
printf("id = %d\n", stu->id);
printf("age = %d\n", stu->age);
printf("name = %s\n", stu->name);
}
return 0;
}