数据结构(4) - 内核链表

这里的内核链表指Linux中实现的一种特殊的双向链表,区别于传统的双向链表包含数据,内核链表结构本身不包含数据,类比于卡车和货物,内核链表是卡车,数据是货物,两者之间联系通过container_of()函数进行映射,内核链表作为一个独立的成员包含在包含数据的结构体中,对数据的操作都是操作结构体中的内核链表对象,此时我们是可以知道内核链表成员对象的地址,然后通过container_of()把结构体的地址逆推出来,我们就可以拿到数据了,Linux内核链表不仅可以用在Linux平台,通过简单的修改(修改GCC编译器专有特性为通用特性即可),也可用于其它平台。

 

 我用Linux 5.x版本的代码移植了一份内核链表的算法文件,特意改了一个在非GCC编译特性的container_of(),如下:

 1 /**
 2  * container_of - cast a member of a structure out to the containing structure
 3  * @ptr:    the pointer to the member.
 4  * @type:   the type of the container struct this is embedded in.
 5  * @member: the name of the member within the struct.
 6  *
 7  */
 8 #ifdef _NOGCC
 9 #define container_of(ptr, type, member) \
10     ((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member)))
11 #else
12 #define container_of(ptr, type, member) ({                  \
13     const typeof( ((type *)0)->member ) *__mptr = (ptr);    \
14     (type *)( (char *)__mptr - offsetof(type,member) );})
15 #endif

完整的Linux 5.x版本内核链表算法文件如下:

