码迷,mamicode.com
首页 > 系统相关 > 详细

第三十二课 linux内核链表剖析

时间:2018-09-16 17:14:51      阅读:187      评论:0      收藏:0      [点我收藏+]

标签:except   联合   img   delete   拷贝   led   spec   c语言   not   

技术分享图片

 

技术分享图片

 

 技术分享图片

 

__builtin_prefetch是gcc扩展的,用来提高访问效率,需要硬件的支持。

在标准C语言中是不允许static inline联合使用的。

删除依赖的头文件,将相应的结构拷贝到LinuxList.h中:

技术分享图片

此外,需要将container_of改写成我们自己的形式。

1 #define container_of(ptr, type, member) ((type *)((char *)ptr - offsetof(type,member)))

 

移植后的内核链表如下:

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

这个文件在linux内核中是list.h文件。

技术分享图片

 

 技术分享图片

 

数据由使用链表的人来定义。

技术分享图片

 

 技术分享图片

上图中的l为头结点,类型转换后list指向了l中的head。

INIT_LIST_HEAD在初始化头结点的时候让自己形成了双向循环链表。

技术分享图片

技术分享图片

 

list_add图解:

技术分享图片

 

 技术分享图片

 

 删除操作图解:

技术分享图片

 

 技术分享图片

 

遍历就是一个for循环,prefetch是gcc内置的宏,为了提高效率,移植之后,我们用不到。

测试程序如下:

 1 #include <stdio.h>
 2 #include "LinuxList.h"
 3 
 4 void list_demo_1()
 5 {
 6     struct Node
 7     {
 8         struct list_head head;
 9         int value;
10     };
11 
12     struct Node l = {0};
13     struct list_head* list = (struct list_head*)&l;
14     struct list_head* slider = NULL;
15     int i = 0;
16 
17     INIT_LIST_HEAD(list);
18 
19     printf("Insert begin ...\n");
20 
21     for(i=0; i<5; i++)
22     {
23         struct Node* n = (struct Node*)malloc(sizeof(struct Node));
24 
25         n->value = i;
26 
27         list_add_tail((struct list_head*)n, list);
28     }
29 
30     list_for_each(slider, list)
31     {
32         printf("%d\n", ((struct Node*)slider)->value);
33     }
34 
35     printf("Insert end ...\n");
36 
37     printf("Delete begin ...\n");
38 
39     list_for_each(slider, list)
40     {
41         if( ((struct Node*)slider)->value == 3 )
42         {
43             list_del(slider);
44             free(slider);
45             break;
46         }
47     }
48 
49     list_for_each(slider, list)
50     {
51         printf("%d\n", ((struct Node*)slider)->value);
52     }
53 
54     printf("Delete end ...\n");
55 }
56 
57 int main()
58 {
59     list_demo_1();
60 
61 
62     return 0;
63 }

结果如下:

技术分享图片

 

上面的程序中链表结构在我们的结构的开头处,所以类似于32行的强制类型转换可以直接用,这是没有问题的,但是如果我们的自定义数据在开头处呢,这就不能用强制类型转换了。

示例:

  1 #include <stdio.h>
  2 #include "LinuxList.h"
  3 
  4 void list_demo_1()
  5 {
  6     struct Node
  7     {
  8         struct list_head head;
  9         int value;
 10     };
 11 
 12     struct Node l = {0};
 13     struct list_head* list = (struct list_head*)&l;
 14     struct list_head* slider = NULL;
 15     int i = 0;
 16 
 17     INIT_LIST_HEAD(list);
 18 
 19     printf("Insert begin ...\n");
 20 
 21     for(i=0; i<5; i++)
 22     {
 23         struct Node* n = (struct Node*)malloc(sizeof(struct Node));
 24 
 25         n->value = i;
 26 
 27         list_add_tail((struct list_head*)n, list);
 28     }
 29 
 30     list_for_each(slider, list)
 31     {
 32         printf("%d\n", ((struct Node*)slider)->value);
 33     }
 34 
 35     printf("Insert end ...\n");
 36 
 37     printf("Delete begin ...\n");
 38 
 39     list_for_each(slider, list)
 40     {
 41         if( ((struct Node*)slider)->value == 3 )
 42         {
 43             list_del(slider);
 44             free(slider);
 45             break;
 46         }
 47     }
 48 
 49     list_for_each(slider, list)
 50     {
 51         printf("%d\n", ((struct Node*)slider)->value);
 52     }
 53 
 54     printf("Delete end ...\n");
 55 }
 56 
 57 void list_demo_2()
 58 {
 59     struct Node
 60     {
 61         int value;
 62         struct list_head head;
 63     };
 64 
 65     struct Node l = {0};
 66     struct list_head* list = &l.head;
 67     struct list_head* slider = NULL;
 68     int i = 0;
 69 
 70     INIT_LIST_HEAD(list);
 71 
 72     printf("Insert begin ...\n");
 73 
 74     for(i=0; i<5; i++)
 75     {
 76         struct Node* n = (struct Node*)malloc(sizeof(struct Node));
 77 
 78         n->value = i;
 79 
 80         list_add(&n->head, list);
 81     }
 82 
 83     list_for_each(slider, list)
 84     {
 85         printf("%d\n", list_entry(slider, struct Node, head)->value);
 86     }
 87 
 88     printf("Insert end ...\n");
 89 
 90 
 91     printf("Delete begin ...\n");
 92 
 93     list_for_each(slider, list)
 94     {
 95         struct Node* n = list_entry(slider, struct Node, head);
 96 
 97         if( n->value == 3 )
 98         {
 99             list_del(slider);
100             free(n);
101             break;
102         }
103     }
104 
105     list_for_each(slider, list)
106     {
107         printf("%d\n", list_entry(slider, struct Node, head)->value);
108     }
109 
110     printf("Delete end ...\n");
111 }
112 
113 int main()
114 {
115     list_demo_1();
116 
117     list_demo_2();
118 
119     return 0;
120 }

在demo2中,我们没有用强制类型转换(这时也不能使用强制类型转换),而是使用了list_entry,这个宏内部使用了container_of。使用list_entry之后就能得到我们自定义的节点的指针了。

运行结果如下:

技术分享图片

 

 

小结:

技术分享图片

 

第三十二课 linux内核链表剖析

标签:except   联合   img   delete   拷贝   led   spec   c语言   not   

原文地址:https://www.cnblogs.com/wanmeishenghuo/p/9656563.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!