linux内核数据结构之链表-实现

代码:list.h

  1 /*
  2  * @file list.h
  3  * @author PF
  4  * @date 2017/05/1
  5  *
  6  * port from linux kernel list.h: https://github.com/torvalds/linux/raw/master/include/linux/list.h
  7  *
  8  * Here is a recipe to cook list.h for user space program.
  9  * 1. copy list.h from linux/include/list.h
 10  * 2. remove
 11  *     - #ifdef __KERNE__ and its #endif
 12  *     - all #include line
 13  *     - prefetch() and rcu related functions
 14  * 3. add macro offsetof() and container_of
 15  */
 16 
 17 #ifndef LIST_H_
 18 #define LIST_H_ (1)
 19 
 20 // import from include/linux/types.h
 21 struct list_head {
 22     struct list_head *next, *prev;
 23 };
 24 
 25 struct hlist_head {
 26     struct hlist_node *first;
 27 };
 28 
 29 struct hlist_node {
 30     struct hlist_node *next, **pprev;
 31 };
 32 
 33 // import from include/linux/poison.h
 34 
 35 /*
 36  * Architectures might want to move the poison pointer offset
 37  * into some well-recognized area such as 0xdead000000000000,
 38  * that is also not mappable by user-space exploits:
 39  */
 40 #ifdef CONFIG_ILLEGAL_POINTER_VALUE
 41 # define POISON_POINTER_DELTA _AC(CONFIG_ILLEGAL_POINTER_VALUE, UL)
 42 #else
 43 # define POISON_POINTER_DELTA (0)
 44 #endif
 45 
 46 /*
 47  * These are non-NULL pointers that will result in page faults
 48  * under normal circumstances, used to verify that nobody uses
 49  * non-initialized list entries.
 50  */
 51 #define LIST_POISON1  ((void *) 0x00100100 + POISON_POINTER_DELTA)
 52 #define LIST_POISON2  ((void *) 0x00200200 + POISON_POINTER_DELTA)
 53 
 54 // import from include/linux/stddef.h
 55 #undef offsetof
 56 #ifdef __compiler_offsetof
 57 #define offsetof(TYPE,MEMBER) __compiler_offsetof(TYPE,MEMBER)
 58 #else
 59 #define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
 60 #endif
 61 
 62 // import from include/linux/kernel.h
 63 /**
 64 * container_of - cast a member of a structure out to the containing structure
 65 * @ptr:        the pointer to the member.
 66 * @type:       the type of the container struct this is embedded in.
 67 * @member:     the name of the member within the struct.
 68 *
 69 */
 70 #define container_of(ptr, type, member) ({                      
 71         const typeof( ((type *)0)->member ) *__mptr = (ptr);    
 72         (type *)( (char *)__mptr - offsetof(type,member) );})
 73 
 74 /*
 75  * Simple doubly linked list implementation.
 76  *
 77  * Some of the internal functions ("__xxx") are useful when
 78  * manipulating whole lists rather than single entries, as
 79  * sometimes we already know the next/prev entries and we can
 80  * generate better code by using them directly rather than
 81  * using the generic single-entry routines.
 82  */
 83 
 84 #define LIST_HEAD_INIT(name) { &(name), &(name) }
 85 
 86 #define LIST_HEAD(name) 
 87     struct list_head name = LIST_HEAD_INIT(name)
 88 
 89 static inline void INIT_LIST_HEAD(struct list_head *list) {
 90     list->next = list;
 91     list->prev = list;
 92 }
 93 
 94 /*
 95  * Insert a new entry between two known consecutive entries.
 96  *
 97  * This is only for internal list manipulation where we know
 98  * the prev/next entries already!
 99  */
