Linux在内核空间中存在一个非常重要且实用的宏container_of(),其作用就是通过一个结构变量中一个成员的地址找到这个结构体变量的首地址。在写驱动程序时非常实用,但是此宏是定义在include/linux/kernel.h中的:
/**
* 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) ({ \
const typeof( ((type *)0)->member ) *__mptr = (ptr); \
(type *)( (char *)__mptr - offsetof(type,member) );})
如果想在用户空间程序也使用此宏的话,可以在用户程序中包含kernel.h,但在编译时需要额外添加包含内核的编译目录。
其实我们完全可以在用户程序中自己定义此宏函数,这样便正常使用,也不需要额外操作。以下是我做的实验code:
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h> // 必须添加此项,offsetof定义在此文件中
struct my_type {
char *name;
int no;
int age;
};
struct my_type nae = {
.name = "hello c",
.no = 12345,
.age = 18,
};
#ifndef container_of
#define container_of(ptr, type, member) ({ \
const typeof( ((type *)0)->member ) *__mptr = (ptr); \
(type *)( (char *)__mptr - offsetof(type,member) );})
#endif
int main()
{
int *tm = &(nae.no);
struct my_type *my = container_of(tm, struct my_type, no);
printf("name = %s\n", my->name);
printf("no = %d\n", my->no);
printf("age = %d\n", my->age);
return 0;
}
实验结果:
name = hello c
no = 12345
age = 18