• linux 内核链表详解


    目录

    1. 老生常谈的两个宏(Linux)

    offset

    测试demo

    container_of

    ({})

    Typeof

    推算结构体起始地址

     测试demo

    2. Linux内核链表剖析

    移植linux内核链表,使其适用于非GNU编译器

    Linux内核链表的位置和依赖

    移植时的注意事项

    移植好的LinuxList.h

    分析linux内核中链表的基本实现

    linux内核链表的实现

    linux内核链表的结点定义 

    测试demo


    C/C++Linux服务器开发/后台架构师【零声教育】-学习视频教程-腾讯课堂

    1. 老生常谈的两个宏(Linux)

    offset

    1. //offsetof用于计算TYPE结构体中MEMBER成员的偏移位置
    2. #ifndef offsetof
    3. #define offsetof(TYPE, MEMBER) ((size_t)&((TYPE*)0)->MEMBER)
    4. #endif

    测试demo

    1. #include <stdio.h>
    2. #ifndef offsetof
    3. #define offsetof(TYPE, MEMBER) ((size_t)&((TYPE*)0)->MEMBER)
    4. #endif
    5. struct ST
    6. {
    7.     int i;     // 0
    8.     int j;     // 4
    9.     char c;    // 8
    10. };
    11. void func(struct ST* pst)
    12. {
    13.     int* pi = &(pst->i);    //  0
    14.     int* pj = &(pst->j);    //  4
    15.     char* pc = &(pst->c);   //  8
    16.     printf("pst = %p\n", pst);
    17.     printf("pi = %p\n", pi);
    18.     printf("pj = %p\n", pj);
    19.     printf("pc = %p\n", pc);
    20. }
    21. int main()
    22. {
    23.     struct ST s = {0};
    24.     func(&s);
    25.     func(NULL);
    26.     printf("offset i: %d\n", offsetof(struct ST, i));
    27.     printf("offset j: %d\n", offsetof(struct ST, j));
    28.     printf("offset c: %d\n", offsetof(struct ST, c));
    29.     return 0;
    30. }

     

    container_of

    ({})

    Typeof

    推算结构体起始地址

    1.typeof(((type*)0)->member)*得到成员数据类型的指针,ptr为指向结构体成员的指针。这样写可进行类型检查。

    2.((char*)__mptr - offsetof(type, member));结构体成员的地址-成员的偏移量来算出结构体的起始地址。

    1. //推算结构体起始地址
    2. #ifndef container_of
    3. #define container_of(ptr, type, member) ({          \
    4.         const typeof(((type*)0)->member)* __mptr = (ptr);   \
    5.         (type*)((char*)__mptr - offsetof(type, member)); })
    6. #endif

     测试demo

    1. #include <stdio.h>
    2. //offsetof用于计算TYPE结构体中MEMBER成员的偏移位置
    3. #ifndef offsetof
    4. #define offsetof(TYPE, MEMBER) ((size_t)&((TYPE*)0)->MEMBER)
    5. #endif
    6. //推算结构体起始地址
    7. #ifndef container_of
    8. #define container_of(ptr, type, member) ({ \
    9. const typeof(((type*)0)->member)* __mptr = (ptr); \
    10. (type*)((char*)__mptr - offsetof(type, member)); })
    11. #endif
    12. //修改后的container_of
    13. #ifndef container_of_new
    14. #define container_of_new(ptr, type, member) ((type*)((char*)(ptr) - offsetof(type, member)))
    15. #endif
    16. struct ST
    17. {
    18. int i; // 0
    19. int j; // 4
    20. char c; // 8
    21. };
    22. int main()
    23. {
    24. struct ST s = {0};
    25. char* pc = &s.c;
    26. struct ST* pst = container_of(pc, struct ST, c);
    27. printf("&s = %p\n", &s);
    28. printf("pst = %p\n", pst);
    29. return 0;
    30. }

     

     

    2. Linux内核链表剖析

    移植linux内核链表,使其适用于非GNU编译器

    Linux内核链表的位置和依赖

    移植时的注意事项

     

    移植好的LinuxList.h

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

    分析linux内核中链表的基本实现

    linux内核链表的实现

    1. 带头结点的双向循环链表,且头结点为表中成员。
    2. 头结点的next指针指向首结点。
    3. 头结点的prev指针指向尾节点

    linux内核链表的结点定义 

    1. struct list_head {
    2. struct list_head *next, *prev;
    3. };

    使用list_head自定义链表结点来存放数据

    1. struct Node
    2. {
    3. struct list_head head;
    4. int value;
    5. };

    测试demo

    Main.c

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

  • 相关阅读:
    [HDLBits] Fsm2s
    C++ Mysql对接实现登录注册
    基于阿里云 Serverless 快速部署 function 的极致体验
    【C/C++】string类的使用&&探索string底层原理
    BigDecimal使用
    C语言 | 类型的基本归类
    JavaScript系列从入门到精通系列第七篇:JavaScrip当中的运算符,主要涉及JavaScript当中的六大数据类型的四则运算
    向量化操作简介和Pandas、Numpy示例
    linux设置ssh免密登录
    【vue】下载导出excel
  • 原文地址:https://blog.csdn.net/kakaka666/article/details/127834244