linux中编写了一个list的结构,这个结构有一个比较巧妙而且与书本里写的list结构不一样的地方,这样用的好处我还没有全面理解,也没有理清楚优化的效果在哪里,但是直观上减轻了链表结构的复杂性,还有一点就是很大程度提高了列表的使用范围以及泛型使用。而不再局限于一种每一个结构单独编写一个链表。对于任何数据类型以及复合型数据结构都能够横好的使用同一个链表,更大提高了代码的复用性,这对于比如linux这类大量代码工程中且需要使用很多链表的工程中能够有很好的使用效果,对待吗的简化以及直观性,c中不存在类似于面向对象这类语言的泛型编程思想,故效果很好。
书上介绍了一种最为典型典型也是最为常见的一种数据结构,即是:
struct list_node
{
.....
data;
....
list_node *pre,*next;
}
这里面的结构体是把链表节点结构体中加入了实际有效数据,以及链表所需指针,导致链表结构以及特有数据的不可分割的特点。也以为着使用多少种数据结构就需要定义多少种数据结构。
linux kernel:
struct list_head { //链表节点指针
struct list_head *next, *prev;
};
这里的链表的结构里面只有链表的指针,这里的链表是一个循环链表。故使用的前后指针。而嵌入真实数据的方式就是想需要使用链表的结构数据中加入一个list_head(链表节点)指针即可。而当要使用这个结构体时则通过遍历这个list_head指针,来遍历整个链表。而这里通过使用list_head(链表节点)指针来查找数据结构体的方式及时使用container_of来实现,而这里的container_of函数的功能及时通过结构体成员指针返回整个结构体指针,linux中极有用的一个工具。而这里对链表的各种操作只需要对结构list_head(链表节点)指针进行操作即可。
static struct phy_driver gmii2rgmii_driver = {
.name = "XILINX GMII2RGMII",
.uid = PHY_GMII2RGMII_ID,
.mask = 0xffffffff,
.features = PHY_GBIT_FEATURES,
.probe = xilinxgmiitorgmii_probe,
.config = xilinxgmiitorgmii_config,
.startup = xilinxgmiitorgmii_startup,
.writeext = xilinxgmiitorgmii_extwrite,
.readext = xilinxgmiitorgmii_extread,
};
int phy_xilinx_gmii2rgmii_init(void)
{
phy_register(&gmii2rgmii_driver);
return 0;
}
phy_xilinx_gmii2rgmii_init
phy_register(&gmii2rgmii_driver);
INIT_LIST_HEAD(&drv->list);
list_add_tail(&drv->list, &phy_drivers);
static LIST_HEAD(phy_drivers);
struct list_head {
struct list_head *next, *prev;
};
#define LIST_HEAD_INIT(name) { &(name), &(name) }
#define LIST_HEAD(name) \
struct list_head name = LIST_HEAD_INIT(name)
static inline void INIT_LIST_HEAD(struct list_head *list)
{
list->next = list;
list->prev = list;
}
/*
* Insert a new entry between two known consecutive entries.
*
* This is only for internal list manipulation where we know
* the prev/next entries already!
*/
static inline void __list_add(struct list_head *new,
struct list_head *prev,
struct list_head *next)
{
next->prev = new;
new->next = next;
new->prev = prev;
prev->next = new;
}
/**
* list_add - add a new entry
* @new: new entry to be added
* @head: list head to add it after
*
* Insert a new entry after the specified head.
* This is good for implementing stacks.
*/
static inline void list_add(struct list_head *new, struct list_head *head)
{
__list_add(new, head, head->next);
}
/**
* list_add_tail - add a new entry
* @new: new entry to be added
* @head: list head to add it before
*
* Insert a new entry before the specified head.
* This is useful for implementing queues.
*/
static inline void list_add_tail(struct list_head *new, struct list_head *head)
{
__list_add(new, head->prev, head);
}
循环中出现另一个prefetch ,该函数在linux的源码中为一个汇编代码,并没仔细去读,但这个代码主要实现向CPU高速cache里面预指定下一个欲取值,从而提高函数的访问 list效率。但我看到一篇博客里面提到有技术大牛测试过这个prefetch函数,但发觉并没有效果, 甚至效果不如没有使用该函数的,由于现在的硬件已经预判了你即将可能取得值并放入到cache中,而且效率比软件进行的效果更优。则有大牛打算取消这个使用。
/* *
* 下述代码中用来一堆宏,而这些宏的使用可以形成一个循环检测
*/
/**
* 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) \
container_of(ptr, type, member)
/**
* list_first_entry - get the first element from a list
* @ptr: the list head to take the element from.
* @type: the type of the struct this is embedded in.
* @member: the name of the list_struct within the struct.
*
* Note, that list is expected to be not empty.
*/
#define list_first_entry(ptr, type, member) \
list_entry((ptr)->next, type, member)
/**
* list_last_entry - get the last element from a list
* @ptr: the list head to take the element from.
* @type: the type of the struct this is embedded in.
* @member: the name of the list_struct within the struct.
*
* Note, that list is expected to be not empty.
*/
#define list_last_entry(ptr, type, member) \
list_entry((ptr)->prev, type, member)
/**
* list_for_each - iterate over a list
* @pos: the &struct list_head to use as a loop cursor.
* @head: the head for your list.
*/
#define list_for_each(pos, head) \
for (pos = (head)->next; prefetch(pos->next), pos != (head); \
pos = pos->next)
/**
* __list_for_each - iterate over a list
* @pos: the &struct list_head to use as a loop cursor.
* @head: the head for your list.
*
* This variant differs from list_for_each() in that it's the
* simplest possible list iteration code, no prefetching is done.
* Use this for code that knows the list to be very short (empty
* or 1 entry) most of the time.
*/
#define __list_for_each(pos, head) \
for (pos = (head)->next; pos != (head); pos = pos->next)
list_for_each(entry, &phy_drivers) {
drv = list_entry(entry, struct phy_driver, list);
if ((drv->uid & drv->mask) == (phy_id & drv->mask))
return drv;
}