1. 程式人生 > 其它 >RT-Thread - rtservice.h分析

RT-Thread - rtservice.h分析

  本筆記作為自己的學習記錄,純屬個人理解。

  rtservice.h是 RT_Thread中關於雙向連結串列和單相連結串列的相關定義。

  雙向連結串列主要實現了節點插入、刪除、是否為空、計算連結串列長度的功能。這裡主要分析一下是否為空、計算連結串列長度的功能。

  是否為空:

1 rt_inline int rt_list_isempty(const rt_list_t *l)
2 {
3     return l->next == l;
4 }

  計算連結串列長度:

 1 rt_inline unsigned int rt_list_len(const rt_list_t *l)
2 { 3 unsigned int len = 0; 4 const rt_list_t *p = l; 5 while (p->next != l) 6 { 7 p = p->next; 8 len ++; 9 } 10 11 return len; 12 }

  這裡輸入的變數 const rt_list_t *l 其實是一個連結串列節點,這個節點作為連結串列頭節點在使用時候建立,並初始化為指向本身,這個節點是一直存在的,也即連結串列至少有一個頭節點存在。理解了這一點上邊兩個函式就好理解了。

  下面在看一個重要的巨集 rt_list_entry,這個巨集本質是 rt_container_of,獲取list的擁有者的入口地址。

1 #define rt_list_entry(node, type, member) \
2     rt_container_of(node, type, member)
1 #define rt_container_of(ptr, type, member) \
2     ((type *)((char *)(ptr) - (unsigned long)(&((type *)0)->member)))

  例如如下一個結構體

1
struct obj { 2 uint8_t m1; 3 uint8_t m2; 4 uint8_t m3; 5 uint8_t m4; 6 rt_list_t list; 7 ... 8 };

  (char *)(ptr):ptr 是一個指向list的指標,轉換為一個char 型別的指標;

  (type *)0:等價於將0轉換為一個指向 obj 型別變數的指標,且變數儲存地址為0;

  (type *)0)->member:獲取 obj 型別的member元素,即 list 元素;

  &((type *)0)->member:獲取 obj 型別的 list 元素的地址,由於首地址為0,所以這個地址也是 list 元素相對於結構體變數的儲存地址的偏移地址

  (char *)(ptr) - (unsigned long)(&((type *)0)->member)):指向list的指標 減去 偏移地址,就指向了 list 元素所在結構體的儲存地址,也即得到了結構體變數指標

  其記憶體地址空間如下:

   

  單相連結串列的內容相對好理解一些,就不再贅述了。下面是rtservice.h的部分程式碼,僅供參考

  1 #define rt_container_of(ptr, type, member) \
  2     ((type *)((char *)(ptr) - (unsigned long)(&((type *)0)->member)))
  3     
  4 #define RT_LIST_OBJECT_INIT(object) { &(object), &(object) }
  5 
  6 rt_inline void rt_list_init(rt_list_t *l)
  7 {
  8     l->next = l->prev = l;
  9 }
 10 
 11 rt_inline void rt_list_insert_after(rt_list_t *l, rt_list_t *n)
 12 {
 13     l->next->prev = n;
 14     n->next = l->next;
 15 
 16     l->next = n;
 17     n->prev = l;
 18 }
 19 
 20 rt_inline void rt_list_insert_before(rt_list_t *l, rt_list_t *n)
 21 {
 22     l->prev->next = n;
 23     n->prev = l->prev;
 24 
 25     l->prev = n;
 26     n->next = l;
 27 }
 28 
 29 rt_inline void rt_list_remove(rt_list_t *n)
 30 {
 31     n->next->prev = n->prev;
 32     n->prev->next = n->next;
 33 
 34     n->next = n->prev = n;
 35 }
 36 
 37 rt_inline int rt_list_isempty(const rt_list_t *l)
 38 {
 39     return l->next == l;
 40 }
 41 
 42 rt_inline unsigned int rt_list_len(const rt_list_t *l)
 43 {
 44     unsigned int len = 0;
 45     const rt_list_t *p = l;
 46     while (p->next != l)
 47     {
 48         p = p->next;
 49         len ++;
 50     }
 51 
 52     return len;
 53 }
 54 
 55 #define rt_list_entry(node, type, member) \
 56     rt_container_of(node, type, member)
 57 
 58 #define rt_list_for_each(pos, head) \
 59     for (pos = (head)->next; pos != (head); pos = pos->next)
 60 
 61 rt_inline void rt_slist_init(rt_slist_t *l)
 62 {
 63     l->next = RT_NULL;
 64 }
 65 
 66 rt_inline void rt_slist_append(rt_slist_t *l, rt_slist_t *n)
 67 {
 68     struct rt_slist_node *node;
 69 
 70     node = l;
 71     while (node->next) node = node->next;
 72 
 73     /* append the node to the tail */
 74     node->next = n;
 75     n->next = RT_NULL;
 76 }
 77 
 78 rt_inline void rt_slist_insert(rt_slist_t *l, rt_slist_t *n)
 79 {
 80     n->next = l->next;
 81     l->next = n;
 82 }
 83 
 84 rt_inline unsigned int rt_slist_len(const rt_slist_t *l)
 85 {
 86     unsigned int len = 0;
 87     const rt_slist_t *list = l->next;
 88     while (list != RT_NULL)
 89     {
 90         list = list->next;
 91         len ++;
 92     }
 93 
 94     return len;
 95 }
 96 
 97 rt_inline rt_slist_t *rt_slist_remove(rt_slist_t *l, rt_slist_t *n)
 98 {
 99     /* remove slist head */
100     struct rt_slist_node *node = l;
101     while (node->next && node->next != n) node = node->next;
102 
103     /* remove node */
104     if (node->next != (rt_slist_t *)0) node->next = node->next->next;
105 
106     return l;
107 }
108 
109 rt_inline rt_slist_t *rt_slist_first(rt_slist_t *l)
110 {
111     return l->next;
112 }
113 
114 rt_inline rt_slist_t *rt_slist_tail(rt_slist_t *l)
115 {
116     while (l->next) l = l->next;
117 
118     return l;
119 }
120 
121 rt_inline rt_slist_t *rt_slist_next(rt_slist_t *n)
122 {
123     return n->next;
124 }
125 
126 rt_inline int rt_slist_isempty(rt_slist_t *l)
127 {
128     return l->next == RT_NULL;
129 }
130 
131 #define rt_slist_entry(node, type, member) \
132     rt_container_of(node, type, member)