struct list_head 解析

来源:互联网 发布:下载动画的软件 编辑:程序博客网 时间:2024/05/22 00:19
     在Linux内核中,提供了一个用来创建双向循环链表的结构list_head。

      kernel中的list_head结构定义在list.h,用户空间使用该结构体或者相关操作函数的话可以根据内核源码头文件中的list.h(/usr/src/linux-headers-3.8.0-29/include/linux/list.h)自己截取所用函数自定义list.h(在文章最后给出),不能直接用内核源码list.h,因为其中包含其他内核头文件。

    struct list_head 的结构定义为

struct list_head {  struct list_head *next, *prev;};

  该结构体只有前后指针,没有数据域,因为它本身就不是用来保存数据的,通常用于其他结构体中,如

typedef struct stud{          char name[20];          long numb;          struct list_head list;}stu;

使用list_head相关函数创建双向链表,根据双向链表可以对父结构体stu中的数据域进行操作,父结构体stu就相当于组成了一个双向链表,只不过需要通过list来操作,如添加,删除,遍历等。


函数说明

   初始化头结点

          INIT_LIST_HEAD(struct list_head* ptr);    //实际上就是将传入的list_head指针的next,prev都指向自己(ptr)。

  检查链表是否为空

         list_empty(struct list_head* ptr);  //如果双向链表为空则返回真,否则返回假。

  添加成员

       list_add(struct list_head* node,struct list_head* head);//在头结点后添加节点,node为父结构体中的list_head指针

  删除

       list_del(struct list_head* node);//不安全删除,只删除节点

       list_del_init(struct list_head* node);//安全删除,删除节点后,初始化节点

  遍历

       list_for_each(struct list_head* ptr,struct list_head* head);//定义为一个for循环ptr从head依次指向其它node

  取父节点

       list_entry(struct list_head* ptr,stu,list);//ptr为当前list_head节点,stu为父结构体类型,list静态名用来进行宏替换,返回当前父结构体指针。

  替换

       list_replace(struct list_head* ptr1,struct list_head* ptr2);//根据每个父结构体中list_head指针将,新的节点替换链表中的节点,注意同在链表中的两节点不能替换


#include <stdio.h>#include<string.h>#include"list.h"  //自定义typedef struct stud{char name[20];long numb;struct list_head list;}stu;int main(void){struct list_head head,head1;stu stu1,stu2,stu3,stu4,stu5;struct list_head* p;stu* entry=NULL;strcpy(stu1.name,"zhaoyun");stu1.numb=1001;strcpy(stu2.name,"machao");stu2.numb=1002;strcpy(stu3.name,"guanyu");stu3.numb=1003;strcpy(stu4.name,"zhangfei");stu4.numb=1004;strcpy(stu5.name,"huangzhong");stu5.numb=1005;//初始化headINIT_LIST_HEAD(&head);if(list_empty(&head)){printf("list is empty\n");}elseprintf("list is not empty\n");//添加成员list_add(&stu1.list,&head);list_add(&stu2.list,&head);list_add(&stu3.list,&head);//遍历list_for_each(p,&head){entry=list_entry(p,stu,list);printf("name:%s,numb:%ld\n",entry->name,entry->numb);}printf("************delete**************\n");//删除//list_del(&stu2.list);list_del_init(&stu2.list);//安全删除//遍历list_for_each(p,&head){entry=list_entry(p,stu,list);printf("name:%s,numb:%ld\n",entry->name,entry->numb);}printf("replace *******************\n");//替换list_replace(&stu3.list,&stu5.list);//遍历list_for_each(p,&head){entry=list_entry(p,stu,list);printf("name:%s,numb:%ld\n",entry->name,entry->numb);}if(list_empty(&head)){printf("list is empty\n");}elseprintf("list is not empty\n");return ;}

输出结果:

