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

Posted 天道酬勤

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了第三十二课 linux内核链表剖析相关的知识,希望对你有一定的参考价值。

 

 

 

 

__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);     \\
以上是关于第三十二课   linux内核链表剖析的主要内容,如果未能解决你的问题,请参考以下文章

python第三十二课——栈

第三十二课Qt中的文件操作

AGG第三十二课 renderer_outline_aa更快的渲染线段算法

Linux内核链表剖析

第32课 Linux内核链表剖析

Linux(内核剖析):14---内核数据结构之链表(struct list_head)