【版权声明:转载请保留出处:blog.csdn.net/gentleliu。邮箱:shallnew*163.com】
linux内核头文件 #include
struct list_head {
struct list_head *next, *prev;
};
struct todo_struct {
int count;
struct list_head list;
};
使用前需要首先声明一个链表头,并初始化。
struct list_head todo_list;
INIT_LIST_HEAD(&todo_list);
static inline void INIT_LIST_HEAD(struct list_head *list)
{
list->next = list;
list->prev = list;
}
list_add(&pnode->list, &todo_list);//在头部添加
list_add_tail(&pnode->list, &todo_list);//在尾部添加
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;
}
static inline void list_add(struct list_head *new, struct list_head *head)
{
__list_add(new, head, head->next);
}
static inline void list_add_tail(struct list_head *new, struct list_head *head)
{
__list_add(new, head->prev, head);
}
list_del(struct list_head *entry);
static inline void __list_del(struct list_head * prev, struct list_head * next)
{
next->prev = prev;
prev->next = next;
}
static inline void list_del(struct list_head *entry)
{
__list_del(entry->prev, entry->next);
entry->next = NULL;
entry->prev = NULL;
}
static inline int list_empty(const struct list_head *head)
{
return head->next == head;
}
当我们遍历该链表时是通过链表list_head中两个的成员来寻找的,但是我们得到的也仅仅是节点结构体中list_head结构体的地址,我们需要得到的是整个结构体的地址,并通过该地址得到该结构体里面的其他成员的值。怎么办呢?我们可以使用宏list_entry(struct list_head *ptr, type_of_struct, field_name)来达到这个目的,该宏可以将list_head指针映射回包含它的大结构指针。
struct todo_struct *pnode = NULL;
struct list_head *ptr = NULL;
pnode = list_entry(ptr, struct todo_struct, list);
此处可以通过传入的list_head指针p得到的拥有该指针的大结构体pnode地址,此时就可以取得结构体中任意变量的值了。
for (ptr = todo_list.next; ptr != &todo_list; ptr = ptr->next) {
pnode = list_entry(ptr, struct todo_struct, list);
// ......
}
#define list_for_each(pos, head) \
for (pos = (head)->next; prefetch(pos->next), pos != (head); \
pos = pos->next)
所以上面代码可以修改为:
list_for_each(pos, head) {
pnode = list_entry(p, struct todo_struct, list);
// ......
}
list_for_each_safe(struct list_head *curser, struct list_head *next, struct list_head *list);
#define list_for_each_safe(pos, n, head) \
for (pos = (head)->next, n = pos->next; pos != (head); \
pos = n, n = pos->next)
list_for_each_entry(type cursor, struct list_head *list, member);
list_for_each_entry_safe(type cursor, type next, struct list_head *list, member);
#define list_for_each_entry(pos, head, member) \
for (pos = list_entry((head)->next, typeof(*pos), member); \
&pos->member != (head); \
pos = list_entry(pos->member.next, typeof(*pos), member))
#define list_for_each_entry_safe(pos, n, head, member) \
for (pos = list_entry((head)->next, typeof(*pos), member), \
n = list_entry(pos->member.next, typeof(*pos), member); \
&pos->member != (head); \
pos = n, n = list_entry(n->member.next, typeof(*n), member))
下面给一个我的一个简单使用示例:
#include
#include
#include
#include
#include
// #include
#include
struct todo_struct {
int count;
struct list_head list;
};
struct list_head todo_list;
//rwlock_t list_lock = RW_LOCK_UNLOCKED;
void sln_list_create(void)
{
int i = 0;
struct todo_struct *pnode = NULL;
for (i = 0; i < 10; i++) {
pnode = (struct todo_struct *)kmalloc(sizeof(struct todo_struct), GFP_ATOMIC);
if (NULL == pnode) {
return;
}
pnode->count = i;
// write_lock(&list_lock);
list_add_tail(&pnode->list, &todo_list);
// write_unlock(&list_lock);
}
}
void sln_list_del(int val)
{
struct todo_struct *pnode = NULL;
struct list_head *p = NULL;
// write_lock(&list_lock);
list_for_each(p, &todo_list) {
pnode = list_entry(p, struct todo_struct, list);
if (pnode->count == val) {
list_del(p);
// write_unlock(&list_lock);
return ;
}
}
// write_unlock(&list_lock);
}
void sln_list_del2(int val)
{
struct todo_struct *pnode = NULL;
struct list_head *p = NULL, *next = NULL;
// write_lock(&list_lock);
list_for_each_safe(p, next, &todo_list) {
pnode = list_entry(p, struct todo_struct, list);
if (pnode->count == val) {
list_del(p);
// write_unlock(&list_lock);
return ;
}
}
// write_unlock(&list_lock);
}
void sln_list_traverse(void)
{
struct todo_struct *pnode = NULL;
struct list_head *p = NULL;
// read_lock(&list_lock);
list_for_each(p, &todo_list) {
pnode = list_entry(p, struct todo_struct, list);
printk(KERN_ALERT"%d\n", pnode->count);
}
printk(KERN_ALERT"\n");
// write_lock(&list_lock);
}
void sln_list_traverse2(void)
{
struct todo_struct *pnode = NULL;
list_for_each_entry(pnode, &todo_list, list) {
printk(KERN_ALERT"%d\n", pnode->count);
}
}
static __init int sln_list_init(void)
{
printk(KERN_ALERT"=====%s=====\n", __func__);
INIT_LIST_HEAD(&todo_list);
sln_list_create();
sln_list_traverse();
sln_list_del(6);
sln_list_traverse();
sln_list_del2(4);
sln_list_traverse2();
return 0;
}
static __exit void sln_list_exit(void)
{
printk(KERN_ALERT"=====%s=====\n", __func__);
}
module_init(sln_list_init);
module_exit(sln_list_exit);
MODULE_LICENSE("GPL");