list is empty
name:guanyu,numb:1003
name:machao,numb:1002
name:zhaoyun,numb:1001
************delete**************
name:guanyu,numb:1003
name:zhaoyun,numb:1001
replace *******************
name:huangzhong,numb:1005
name:zhaoyun,numb:1001
list is not empty


自定义list.h

#ifndef _LIST_H_#define _LIST_H_#define offsetof(type, member) ((size_t) &((type *)0)->member)#define container_of(ptr, type, member) ({\const typeof( ((type *)0)->member ) *__mptr = (ptr);\(type *)( (char *)__mptr - offsetof(type,member) );})/* * Simple doubly linked list implementation. * * Some of the internal functions ("__xxx") are useful when * manipulating whole lists rather than single entries, as * sometimes we already know the next/prev entries and we can * generate better code by using them directly rather than * using the generic single-entry routines. */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;}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);}/* * Delete a list entry by making the prev/next entries * point to each other. * * This is only for internal list manipulation where we know * the prev/next entries already! */static inline void __list_del(struct list_head * prev, struct list_head * next){next->prev = prev;prev->next = next;}/** * list_del - deletes entry from list. * @entry: the element to delete from the list. * Note: list_empty() on entry does not return true after this, the entry is * in an undefined state. */static inline void list_del(struct list_head *entry){__list_del(entry->prev, entry->next);//entry->next = 0;//entry->prev = 0;}/** * list_replace - replace old entry by new one * @old : the element to be replaced * @new : the new element to insert * * If @old was empty, it will be overwritten. */static inline void list_replace(struct list_head *old,struct list_head *new){new->next = old->next;new->next->prev = new;new->prev = old->prev;new->prev->next = new;}static inline void list_replace_init(struct list_head *old,struct list_head *new){list_replace(old, new);INIT_LIST_HEAD(old);}/** * list_del_init - deletes entry from list and reinitialize it. * @entry: the element to delete from the list. */static inline void list_del_init(struct list_head *entry){__list_del(entry->prev, entry->next);INIT_LIST_HEAD(entry);}/** * list_move - delete from one list and add as another's head * @list: the entry to move * @head: the head that will precede our entry */static inline void list_move(struct list_head *list, struct list_head *head){__list_del(list->prev, list->next);list_add(list, head);}/** * list_move_tail - delete from one list and add as another's tail * @list: the entry to move * @head: the head that will follow our entry */static inline void list_move_tail(struct list_head *list,  struct list_head *head){__list_del(list->prev, list->next);list_add_tail(list, head);}/** * list_is_last - tests whether @list is the last entry in list @head * @list: the entry to test * @head: the head of the list */static inline int list_is_last(const struct list_head *list,const struct list_head *head){return list->next == head;}/** * list_empty - tests whether a list is empty * @head: the list to test. */static inline int list_empty(const struct list_head *head){return head->next == head;}/** * 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_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;  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_prev-iterate over a list backwards * @pos:the &struct list_head to use as a loop cursor. * @head:the head for your list. */#define list_for_each_prev(pos, head) \for (pos = (head)->prev;  pos != (head); \        pos = pos->prev)/** * list_for_each_safe - iterate over a list safe against removal of list entry * @pos:the &struct list_head to use as a loop cursor. * @n:another &struct list_head to use as temporary storage * @head:the head for your 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_prev_safe - iterate over a list backwards safe against removal of list entry * @pos:the &struct list_head to use as a loop cursor. * @n:another &struct list_head to use as temporary storage * @head:the head for your list. */#define list_for_each_prev_safe(pos, n, head) \for (pos = (head)->prev, n = pos->prev; \     pos != (head); \     pos = n, n = pos->prev)/** * list_for_each_entry-iterate over list of given type * @pos:the type * to use as a loop cursor. * @head:the head for your list. * @member:the name of the list_struct within the struct. */#define list_for_each_entry(pos, head, member)\for (pos = list_entry((head)->next, typeof(*pos), member);\     prefetch(pos->member.next), &pos->member != (head); \     pos = list_entry(pos->member.next, typeof(*pos), member))/** * list_for_each_entry_reverse - iterate backwards over list of given type. * @pos:the type * to use as a loop cursor. * @head:the head for your list. * @member:the name of the list_struct within the struct. */#define list_for_each_entry_reverse(pos, head, member)\for (pos = list_entry((head)->prev, typeof(*pos), member);\      &pos->member != (head); \     pos = list_entry(pos->member.prev, typeof(*pos), member))/** * list_prepare_entry - prepare a pos entry for use in list_for_each_entry_continue() * @pos:the type * to use as a start point * @head:the head of the list * @member:the name of the list_struct within the struct. * * Prepares a pos entry for use as a start point in list_for_each_entry_continue(). */#define list_prepare_entry(pos, head, member) \((pos) ? : list_entry(head, typeof(*pos), member))/** * list_for_each_entry_continue - continue iteration over list of given type * @pos:the type * to use as a loop cursor. * @head:the head for your list. * @member:the name of the list_struct within the struct. * * Continue to iterate over list of given type, continuing after * the current position. */#define list_for_each_entry_continue(pos, head, member) \for (pos = list_entry(pos->member.next, typeof(*pos), member);\     &pos->member != (head);\     pos = list_entry(pos->member.next, typeof(*pos), member))/** * list_for_each_entry_continue_reverse - iterate backwards from the given point * @pos:the type * to use as a loop cursor. * @head:the head for your list. * @member:the name of the list_struct within the struct. * * Start to iterate over list of given type backwards, continuing after * the current position. */#define list_for_each_entry_continue_reverse(pos, head, member)\for (pos = list_entry(pos->member.prev, typeof(*pos), member);\      &pos->member != (head);\     pos = list_entry(pos->member.prev, typeof(*pos), member))/** * list_for_each_entry_from - iterate over list of given type from the current point * @pos:the type * to use as a loop cursor. * @head:the head for your list. * @member:the name of the list_struct within the struct. * * Iterate over list of given type, continuing from current position. */#define list_for_each_entry_from(pos, head, member) \for (; &pos->member != (head);\     pos = list_entry(pos->member.next, typeof(*pos), member))/** * list_for_each_entry_safe - iterate over list of given type safe against removal of list entry * @pos:the type * to use as a loop cursor. * @n:another type * to use as temporary storage * @head:the head for your list. * @member:the name of the list_struct within the struct. */#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))/** * list_for_each_entry_safe_continue * @pos:the type * to use as a loop cursor. * @n:another type * to use as temporary storage * @head:the head for your list. * @member:the name of the list_struct within the struct. * * Iterate over list of given type, continuing after current point, * safe against removal of list entry. */#define list_for_each_entry_safe_continue(pos, n, head, member) \for (pos = list_entry(pos->member.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))/** * list_for_each_entry_safe_from * @pos:the type * to use as a loop cursor. * @n:another type * to use as temporary storage * @head:the head for your list. * @member:the name of the list_struct within the struct. * * Iterate over list of given type from current point, safe against * removal of list entry. */#define list_for_each_entry_safe_from(pos, n, head, member) \for (n = list_entry(pos->member.next, typeof(*pos), member);\     &pos->member != (head);\     pos = n, n = list_entry(n->member.next, typeof(*n), member))/** * list_for_each_entry_safe_reverse * @pos:the type * to use as a loop cursor. * @n:another type * to use as temporary storage * @head:the head for your list. * @member:the name of the list_struct within the struct. * * Iterate backwards over list of given type, safe against removal * of list entry. */#define list_for_each_entry_safe_reverse(pos, n, head, member)\for (pos = list_entry((head)->prev, typeof(*pos), member),\n = list_entry(pos->member.prev, typeof(*pos), member);\     &pos->member != (head); \     pos = n, n = list_entry(n->member.prev, typeof(*n), member))#endif


0 0