一般我们想要实现一种数据结构的双链队列,一般都是这样操作:
typedef struct Datastructure
{
struct Datastructure *next;
struct Datastructure *prev;
//......
}datastructure;
然而在Linux内核中,使用了大量不同的数据结构的双链队列。
因此,内核作者们把指针prev和next从具体的宿主中抽象出来成为了一种数据结构list_head。
struct list_head
{
struct list_head *next, *prev;
};
在其宿主结构中:
typedef struct page
{
struct list_head list;
//.......
struct page *next_hash;
//.......
struct list_head lru;
};
数据结构之间的连接操作都通过list_head执行。
接着内核定义了如下的一个函数:memlist_entry(cur, struct page, list);
这个函数将list_head的指针curr换算成了宿主结构的其实地址,也就是其宿主page结构的指针。
但事实上,同一文件中将memlist_entry定义为list_entry。page = (struct page*)((char*)(curr) - (usigned long)(& (struct page*)0) -> list));
其中curr是page结构中成分list的地址,page本身的地址,通过curr减去一个位移量就能得出,而这个位移量,就是page刚好在地址0时其成分list的地址,既:& (struct page*)0) -> list)