大家好,linux内核链表结构的一个问题?请帮忙

时间:2022-07-27 23:37:59
/**
 * 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)))

请问这个函数是什么意思,有什么功能?
请诸位分析一下(详细)

11 个解决方案

#1


<linux/list.h>中,请各位帮忙
感激不尽

#2


(&((type *)0)->member)表示取得结构type的成员member的偏移量。强制转换为(unsigned long)。
ptr减去上边算出的偏移量,然后将所得的地址强制转换为(type *)。

#3


那么这个宏是做什么用的呢?麻烦能举个例子说的详细一点嘛?

不胜感激

#4


顺便问一下 , 宏中的各个变量都是什么含义 ,我翻译的不是很透彻
谢谢各位了

#5


typedef struct A_
{
    int a;
    long l;
    short s;
}A;

A a;

void* p = &a.l;

A* pa = list_entry(p, A, l); // 结构(实体)成员地址,结构(实体)类型定义,成员名




#6


这个是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)。

#7


简单的举个例子:
有一个结构体
struct {
     ...
     struct list_head next;
     ...
}StructType;
StructType MyStruct;
你用listentry( p , StructType, next )就得到了指向Mystruct的指针
下边是图示

   ->----------    MyStruct->---------------
    |  。 。  |           |     。。     |
     +---------+          p->+--------------+
    |list_head|   <==>    |    list_head | 
     +---------+             +--------------+
    |  。 。  |           |     。。     |
     +---------+             +--------------+

#8


对阿 ,我当初分析的时候就就感到奇怪,为了将链表操作与特定数据分离,有两种方法,
linux中的这用方法是属于完全分离,与特定数据一点关系都没有,这样虽然可以通过链表
嵌入进行连接操作,但包含它的那个struct却不知如何如何定位!

         终于明白了  谢谢各位
请继续讨论

#9


分析的很透彻啊,佩服各位。这些都是c中链表操作控制

#10


主要就是看懂 (&((type *)0)->member) 的意思。

#11


mark

cvsuser(猪头)

#1


<linux/list.h>中,请各位帮忙
感激不尽

#2


(&((type *)0)->member)表示取得结构type的成员member的偏移量。强制转换为(unsigned long)。
ptr减去上边算出的偏移量,然后将所得的地址强制转换为(type *)。

#3


那么这个宏是做什么用的呢?麻烦能举个例子说的详细一点嘛?

不胜感激

#4


顺便问一下 , 宏中的各个变量都是什么含义 ,我翻译的不是很透彻
谢谢各位了

#5


typedef struct A_
{
    int a;
    long l;
    short s;
}A;

A a;

void* p = &a.l;

A* pa = list_entry(p, A, l); // 结构(实体)成员地址,结构(实体)类型定义,成员名




#6


这个是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)。

#7


简单的举个例子:
有一个结构体
struct {
     ...
     struct list_head next;
     ...
}StructType;
StructType MyStruct;
你用listentry( p , StructType, next )就得到了指向Mystruct的指针
下边是图示

   ->----------    MyStruct->---------------
    |  。 。  |           |     。。     |
     +---------+          p->+--------------+
    |list_head|   <==>    |    list_head | 
     +---------+             +--------------+
    |  。 。  |           |     。。     |
     +---------+             +--------------+

#8


对阿 ,我当初分析的时候就就感到奇怪,为了将链表操作与特定数据分离,有两种方法,
linux中的这用方法是属于完全分离,与特定数据一点关系都没有,这样虽然可以通过链表
嵌入进行连接操作,但包含它的那个struct却不知如何如何定位!

         终于明白了  谢谢各位
请继续讨论

#9


分析的很透彻啊,佩服各位。这些都是c中链表操作控制

#10


主要就是看懂 (&((type *)0)->member) 的意思。

#11


mark

cvsuser(猪头)