当前位置: 技术问答>linux和unix
大家好,linux内核链表结构的一个问题?请帮忙
来源: 互联网 发布时间:2015-04-08
本文导语: /** * list_entry - get the struct for this entry * @ptr: the &struct list_head pointer. * @type: the type of the struct this is embedded in. * @member: the name of the list_struct within the struct. */ #define list_entry(ptr, type, member) ...
/**
* list_entry - get the struct for this entry
* @ptr: the &struct list_head pointer.
* @type: the type of the struct this is embedded in.
* @member: the name of the list_struct within the struct.
*/
#define list_entry(ptr, type, member)
((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member)))
请问这个函数是什么意思,有什么功能?
请诸位分析一下(详细)
* list_entry - get the struct for this entry
* @ptr: the &struct list_head pointer.
* @type: the type of the struct this is embedded in.
* @member: the name of the list_struct within the struct.
*/
#define list_entry(ptr, type, member)
((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member)))
请问这个函数是什么意思,有什么功能?
请诸位分析一下(详细)
|
(&((type *)0)->member)表示取得结构type的成员member的偏移量。强制转换为(unsigned long)。
ptr减去上边算出的偏移量,然后将所得的地址强制转换为(type *)。
ptr减去上边算出的偏移量,然后将所得的地址强制转换为(type *)。
|
typedef struct A_
{
int a;
long l;
short s;
}A;
A a;
void* p = &a.l;
A* pa = list_entry(p, A, l); // 结构(实体)成员地址,结构(实体)类型定义,成员名
{
int a;
long l;
short s;
}A;
A a;
void* p = &a.l;
A* pa = list_entry(p, A, l); // 结构(实体)成员地址,结构(实体)类型定义,成员名
|
这个是linux内核使用的一个通用双向链表结构的一部分。该链表结构是这样的:
struct list_head {
struct list_head *next, *prev;
};
例如要建立一个双向链表,可以这样:
struct cpufreq_governor {
char name[CPUFREQ_NAME_LEN];
int (*governor) (struct cpufreq_policy *policy,
unsigned int event);
struct list_head governor_list;
struct module *owner;
};
注意其中的governor_list,它是用来实现cpufreq_governor双向链表的关键:
cpufreq_governor governor;
list_add(&governor->governor_list, &cpufreq_governor_list);
其中cpufreq_governor_list是struct list_head类型,是整个链表的head。这样就用list_head这个双向链表将cpufreq_governor的成员governor_list链接了起来,也就是说从以cpufreq_governor_list为head的链表里能够访问到的是每个cpufreq_governor的成员变量governor_list。然而我们实际需要的是cpufreq_governor,即整个结构,于是就有了list_entry这个宏:将governor_list这个成员变量的地址减去它在结构中的偏移量就是结构的地址。
所以,ptr就是成员变量的地址(例子中的governor_list的地址),type是结构名(例子中的cpufreq_governor),member就是成员变量的名字(例子中的governor_list)。
struct list_head {
struct list_head *next, *prev;
};
例如要建立一个双向链表,可以这样:
struct cpufreq_governor {
char name[CPUFREQ_NAME_LEN];
int (*governor) (struct cpufreq_policy *policy,
unsigned int event);
struct list_head governor_list;
struct module *owner;
};
注意其中的governor_list,它是用来实现cpufreq_governor双向链表的关键:
cpufreq_governor governor;
list_add(&governor->governor_list, &cpufreq_governor_list);
其中cpufreq_governor_list是struct list_head类型,是整个链表的head。这样就用list_head这个双向链表将cpufreq_governor的成员governor_list链接了起来,也就是说从以cpufreq_governor_list为head的链表里能够访问到的是每个cpufreq_governor的成员变量governor_list。然而我们实际需要的是cpufreq_governor,即整个结构,于是就有了list_entry这个宏:将governor_list这个成员变量的地址减去它在结构中的偏移量就是结构的地址。
所以,ptr就是成员变量的地址(例子中的governor_list的地址),type是结构名(例子中的cpufreq_governor),member就是成员变量的名字(例子中的governor_list)。
|
简单的举个例子:
有一个结构体
struct {
...
struct list_head next;
...
}StructType;
StructType MyStruct;
你用listentry( p , StructType, next )就得到了指向Mystruct的指针
下边是图示
->---------- MyStruct->---------------
| 。 。 | | 。。 |
+---------+ p->+--------------+
|list_head| | list_head |
+---------+ +--------------+
| 。 。 | | 。。 |
+---------+ +--------------+
有一个结构体
struct {
...
struct list_head next;
...
}StructType;
StructType MyStruct;
你用listentry( p , StructType, next )就得到了指向Mystruct的指针
下边是图示
->---------- MyStruct->---------------
| 。 。 | | 。。 |
+---------+ p->+--------------+
|list_head| | list_head |
+---------+ +--------------+
| 。 。 | | 。。 |
+---------+ +--------------+