list.h (以linux_5.x/include/linux/list.h为基础,添加其依赖制作).

   1 /* SPDX-License-Identifier: GPL-2.0 */
   2 #ifndef _LINUX_LIST_H
   3 #define _LINUX_LIST_H
   4 
   5 #include <stdbool.h>
   6 
   7 /*
   8  * Architectures might want to move the poison pointer offset
   9  * into some well-recognized area such as 0xdead000000000000,
  10  * that is also not mappable by user-space exploits:
  11  */
  12 #define POISON_POINTER_DELTA    0
  13 
  14 /*
  15  * These are non-NULL pointers that will result in page faults
  16  * under normal circumstances, used to verify that nobody uses
  17  * non-initialized list entries.
  18  */
  19 #define LIST_POISON1            ((void *) 0x100 + POISON_POINTER_DELTA)
  20 #define LIST_POISON2            ((void *) 0x122 + POISON_POINTER_DELTA)
  21 
  22 #define offsetof(TYPE, MEMBER)  ((size_t) &((TYPE *)0)->MEMBER)
  23 
  24 /**
  25  * container_of - cast a member of a structure out to the containing structure
  26  * @ptr:    the pointer to the member.
  27  * @type:   the type of the container struct this is embedded in.
  28  * @member: the name of the member within the struct.
  29  *
  30  */
  31 #ifdef _NOGCC
  32 #define container_of(ptr, type, member) \
  33     ((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member)))
  34 #else
  35 #define container_of(ptr, type, member) ({                  \
  36     const typeof( ((type *)0)->member ) *__mptr = (ptr);    \
  37     (type *)( (char *)__mptr - offsetof(type,member) );})
  38 #endif
  39 
  40 #define WRITE_ONCE(var, val) \
  41     (*((volatile typeof(val) *)(&(var))) = (val))
  42 
  43 #define READ_ONCE(var) (*((volatile typeof(var) *)(&(var))))
  44 
  45 /*
  46  * Simple doubly linked list implementation.
  47  *
  48  * Some of the internal functions ("__xxx") are useful when
  49  * manipulating whole lists rather than single entries, as
  50  * sometimes we already know the next/prev entries and we can
  51  * generate better code by using them directly rather than
  52  * using the generic single-entry routines.
  53  */
  54 
  55 #define LIST_HEAD_INIT(name)    { &(name), &(name) }
  56 
  57 #define LIST_HEAD(name) \
  58     struct list_head name = LIST_HEAD_INIT(name)
  59 
  60 
  61 struct list_head {
  62     struct list_head *next, *prev;
  63 };
  64 
  65 struct hlist_head {
  66     struct hlist_node *first;
  67 };
  68 
  69 struct hlist_node {
  70     struct hlist_node *next, **pprev;
  71 };
  72 
  73 
  74 /**
  75  * INIT_LIST_HEAD - Initialize a list_head structure
  76  * @list: list_head structure to be initialized.
  77  *
  78  * Initializes the list_head to point to itself.  If it is a list header,
  79  * the result is an empty list.
  80  */
  81 static inline void INIT_LIST_HEAD(struct list_head *list)
  82 {
  83     WRITE_ONCE(list->next, list);
  84     list->prev = list;
  85 }
  86 
  87 #ifdef CONFIG_DEBUG_LIST
  88 extern bool __list_add_valid(struct list_head *new,
  89                 struct list_head *prev,
  90                 struct list_head *next);
  91 extern bool __list_del_entry_valid(struct list_head *entry);
  92 #else
  93 static inline bool __list_add_valid(struct list_head *new,
  94                 struct list_head *prev,
  95                 struct list_head *next)
  96 {
  97     return true;
  98 }
  99 static inline bool __list_del_entry_valid(struct list_head *entry)
 100 {
 101     return true;
 102 }
 103 #endif
 104 
 105 /*
 106  * Insert a new entry between two known consecutive entries.
 107  *
 108  * This is only for internal list manipulation where we know
 109  * the prev/next entries already!
 110  */
 111 static inline void __list_add(struct list_head *new,
 112                     struct list_head *prev,
 113                     struct list_head *next)
 114 {
 115     if (!__list_add_valid(new, prev, next))
 116         return;
 117 
 118     next->prev = new;
 119     new->next = next;
 120     new->prev = prev;
 121     WRITE_ONCE(prev->next, new);
 122 }
 123 
 124 /**
 125  * list_add - add a new entry
 126  * @new: new entry to be added
 127  * @head: list head to add it after
 128  *
 129  * Insert a new entry after the specified head.
 130  * This is good for implementing stacks.
 131  */
 132 static inline void list_add(struct list_head *new, struct list_head *head)
 133 {
 134     __list_add(new, head, head->next);
 135 }
 136 
 137 
 138 /**
 139  * list_add_tail - add a new entry
 140  * @new: new entry to be added
 141  * @head: list head to add it before
 142  *
 143  * Insert a new entry before the specified head.
 144  * This is useful for implementing queues.
 145  */
 146 static inline void list_add_tail(struct list_head *new, struct list_head *head)
 147 {
 148     __list_add(new, head->prev, head);
 149 }
 150 
 151 /*
 152  * Delete a list entry by making the prev/next entries
 153  * point to each other.
 154  *
 155  * This is only for internal list manipulation where we know
 156  * the prev/next entries already!
 157  */
 158 static inline void __list_del(struct list_head * prev, struct list_head * next)
 159 {
 160     next->prev = prev;
 161     WRITE_ONCE(prev->next, next);
 162 }
 163 
 164 /*
 165  * Delete a list entry and clear the 'prev' pointer.
 166  *
 167  * This is a special-purpose list clearing method used in the networking code
 168  * for lists allocated as per-cpu, where we don't want to incur the extra
 169  * WRITE_ONCE() overhead of a regular list_del_init(). The code that uses this
 170  * needs to check the node 'prev' pointer instead of calling list_empty().
 171  */
 172 static inline void __list_del_clearprev(struct list_head *entry)
 173 {
 174     __list_del(entry->prev, entry->next);
 175     entry->prev = NULL;
 176 }
 177 
 178 static inline void __list_del_entry(struct list_head *entry)
 179 {
 180     if (!__list_del_entry_valid(entry))
 181         return;
 182 
 183     __list_del(entry->prev, entry->next);
 184 }
 185 
 186 /**
 187  * list_del - deletes entry from list.
 188  * @entry: the element to delete from the list.
 189  * Note: list_empty() on entry does not return true after this, the entry is
 190  * in an undefined state.
 191  */
 192 static inline void list_del(struct list_head *entry)
 193 {
 194     __list_del_entry(entry);
 195     entry->next = LIST_POISON1;
 196     entry->prev = LIST_POISON2;
 197 }
 198 
 199 /**
 200  * list_replace - replace old entry by new one
 201  * @old : the element to be replaced
 202  * @new : the new element to insert
 203  *
 204  * If @old was empty, it will be overwritten.
 205  */
 206 static inline void list_replace(struct list_head *old,
 207                 struct list_head *new)
 208 {
 209     new->next = old->next;
 210     new->next->prev = new;
 211     new->prev = old->prev;
 212     new->prev->next = new;
 213 }
 214 
 215 /**
 216  * list_replace_init - replace old entry by new one and initialize the old one
 217  * @old : the element to be replaced
 218  * @new : the new element to insert
 219  *
 220  * If @old was empty, it will be overwritten.
 221  */
 222 static inline void list_replace_init(struct list_head *old,
 223                         struct list_head *new)
 224 {
 225     list_replace(old, new);
 226     INIT_LIST_HEAD(old);
 227 }
 228 
 229 /**
 230  * list_swap - replace entry1 with entry2 and re-add entry1 at entry2's position
 231  * @entry1: the location to place entry2
 232  * @entry2: the location to place entry1
 233  */
 234 static inline void list_swap(struct list_head *entry1,
 235                     struct list_head *entry2)
 236 {
 237     struct list_head *pos = entry2->prev;
 238 
 239     list_del(entry2);
 240     list_replace(entry1, entry2);
 241     if (pos == entry1)
 242         pos = entry2;
 243     list_add(entry1, pos);
 244 }
 245 
 246 /**
 247  * list_del_init - deletes entry from list and reinitialize it.
 248  * @entry: the element to delete from the list.
 249  */
 250 static inline void list_del_init(struct list_head *entry)
 251 {
 252     __list_del_entry(entry);
 253     INIT_LIST_HEAD(entry);
 254 }
 255 
 256 /**
 257  * list_move - delete from one list and add as another's head
 258  * @list: the entry to move
 259  * @head: the head that will precede our entry
 260  */
 261 static inline void list_move(struct list_head *list, struct list_head *head)
 262 {
 263     __list_del_entry(list);
 264     list_add(list, head);
 265 }
 266 
 267 /**
 268  * list_move_tail - delete from one list and add as another's tail
 269  * @list: the entry to move
 270  * @head: the head that will follow our entry
 271  */
 272 static inline void list_move_tail(struct list_head *list,
 273                     struct list_head *head)
 274 {
 275     __list_del_entry(list);
 276     list_add_tail(list, head);
 277 }
 278 
 279 /**
 280  * list_bulk_move_tail - move a subsection of a list to its tail
 281  * @head: the head that will follow our entry
 282  * @first: first entry to move
 283  * @last: last entry to move, can be the same as first
 284  *
 285  * Move all entries between @first and including @last before @head.
 286  * All three entries must belong to the same linked list.
 287  */
 288 static inline void list_bulk_move_tail(struct list_head *head,
 289                         struct list_head *first,
 290                         struct list_head *last)
 291 {
 292     first->prev->next = last->next;
 293     last->next->prev = first->prev;
 294 
 295     head->prev->next = first;
 296     first->prev = head->prev;
 297 
 298     last->next = head;
 299     head->prev = last;
 300 }
 301 
 302 /**
 303  * list_is_first -- tests whether @list is the first entry in list @head
 304  * @list: the entry to test
 305  * @head: the head of the list
 306  */
 307 static inline int list_is_first(const struct list_head *list,
 308                     const struct list_head *head)
 309 {
 310     return list->prev == head;
 311 }
 312 
 313 /**
 314  * list_is_last - tests whether @list is the last entry in list @head
 315  * @list: the entry to test
 316  * @head: the head of the list
 317  */
 318 static inline int list_is_last(const struct list_head *list,
 319                 const struct list_head *head)
 320 {
 321     return list->next == head;
 322 }
 323 
 324 /**
 325  * list_empty - tests whether a list is empty
 326  * @head: the list to test.
 327  */
 328 static inline int list_empty(const struct list_head *head)
 329 {
 330     return READ_ONCE(head->next) == head;
 331 }
 332 
 333 /**
 334  * list_rotate_left - rotate the list to the left
 335  * @head: the head of the list
 336  */
 337 static inline void list_rotate_left(struct list_head *head)
 338 {
 339     struct list_head *first;
 340 
 341     if (!list_empty(head)) {
 342         first = head->next;
 343         list_move_tail(first, head);
 344     }
 345 }
 346 
 347 /**
 348  * list_rotate_to_front() - Rotate list to specific item.
 349  * @list: The desired new front of the list.
 350  * @head: The head of the list.
 351  *
 352  * Rotates list so that @list becomes the new front of the list.
 353  */
 354 static inline void list_rotate_to_front(struct list_head *list,
 355                     struct list_head *head)
 356 {
 357     /**
 358      * Deletes the list head from the list denoted by @head and
 359      * places it as the tail of @list, this effectively rotates the
 360      * list so that @list is at the front.
 361     */
 362     list_move_tail(head, list);
 363 }
 364 
 365 /**
 366  * list_is_singular - tests whether a list has just one entry.
 367  * @head: the list to test.
 368  */
 369 static inline int list_is_singular(const struct list_head *head)
 370 {
 371     return !list_empty(head) && (head->next == head->prev);
 372 }
 373 
 374 static inline void __list_cut_position(struct list_head *list,
 375         struct list_head *head, struct list_head *entry)
 376 {
 377     struct list_head *new_first = entry->next;
 378     list->next = head->next;
 379     list->next->prev = list;
 380     list->prev = entry;
 381     entry->next = list;
 382     head->next = new_first;
 383     new_first->prev = head;
 384 }
 385 
 386 /**
 387  * list_cut_position - cut a list into two
 388  * @list: a new list to add all removed entries
 389  * @head: a list with entries
 390  * @entry: an entry within head, could be the head itself
 391  *    and if so we won't cut the list
 392  *
 393  * This helper moves the initial part of @head, up to and
 394  * including @entry, from @head to @list. You should
 395  * pass on @entry an element you know is on @head. @list
 396  * should be an empty list or a list you do not care about
 397  * losing its data.
 398  *
 399  */
 400 static inline void list_cut_position(struct list_head *list,
 401         struct list_head *head, struct list_head *entry)
 402 {
 403     if (list_empty(head))
 404         return;
 405     if (list_is_singular(head) &&
 406         (head->next != entry && head != entry))
 407         return;
 408     if (entry == head)
 409         INIT_LIST_HEAD(list);
 410     else
 411         __list_cut_position(list, head, entry);
 412 }
 413 
 414 /**
 415  * list_cut_before - cut a list into two, before given entry
 416  * @list: a new list to add all removed entries
 417  * @head: a list with entries
 418  * @entry: an entry within head, could be the head itself
 419  *
 420  * This helper moves the initial part of @head, up to but
 421  * excluding @entry, from @head to @list.  You should pass
 422  * in @entry an element you know is on @head.  @list should
 423  * be an empty list or a list you do not care about losing
 424  * its data.
 425  * If @entry == @head, all entries on @head are moved to
 426  * @list.
 427  */
 428 static inline void list_cut_before(struct list_head *list,
 429                     struct list_head *head,
 430                     struct list_head *entry)
 431 {
 432     if (head->next == entry) {
 433         INIT_LIST_HEAD(list);
 434         return;
 435     }
 436     list->next = head->next;
 437     list->next->prev = list;
 438     list->prev = entry->prev;
 439     list->prev->next = list;
 440     head->next = entry;
 441     entry->prev = head;
 442 }
 443 
 444 static inline void __list_splice(const struct list_head *list,
 445                     struct list_head *prev,
 446                     struct list_head *next)
 447 {
 448     struct list_head *first = list->next;
 449     struct list_head *last = list->prev;
 450 
 451     first->prev = prev;
 452     prev->next = first;
 453 
 454     last->next = next;
 455     next->prev = last;
 456 }
 457 
 458 /**
 459  * list_splice - join two lists, this is designed for stacks
 460  * @list: the new list to add.
 461  * @head: the place to add it in the first list.
 462  */
 463 static inline void list_splice(const struct list_head *list,
 464                 struct list_head *head)
 465 {
 466     if (!list_empty(list))
 467         __list_splice(list, head, head->next);
 468 }
 469 
 470 /**
 471  * list_splice_tail - join two lists, each list being a queue
 472  * @list: the new list to add.
 473  * @head: the place to add it in the first list.
 474  */
 475 static inline void list_splice_tail(struct list_head *list,
 476                 struct list_head *head)
 477 {
 478     if (!list_empty(list))
 479         __list_splice(list, head->prev, head);
 480 }
 481 
 482 /**
 483  * list_splice_init - join two lists and reinitialise the emptied list.
 484  * @list: the new list to add.
 485  * @head: the place to add it in the first list.
 486  *
 487  * The list at @list is reinitialised
 488  */
 489 static inline void list_splice_init(struct list_head *list,
 490                     struct list_head *head)
 491 {
 492     if (!list_empty(list)) {
 493         __list_splice(list, head, head->next);
 494         INIT_LIST_HEAD(list);
 495     }
 496 }
 497 
 498 /**
 499  * list_splice_tail_init - join two lists and reinitialise the emptied list
 500  * @list: the new list to add.
 501  * @head: the place to add it in the first list.
 502  *
 503  * Each of the lists is a queue.
 504  * The list at @list is reinitialised
 505  */
 506 static inline void list_splice_tail_init(struct list_head *list,
 507                     struct list_head *head)
 508 {
 509     if (!list_empty(list)) {
 510         __list_splice(list, head->prev, head);
 511         INIT_LIST_HEAD(list);
 512     }
 513 }
 514 
 515 /**
 516  * list_entry - get the struct for this entry
 517  * @ptr:    the &struct list_head pointer.
 518  * @type:   the type of the struct this is embedded in.
 519  * @member: the name of the list_head within the struct.
 520  */
 521 #define list_entry(ptr, type, member) \
 522     container_of(ptr, type, member)
 523 
 524 /**
 525  * list_first_entry - get the first element from a list
 526  * @ptr:    the list head to take the element from.
 527  * @type:   the type of the struct this is embedded in.
 528  * @member: the name of the list_head within the struct.
 529  *
 530  * Note, that list is expected to be not empty.
 531  */
 532 #define list_first_entry(ptr, type, member) \
 533     list_entry((ptr)->next, type, member)
 534 
 535 /**
 536  * list_last_entry - get the last element from a list
 537  * @ptr:    the list head to take the element from.
 538  * @type:   the type of the struct this is embedded in.
 539  * @member: the name of the list_head within the struct.
 540  *
 541  * Note, that list is expected to be not empty.
 542  */
 543 #define list_last_entry(ptr, type, member) \
 544     list_entry((ptr)->prev, type, member)
 545 
 546 /**
 547  * list_first_entry_or_null - get the first element from a list
 548  * @ptr:    the list head to take the element from.
 549  * @type:   the type of the struct this is embedded in.
 550  * @member: the name of the list_head within the struct.
 551  *
 552  * Note that if the list is empty, it returns NULL.
 553  */
 554 #define list_first_entry_or_null(ptr, type, member) ({          \
 555     struct list_head *head__ = (ptr);                           \
 556     struct list_head *pos__ = READ_ONCE(head__->next);          \
 557     pos__ != head__ ? list_entry(pos__, type, member) : NULL;   \
 558 })
 559 
 560 /**
 561  * list_next_entry - get the next element in list
 562  * @pos:    the type * to cursor
 563  * @member: the name of the list_head within the struct.
 564  */
 565 #define list_next_entry(pos, member) \
 566     list_entry((pos)->member.next, typeof(*(pos)), member)
 567 
 568 /**
 569  * list_prev_entry - get the prev element in list
 570  * @pos:    the type * to cursor
 571  * @member: the name of the list_head within the struct.
 572  */
 573 #define list_prev_entry(pos, member) \
 574     list_entry((pos)->member.prev, typeof(*(pos)), member)
 575 
 576 /**
 577  * list_for_each - iterate over a list
 578  * @pos:    the &struct list_head to use as a loop cursor.
 579  * @head:   the head for your list.
 580  */
 581 #define list_for_each(pos, head) \
 582     for (pos = (head)->next; pos != (head); pos = pos->next)
 583 
 584 /**
 585  * list_for_each_continue - continue iteration over a list
 586  * @pos:    the &struct list_head to use as a loop cursor.
 587  * @head:   the head for your list.
 588  *
 589  * Continue to iterate over a list, continuing after the current position.
 590  */
 591 #define list_for_each_continue(pos, head) \
 592     for (pos = pos->next; pos != (head); pos = pos->next)
 593 
 594 /**
 595  * list_for_each_prev - iterate over a list backwards
 596  * @pos:    the &struct list_head to use as a loop cursor.
 597  * @head:   the head for your list.
 598  */
 599 #define list_for_each_prev(pos, head) \
 600     for (pos = (head)->prev; pos != (head); pos = pos->prev)
 601 
 602 /**
 603  * list_for_each_safe - iterate over a list safe against removal of list entry
 604  * @pos:    the &struct list_head to use as a loop cursor.
 605  * @n:      another &struct list_head to use as temporary storage
 606  * @head:   the head for your list.
 607  */
 608 #define list_for_each_safe(pos, n, head)                        \
 609     for (pos = (head)->next, n = pos->next; pos != (head);      \
 610         pos = n, n = pos->next)
 611 
 612 /**
 613  * list_for_each_prev_safe - iterate over a list backwards safe against removal of list entry
 614  * @pos:    the &struct list_head to use as a loop cursor.
 615  * @n:      another &struct list_head to use as temporary storage
 616  * @head:   the head for your list.
 617  */
 618 #define list_for_each_prev_safe(pos, n, head) \
 619     for (pos = (head)->prev, n = pos->prev; \
 620             pos != (head); \
 621             pos = n, n = pos->prev)
 622 
 623 /**
 624  * list_for_each_entry - iterate over list of given type
 625  * @pos:    the type * to use as a loop cursor.
 626  * @head:   the head for your list.
 627  * @member: the name of the list_head within the struct.
 628  */
 629 #define list_for_each_entry(pos, head, member)                  \
 630     for (pos = list_first_entry(head, typeof(*pos), member);    \
 631             &pos->member != (head);                             \
 632             pos = list_next_entry(pos, member))
 633 
 634 /**
 635  * list_for_each_entry_reverse - iterate backwards over list of given type.
 636  * @pos:    the type * to use as a loop cursor.
 637  * @head:   the head for your list.
 638  * @member: the name of the list_head within the struct.
 639  */
 640 #define list_for_each_entry_reverse(pos, head, member)          \
 641     for (pos = list_last_entry(head, typeof(*pos), member);     \
 642             &pos->member != (head);                             \
 643             pos = list_prev_entry(pos, member))
 644 
 645 /**
 646  * list_prepare_entry - prepare a pos entry for use in list_for_each_entry_continue()
 647  * @pos:    the type * to use as a start point
 648  * @head:   the head of the list
 649  * @member: the name of the list_head within the struct.
 650  *
 651  * Prepares a pos entry for use as a start point in list_for_each_entry_continue().
 652  */
 653 #define list_prepare_entry(pos, head, member) \
 654     ((pos) ? : list_entry(head, typeof(*pos), member))
 655 
 656 /**
 657  * list_for_each_entry_continue - continue iteration over list of given type
 658  * @pos:    the type * to use as a loop cursor.
 659  * @head:   the head for your list.
 660  * @member: the name of the list_head within the struct.
 661  *
 662  * Continue to iterate over list of given type, continuing after
 663  * the current position.
 664  */
 665 #define list_for_each_entry_continue(pos, head, member)         \
 666     for (pos = list_next_entry(pos, member);                    \
 667             &pos->member != (head);                             \
 668             pos = list_next_entry(pos, member))
 669 
 670 /**
 671  * list_for_each_entry_continue_reverse - iterate backwards from the given point
 672  * @pos:    the type * to use as a loop cursor.
 673  * @head:   the head for your list.
 674  * @member: the name of the list_head within the struct.
 675  *
 676  * Start to iterate over list of given type backwards, continuing after
 677  * the current position.
 678  */
 679 #define list_for_each_entry_continue_reverse(pos, head, member) \
 680     for (pos = list_prev_entry(pos, member);                    \
 681             &pos->member != (head);                             \
 682             pos = list_prev_entry(pos, member))
 683 
 684 /**
 685  * list_for_each_entry_from - iterate over list of given type from the current point
 686  * @pos:    the type * to use as a loop cursor.
 687  * @head:   the head for your list.
 688  * @member: the name of the list_head within the struct.
 689  *
 690  * Iterate over list of given type, continuing from current position.
 691  */
 692 #define list_for_each_entry_from(pos, head, member)             \
 693     for (; &pos->member != (head);                              \
 694             pos = list_next_entry(pos, member))
 695 
 696 /**
 697  * list_for_each_entry_from_reverse - iterate backwards over list of given type
 698  *                                    from the current point
 699  * @pos:    the type * to use as a loop cursor.
 700  * @head:   the head for your list.
 701  * @member: the name of the list_head within the struct.
 702  *
 703  * Iterate backwards over list of given type, continuing from current position.
 704  */
 705 #define list_for_each_entry_from_reverse(pos, head, member)     \
 706     for (; &pos->member != (head);                              \
 707             pos = list_prev_entry(pos, member))
 708 
 709 /**
 710  * list_for_each_entry_safe - iterate over list of given type safe against removal of list entry
 711  * @pos:    the type * to use as a loop cursor.
 712  * @n:      another type * to use as temporary storage
 713  * @head:   the head for your list.
 714  * @member: the name of the list_head within the struct.
 715  */
 716 #define list_for_each_entry_safe(pos, n, head, member)          \
 717     for (pos = list_first_entry(head, typeof(*pos), member),    \
 718         n = list_next_entry(pos, member);                       \
 719             &pos->member != (head);                             \
 720             pos = n, n = list_next_entry(n, member))
 721 
 722 /**
 723  * list_for_each_entry_safe_continue - continue list iteration safe against removal
 724  * @pos:    the type * to use as a loop cursor.
 725  * @n:      another type * to use as temporary storage
 726  * @head:   the head for your list.
 727  * @member: the name of the list_head within the struct.
 728  *
 729  * Iterate over list of given type, continuing after current point,
 730  * safe against removal of list entry.
 731  */
 732 #define list_for_each_entry_safe_continue(pos, n, head, member) \
 733     for (pos = list_next_entry(pos, member),                    \
 734         n = list_next_entry(pos, member);                       \
 735             &pos->member != (head);                             \
 736             pos = n, n = list_next_entry(n, member))
 737 
 738 /**
 739  * list_for_each_entry_safe_from - iterate over list from current point safe against removal
 740  * @pos:    the type * to use as a loop cursor.
 741  * @n:      another type * to use as temporary storage
 742  * @head:   the head for your list.
 743  * @member: the name of the list_head within the struct.
 744  *
 745  * Iterate over list of given type from current point, safe against
 746  * removal of list entry.
 747  */
 748 #define list_for_each_entry_safe_from(pos, n, head, member)     \
 749     for (n = list_next_entry(pos, member);                      \
 750             &pos->member != (head);                             \
 751             pos = n, n = list_next_entry(n, member))
 752 
 753 /**
 754  * list_for_each_entry_safe_reverse - iterate backwards over list safe against removal
 755  * @pos:    the type * to use as a loop cursor.
 756  * @n:      another type * to use as temporary storage
 757  * @head:   the head for your list.
 758  * @member: the name of the list_head within the struct.
 759  *
 760  * Iterate backwards over list of given type, safe against removal
 761  * of list entry.
 762  */
 763 #define list_for_each_entry_safe_reverse(pos, n, head, member)  \
 764     for (pos = list_last_entry(head, typeof(*pos), member),     \
 765         n = list_prev_entry(pos, member);                       \
 766             &pos->member != (head);                             \
 767             pos = n, n = list_prev_entry(n, member))
 768 
 769 /**
 770  * list_safe_reset_next - reset a stale list_for_each_entry_safe loop
 771  * @pos:    the loop cursor used in the list_for_each_entry_safe loop
 772  * @n:      temporary storage used in list_for_each_entry_safe
 773  * @member: the name of the list_head within the struct.
 774  *
 775  * list_safe_reset_next is not safe to use in general if the list may be
 776  * modified concurrently (eg. the lock is dropped in the loop body). An
 777  * exception to this is if the cursor element (pos) is pinned in the list,
 778  * and list_safe_reset_next is called after re-taking the lock and before
 779  * completing the current iteration of the loop body.
 780  */
 781 #define list_safe_reset_next(pos, n, member)            \
 782     n = list_next_entry(pos, member)
 783 
 784 /*
 785  * Double linked lists with a single pointer list head.
 786  * Mostly useful for hash tables where the two pointer list head is
 787  * too wasteful.
 788  * You lose the ability to access the tail in O(1).
 789  */
 790 
 791 #define HLIST_HEAD_INIT { .first = NULL }
 792 #define HLIST_HEAD(name) struct hlist_head name = {  .first = NULL }
 793 #define INIT_HLIST_HEAD(ptr) ((ptr)->first = NULL)
 794 static inline void INIT_HLIST_NODE(struct hlist_node *h)
 795 {
 796     h->next = NULL;
 797     h->pprev = NULL;
 798 }
 799 
 800 /**
 801  * hlist_unhashed - Has node been removed from list and reinitialized?
 802  * @h: Node to be checked
 803  *
 804  * Not that not all removal functions will leave a node in unhashed
 805  * state.  For example, hlist_nulls_del_init_rcu() does leave the
 806  * node in unhashed state, but hlist_nulls_del() does not.
 807  */
 808 static inline int hlist_unhashed(const struct hlist_node *h)
 809 {
 810     return !h->pprev;
 811 }
 812 
 813 /**
 814  * hlist_unhashed_lockless - Version of hlist_unhashed for lockless use
 815  * @h: Node to be checked
 816  *
 817  * This variant of hlist_unhashed() must be used in lockless contexts
 818  * to avoid potential load-tearing.  The READ_ONCE() is paired with the
 819  * various WRITE_ONCE() in hlist helpers that are defined below.
 820  */
 821 static inline int hlist_unhashed_lockless(const struct hlist_node *h)
 822 {
 823     return !READ_ONCE(h->pprev);
 824 }
 825 
 826 /**
 827  * hlist_empty - Is the specified hlist_head structure an empty hlist?
 828  * @h: Structure to check.
 829  */
 830 static inline int hlist_empty(const struct hlist_head *h)
 831 {
 832     return !READ_ONCE(h->first);
 833 }
 834 
 835 static inline void __hlist_del(struct hlist_node *n)
 836 {
 837     struct hlist_node *next = n->next;
 838     struct hlist_node **pprev = n->pprev;
 839 
 840     WRITE_ONCE(*pprev, next);
 841     if (next)
 842         WRITE_ONCE(next->pprev, pprev);
 843 }
 844 
 845 /**
 846  * hlist_del - Delete the specified hlist_node from its list
 847  * @n: Node to delete.
 848  *
 849  * Note that this function leaves the node in hashed state.  Use
 850  * hlist_del_init() or similar instead to unhash @n.
 851  */
 852 static inline void hlist_del(struct hlist_node *n)
 853 {
 854     __hlist_del(n);
 855     n->next = LIST_POISON1;
 856     n->pprev = LIST_POISON2;
 857 }
 858 
 859 /**
 860  * hlist_del_init - Delete the specified hlist_node from its list and initialize
 861  * @n: Node to delete.
 862  *
 863  * Note that this function leaves the node in unhashed state.
 864  */
 865 static inline void hlist_del_init(struct hlist_node *n)
 866 {
 867     if (!hlist_unhashed(n)) {
 868         __hlist_del(n);
 869         INIT_HLIST_NODE(n);
 870     }
 871 }
 872 
 873 /**
 874  * hlist_add_head - add a new entry at the beginning of the hlist
 875  * @n: new entry to be added
 876  * @h: hlist head to add it after
 877  *
 878  * Insert a new entry after the specified head.
 879  * This is good for implementing stacks.
 880  */
 881 static inline void hlist_add_head(struct hlist_node *n, struct hlist_head *h)
 882 {
 883     struct hlist_node *first = h->first;
 884     WRITE_ONCE(n->next, first);
 885     if (first)
 886         WRITE_ONCE(first->pprev, &n->next);
 887     WRITE_ONCE(h->first, n);
 888     WRITE_ONCE(n->pprev, &h->first);
 889 }
 890 
 891 /**
 892  * hlist_add_before - add a new entry before the one specified
 893  * @n: new entry to be added
 894  * @next: hlist node to add it before, which must be non-NULL
 895  */
 896 static inline void hlist_add_before(struct hlist_node *n,
 897                     struct hlist_node *next)
 898 {
 899     WRITE_ONCE(n->pprev, next->pprev);
 900     WRITE_ONCE(n->next, next);
 901     WRITE_ONCE(next->pprev, &n->next);
 902     WRITE_ONCE(*(n->pprev), n);
 903 }
 904 
 905 /**
 906  * hlist_add_behing - add a new entry after the one specified
 907  * @n: new entry to be added
 908  * @prev: hlist node to add it after, which must be non-NULL
 909  */
 910 static inline void hlist_add_behind(struct hlist_node *n,
 911                     struct hlist_node *prev)
 912 {
 913     WRITE_ONCE(n->next, prev->next);
 914     WRITE_ONCE(prev->next, n);
 915     WRITE_ONCE(n->pprev, &prev->next);
 916 
 917     if (n->next)
 918         WRITE_ONCE(n->next->pprev, &n->next);
 919 }
 920 
 921 /**
 922  * hlist_add_fake - create a fake hlist consisting of a single headless node
 923  * @n: Node to make a fake list out of
 924  *
 925  * This makes @n appear to be its own predecessor on a headless hlist.
 926  * The point of this is to allow things like hlist_del() to work correctly
 927  * in cases where there is no list.
 928  */
 929 static inline void hlist_add_fake(struct hlist_node *n)
 930 {
 931     n->pprev = &n->next;
 932 }
 933 
 934 /**
 935  * hlist_fake: Is this node a fake hlist?
 936  * @h: Node to check for being a self-referential fake hlist.
 937  */
 938 static inline bool hlist_fake(struct hlist_node *h)
 939 {
 940     return h->pprev == &h->next;
 941 }
 942 
 943 /**
 944  * hlist_is_singular_node - is node the only element of the specified hlist?
 945  * @n: Node to check for singularity.
 946  * @h: Header for potentially singular list.
 947  *
 948  * Check whether the node is the only node of the head without
 949  * accessing head, thus avoiding unnecessary cache misses.
 950  */
 951 static inline bool
 952 hlist_is_singular_node(struct hlist_node *n, struct hlist_head *h)
 953 {
 954     return !n->next && n->pprev == &h->first;
 955 }
 956 
 957 /**
 958  * hlist_move_list - Move an hlist
 959  * @old: hlist_head for old list.
 960  * @new: hlist_head for new list.
 961  *
 962  * Move a list from one list head to another. Fixup the pprev
 963  * reference of the first entry if it exists.
 964  */
 965 static inline void hlist_move_list(struct hlist_head *old,
 966                     struct hlist_head *new)
 967 {
 968     new->first = old->first;
 969     if (new->first)
 970         new->first->pprev = &new->first;
 971     old->first = NULL;
 972 }
 973 
 974 #define hlist_entry(ptr, type, member) container_of(ptr,type,member)
 975 
 976 #define hlist_for_each(pos, head) \
 977     for (pos = (head)->first; pos ; pos = pos->next)
 978 
 979 #define hlist_for_each_safe(pos, n, head) \
 980     for (pos = (head)->first; pos && ({ n = pos->next; 1; }); \
 981          pos = n)
 982 
 983 #define hlist_entry_safe(ptr, type, member) \
 984     ({ typeof(ptr) ____ptr = (ptr); \
 985         ____ptr ? hlist_entry(____ptr, type, member) : NULL; \
 986     })
 987 
 988 /**
 989  * hlist_for_each_entry    - iterate over list of given type
 990  * @pos:    the type * to use as a loop cursor.
 991  * @head:   the head for your list.
 992  * @member: the name of the hlist_node within the struct.
 993  */
 994 #define hlist_for_each_entry(pos, head, member)                         \
 995     for (pos = hlist_entry_safe((head)->first, typeof(*(pos)), member); \
 996             pos;                                                        \
 997             pos = hlist_entry_safe((pos)->member.next, typeof(*(pos)), member))
 998 
 999 /**
1000  * hlist_for_each_entry_continue - iterate over a hlist continuing after current point
1001  * @pos:    the type * to use as a loop cursor.
1002  * @member: the name of the hlist_node within the struct.
1003  */
1004 #define hlist_for_each_entry_continue(pos, member)                          \
1005     for (pos = hlist_entry_safe((pos)->member.next, typeof(*(pos)), member);\
1006             pos;                                                            \
1007             pos = hlist_entry_safe((pos)->member.next, typeof(*(pos)), member))
1008 
1009 /**
1010  * hlist_for_each_entry_from - iterate over a hlist continuing from current point
1011  * @pos:    the type * to use as a loop cursor.
1012  * @member: the name of the hlist_node within the struct.
1013  */
1014 #define hlist_for_each_entry_from(pos, member)  \
1015     for (; pos;                                 \
1016             pos = hlist_entry_safe((pos)->member.next, typeof(*(pos)), member))
1017 
1018 /**
1019  * hlist_for_each_entry_safe - iterate over list of given type safe against removal of list entry
1020  * @pos:    the type * to use as a loop cursor.
1021  * @n:      a &struct hlist_node to use as temporary storage
1022  * @head:   the head for your list.
1023  * @member: the name of the hlist_node within the struct.
1024  */
1025 #define hlist_for_each_entry_safe(pos, n, head, member)                 \
1026     for (pos = hlist_entry_safe((head)->first, typeof(*pos), member);   \
1027             pos && ({ n = pos->member.next; 1; });                      \
1028             pos = hlist_entry_safe(n, typeof(*pos), member))
1029 
1030 #endif
View Code