100 #ifndef CONFIG_DEBUG_LIST
101 static inline void __list_add(struct list_head *new,
102     struct list_head *prev,
103     struct list_head *next) {
104     next->prev = new;
105     new->next = next;
106     new->prev = prev;
107     prev->next = new;
108 }
109 #else
110 extern void __list_add(struct list_head *new,
111                   struct list_head *prev,
112                   struct list_head *next);
113 #endif
114 
115 /**
116  * list_add - add a new entry
117  * @new: new entry to be added
118  * @head: list head to add it after
119  *
120  * Insert a new entry after the specified head.
121  * This is good for implementing stacks.
122  */
123 static inline void list_add(struct list_head *new, struct list_head *head) {
124     __list_add(new, head, head->next);
125 }
126 
127 /**
128  * list_add_tail - add a new entry
129  * @new: new entry to be added
130  * @head: list head to add it before
131  *
132  * Insert a new entry before the specified head.
133  * This is useful for implementing queues.
134  */
135 static inline void list_add_tail(struct list_head *new, struct list_head *head) {
136     __list_add(new, head->prev, head);
137 }
138 
139 /*
140  * Delete a list entry by making the prev/next entries
141  * point to each other.
142  *
143  * This is only for internal list manipulation where we know
144  * the prev/next entries already!
145  */
146 static inline void __list_del(struct list_head *prev, struct list_head *next) {
147     next->prev = prev;
148     prev->next = next;
149 }
150 
151 /**
152  * list_del - deletes entry from list.
153  * @entry: the element to delete from the list.
154  * Note: list_empty() on entry does not return true after this, the entry is
155  * in an undefined state.
156  */
157 #ifndef CONFIG_DEBUG_LIST
158 
159 static inline void __list_del_entry(struct list_head *entry) {
160     __list_del(entry->prev, entry->next);
161 }
162 
163 static inline void list_del(struct list_head *entry) {
164     __list_del(entry->prev, entry->next);
165     entry->next = LIST_POISON1;
166     entry->prev = LIST_POISON2;
167 }
168 
169 #else
170 extern void __list_del_entry(struct list_head *entry);
171 extern void list_del(struct list_head *entry);
172 #endif
173 
174 /**
175  * list_replace - replace old entry by new one
176  * @old : the element to be replaced
177  * @new : the new element to insert
178  *
179  * If @old was empty, it will be overwritten.
180  */
181 static inline void list_replace(struct list_head *old,
182         struct list_head *new) {
183     new->next = old->next;
184     new->next->prev = new;
185     new->prev = old->prev;
186     new->prev->next = new;
187 }
188 
189 static inline void list_replace_init(struct list_head *old,
190         struct list_head *new) {
191     list_replace(old, new);
192     INIT_LIST_HEAD(old);
193 }
194 
195 /**
196  * list_del_init - deletes entry from list and reinitialize it.
197  * @entry: the element to delete from the list.
198  */
199 static inline void list_del_init(struct list_head *entry) {
200     __list_del_entry(entry);
201     INIT_LIST_HEAD(entry);
202 }
203 
204 /**
205  * list_move - delete from one list and add as another's head
206  * @list: the entry to move
207  * @head: the head that will precede our entry
208  */
209 static inline void list_move(struct list_head *list, struct list_head *head) {
210     __list_del_entry(list);
211     list_add(list, head);
212 }
213 
214 /**
215  * list_move_tail - delete from one list and add as another's tail
216  * @list: the entry to move
217  * @head: the head that will follow our entry
218  */
219 static inline void list_move_tail(struct list_head *list,
220         struct list_head *head) {
221     __list_del_entry(list);
222     list_add_tail(list, head);
223 }
224 
225 /**
226  * list_is_last - tests whether @list is the last entry in list @head
227  * @list: the entry to test
228  * @head: the head of the list
229  */
230 static inline int list_is_last(const struct list_head *list,
231         const struct list_head *head) {
232     return list->next == head;
233 }
234 
235 /**
236  * list_empty - tests whether a list is empty
237  * @head: the list to test.
238  */
239 static inline int list_empty(const struct list_head *head) {
240     return head->next == head;
241 }
242 
243 /**
244  * list_empty_careful - tests whether a list is empty and not being modified
245  * @head: the list to test
246  *
247  * Description:
248  * tests whether a list is empty _and_ checks that no other CPU might be
249  * in the process of modifying either member (next or prev)
250  *
251  * NOTE: using list_empty_careful() without synchronization
252  * can only be safe if the only activity that can happen
253  * to the list entry is list_del_init(). Eg. it cannot be used
254  * if another CPU could re-list_add() it.
255  */
256 static inline int list_empty_careful(const struct list_head *head) {
257     struct list_head *next = head->next;
258     return (next == head) && (next == head->prev);
259 }
260 
261 /**
262  * list_rotate_left - rotate the list to the left
263  * @head: the head of the list
264  */
265 static inline void list_rotate_left(struct list_head *head) {
266     struct list_head *first;
267 
268     if (!list_empty(head)) {
269         first = head->next;
270         list_move_tail(first, head);
271     }
272 }
273 
274 /**
275  * list_is_singular - tests whether a list has just one entry.
276  * @head: the list to test.
277  */
278 static inline int list_is_singular(const struct list_head *head) {
279     return !list_empty(head) && (head->next == head->prev);
280 }
281 
282 static inline void __list_cut_position(struct list_head *list,
283         struct list_head *head, struct list_head *entry) {
284     struct list_head *new_first = entry->next;
285     list->next = head->next;
286     list->next->prev = list;
287     list->prev = entry;
288     entry->next = list;
289     head->next = new_first;
290     new_first->prev = head;
291 }
292 
293 /**
294  * list_cut_position - cut a list into two
295  * @list: a new list to add all removed entries
296  * @head: a list with entries
297  * @entry: an entry within head, could be the head itself
298  *  and if so we won't cut the list
299  *
300  * This helper moves the initial part of @head, up to and
301  * including @entry, from @head to @list. You should
302  * pass on @entry an element you know is on @head. @list
303  * should be an empty list or a list you do not care about
304  * losing its data.
305  *
306  */
307 static inline void list_cut_position(struct list_head *list,
308         struct list_head *head, struct list_head *entry) {
309     if (list_empty(head)) {
310         return;
311     }
312     if (list_is_singular(head) &&
313             (head->next != entry && head != entry)) {
314         return;
315     }
316     if (entry == head) {
317         INIT_LIST_HEAD(list);
318     } else {
319         __list_cut_position(list, head, entry);
320     }
321 }
322 
323 static inline void __list_splice(const struct list_head *list,
324         struct list_head *prev,
325         struct list_head *next) {
326     struct list_head *first = list->next;
327     struct list_head *last = list->prev;
328 
329     first->prev = prev;
330     prev->next = first;
331 
332     last->next = next;
333     next->prev = last;
334 }
335 
336 /**
337  * list_splice - join two lists, this is designed for stacks
338  * @list: the new list to add.
339  * @head: the place to add it in the first list.
340  */
341 static inline void list_splice(const struct list_head *list,
342         struct list_head *head) {
343     if (!list_empty(list)) {
344         __list_splice(list, head, head->next);
345     }
346 }
347 
348 /**
349  * list_splice_tail - join two lists, each list being a queue
350  * @list: the new list to add.
351  * @head: the place to add it in the first list.
352  */
353 static inline void list_splice_tail(struct list_head *list,
354         struct list_head *head) {
355     if (!list_empty(list)) {
356         __list_splice(list, head->prev, head);
357     }
358 }
359 
360 /**
361  * list_splice_init - join two lists and reinitialise the emptied list.
362  * @list: the new list to add.
363  * @head: the place to add it in the first list.
364  *
365  * The list at @list is reinitialised
366  */
367 static inline void list_splice_init(struct list_head *list,
368         struct list_head *head) {
369     if (!list_empty(list)) {
370         __list_splice(list, head, head->next);
371         INIT_LIST_HEAD(list);
372     }
373 }
374 
375 /**
376  * list_splice_tail_init - join two lists and reinitialise the emptied list
377  * @list: the new list to add.
378  * @head: the place to add it in the first list.
379  *
380  * Each of the lists is a queue.
381  * The list at @list is reinitialised
382  */
383 static inline void list_splice_tail_init(struct list_head *list,
384         struct list_head *head) {
385     if (!list_empty(list)) {
386         __list_splice(list, head->prev, head);
387         INIT_LIST_HEAD(list);
388     }
389 }
390 
391 /**
392  * list_entry - get the struct for this entry
393  * @ptr:    the &struct list_head pointer.
394  * @type:   the type of the struct this is embedded in.
395  * @member: the name of the list_head within the struct.
396  */
397 #define list_entry(ptr, type, member) 
398     container_of(ptr, type, member)
399 
400 /**
401  * list_first_entry - get the first element from a list
402  * @ptr:    the list head to take the element from.
403  * @type:   the type of the struct this is embedded in.
404  * @member: the name of the list_head within the struct.
405  *
406  * Note, that list is expected to be not empty.
407  */
408 #define list_first_entry(ptr, type, member) 
409     list_entry((ptr)->next, type, member)
410 
411 /**
412  * list_last_entry - get the last element from a list
413  * @ptr:    the list head to take the element from.
414  * @type:   the type of the struct this is embedded in.
415  * @member: the name of the list_head within the struct.
416  *
417  * Note, that list is expected to be not empty.
418  */
419 #define list_last_entry(ptr, type, member) 
420     list_entry((ptr)->prev, type, member)
421 
422 /**
423  * list_first_entry_or_null - get the first element from a list
424  * @ptr:    the list head to take the element from.
425  * @type:   the type of the struct this is embedded in.
426  * @member: the name of the list_head within the struct.
427  *
428  * Note that if the list is empty, it returns NULL.
429  */
430 #define list_first_entry_or_null(ptr, type, member) 
431     (!list_empty(ptr) ? list_first_entry(ptr, type, member) : NULL)
432 
433 /**
434  * list_next_entry - get the next element in list
435  * @pos:    the type * to cursor
436  * @member: the name of the list_head within the struct.
437  */
438 #define list_next_entry(pos, member) 
439     list_entry((pos)->member.next, typeof(*(pos)), member)
440 
441 /**
442  * list_prev_entry - get the prev element in list
443  * @pos:    the type * to cursor
444  * @member: the name of the list_head within the struct.
445  */
446 #define list_prev_entry(pos, member) 
447     list_entry((pos)->member.prev, typeof(*(pos)), member)
448 
449 /**
450  * list_for_each    -   iterate over a list
451  * @pos:    the &struct list_head to use as a loop cursor.
452  * @head:   the head for your list.
453  */
454 #define list_for_each(pos, head) 
455     for (pos = (head)->next; pos != (head); pos = pos->next)
456 
457 /**
458  * list_for_each_prev   -   iterate over a list backwards
459  * @pos:    the &struct list_head to use as a loop cursor.
460  * @head:   the head for your list.
461  */
462 #define list_for_each_prev(pos, head) 
463     for (pos = (head)->prev; pos != (head); pos = pos->prev)
464 
465 /**
466  * list_for_each_safe - iterate over a list safe against removal of list entry
467  * @pos:    the &struct list_head to use as a loop cursor.
468  * @n:      another &struct list_head to use as temporary storage
469  * @head:   the head for your list.
470  */
471 #define list_for_each_safe(pos, n, head) 
472     for (pos = (head)->next, n = pos->next; pos != (head); 
473         pos = n, n = pos->next)
474 
475 /**
476  * list_for_each_prev_safe - iterate over a list backwards safe against removal of list entry
477  * @pos:    the &struct list_head to use as a loop cursor.
478  * @n:      another &struct list_head to use as temporary storage
479  * @head:   the head for your list.
480  */
481 #define list_for_each_prev_safe(pos, n, head) 
482     for (pos = (head)->prev, n = pos->prev; 
483          pos != (head); 
484          pos = n, n = pos->prev)
485 
486 /**
487  * list_for_each_entry  -   iterate over list of given type
488  * @pos:    the type * to use as a loop cursor.
489  * @head:   the head for your list.
490  * @member: the name of the list_head within the struct.
491  */
492 #define list_for_each_entry(pos, head, member)                
493     for (pos = list_first_entry(head, typeof(*pos), member);    
494          &pos->member != (head);                    
495          pos = list_next_entry(pos, member))
496 
497 /**
498  * list_for_each_entry_reverse - iterate backwards over list of given type.
499  * @pos:    the type * to use as a loop cursor.
500  * @head:   the head for your list.
501  * @member: the name of the list_head within the struct.
502  */
503 #define list_for_each_entry_reverse(pos, head, member)            
504     for (pos = list_last_entry(head, typeof(*pos), member);        
505          &pos->member != (head);                    
506          pos = list_prev_entry(pos, member))
507 
508 /**
509  * list_prepare_entry - prepare a pos entry for use in list_for_each_entry_continue()
510  * @pos:    the type * to use as a start point
511  * @head:   the head of the list
512  * @member: the name of the list_head within the struct.
513  *
514  * Prepares a pos entry for use as a start point in list_for_each_entry_continue().
515  */
516 #define list_prepare_entry(pos, head, member) 
517     ((pos) ? : list_entry(head, typeof(*pos), member))
518 
519 /**
520  * list_for_each_entry_continue - continue iteration over list of given type
521  * @pos:    the type * to use as a loop cursor.
522  * @head:   the head for your list.
523  * @member: the name of the list_head within the struct.
524  *
525  * Continue to iterate over list of given type, continuing after
526  * the current position.
527  */
528 #define list_for_each_entry_continue(pos, head, member)        
529     for (pos = list_next_entry(pos, member);            
530          &pos->member != (head);                    
531          pos = list_next_entry(pos, member))
532 
533 /**
534  * list_for_each_entry_continue_reverse - iterate backwards from the given point
535  * @pos:    the type * to use as a loop cursor.
536  * @head:   the head for your list.
537  * @member: the name of the list_head within the struct.
538  *
539  * Start to iterate over list of given type backwards, continuing after
540  * the current position.
541  */
542 #define list_for_each_entry_continue_reverse(pos, head, member)        
543     for (pos = list_prev_entry(pos, member);            
544          &pos->member != (head);                    
545          pos = list_prev_entry(pos, member))
546 
547 /**
548  * list_for_each_entry_from - iterate over list of given type from the current point
549  * @pos:    the type * to use as a loop cursor.
550  * @head:   the head for your list.
551  * @member: the name of the list_head within the struct.
552  *
553  * Iterate over list of given type, continuing from current position.
554  */
555 #define list_for_each_entry_from(pos, head, member)            
556     for (; &pos->member != (head);                    
557          pos = list_next_entry(pos, member))
558 
559 /**
560  * list_for_each_entry_safe - iterate over list of given type safe against removal of list entry
561  * @pos:    the type * to use as a loop cursor.
562  * @n:      another type * to use as temporary storage
563  * @head:   the head for your list.
564  * @member: the name of the list_head within the struct.
565  */
566 #define list_for_each_entry_safe(pos, n, head, member)            
567     for (pos = list_first_entry(head, typeof(*pos), member),    
568         n = list_next_entry(pos, member);            
569          &pos->member != (head);                    
570          pos = n, n = list_next_entry(n, member))
571 
572 /**
573  * list_for_each_entry_safe_continue - continue list iteration safe against removal
574  * @pos:    the type * to use as a loop cursor.
575  * @n:      another type * to use as temporary storage
576  * @head:   the head for your list.
577  * @member: the name of the list_head within the struct.
578  *
579  * Iterate over list of given type, continuing after current point,
580  * safe against removal of list entry.
581  */
582 #define list_for_each_entry_safe_continue(pos, n, head, member)        
583     for (pos = list_next_entry(pos, member),                
584         n = list_next_entry(pos, member);                
585          &pos->member != (head);                        
586          pos = n, n = list_next_entry(n, member))
587 
588 /**
589  * list_for_each_entry_safe_from - iterate over list from current point safe against removal
590  * @pos:    the type * to use as a loop cursor.
591  * @n:      another type * to use as temporary storage
592  * @head:   the head for your list.
593  * @member: the name of the list_head within the struct.
594  *
595  * Iterate over list of given type from current point, safe against
596  * removal of list entry.
597  */
598 #define list_for_each_entry_safe_from(pos, n, head, member)            
599     for (n = list_next_entry(pos, member);                    
600          &pos->member != (head);                        
601          pos = n, n = list_next_entry(n, member))
602 
603 /**
604  * list_for_each_entry_safe_reverse - iterate backwards over list safe against removal
605  * @pos:    the type * to use as a loop cursor.
606  * @n:      another type * to use as temporary storage
607  * @head:   the head for your list.
608  * @member: the name of the list_head within the struct.
609  *
610  * Iterate backwards over list of given type, safe against removal
611  * of list entry.
612  */
613 #define list_for_each_entry_safe_reverse(pos, n, head, member)        
614     for (pos = list_last_entry(head, typeof(*pos), member),        
615         n = list_prev_entry(pos, member);            
616          &pos->member != (head);                    
617          pos = n, n = list_prev_entry(n, member))
618 
619 /**
620  * list_safe_reset_next - reset a stale list_for_each_entry_safe loop
621  * @pos:    the loop cursor used in the list_for_each_entry_safe loop
622  * @n:      temporary storage used in list_for_each_entry_safe
623  * @member: the name of the list_head within the struct.
624  *
625  * list_safe_reset_next is not safe to use in general if the list may be
626  * modified concurrently (eg. the lock is dropped in the loop body). An
627  * exception to this is if the cursor element (pos) is pinned in the list,
628  * and list_safe_reset_next is called after re-taking the lock and before
629  * completing the current iteration of the loop body.
630  */
631 #define list_safe_reset_next(pos, n, member)                
632     n = list_next_entry(pos, member)
633 
634 /*
635  * Double linked lists with a single pointer list head.
636  * Mostly useful for hash tables where the two pointer list head is
637  * too wasteful.
638  * You lose the ability to access the tail in O(1).
639  */
640 
641 #define HLIST_HEAD_INIT { .first = NULL }
642 #define HLIST_HEAD(name) struct hlist_head name = {  .first = NULL }
643 #define INIT_HLIST_HEAD(ptr) ((ptr)->first = NULL)
644 
645 static inline void INIT_HLIST_NODE(struct hlist_node *h) {
646     h->next = NULL;
647     h->pprev = NULL;
648 }
649 
650 static inline int hlist_unhashed(const struct hlist_node *h) {
651     return !h->pprev;
652 }
653 
654 static inline int hlist_empty(const struct hlist_head *h) {
655     return !h->first;
656 }
657 
658 static inline void __hlist_del(struct hlist_node *n) {
659     struct hlist_node *next = n->next;
660     struct hlist_node **pprev = n->pprev;
661     *pprev = next;
662     if (next)
663         next->pprev = pprev;
664 }
665 
666 static inline void hlist_del(struct hlist_node *n) {
667     __hlist_del(n);
668     n->next = LIST_POISON1;
669     n->pprev = LIST_POISON2;
670 }
671 
672 static inline void hlist_del_init(struct hlist_node *n) {
673     if (!hlist_unhashed(n)) {
674         __hlist_del(n);
675         INIT_HLIST_NODE(n);
676     }
677 }
678 
679 static inline void hlist_add_head(struct hlist_node *n, struct hlist_head *h) {
680     struct hlist_node *first = h->first;
681     n->next = first;
682     if (first) {
683         first->pprev = &n->next;
684     }
685     h->first = n;
686     n->pprev = &h->first;
687 }
688 
689 /* next must be != NULL */
690 static inline void hlist_add_before(struct hlist_node *n,
691         struct hlist_node *next) {
692     n->pprev = next->pprev;
693     n->next = next;
694     next->pprev = &n->next;
695     *(n->pprev) = n;
696 }
697 
698 static inline void hlist_add_behind(struct hlist_node *n,
699         struct hlist_node *prev) {
700     n->next = prev->next;
701     prev->next = n;
702     n->pprev = &prev->next;
703 
704     if (n->next) {
705         n->next->pprev = &n->next;
706     }
707 }
708 
709 /* after that we'll appear to be on some hlist and hlist_del will work */
710 static inline void hlist_add_fake(struct hlist_node *n) {
711     n->pprev = &n->next;
712 }
713 
714 /*
715  * Move a list from one list head to another. Fixup the pprev
716  * reference of the first entry if it exists.
717  */
718 static inline void hlist_move_list(struct hlist_head *old,
719         struct hlist_head *new) {
720     new->first = old->first;
721     if (new->first) {
722         new->first->pprev = &new->first;
723     }
724     old->first = NULL;
725 }
726 
727 #define hlist_entry(ptr, type, member) container_of(ptr,type,member)
728 
729 #define hlist_for_each(pos, head) 
730     for (pos = (head)->first; pos ; pos = pos->next)
731 
732 #define hlist_for_each_safe(pos, n, head) 
733     for (pos = (head)->first; pos && ({ n = pos->next; 1; }); 
734          pos = n)
735 
736 #define hlist_entry_safe(ptr, type, member) 
737     ({ typeof(ptr) ____ptr = (ptr); 
738        ____ptr ? hlist_entry(____ptr, type, member) : NULL; 
739     })
740 
741 /**
742  * hlist_for_each_entry - iterate over list of given type
743  * @pos:    the type * to use as a loop cursor.
744  * @head:   the head for your list.
745  * @member: the name of the hlist_node within the struct.
746  */
747 #define hlist_for_each_entry(pos, head, member)                
748     for (pos = hlist_entry_safe((head)->first, typeof(*(pos)), member);
749          pos;                            
750          pos = hlist_entry_safe((pos)->member.next, typeof(*(pos)), member))
751 
752 /**
753  * hlist_for_each_entry_continue - iterate over a hlist continuing after current point
754  * @pos:    the type * to use as a loop cursor.
755  * @member: the name of the hlist_node within the struct.
756  */
757 #define hlist_for_each_entry_continue(pos, member)            
758     for (pos = hlist_entry_safe((pos)->member.next, typeof(*(pos)), member);
759          pos;                            
760          pos = hlist_entry_safe((pos)->member.next, typeof(*(pos)), member))
761 
762 /**
763  * hlist_for_each_entry_from - iterate over a hlist continuing from current point
764  * @pos:    the type * to use as a loop cursor.
765  * @member: the name of the hlist_node within the struct.
766  */
767 #define hlist_for_each_entry_from(pos, member)                
768     for (; pos;                            
769          pos = hlist_entry_safe((pos)->member.next, typeof(*(pos)), member))
770 
771 /**
772  * hlist_for_each_entry_safe - iterate over list of given type safe against removal of list entry
773  * @pos:    the type * to use as a loop cursor.
774  * @n:      another &struct hlist_node to use as temporary storage
775  * @head:   the head for your list.
776  * @member: the name of the hlist_node within the struct.
777  */
778 #define hlist_for_each_entry_safe(pos, n, head, member)        
779     for (pos = hlist_entry_safe((head)->first, typeof(*pos), member);
780          pos && ({ n = pos->member.next; 1; });            
781          pos = hlist_entry_safe(n, typeof(*pos), member))
782 
783 #endif // LIST_H_

