contributed by < flawless0714 >
Linux source code version: 4.20.13
iterator
為用來走訪 list 的指標),看到 macro 名稱就可以直覺知道其功用,相較之下,看到 for 迴圈後還需要思考其中初始值、條件式及遞增式的操作。NetLabel
此為 kernel 中用於為通訊封包(network, IPC…)附加標籤(security label)用的 framework。
__list_add_rcu
此 macro 用於將新節點插入 list 中。考慮以下程式碼,雖然只是簡單的節點插入,但其中為什麼要用 rcu_assign_pointer()
來 assign 節點呢?這是為了保證在這之前的 assigments 一定會在執行此 assignment (rcu_assign_pointer()
)之前完成,還有避免編譯器最佳化造成過早完成 assignment (此舉可能會造成 reader 拿到更新到一半的資料,從程式碼中可以看到13、14行正在初始化新節點,假如 assign 在這兩行之前完成,則 reader 就有可能拿到空指標)。
root_task_group
、初始化每個 CPU 的 rq queue、將 init_task
行程轉變為 idle 行程)。其中 list_add
這個 macro 把 root_task_group.list
(系統中所有 task 都屬於此 group)這個鏈結插入 task_groups
(插入後 task_groups 會從原本的 task_groups.next = task_groups
(LIST_HEAD_INIT
這個 macro 做的,它會把新建立的節點的 prev 及 next 指標指向自己)變成 task_groups.next = root_task_group.list
。這邊我們就可以聯想到 container_of
這個 macro 的用途,因為 list_head 在 Linux kernel 中都只被當作結構體的成員,所以我們才會需要這個 macro 來做 offset,找到現在 linked list 所指到的成員的本體,例如本文中的 root_task_group
。
warning: comparison of distinct pointer types lacks a cast
,此段警告為當比較兩個不同型態的指標時未使用 cast 轉型。如此就可以發現程式碼中的 typo 等問題了。此段程式碼原理為先以參數 type
宣告一變數 a,再以令個參數 x
宣告一變數 b
,之後再對兩個變數做 address of
的比較(此處假如兩者資料型態不同,編譯器就會跳警告了),然後把結果轉為 void
型態,以使得此段程式在編譯器最佳化時就被刪除,以免在執行時期遭到濫用。list.h
還定義一系列操作,為什麼呢?這些有什麼益處?LIST_POISONING
這樣的設計有何意義?list_for_each_safe
和 list_for_each
的差異在哪?"safe" 在執行時期的影響為何?@
符號,這有何意義?你能否應用在後續的程式開發呢?
tests/
目錄底下的 unit test 的作用為何?就軟體工程來說的精神為何?tests/
目錄的 unit test 可如何持續精進和改善呢?rcu_access_pointer()
, rcu_dereference()
)linux2019