main.c

  1 /**
  2  * C data structure kernel linked list example.
  3  * 
  4  * License - MIT.
  5 */
  6 
  7 #include <stdio.h>
  8 #include <stdlib.h>
  9 
 10 #include "list.h"
 11 
 12 
 13 #define MAX_TEST_NUM                10
 14 
 15 
 16 typedef struct _TESTDATA {
 17     int data;
 18     struct list_head list;
 19 } TESTDATA, *LPTESTDATA;
 20 
 21 
 22 /**
 23  * test_show - Display data.
 24 */
 25 int test_show(LPTESTDATA lphead)
 26 {
 27     LPTESTDATA tmp = NULL;
 28 
 29     list_for_each_entry(tmp, &lphead->list, list)
 30         printf("%d ", tmp->data);
 31 
 32     printf("\n");
 33 
 34     return 0;
 35 }
 36 
 37 
 38 /**
 39  * test_create - Create kernel linked list.
 40 */
 41 int test_create(LPTESTDATA lphead)
 42 {
 43     LPTESTDATA node;
 44     int buf[MAX_TEST_NUM] = {92, 26, 35, 82, 57, 46, 50, 3, 22, 81};
 45 
 46     for (int i = 0; i < MAX_TEST_NUM; i++) {
 47         node = (LPTESTDATA) malloc(sizeof(TESTDATA));
 48 
 49         if (NULL == node) {
 50             printf("Error in create.\n");
 51             return -1;
 52         }
 53 
 54         node->data = buf[i];
 55 
 56         list_add_tail(&node->list, &lphead->list);
 57     }
 58 
 59     return 0;
 60 }
 61 
 62 
 63 /**
 64  * test_init - Initialize kernel linked list.
 65 */
 66 int test_init(LPTESTDATA *lphead)
 67 {
 68     *lphead = (LPTESTDATA) malloc(sizeof(TESTDATA));
 69 
 70     if (NULL == *lphead) {
 71         printf("Error in init.\n");
 72         return -1;
 73     }
 74 
 75     INIT_LIST_HEAD(&(*lphead)->list);
 76 
 77     return 0;
 78 }
 79 
 80 
 81 /**
 82  * test_clear - Clear kernel linked list data.
 83 */
 84 int test_clear(LPTESTDATA lphead)
 85 {
 86     LPTESTDATA pos = NULL, n = NULL;
 87 
 88     list_for_each_entry_safe(pos, n, &lphead->list, list) {
 89         list_del(&pos->list);
 90 
 91         free(pos);
 92     }
 93 
 94     free(lphead);
 95 
 96     pos     = NULL;
 97     n       = NULL;
 98     lphead  = NULL;
 99 
100     return 0;
101 }
102 
103 
104 /**
105  * Main function.
106 */
107 int main(void)
108 {
109     LPTESTDATA lphead;
110 
111     test_init(&lphead);
112 
113     test_create(lphead);
114 
115     test_show(lphead);
116 
117     test_clear(lphead);
118 
119     return 0;
120 }

Makefile

 1 # Makefile
 2 CC = gcc
 3 CFLAGS = -Wall -g -O0
 4 
 5 SRC = main.c
 6 
 7 OBJ = kerlist-test
 8 
 9 $(OBJ) : $(SRC)
10     $(CC) $(CFLAGS) -o $@ $^
11 
12 clean:
13     $(RM) $(OBJ) *.o *.*.sw?

 

详细请参考Github: [Link] [https://github.com/Phoebus-Ma/C-Helper/tree/main/Class-1/List.C].

posted @ 2022-06-25 15:02  this毛豆  阅读(157)  评论(0编辑  收藏  举报