这个代码不是我写的,就是用别人现成的,具体:https://www.cnblogs.com/muahao/p/8109733.html博主的代码

测试代码:testLi.c

 1 #include <stdio.h>                                                                                    
 2 #include <stdlib.h>
 3 #include <stdbool.h>
 4 #include "list.h"
 5 
 6 #define MaxSize 10
 7 
 8 typedef struct _stu{
 9     int id;
10     bool sex;
11     char name[MaxSize];
12 
13     struct list_head list;
14 } Student;
15 
16 void creatNumStudent(Student *mylist){
17     int num = 0;
18     printf("please input you want create the number, not zero: ");
19     scanf("%d", &num);
20 
21     for(int i=num; i!=0; --i){
22         Student *tmp= (Student *)malloc(sizeof(Student));
23         printf("enter id sex and name:");
24         scanf("%d %d %s", &tmp->id, &tmp->sex, &tmp->name);
25         list_add(&(tmp->list), &(mylist->list));
26     }
27     printf("
");
28 
29     return;
30 }
31 
32 int main(int argc, char **argv){
33 
34     Student *tmp;
35     struct list_head *pos, *q;
36     //unsigned int i;
37 
38     Student mylist;
39     INIT_LIST_HEAD(&mylist.list);
40 
41     creatNumStudent(&mylist);
42 
43     printf("traversing the list using list_for_each_entry()
");
44     list_for_each_entry(tmp, &mylist.list, list)
45         if(tmp->sex){
46             printf("id= %d sex= %s name= %s
", tmp->id, "female", tmp->name);
47         }else{
48             printf("id= %d sex= %s name= %s
", tmp->id, "male", tmp->name);
49         }
50     printf("
");
51 
52     printf("deleting the list using list_for_each_safe()
");
53     list_for_each_safe(pos, q, &mylist.list){
54         tmp= list_entry(pos, Student, list);
55 
56     if(tmp->sex){
57         printf("id= %d sex= %s name= %s
", tmp->id, "female", tmp->name);
58     }else{
59         printf("id= %d sex= %s name= %s
", tmp->id, "male", tmp->name);
60     }
61         list_del(pos);
62         free(tmp);
63     }
64 
65     return 0;
66 }

测试结果:

please input you want create the number, not zero: 3   
enter id sex and name:101 0 zhangsan
enter id sex and name:102 1 lisi
enter id sex and name:103 0 wangwu

traversing the list using list_for_each_entry()
id= 103 sex= male name= wangwu
id= 102 sex= female name= lisi
id= 101 sex= male name= zhangsan

deleting the list using list_for_each_safe()
id= 103 sex= male name= wangwu
id= 102 sex= female name= lisi
id= 101 sex= male name= zhangsan

这个也是一个链表的实现,但是几乎没有实现任何的函数就实现了一个链表,主要是使用了linux的内核链表,无需自己实现,直接使用即可:由于这里的list.h文件不是自己改造的,所以目前不多说明。以下针对使用linux你和的链表使用说明如下:

1、list.h文件中几乎实现了链表的所有操作,无论是你能想到的,或者是想不到的,安全的不安全都有了,几乎不需要添加,根据个人需求,可以把不需要的删除即可

2、头文件中仅仅是实现了纯粹的链表,没有关联到数据,什么意思,也就是说改变数据的结构和类型,不影响链表的使用方法。

3、内核链表打破了普通链表中的链表和数据结合很深的缺点,大大增强了链表的使用的灵活性,一般链表的实现中数据中有链表,链表中有数据,相互包含,相互引用;但是内核链表中数据和链表是经纬分明的,可以自由组合,随时能够分离的,大大提高了链表和数据使用的灵活性,增强了链表的使用的范围,缺点就是不太容易理解。

改变数据类型:测试函数为:

 1 #include <stdio.h>
 2 #include <stdlib.h>
 3 #include <stdbool.h>
 4 #include <string.h>
 5 #include "list.h"
 6 
 7 #define MaxSize 10
 8 
 9 typedef struct _doc{
10     int id;
11     bool sex;
12     char name[MaxSize];
13     char typed[MaxSize];
14 
15     struct list_head list;
16 } Doctor;
17 
18 void creatNumStudent(Doctor *mylist){
19     int num = 0;
20     printf("please input you want create the number, not zero: ");
21     scanf("%d", &num);
22 
23     for(int i=num; i!=0; --i){
24         Doctor *tmp= (Doctor *)malloc(sizeof(Doctor));
25         printf("enter id sex and name  and typed:");
26         scanf("%d %d %s %s", &tmp->id, &tmp->sex, &tmp->name, &tmp->typed);
27         list_add(&(tmp->list), &(mylist->list));
28     }
29     printf("
");
30 
31     return;
32 }
33 
34 void outputInfo(bool sex, Doctor *tmp){
35     char str[MaxSize];
36 
37     if(sex){
38         strcpy(str, "female");
39     }else{
40         strcpy(str, "male");
41     }
42 
43     printf("id= %d sex= %s name= %s  typed= %s
", tmp->id, str, tmp->name, tmp->typed);
44 
45     return;
46 }
47 
48 int main(int argc, char **argv){
49 
50     Doctor *tmp;
51     struct list_head *pos, *q;
52     //unsigned int i;
53 
54     Doctor mylist;
55     INIT_LIST_HEAD(&mylist.list);
56 
57     creatNumStudent(&mylist);
58 
59     printf("traversing the list using list_for_each_entry()
");
60     list_for_each_entry(tmp, &mylist.list, list){
61         outputInfo(tmp->sex, tmp);
62     }
63     printf("
");                                                                                                
64 
65     printf("deleting the list using list_for_each_safe()
");
66     list_for_each_safe(pos, q, &mylist.list){
67         tmp= list_entry(pos, Doctor, list);
68 
69         outputInfo(tmp->sex, tmp);
70 
71         list_del(pos);
72         free(tmp);
73     }
74 
75     return 0;
76 }

测试结果为:

please input you want create the number, not zero: 4
enter id sex and name  and typed:101 0 zhangsan tooth
enter id sex and name  and typed:102 1 lisi nose
enter id sex and name  and typed:103 0 wangwu eye
enter id sex and name  and typed:104 1 zhaoliu mouth

traversing the list using list_for_each_entry()
id= 104 sex= female name= zhaoliu  typed= mouth
id= 103 sex= male name= wangwu  typed= eye
id= 102 sex= female name= lisi  typed= nose
id= 101 sex= male name= zhangsan  typed= tooth

deleting the list using list_for_each_safe()
id= 104 sex= female name= zhaoliu  typed= mouth
id= 103 sex= male name= wangwu  typed= eye
id= 102 sex= female name= lisi  typed= nose
id= 101 sex= male name= zhangsan  typed= tooth

说明:1、很明显看到,更换了数据的类型,由Student变成了Doctor,成员增加了一个,

      2、优化了性别判别的方法,代码稍微重构一下

   3、list.h中的链表的实现丝毫没有任何的改变,就让链表重新实现了新的数据的应用,是不是觉得很神奇,很不可思议,这就对了,普通人怎么能和linux的内核开发大神想的一样的呢

      4、还有一个要注意的是,这里其实也实现了数据和链表的互相隔离,从而能达到使用更加灵活的目的了。

人就像是被蒙着眼推磨的驴子,生活就像一条鞭子;当鞭子抽到你背上时,你就只能一直往前走,虽然连你也不知道要走到什么时候为止,便一直这么坚持着。
原文地址:https://www.cnblogs.com/guochaoxxl/p/15168231.html