Linux核心API¶
列表管理函式¶
-
void INIT_LIST_HEAD(struct list_head *list)¶
初始化list_head結構
引數
struct list_head *list要初始化的list_head結構。
描述
初始化list_head使其指向自身。如果是列表頭,則結果是一個空列表。
-
void list_add(struct list_head *new, struct list_head *head)¶
新增一個新條目
引數
struct list_head *new要新增的新條目
struct list_head *head在其後新增的列表頭
描述
在指定的頭部之後插入一個新條目。 這對於實現堆疊很有用。
-
void list_add_tail(struct list_head *new, struct list_head *head)¶
新增一個新條目
引數
struct list_head *new要新增的新條目
struct list_head *head在其前新增的列表頭
描述
在指定的頭部之前插入一個新條目。 這對於實現佇列很有用。
-
void list_del(struct list_head *entry)¶
從列表中刪除條目。
-
void list_replace(struct list_head *old, struct list_head *new)¶
用新條目替換舊條目
引數
struct list_head *old要替換的元素
struct list_head *new要插入的新元素
描述
如果 old 為空,則將被覆蓋。
-
void list_replace_init(struct list_head *old, struct list_head *new)¶
用新條目替換舊條目並初始化舊條目
引數
struct list_head *old要替換的元素
struct list_head *new要插入的新元素
描述
如果 old 為空,則將被覆蓋。
-
void list_swap(struct list_head *entry1, struct list_head *entry2)¶
用entry2替換entry1,並在entry2的位置重新新增entry1
引數
struct list_head *entry1放置entry2的位置
struct list_head *entry2放置entry1的位置
-
void list_del_init(struct list_head *entry)¶
從列表中刪除條目並重新初始化它。
引數
struct list_head *entry要從列表中刪除的元素。
-
void list_move(struct list_head *list, struct list_head *head)¶
從一個列表刪除並作為另一個列表的頭部新增
引數
struct list_head *list要移動的條目
struct list_head *head將位於我們的條目之前的頭部
-
void list_move_tail(struct list_head *list, struct list_head *head)¶
從一個列表刪除並作為另一個列表的尾部新增
引數
struct list_head *list要移動的條目
struct list_head *head將跟隨我們的條目的頭部
-
void list_bulk_move_tail(struct list_head *head, struct list_head *first, struct list_head *last)¶
將列表的一個子段移動到它的尾部
引數
struct list_head *head將跟隨我們的條目的頭部
struct list_head *first要移動的第一個條目
struct list_head *last要移動的最後一個條目,可以與第一個條目相同
描述
將 first 和包括 last 之間的所有條目移動到 head 之前。所有三個條目必須屬於同一個連結串列。
-
int list_is_first(const struct list_head *list, const struct list_head *head)¶
測試 list 是否為列表 head 中的第一個條目
引數
const struct list_head *list要測試的條目
const struct list_head *head列表的頭部
-
int list_is_last(const struct list_head *list, const struct list_head *head)¶
測試 list 是否為列表 head 中的最後一個條目
引數
const struct list_head *list要測試的條目
const struct list_head *head列表的頭部
-
int list_is_head(const struct list_head *list, const struct list_head *head)¶
測試 list 是否為列表 head
引數
const struct list_head *list要測試的條目
const struct list_head *head列表的頭部
-
int list_empty(const struct list_head *head)¶
測試列表是否為空
引數
const struct list_head *head要測試的列表。
-
void list_del_init_careful(struct list_head *entry)¶
從列表中刪除條目並重新初始化它。
引數
struct list_head *entry要從列表中刪除的元素。
描述
這與 list_del_init() 相同,除了設計用於與 list_empty_careful() 一起使用,以保證其他記憶體操作的順序。
在 list_del_init_careful() 之前完成的任何記憶體操作都保證在 list_empty_careful() 測試後可見。
-
int list_empty_careful(const struct list_head *head)¶
測試列表是否為空且未被修改
引數
const struct list_head *head要測試的列表
描述
測試列表是否為空 _and_ 檢查是否沒有其他CPU可能正在修改任何成員(next或prev)
注意
如果沒有同步,使用 list_empty_careful() 只能在可以對列表條目執行的唯一活動是 list_del_init() 的情況下是安全的。例如,如果另一個CPU可以重新 list_add() 它,則不能使用它。
-
void list_rotate_left(struct list_head *head)¶
將列表向左旋轉
引數
struct list_head *head列表的頭部
-
void list_rotate_to_front(struct list_head *list, struct list_head *head)¶
將列表旋轉到特定專案。
引數
struct list_head *list所需的列表的新頭部。
struct list_head *head列表的頭部。
描述
旋轉列表,使 list 成為列表的新頭部。
-
int list_is_singular(const struct list_head *head)¶
測試列表是否只有一個條目。
引數
const struct list_head *head要測試的列表。
-
void list_cut_position(struct list_head *list, struct list_head *head, struct list_head *entry)¶
將列表切割成兩個
引數
struct list_head *list一個用於新增所有已刪除條目的新列表
struct list_head *head一個包含條目的列表
struct list_head *entry頭部中的一個條目,可以是頭部本身,如果是這樣,我們將不會切割列表
描述
此助手將 head 的初始部分(直到幷包括 entry)從 head 移動到 list。您應該將已知位於 head 上的元素傳遞給 entry。list 應該是一個空列表或一個您不介意丟失其資料的列表。
-
void list_cut_before(struct list_head *list, struct list_head *head, struct list_head *entry)¶
在給定條目之前將連結串列剪下成兩部分
引數
struct list_head *list一個用於新增所有已刪除條目的新列表
struct list_head *head一個包含條目的列表
struct list_head *entryhead 中的一個條目,可以是 head 本身
描述
此輔助函式將 **head** 的初始部分(直到但不包括 **entry**)從 **head** 移動到 **list**。 你應該傳入一個你確定在 **head** 上的元素 **entry**。**list** 應該是一個空連結串列或者一個你不在意丟失資料的連結串列。 如果 **entry** == **head**,則 **head** 上的所有條目都會移動到 **list**。
-
void list_splice(const struct list_head *list, struct list_head *head)¶
連線兩個連結串列,此函式設計用於棧
引數
const struct list_head *list要新增的新連結串列。
struct list_head *head在第一個連結串列中新增的位置。
-
void list_splice_tail(struct list_head *list, struct list_head *head)¶
連線兩個連結串列,每個連結串列都是一個佇列
引數
struct list_head *list要新增的新連結串列。
struct list_head *head在第一個連結串列中新增的位置。
-
void list_splice_init(struct list_head *list, struct list_head *head)¶
連線兩個連結串列並重新初始化空連結串列。
引數
struct list_head *list要新增的新連結串列。
struct list_head *head在第一個連結串列中新增的位置。
描述
**list** 處的連結串列被重新初始化
-
void list_splice_tail_init(struct list_head *list, struct list_head *head)¶
連線兩個連結串列並重新初始化空連結串列
引數
struct list_head *list要新增的新連結串列。
struct list_head *head在第一個連結串列中新增的位置。
描述
每個連結串列都是一個佇列。**list** 處的連結串列被重新初始化
-
list_entry¶
list_entry (ptr, type, member)
獲取此條目的結構體
引數
ptrstruct list_head指標。type嵌入此結構的結構體型別。
member結構體中 list_head 的名稱。
-
list_first_entry¶
list_first_entry (ptr, type, member)
從連結串列中獲取第一個元素
引數
ptr從中獲取元素的連結串列頭。
type嵌入此結構的結構體型別。
member結構體中 list_head 的名稱。
描述
請注意,預期連結串列不為空。
-
list_last_entry¶
list_last_entry (ptr, type, member)
從連結串列中獲取最後一個元素
引數
ptr從中獲取元素的連結串列頭。
type嵌入此結構的結構體型別。
member結構體中 list_head 的名稱。
描述
請注意,預期連結串列不為空。
-
list_first_entry_or_null¶
list_first_entry_or_null (ptr, type, member)
從連結串列中獲取第一個元素
引數
ptr從中獲取元素的連結串列頭。
type嵌入此結構的結構體型別。
member結構體中 list_head 的名稱。
描述
請注意,如果連結串列為空,則返回 NULL。
-
list_next_entry¶
list_next_entry (pos, member)
獲取連結串列中的下一個元素
引數
pos型別 * 指向遊標
member結構體中 list_head 的名稱。
-
list_next_entry_circular¶
list_next_entry_circular (pos, head, member)
獲取連結串列中的下一個元素
引數
pos型別 * 指向遊標。
head從中獲取元素的連結串列頭。
member結構體中 list_head 的名稱。
描述
如果 pos 是最後一個元素,則迴繞(返回第一個元素)。請注意,預期連結串列不為空。
-
list_prev_entry¶
list_prev_entry (pos, member)
獲取連結串列中的上一個元素
引數
pos型別 * 指向遊標
member結構體中 list_head 的名稱。
-
list_prev_entry_circular¶
list_prev_entry_circular (pos, head, member)
獲取連結串列中的上一個元素
引數
pos型別 * 指向遊標。
head從中獲取元素的連結串列頭。
member結構體中 list_head 的名稱。
描述
如果 pos 是第一個元素,則迴繞(返回最後一個元素)。請注意,預期連結串列不為空。
-
list_for_each¶
list_for_each (pos, head)
迭代連結串列
引數
posstruct list_head用作循環遊標。head連結串列的頭部。
-
list_for_each_rcu¶
list_for_each_rcu (pos, head)
以 RCU 安全的方式迭代連結串列
引數
posstruct list_head用作循環遊標。head連結串列的頭部。
-
list_for_each_continue¶
list_for_each_continue (pos, head)
繼續迭代連結串列
引數
posstruct list_head用作循環遊標。head連結串列的頭部。
描述
繼續迭代連結串列,在當前位置之後繼續。
-
list_for_each_prev¶
list_for_each_prev (pos, head)
向後迭代連結串列
引數
posstruct list_head用作循環遊標。head連結串列的頭部。
-
list_for_each_safe¶
list_for_each_safe (pos, n, head)
迭代連結串列,防止刪除連結串列條目
引數
posstruct list_head用作循環遊標。n另一個
struct list_head用作臨時儲存head連結串列的頭部。
-
list_for_each_prev_safe¶
list_for_each_prev_safe (pos, n, head)
向後迭代連結串列,防止刪除連結串列條目
引數
posstruct list_head用作循環遊標。n另一個
struct list_head用作臨時儲存head連結串列的頭部。
-
size_t list_count_nodes(struct list_head *head)¶
計算連結串列中的節點數
引數
struct list_head *head連結串列的頭部。
-
list_entry_is_head¶
list_entry_is_head (pos, head, member)
測試條目是否指向連結串列的頭部
引數
pos型別 * 指向遊標
head連結串列的頭部。
member結構體中 list_head 的名稱。
-
list_for_each_entry¶
list_for_each_entry (pos, head, member)
迭代給定型別的連結串列
引數
pos用作循環遊標的 型別 *。
head連結串列的頭部。
member結構體中 list_head 的名稱。
-
list_for_each_entry_reverse¶
list_for_each_entry_reverse (pos, head, member)
向後迭代給定型別的連結串列。
引數
pos用作循環遊標的 型別 *。
head連結串列的頭部。
member結構體中 list_head 的名稱。
-
list_prepare_entry¶
list_prepare_entry (pos, head, member)
準備一個 pos 條目以用於
list_for_each_entry_continue()
引數
pos用作起始點的 型別 *
head列表的頭部
member結構體中 list_head 的名稱。
描述
準備一個 pos 條目,用作 list_for_each_entry_continue() 中的起始點。
-
list_for_each_entry_continue¶
list_for_each_entry_continue (pos, head, member)
繼續迭代給定型別的連結串列
引數
pos用作循環遊標的 型別 *。
head連結串列的頭部。
member結構體中 list_head 的名稱。
描述
繼續迭代給定型別的連結串列,在當前位置之後繼續。
-
list_for_each_entry_continue_reverse¶
list_for_each_entry_continue_reverse (pos, head, member)
從給定的點向後迭代
引數
pos用作循環遊標的 型別 *。
head連結串列的頭部。
member結構體中 list_head 的名稱。
描述
開始向後迭代給定型別的連結串列,在當前位置之後繼續。
-
list_for_each_entry_from¶
list_for_each_entry_from (pos, head, member)
從當前點迭代給定型別的連結串列
引數
pos用作循環遊標的 型別 *。
head連結串列的頭部。
member結構體中 list_head 的名稱。
描述
迭代給定型別的連結串列,從當前位置繼續。
-
list_for_each_entry_from_reverse¶
list_for_each_entry_from_reverse (pos, head, member)
從當前點向後迭代給定型別的連結串列
引數
pos用作循環遊標的 型別 *。
head連結串列的頭部。
member結構體中 list_head 的名稱。
描述
向後迭代給定型別的連結串列,從當前位置繼續。
-
list_for_each_entry_safe¶
list_for_each_entry_safe (pos, n, head, member)
迭代給定型別的連結串列,防止刪除連結串列條目
引數
pos用作循環遊標的 型別 *。
n另一個 型別 * 用作臨時儲存
head連結串列的頭部。
member結構體中 list_head 的名稱。
-
list_for_each_entry_safe_continue¶
list_for_each_entry_safe_continue (pos, n, head, member)
繼續連結串列迭代,防止刪除
引數
pos用作循環遊標的 型別 *。
n另一個 型別 * 用作臨時儲存
head連結串列的頭部。
member結構體中 list_head 的名稱。
描述
迭代給定型別的連結串列,在當前點之後繼續,防止刪除連結串列條目。
-
list_for_each_entry_safe_from¶
list_for_each_entry_safe_from (pos, n, head, member)
從當前點迭代連結串列,防止刪除
引數
pos用作循環遊標的 型別 *。
n另一個 型別 * 用作臨時儲存
head連結串列的頭部。
member結構體中 list_head 的名稱。
描述
迭代給定型別的連結串列,從當前點開始,防止刪除連結串列條目。
-
list_for_each_entry_safe_reverse¶
list_for_each_entry_safe_reverse (pos, n, head, member)
向後迭代連結串列,防止刪除
引數
pos用作循環遊標的 型別 *。
n另一個 型別 * 用作臨時儲存
head連結串列的頭部。
member結構體中 list_head 的名稱。
描述
向後迭代給定型別的連結串列,防止刪除連結串列條目。
-
list_safe_reset_next¶
list_safe_reset_next (pos, n, member)
重置過時的 list_for_each_entry_safe 迴圈
引數
poslist_for_each_entry_safe 迴圈中使用的循環遊標
nlist_for_each_entry_safe 中使用的臨時儲存
member結構體中 list_head 的名稱。
描述
如果列表可能同時被修改,通常 list_safe_reset_next 不安全使用(例如,在迴圈體中釋放鎖)。一個例外是,如果遊標元素 (pos) 固定在列表中,並且在重新獲取鎖並在完成迴圈體的當前迭代之前呼叫 list_safe_reset_next。
-
int hlist_unhashed(const struct hlist_node *h)¶
節點是否已從連結串列中移除並重新初始化?
引數
const struct hlist_node *h要檢查的節點
描述
請注意,並非所有移除函式都會使節點處於未雜湊狀態。例如,hlist_nulls_del_init_rcu() 會使節點處於未雜湊狀態,但 hlist_nulls_del() 不會。
-
int hlist_unhashed_lockless(const struct hlist_node *h)¶
hlist_unhashed 的無鎖版本
引數
const struct hlist_node *h要檢查的節點
描述
必須在無鎖上下文中使用此 hlist_unhashed() 變體,以避免潛在的載入撕裂。 READ_ONCE() 與下面定義的 hlist 輔助函式中的各種 WRITE_ONCE() 配對。
-
int hlist_empty(const struct hlist_head *h)¶
指定的 hlist_head 結構是否為空 hlist?
引數
const struct hlist_head *h要檢查的結構。
-
void hlist_del(struct hlist_node *n)¶
從其連結串列中刪除指定的 hlist_node
-
void hlist_del_init(struct hlist_node *n)¶
從其連結串列中刪除指定的 hlist_node 並初始化
引數
struct hlist_node *n要刪除的節點。
描述
請注意,此函式使節點處於未雜湊狀態。
-
void hlist_add_head(struct hlist_node *n, struct hlist_head *h)¶
將新條目新增到 hlist 的開頭
引數
struct hlist_node *n要新增的新條目
struct hlist_head *hhlist 頭,將在其後新增
描述
在指定的頭部之後插入一個新條目。 這對於實現堆疊很有用。
-
void hlist_add_before(struct hlist_node *n, struct hlist_node *next)¶
在指定的條目之前新增新條目
引數
struct hlist_node *n要新增的新條目
struct hlist_node *nexthlist 節點,將在其之前新增,必須為非 NULL
-
void hlist_add_behind(struct hlist_node *n, struct hlist_node *prev)¶
在指定的條目之後新增新條目
引數
struct hlist_node *n要新增的新條目
struct hlist_node *prevhlist 節點,將在其之後新增,必須為非 NULL
-
void hlist_add_fake(struct hlist_node *n)¶
建立一個由單個無頭節點組成的偽造 hlist
引數
struct hlist_node *n從中建立一個偽造列表的節點
描述
這使 n 看起來像它自己在一個無頭 hlist 上的前身。 這樣做的目的是允許像 hlist_del() 在沒有列表的情況下正常工作。
-
bool hlist_fake(struct hlist_node *h)¶
此節點是偽造的 hlist 嗎?
引數
struct hlist_node *h要檢查是否為自引用偽造 hlist 的節點。
-
bool hlist_is_singular_node(struct hlist_node *n, struct hlist_head *h)¶
節點是否為指定 hlist 的唯一元素?
引數
struct hlist_node *n要檢查奇異性的節點。
struct hlist_head *h可能為奇異列表的標頭。
描述
檢查節點是否為標頭的唯一節點,而無需訪問標頭,從而避免不必要的快取未命中。
-
void hlist_move_list(struct hlist_head *old, struct hlist_head *new)¶
移動一個 hlist
引數
struct hlist_head *old舊列表的 hlist_head。
struct hlist_head *new新列表的 hlist_head。
描述
將列表從一個列表頭移動到另一個列表頭。如果第一個條目存在,則修復 pprev 引用。
-
void hlist_splice_init(struct hlist_head *from, struct hlist_node *last, struct hlist_head *to)¶
將所有條目從一個列表移動到另一個列表
引數
struct hlist_head *from將從中移動條目的 hlist_head
struct hlist_node *lastfrom 列表上的最後一個條目
struct hlist_head *to將條目移動到的 hlist_head
描述
to 可以為空,from 必須至少包含 last。
-
hlist_for_each_entry¶
hlist_for_each_entry (pos, head, member)
迭代給定型別的連結串列
引數
pos用作循環遊標的 型別 *。
head連結串列的頭部。
member結構體中 hlist_node 的名稱。
-
hlist_for_each_entry_continue¶
hlist_for_each_entry_continue (pos, member)
在當前點之後繼續迭代 hlist
引數
pos用作循環遊標的 型別 *。
member結構體中 hlist_node 的名稱。
-
hlist_for_each_entry_from¶
hlist_for_each_entry_from (pos, member)
從當前點繼續迭代 hlist
引數
pos用作循環遊標的 型別 *。
member結構體中 hlist_node 的名稱。
-
hlist_for_each_entry_safe¶
hlist_for_each_entry_safe (pos, n, head, member)
迭代給定型別的連結串列,防止刪除連結串列條目
引數
pos用作循環遊標的 型別 *。
n要用作臨時儲存的
struct hlist_nodehead連結串列的頭部。
member結構體中 hlist_node 的名稱。
-
size_t hlist_count_nodes(struct hlist_head *head)¶
計算 hlist 中的節點數
引數
struct hlist_head *head您的 hlist 的頭。
基本 C 庫函式¶
在編寫驅動程式時,通常無法使用 C 庫中的例程。 一些函式已被發現普遍有用,並在下面列出。 這些函式的行為可能與 ANSI 定義的行為略有不同,並且這些偏差在文字中註明。
字串轉換¶
-
unsigned long long simple_strtoull(const char *cp, char **endp, unsigned int base)¶
將字串轉換為無符號長長整型
引數
const char *cp字串的開頭
char **endp指向已解析字串結尾的指標將放置在此處
unsigned int base要使用的進位制
描述
此函式有注意事項。請改用 kstrtoull。
-
unsigned long simple_strtoul(const char *cp, char **endp, unsigned int base)¶
將字串轉換為無符號長整型
引數
const char *cp字串的開頭
char **endp指向已解析字串結尾的指標將放置在此處
unsigned int base要使用的進位制
描述
此函式有注意事項。請改用 kstrtoul。
-
long simple_strtol(const char *cp, char **endp, unsigned int base)¶
將字串轉換為帶符號長整型
引數
const char *cp字串的開頭
char **endp指向已解析字串結尾的指標將放置在此處
unsigned int base要使用的進位制
描述
此函式有注意事項。請改用 kstrtol。
-
long long simple_strtoll(const char *cp, char **endp, unsigned int base)¶
將字串轉換為帶符號長長整型
引數
const char *cp字串的開頭
char **endp指向已解析字串結尾的指標將放置在此處
unsigned int base要使用的進位制
描述
此函式有注意事項。請改用 kstrtoll。
-
int vsnprintf(char *buf, size_t size, const char *fmt_str, va_list args)¶
格式化字串並將其放入緩衝區
引數
char *buf要將結果放入的緩衝區
size_t size緩衝區的大小,包括尾隨空空格
const char *fmt_str要使用的格式字串
va_list args格式字串的引數
描述
此函式通常遵循 C99 vsnprintf,但有一些擴充套件和一些限制
``n``不受支援
``p*``由 pointer() 處理
有關更廣泛的描述,請參閱 pointer() 或 如何正確獲取 printk 格式說明符。
進行更改時,請同時更新這兩個位置的文件
返回值是為給定輸入生成的字元數,不包括尾隨的“0”,按照 ISO C99。如果您想獲得寫入 buf 的確切字元數作為返回值(不包括尾隨的“0”),請使用 vscnprintf()。如果返回值大於或等於 size,則生成的字串將被截斷。
如果您尚未處理 va_list,請考慮使用 snprintf()。
-
int vscnprintf(char *buf, size_t size, const char *fmt, va_list args)¶
格式化字串並將其放入緩衝區
引數
char *buf要將結果放入的緩衝區
size_t size緩衝區的大小,包括尾隨空空格
const char *fmt要使用的格式字串
va_list args格式字串的引數
描述
返回值是已寫入 buf 的字元數,不包括尾隨的“0”。如果 size == 0,則該函式返回 0。
如果您尚未處理 va_list,請考慮使用 scnprintf()。
有關 C99 的格式字串擴充套件,請參閱 vsnprintf() 文件。
-
int snprintf(char *buf, size_t size, const char *fmt, ...)¶
格式化字串並將其放入緩衝區
引數
char *buf要將結果放入的緩衝區
size_t size緩衝區的大小,包括尾隨空空格
const char *fmt要使用的格式字串
...格式字串的引數
描述
返回值是為給定輸入生成的字元數,不包括尾隨的空字元,按照 ISO C99。如果返回值大於或等於 size,則生成的字串將被截斷。
有關 C99 的格式字串擴充套件,請參閱 vsnprintf() 文件。
-
int scnprintf(char *buf, size_t size, const char *fmt, ...)¶
格式化字串並將其放入緩衝區
引數
char *buf要將結果放入的緩衝區
size_t size緩衝區的大小,包括尾隨空空格
const char *fmt要使用的格式字串
...格式字串的引數
描述
返回值是寫入 buf 的字元數,不包括尾隨的“0”。如果 size == 0,則該函式返回 0。
-
int vsprintf(char *buf, const char *fmt, va_list args)¶
格式化字串並將其放入緩衝區
引數
char *buf要將結果放入的緩衝區
const char *fmt要使用的格式字串
va_list args格式字串的引數
描述
該函式返回寫入 buf 的字元數。請使用 vsnprintf() 或 vscnprintf(),以避免緩衝區溢位。
如果您尚未處理 va_list,請考慮使用 sprintf()。
有關 C99 的格式字串擴充套件,請參閱 vsnprintf() 文件。
-
int sprintf(char *buf, const char *fmt, ...)¶
格式化字串並將其放入緩衝區
引數
char *buf要將結果放入的緩衝區
const char *fmt要使用的格式字串
...格式字串的引數
描述
該函式返回寫入 buf 的字元數。為了避免緩衝區溢位,請使用 snprintf() 或 scnprintf()。
有關 C99 的格式字串擴充套件,請參閱 vsnprintf() 文件。
-
int vbin_printf(u32 *bin_buf, size_t size, const char *fmt_str, va_list args)¶
解析格式化字串並將 args 的二進位制值放入緩衝區
引數
u32 *bin_buf用於放置 args 二進位制值的緩衝區
size_t size緩衝區的大小(以字(32 位)為單位,而不是字元)
const char *fmt_str要使用的格式字串
va_list args格式字串的引數
描述
格式遵循 C99 vsnprintf,除了 n 被忽略,並且其引數被跳過。
返回值是為給定輸入生成的字(32 位)的數量。
注意
如果返回值大於 size,則生成的 bin_buf 對於 bstr_printf() 無效。
-
int bstr_printf(char *buf, size_t size, const char *fmt_str, const u32 *bin_buf)¶
從二進位制引數格式化字串,並將其放入緩衝區
引數
char *buf要將結果放入的緩衝區
size_t size緩衝區的大小,包括尾隨空空格
const char *fmt_str要使用的格式字串
const u32 *bin_buf格式化字串的二進位制引數
描述
此函式類似於 C99 vsnprintf,但不同之處在於 vsnprintf 從堆疊獲取引數,而 bstr_printf 從 bin_buf 獲取引數,bin_buf 是由 vbin_printf 生成的二進位制緩衝區。
- 格式遵循 C99 vsnprintf,但有一些擴充套件
有關詳細資訊,請參閱 vsnprintf 註釋。
返回值是為給定輸入生成的字元數,不包括尾隨的“0”,按照 ISO C99。如果您想獲得寫入 buf 的確切字元數作為返回值(不包括尾隨的“0”),請使用 vscnprintf()。如果返回值大於或等於 size,則生成的字串將被截斷。
-
int vsscanf(const char *buf, const char *fmt, va_list args)¶
將緩衝區反格式化為引數列表
引數
const char *buf輸入緩衝區
const char *fmt緩衝區的格式
va_list args引數
-
int sscanf(const char *buf, const char *fmt, ...)¶
將緩衝區反格式化為引數列表
引數
const char *buf輸入緩衝區
const char *fmt緩衝區的格式化
...生成的引數
-
int kstrtoul(const char *s, unsigned int base, unsigned long *res)¶
將字串轉換為無符號長整型
引數
const char *s字串的開頭。字串必須以 null 結尾,並且還可以在其終止 null 之前包含單個換行符。第一個字元也可以是加號,但不能是減號。
unsigned int base要使用的數字基數。支援的最大基數為 16。如果基數給出為 0,則字串的基數將自動使用傳統語義進行檢測 - 如果它以 0x 開頭,則該數字將被解析為十六進位制(不區分大小寫),如果它以 0 開頭,它將被解析為八進位制數。否則它將被解析為十進位制。
unsigned long *res成功時,將轉換結果寫入的位置。
描述
成功時返回 0,溢位時返回 -ERANGE,解析錯誤時返回 -EINVAL。優於 simple_strtoul()。必須檢查返回程式碼。
-
int kstrtol(const char *s, unsigned int base, long *res)¶
將字串轉換為 long
引數
const char *s字串的開頭。字串必須以 null 結尾,並且還可以在其終止 null 之前包含單個換行符。第一個字元也可以是加號或減號。
unsigned int base要使用的數字基數。支援的最大基數為 16。如果基數給出為 0,則字串的基數將自動使用傳統語義進行檢測 - 如果它以 0x 開頭,則該數字將被解析為十六進位制(不區分大小寫),如果它以 0 開頭,它將被解析為八進位制數。否則它將被解析為十進位制。
long *res成功時,將轉換結果寫入的位置。
描述
成功時返回 0,溢位時返回 -ERANGE,解析錯誤時返回 -EINVAL。優於 simple_strtol()。必須檢查返回程式碼。
-
int kstrtoull(const char *s, unsigned int base, unsigned long long *res)¶
將字串轉換為無符號長長整型
引數
const char *s字串的開頭。字串必須以 null 結尾,並且還可以在其終止 null 之前包含單個換行符。第一個字元也可以是加號,但不能是減號。
unsigned int base要使用的數字基數。支援的最大基數為 16。如果基數給出為 0,則字串的基數將自動使用傳統語義進行檢測 - 如果它以 0x 開頭,則該數字將被解析為十六進位制(不區分大小寫),如果它以 0 開頭,它將被解析為八進位制數。否則它將被解析為十進位制。
unsigned long long *res成功時,將轉換結果寫入的位置。
描述
成功時返回 0,溢位時返回 -ERANGE,解析錯誤時返回 -EINVAL。優於 simple_strtoull()。必須檢查返回程式碼。
-
int kstrtoll(const char *s, unsigned int base, long long *res)¶
將字串轉換為 long long
引數
const char *s字串的開頭。字串必須以 null 結尾,並且還可以在其終止 null 之前包含單個換行符。第一個字元也可以是加號或減號。
unsigned int base要使用的數字基數。支援的最大基數為 16。如果基數給出為 0,則字串的基數將自動使用傳統語義進行檢測 - 如果它以 0x 開頭,則該數字將被解析為十六進位制(不區分大小寫),如果它以 0 開頭,它將被解析為八進位制數。否則它將被解析為十進位制。
long long *res成功時,將轉換結果寫入的位置。
描述
成功時返回 0,溢位時返回 -ERANGE,解析錯誤時返回 -EINVAL。優於 simple_strtoll()。必須檢查返回程式碼。
-
int kstrtouint(const char *s, unsigned int base, unsigned int *res)¶
將字串轉換為無符號整數
引數
const char *s字串的開頭。字串必須以 null 結尾,並且還可以在其終止 null 之前包含單個換行符。第一個字元也可以是加號,但不能是減號。
unsigned int base要使用的數字基數。支援的最大基數為 16。如果基數給出為 0,則字串的基數將自動使用傳統語義進行檢測 - 如果它以 0x 開頭,則該數字將被解析為十六進位制(不區分大小寫),如果它以 0 開頭,它將被解析為八進位制數。否則它將被解析為十進位制。
unsigned int *res成功時,將轉換結果寫入的位置。
描述
成功時返回 0,溢位時返回 -ERANGE,解析錯誤時返回 -EINVAL。優於 simple_strtoul()。必須檢查返回程式碼。
-
int kstrtoint(const char *s, unsigned int base, int *res)¶
將字串轉換為整數
引數
const char *s字串的開頭。字串必須以 null 結尾,並且還可以在其終止 null 之前包含單個換行符。第一個字元也可以是加號或減號。
unsigned int base要使用的數字基數。支援的最大基數為 16。如果基數給出為 0,則字串的基數將自動使用傳統語義進行檢測 - 如果它以 0x 開頭,則該數字將被解析為十六進位制(不區分大小寫),如果它以 0 開頭,它將被解析為八進位制數。否則它將被解析為十進位制。
int *res成功時,將轉換結果寫入的位置。
描述
成功時返回 0,溢位時返回 -ERANGE,解析錯誤時返回 -EINVAL。優於 simple_strtol()。必須檢查返回程式碼。
-
int kstrtobool(const char *s, bool *res)¶
將常見的使用者輸入轉換為布林值
引數
const char *s輸入字串
bool *res結果
描述
當第一個字元是 ‘YyTt1NnFf0’ 或 [oO][NnFf](表示“on”和“off”)時,此例程返回 0。否則,它將返回 -EINVAL。在找到匹配項時,將更新 res 指向的值。
-
int string_get_size(u64 size, u64 blk_size, const enum string_size_units units, char *buf, int len)¶
以指定的單位獲取大小
引數
u64 size要以塊為單位轉換的大小
u64 blk_size塊的大小(以位元組為單位使用 1)
const enum string_size_units units要使用的單位(1000 或 1024 的冪),是否包含空格分隔符
char *buf要格式化的緩衝區
int len緩衝區長度
描述
此函式返回格式化為 3 位有效數字的字串,給出所需單位的大小。buf 至少應有 9 個位元組的空間,並且始終以零結尾。
返回值:將要寫入的輸出字元數(如果輸出被截斷,則可能大於 len)。
-
int parse_int_array_user(const char __user *from, size_t count, int **array)¶
將字串拆分為整數序列
引數
const char __user *from要讀取的使用者空間緩衝區
size_t count要讀取的最大位元組數
int **array返回指向整數序列的指標
描述
成功時,array 將被分配和初始化,其中包含從 from 提取的整數序列,以及一個開始該序列並指定整數計數的附加元素。
呼叫者負責在不再需要 array 時釋放它。
-
int string_unescape(char *src, char *dst, size_t size, unsigned int flags)¶
取消給定字串中的跳脫字元
引數
char *src源緩衝區(已轉義)
char *dst目標緩衝區(未轉義)
size_t size目標緩衝區的大小(0 表示無限制)
unsigned int flags標誌的組合。
描述
該函式取消給定字串中的跳脫字元。
由於輸出的大小將與輸入的大小相同或更小,因此可以在原地執行轉換。
呼叫者必須提供有效的源指標和目標指標。請注意,目標緩衝區將始終以 NULL 結尾。源字串也必須以 NULL 結尾。支援的標誌有
UNESCAPE_SPACE:
'\f' - form feed
'\n' - new line
'\r' - carriage return
'\t' - horizontal tab
'\v' - vertical tab
UNESCAPE_OCTAL:
'\NNN' - byte with octal value NNN (1 to 3 digits)
UNESCAPE_HEX:
'\xHH' - byte with hexadecimal value HH (1 to 2 digits)
UNESCAPE_SPECIAL:
'\"' - double quote
'\\' - backslash
'\a' - alert (BEL)
'\e' - escape
UNESCAPE_ANY:
all previous together
返回
返回處理到目標緩衝區的字元數,不包括尾部的 ‘0’。
-
int string_escape_mem(const char *src, size_t isz, char *dst, size_t osz, unsigned int flags, const char *only)¶
引用給定記憶體緩衝區中的字元
引數
const char *src源緩衝區(未轉義)
size_t isz源緩衝區大小
char *dst目標緩衝區(已轉義)
size_t osz目標緩衝區大小
unsigned int flags標誌的組合
const char *only以 NULL 結尾的字串,其中包含用於限制所選轉義類的字元。如果 only 中包含的字元通常不會被 flags 中選擇的類轉義,則它們將以未轉義的形式複製到 dst。
描述
轉義位元組緩衝區的過程包括幾個部分。它們按以下順序應用。
該字元與 only 字串中的一個不匹配,因此必須原樣輸出。
該字元與可列印和 ASCII 類匹配(如果需要),如果匹配,則將其傳遞到輸出。
該字元與可列印或 ASCII 類匹配(如果需要),如果匹配,則將其傳遞到輸出。
檢查該字元是否屬於 flags 給出的類。
ESCAPE_OCTAL和ESCAPE_HEX最後執行,因為它們覆蓋任何字元。請注意,它們實際上不能一起使用,否則ESCAPE_HEX將被忽略。
呼叫者必須提供有效的源指標和目標指標。請注意,目標緩衝區不會以 NULL 結尾,因此如果需要,呼叫者必須附加它。支援的標誌有
%ESCAPE_SPACE: (special white space, not space itself)
'\f' - form feed
'\n' - new line
'\r' - carriage return
'\t' - horizontal tab
'\v' - vertical tab
%ESCAPE_SPECIAL:
'\"' - double quote
'\\' - backslash
'\a' - alert (BEL)
'\e' - escape
%ESCAPE_NULL:
'\0' - null
%ESCAPE_OCTAL:
'\NNN' - byte with octal value NNN (3 digits)
%ESCAPE_ANY:
all previous together
%ESCAPE_NP:
escape only non-printable characters, checked by isprint()
%ESCAPE_ANY_NP:
all previous together
%ESCAPE_HEX:
'\xHH' - byte with hexadecimal value HH (2 digits)
%ESCAPE_NA:
escape only non-ascii characters, checked by isascii()
%ESCAPE_NAP:
escape only non-printable or non-ascii characters
%ESCAPE_APPEND:
append characters from @only to be escaped by the given classes
當提供 ESCAPE_NP、ESCAPE_NA 或 ESCAPE_NAP 之一時,ESCAPE_APPEND 將有助於將附加字元傳遞給跳脫字元。
一個值得注意的警告是,ESCAPE_NAP、ESCAPE_NP 和 ESCAPE_NA 的優先順序高於其餘標誌(ESCAPE_NAP 優先順序最高)。如果不使用 ESCAPE_OCTAL 或 ESCAPE_HEX,則使用它們中的任何一個都沒有意義,因為它們涵蓋了大多數其他字元類。ESCAPE_NAP 除了上述內容外,還可以使用 ESCAPE_SPACE 或 ESCAPE_SPECIAL。
返回
對於給定的輸入和標誌,將生成的轉義輸出的總大小。 要檢查輸出是否被截斷,請將返回值與 osz 進行比較。 當且僅當 ret < osz 時,dst 中才剩餘空間用於 '0' 終止符。
-
char **kasprintf_strarray(gfp_t gfp, const char *prefix, size_t n)¶
分配和填充順序字串陣列
引數
gfp_t gfpslab 分配器的標誌
const char *prefix要使用的字首
size_t n要分配和填充的行數
描述
使用模式 “s-````zu” 分配和填充 n 個字串,其中字首由呼叫者提供。 呼叫者負責在使用後使用 kfree_strarray() 釋放它們。
返回字串陣列,如果無法分配記憶體,則返回 NULL。
-
void kfree_strarray(char **array, size_t n)¶
釋放陣列中包含的多個動態分配的字串以及陣列本身
引數
char **array要釋放的字串的動態分配陣列。
size_t n要釋放的字串數(從陣列的開頭開始)。
描述
傳遞非 NULL array 和 n == 0 以及 NULL array 是有效的用例。如果 array 為 NULL,則該函式不執行任何操作。
-
char *skip_spaces(const char *str)¶
從 str 中刪除前導空格。
引數
const char *str要剝離的字串。
描述
返回指向 str 中第一個非空格字元的指標。
-
char *strim(char *s)¶
從 s 中刪除前導和尾隨空格。
引數
char *s要剝離的字串。
描述
請注意,第一個尾隨空格將替換為給定字串 s 中的 NUL-終止符。 返回指向 s 中第一個非空格字元的指標。
-
bool sysfs_streq(const char *s1, const char *s2)¶
如果字串相等,則返回 true,模尾隨換行符
引數
const char *s1一個字串
const char *s2另一個字串
描述
當且僅當兩個字串相等時,此例程才返回 true,將 NUL 和換行符加 NUL 都視為等效的字串終止。 它適用於 sysfs 輸入字串,這些字串通常以換行符結尾,但與不帶換行符的值進行比較。
-
int match_string(const char *const *array, size_t n, const char *string)¶
匹配陣列中給定的字串
引數
const char * const *array字串陣列
size_t n陣列中字串的數量,對於 NULL 終止的陣列,則為 -1
const char *string要匹配的字串
描述
此例程將在字串陣列中查詢字串,直到陣列中的第 n 個元素或直到第一個 NULL 元素。
從歷史上看,n 的值為 -1 用於在 NULL 終止的陣列中搜索。 但是,該函式在完成搜尋時沒有做出區分:要麼比較了 n 個元素,要麼找到了第一個 NULL 元素。
返回
如果匹配,則為 array 中 string 的索引,否則為 -EINVAL。
-
int __sysfs_match_string(const char *const *array, size_t n, const char *str)¶
匹配陣列中給定的字串
引數
const char * const *array字串陣列
size_t n陣列中字串的數量,對於 NULL 終止的陣列,則為 -1
const char *str要匹配的字串
描述
返回 array 中 str 的索引或 -EINVAL,就像 match_string() 一樣。 使用 sysfs_streq 而不是 strcmp 進行匹配。
此例程將在字串陣列中查詢字串,直到陣列中的第 n 個元素或直到第一個 NULL 元素。
從歷史上看,n 的值為 -1 用於在 NULL 終止的陣列中搜索。 但是,該函式在完成搜尋時沒有做出區分:要麼比較了 n 個元素,要麼找到了第一個 NULL 元素。
-
char *strreplace(char *str, char old, char new)¶
替換字串中字元的所有出現項。
引數
char *str要操作的字串。
char old要替換的字元。
char newold 將替換為的字元。
描述
在給定的字串 str 中,將每個 old 字元替換為 new 字元。
返回
指向字串 str 本身的指標。
-
void memcpy_and_pad(void *dest, size_t dest_len, const void *src, size_t count, int pad)¶
將一個緩衝區複製到另一個緩衝區並進行填充
引數
void *dest要複製到的位置
size_t dest_len目標緩衝區大小
const void *src要從其複製的位置
size_t count要複製的位元組數
int pad如果目標中剩餘空間,則用於填充的字元。
字串操作¶
-
unsafe_memcpy¶
unsafe_memcpy (dst, src, bytes, justification)
memcpy 實現,沒有 FORTIFY 邊界檢查
引數
dst要寫入的目標記憶體地址
src要從中讀取的源記憶體地址
bytes要從 src 寫入到 dst 的位元組數
justification描述為什麼需要使用的自由文字或註釋
描述
這應該用於編譯器無法正確執行的極端情況,或者在 API 之間的轉換期間等等。 它應該很少使用,並且包含一個理由位置,詳細說明邊界檢查發生的位置以及為什麼無法採用現有解決方案。
-
char *strncpy(char *const p, const char *q, __kernel_size_t size)¶
將字串複製到記憶體,但不能保證 NUL 填充
引數
char * const p指向副本目標的指標
const char *q指向要複製的 NUL 終止的源字串的指標
__kernel_size_t size要在 p 處寫入的位元組
描述
如果 strlen(q) >= size,則對 q 的複製將在 size 位元組後停止,並且 p 將不會 NUL 終止
如果 strlen(q) < size,則在複製 q 之後,會將尾隨 NUL 位元組寫入 p,直到寫入總共 size 個位元組。
請勿使用此函式。 雖然 FORTIFY_SOURCE 嘗試避免過度讀取 q,但它無法防禦將未終止的結果寫入 p。 使用 strncpy() 仍然模稜兩可且脆弱。 請改用其他方法,以便對 p 內容的期望是明確的
p 需要 |
填充到 size |
未填充 |
|---|---|---|
NUL 終止 |
||
未 NUL 終止 |
請注意 strscpy*() 用於檢測截斷的不同返回值,以及 strtomem*() 對目標的期望,即當它是一個字元陣列時,標記為 __nonstring。
-
__kernel_size_t strnlen(const char *const p, __kernel_size_t maxlen)¶
返回 NUL 終止的字串中字元的邊界計數
引數
const char * const p指向要計數的 NUL 終止的字串的指標。
__kernel_size_t maxlen要計數的最大字元數。
描述
返回 p 中的字元數(不包括最終的 NUL),或者如果到那裡為止未找到 NUL,則返回 maxlen。
-
strlen¶
strlen (p)
返回 NUL 終止的字串中字元的計數
引數
p指向要計數的 NUL 終止的字串的指標。
描述
除非在編譯時知道字串長度,否則不要使用此函式。 當 p 未終止時,此函式可能會崩潰或返回意外的計數,從而可能導致記憶體內容暴露。 首選 strnlen()。
返回 p 中的字元數(不包括最終的 NUL)。
-
size_t strlcat(char *const p, const char *const q, size_t avail)¶
將字串追加到現有字串
引數
char * const p指向要追加到的
NUL-終止字串的指標const char * const q指向要從中追加的
NUL-終止字串的指標size_t availp 中的最大可用位元組數
描述
在 p 處的 NUL-終止 字串之後追加 NUL-終止 字串 q,但不會寫入超出 avail 位元組的總數,可能會截斷來自 q 的副本。 只有當 NUL 已經存在於 p 的 avail 位元組中時,p 才會保持 NUL-終止。 如果是這樣,則從 q 複製的生成的位元組數最多為 “avail - strlen(p) - 1”。
請勿使用此函式。 雖然 FORTIFY_SOURCE 嘗試避免讀取和寫入溢位,但這隻有在編譯器知道 p 和 q 的大小的情況下才有可能。 首選透過 scnprintf()、seq_buf 或類似方法使用格式設定來構建字串。
返回 _would_ 已包含在 p 中的總位元組數,無論截斷與否,類似於 snprintf()。 如果返回值 >= avail,則字串已被截斷。
-
char *strcat(char *const p, const char *q)¶
將字串追加到現有字串
引數
char * const p指向要追加到的 NUL 終止的字串的指標
const char *q指向要從中追加的 NUL 終止的源字串的指標
描述
請勿使用此函式。 雖然 FORTIFY_SOURCE 嘗試避免讀取和寫入溢位,但這隻有在編譯器知道目標緩衝區大小的情況下才有可能。 首選透過 scnprintf() 或類似方法使用格式設定來構建字串。 至少,使用 strncat()。
返回 p。
-
char *strncat(char *const p, const char *const q, __kernel_size_t count)¶
將字串追加到現有字串
引數
char * const p指向要追加到的 NUL 終止的字串的指標
const char * const q指向要從中追加的源字串的指標
__kernel_size_t count要從 q 讀取的最大位元組數
描述
在 p 處的 NUL 終止的字串之後,從 q 追加最多 count 個位元組(在第一個 NUL 位元組處停止)。 p 將被 NUL 終止。
不要使用此函式。雖然 FORTIFY_SOURCE 嘗試避免讀取和寫入溢位,但這隻有在編譯器知道 p 和 q 的大小時才有可能。 建議使用格式化構建字串,透過 scnprintf() 或類似函式。
返回 p。
-
char *strcpy(char *const p, const char *const q)¶
將一個字串複製到另一個字串緩衝區中
引數
char * const p指向副本目標的指標
const char * const q指向要複製的 NUL 終止的源字串的指標
描述
不要使用此函式。 雖然 FORTIFY_SOURCE 嘗試避免溢位,但這隻有在編譯器知道 q 和 p 的大小時才有可能。 建議使用 strscpy(),但請注意它用於檢測截斷的不同返回值。
返回 p。
-
int strncasecmp(const char *s1, const char *s2, size_t len)¶
不區分大小寫,長度限制的字串比較
引數
const char *s1一個字串
const char *s2另一個字串
size_t len要比較的最大字元數
-
char *stpcpy(char *__restrict__ dest, const char *__restrict__ src)¶
將字串從 src 複製到 dest,返回指向 dest 新末尾的指標,包括 src 的
NUL-終止符。 可能會超出 dest 的範圍。
引數
char *__restrict__ dest指向要複製到的字串的末尾。 必須足夠大以接收副本。
const char *__restrict__ src指向要複製的字串的開頭。 不得與 dest 重疊。
描述
stpcpy 與 strcpy 的一個關鍵區別是:返回值是指向 dest 中新的 NUL-終止 字元的指標。(對於 strcpy,返回值是指向 dest 開頭的指標)。此介面被認為是不安全的,因為它不對輸入執行邊界檢查。 因此,不建議使用它。 相反,提供其定義是為了防止編譯器將其他 libcalls 降低到 stpcpy。
-
int strcmp(const char *cs, const char *ct)¶
比較兩個字串
引數
const char *cs一個字串
const char *ct另一個字串
-
int strncmp(const char *cs, const char *ct, size_t count)¶
比較兩個長度受限的字串
引數
const char *cs一個字串
const char *ct另一個字串
size_t count要比較的最大位元組數
-
char *strchr(const char *s, int c)¶
查詢字串中第一次出現的字元
引數
const char *s要搜尋的字串
int c要搜尋的字元
描述
請注意,NUL-終止符 被認為是字串的一部分,可以搜尋。
-
char *strchrnul(const char *s, int c)¶
在字串中查詢並返回一個字元,或字串的結尾
引數
const char *s要搜尋的字串
int c要搜尋的字元
描述
返回指向 s 中第一次出現 ‘c’ 的指標。如果未找到 c,則返回指向 s 末尾的空位元組的指標。
-
char *strrchr(const char *s, int c)¶
查詢字串中最後一次出現的字元
引數
const char *s要搜尋的字串
int c要搜尋的字元
-
char *strnchr(const char *s, size_t count, int c)¶
在長度限制的字串中查詢字元
引數
const char *s要搜尋的字串
size_t count要搜尋的字元數
int c要搜尋的字元
描述
請注意,NUL-終止符 被認為是字串的一部分,可以搜尋。
-
size_t strspn(const char *s, const char *accept)¶
計算 s 的初始子字串的長度,該子字串僅包含 accept 中的字母
引數
const char *s要搜尋的字串
const char *accept要搜尋的字串
-
size_t strcspn(const char *s, const char *reject)¶
計算 s 的初始子字串的長度,該子字串不包含 reject 中的字母
引數
const char *s要搜尋的字串
const char *reject要避免的字串
-
char *strpbrk(const char *cs, const char *ct)¶
查詢一組字元的第一次出現
引數
const char *cs要搜尋的字串
const char *ct要搜尋的字元
-
char *strsep(char **s, const char *ct)¶
將字串拆分為標記
引數
char **s要搜尋的字串
const char *ct要搜尋的字元
描述
strsep() 更新 s 以指向標記之後,準備好進行下一次呼叫。
它也會返回空標記,其行為與該名稱的 libc 函式完全相同。 事實上,它是從 glibc2 偷來的,並且經過了簡化。 相同的語義,更苗條的形狀。 ;)
-
void *memset(void *s, int c, size_t count)¶
用給定的值填充記憶體區域
引數
void *s指向該區域的開頭。
int c用於填充該區域的位元組
size_t count該區域的大小。
描述
不要使用 memset() 訪問 IO 空間,而應使用 memset_io()。
-
void *memset16(uint16_t *s, uint16_t v, size_t count)¶
用 uint16_t 填充記憶體區域
引數
uint16_t *s指向該區域的開頭。
uint16_t v用於填充該區域的值
size_t count要儲存的值的數量
描述
與 memset() 的不同之處在於,它使用 uint16_t 而不是位元組填充。 請記住,count 是要儲存的 uint16_ts 的數量,而不是位元組數。
-
void *memset32(uint32_t *s, uint32_t v, size_t count)¶
用 uint32_t 填充記憶體區域
引數
uint32_t *s指向該區域的開頭。
uint32_t v用於填充該區域的值
size_t count要儲存的值的數量
描述
與 memset() 的不同之處在於,它使用 uint32_t 而不是位元組填充。 請記住,count 是要儲存的 uint32_ts 的數量,而不是位元組數。
-
void *memset64(uint64_t *s, uint64_t v, size_t count)¶
用 uint64_t 填充記憶體區域
引數
uint64_t *s指向該區域的開頭。
uint64_t v用於填充該區域的值
size_t count要儲存的值的數量
描述
與 memset() 的不同之處在於,它使用 uint64_t 而不是位元組填充。 請記住,count 是要儲存的 uint64_ts 的數量,而不是位元組數。
-
void *memcpy(void *dest, const void *src, size_t count)¶
將一個記憶體區域複製到另一個記憶體區域
引數
void *dest要複製到的位置
const void *src要從其複製的位置
size_t count該區域的大小。
描述
您不應使用此函式訪問 IO 空間,而應使用 memcpy_toio() 或 memcpy_fromio()。
-
void *memmove(void *dest, const void *src, size_t count)¶
將一個記憶體區域複製到另一個記憶體區域
引數
void *dest要複製到的位置
const void *src要從其複製的位置
size_t count該區域的大小。
描述
-
__visible int memcmp(const void *cs, const void *ct, size_t count)¶
比較兩個記憶體區域
引數
const void *cs一個記憶體區域
const void *ct另一個記憶體區域
size_t count該區域的大小。
-
int bcmp(const void *a, const void *b, size_t len)¶
當且僅當緩衝區具有相同內容時才返回 0。
引數
const void *a指向第一個緩衝區的指標。
const void *b指向第二個緩衝區的指標。
size_t len緩衝區的大小。
描述
非零返回值的符號或大小沒有特定含義,並且架構可以實現它們自己更有效的 bcmp()。 因此,雖然此特定實現是對 memcmp 的簡單(尾部)呼叫,但不要依賴除返回值是否為零或非零之外的任何內容。
-
void *memscan(void *addr, int c, size_t size)¶
在記憶體區域中查詢字元。
引數
void *addr記憶體區域
int c要查詢的位元組
size_t size該區域的大小。
描述
返回 **c** 首次出現的地址,如果未找到 **c**,則返回區域後 1 位元組
-
char *strstr(const char *s1, const char *s2)¶
在以
NUL結尾的字串中查詢第一個子字串
引數
const char *s1要搜尋的字串
const char *s2要搜尋的字串
-
char *strnstr(const char *s1, const char *s2, size_t len)¶
在長度受限的字串中查詢第一個子字串
引數
const char *s1要搜尋的字串
const char *s2要搜尋的字串
size_t len要搜尋的最大字元數
-
void *memchr(const void *s, int c, size_t n)¶
在記憶體區域中查詢字元。
引數
const void *s記憶體區域
int c要查詢的位元組
size_t n該區域的大小。
描述
返回 **c** 首次出現的地址,如果未找到 **c**,則返回 NULL
-
void *memchr_inv(const void *start, int c, size_t bytes)¶
在記憶體區域中查詢不匹配的字元。
引數
const void *start記憶體區域
int c查詢除 c 以外的字元
size_t bytes該區域的大小。
描述
返回除 **c** 以外的第一個字元的地址,如果整個緩衝區僅包含 **c**,則返回 NULL。
-
void *memdup_array_user(const void __user *src, size_t n, size_t size)¶
從使用者空間複製陣列
引數
const void __user *src使用者空間中的源地址
size_t n要複製的陣列元素的數量
size_t size一個數組元素的大小
返回
-
void *vmemdup_array_user(const void __user *src, size_t n, size_t size)¶
從使用者空間複製陣列
引數
const void __user *src使用者空間中的源地址
size_t n要複製的陣列元素的數量
size_t size一個數組元素的大小
返回
-
strscpy¶
strscpy (dst, src, ...)
將 C 字串複製到具有大小限制的緩衝區中
引數
dst要將字串複製到的位置
src要從哪裡複製字串
...目標緩衝區的大小(可選)
描述
將源字串 **src** 複製到目標 **dst** 緩衝區中,或儘可能多地複製。如果字串緩衝區重疊,則行為未定義。除非目標 **dst** 緩衝區的大小為零,否則始終以 NUL 結尾。
只有當 **dst** 不是陣列,或者複製需要小於 sizeof(**dst**) 時,才需要大小引數 **...** 。
優於 strncpy(),因為它始終返回有效字串,並且不會不必要地強制目標緩衝區的尾部填充零。如果需要填充,請使用 strscpy_pad()。
返回 **dst** 中複製的字元數(不包括尾隨的 NUL),如果 **size** 為 0 或從 **src** 複製被截斷,則返回 -E2BIG。
-
strscpy_pad¶
strscpy_pad (dst, src, ...)
將 C 字串複製到具有大小限制的緩衝區中
引數
dst要將字串複製到的位置
src要從哪裡複製字串
...目標緩衝區的大小
描述
將字串複製到目標緩衝區中,或儘可能多地複製。如果字串緩衝區重疊,則行為未定義。除非目標緩衝區的大小為零,否則始終以 NUL 結尾。
如果源字串短於目標緩衝區,則緩衝區中剩餘的位元組將填充 NUL 位元組。
有關為什麼可能需要考慮使用“strscpy”函式的完整說明,請參閱 strscpy() 的函式文件字串。
返回
複製的字元數(不包括尾隨的
NULs)如果 count 為 0 或 **src** 被截斷,則返回 -E2BIG。
-
bool mem_is_zero(const void *s, size_t n)¶
檢查記憶體區域是否全部為 0。
引數
const void *s記憶體區域
size_t n區域的大小
返回
如果記憶體區域全部為 0,則為 True。
-
sysfs_match_string¶
sysfs_match_string (_a, _s)
匹配陣列中給定的字串
-
bool strstarts(const char *str, const char *prefix)¶
**str** 是否以 **prefix** 開頭?
引數
const char *str要檢查的字串
const char *prefix要查詢的字首。
-
void memzero_explicit(void *s, size_t count)¶
用 0 填充記憶體區域(例如,敏感金鑰資料)。
引數
void *s指向該區域的開頭。
size_t count該區域的大小。
注意
通常使用 memset() 就可以了 (!),但在需要在作用域末尾清除 _local_ 資料的情況下,應使用 memzero_explicit(),以防止編譯器最佳化掉清零操作。
描述
memzero_explicit() 不需要特定於體系結構的版本,因為它只是隱式地呼叫 memset()。
-
const char *kbasename(const char *path)¶
返回路徑名的最後一部分。
引數
const char *path從中提取檔名的路徑。
-
strtomem_pad¶
strtomem_pad (dest, src, pad)
將以 NUL 結尾的字串複製到非 NUL 結尾的緩衝區
引數
dest目標字元陣列的指標(標記為 __nonstring)
src指向以 NUL 結尾的字串的指標
pad複製後,用於填充 **dest** 剩餘位元組的填充字元
描述
這是 strncpy() 用法的替代方法,其中目標不是以 NUL 結尾的字串,但對源大小進行邊界檢查,並使用顯式填充字元。如果不需要填充,請使用 strtomem()。
請注意,**dest** 的大小不是引數,因為編譯器必須能夠發現 **dest** 的長度。
-
strtomem¶
strtomem (dest, src)
將以 NUL 結尾的字串複製到非 NUL 結尾的緩衝區
引數
dest目標字元陣列的指標(標記為 __nonstring)
src指向以 NUL 結尾的字串的指標
描述
這是 strncpy() 用法的替代方法,其中目標不是以 NUL 結尾的字串,但對源大小進行邊界檢查,並且沒有尾隨填充。如果需要填充,請使用 strtomem_pad()。
請注意,**dest** 的大小不是引數,因為編譯器必須能夠發現 **dest** 的長度。
-
memtostr¶
memtostr (dest, src)
將可能不是以 NUL 結尾的字串複製到以 NUL 結尾的字串
引數
dest指向以 NUL 結尾的目標字串的指標
src指向字元陣列的指標(可能標記為 __nonstring)
描述
這是 strncpy() 用法的替代方法,其中源不是以 NUL 結尾的字串。
請注意,**dest** 和 **src** 的大小必須在編譯時已知。
-
memtostr_pad¶
memtostr_pad (dest, src)
將可能不是以 NUL 結尾的字串複製到以 NUL 結尾的字串,並在目標中填充 NUL
引數
dest指向以 NUL 結尾的目標字串的指標
src指向字元陣列的指標(可能標記為 __nonstring)
描述
這是 strncpy() 用法的替代方法,其中源不是以 NUL 結尾的字串。
請注意,**dest** 和 **src** 的大小必須在編譯時已知。
-
memset_after¶
memset_after (obj, v, member)
在結構成員之後設定一個值到結構的末尾
引數
obj目標結構例項的地址
v要重複寫入的位元組值
member在此結構成員之後開始寫入位元組
描述
這非常適合清除給定成員之後的填充。
-
memset_startat¶
memset_startat (obj, v, member)
從成員的起始位置到結構體的末尾設定一個值
引數
obj目標結構例項的地址
v要重複寫入的位元組值
member要開始寫入的結構成員
描述
請注意,如果前一個成員和目標成員之間存在填充,則應使用 memset_after() 來清除前一個填充。
-
size_t str_has_prefix(const char *str, const char *prefix)¶
測試字串是否具有給定的字首
引數
const char *str要測試的字串
const char *prefix用於檢視 **str** 是否以此開頭的字串
描述
- 測試字串字首的常用方法是
strncmp(str, prefix, sizeof(prefix) - 1)
但這可能會因拼寫錯誤或字首是指標而不是常量而導致錯誤。請改用 str_has_prefix()。
返回
如果 **str** 以 **prefix** 開頭,則返回 strlen(**prefix**)
如果 **str** 不以 **prefix** 開頭,則返回 0
-
char *kstrdup(const char *s, gfp_t gfp)¶
分配空間並複製現有字串
-
const char *kstrdup_const(const char *s, gfp_t gfp)¶
有條件地複製現有的 const 字串
引數
const char *s要複製的字串
gfp_t gfp在分配記憶體時
kmalloc()呼叫中使用的 GFP 掩碼
注意
由 kstrdup_const 分配的字串應由 kfree_const 釋放,並且不得傳遞給 krealloc()。
返回
如果源字串位於 .rodata 節中,則返回源字串,否則回退到 kstrdup。
-
char *kstrndup(const char *s, size_t max, gfp_t gfp)¶
分配空間並複製現有字串
引數
const char *s要複製的字串
size_t max從 **s** 中最多讀取 **max** 個字元
gfp_t gfp在分配記憶體時
kmalloc()呼叫中使用的 GFP 掩碼
注意
如果大小已知,請改用 kmemdup_nul()。
返回
新分配的 **s** 副本,如果出錯,則返回 NULL
-
void *kmemdup(const void *src, size_t len, gfp_t gfp)¶
複製記憶體區域
引數
const void *src要複製的記憶體區域
size_t len記憶體區域長度
gfp_t gfp要使用的 GFP 掩碼
返回
src 的新分配的副本,或者在出錯情況下為 NULL,結果是物理上連續的。使用 kfree() 釋放。
-
char *kmemdup_nul(const char *s, size_t len, gfp_t gfp)¶
從非空終止的資料建立 NUL 終止的字串
引數
const char *s要字串化的資料
size_t len資料的大小
gfp_t gfp在分配記憶體時
kmalloc()呼叫中使用的 GFP 掩碼
返回
帶有 NUL 終止符的 s 的新分配副本,或者在出錯情況下為 NULL
-
void *memdup_user(const void __user *src, size_t len)¶
從使用者空間複製記憶體區域
引數
const void __user *src使用者空間中的源地址
size_t len要複製的位元組數
返回
-
void *vmemdup_user(const void __user *src, size_t len)¶
從使用者空間複製記憶體區域
引數
const void __user *src使用者空間中的源地址
size_t len要複製的位元組數
返回
-
char *strndup_user(const char __user *s, long n)¶
從使用者空間複製現有字串
-
void *memdup_user_nul(const void __user *src, size_t len)¶
從使用者空間複製記憶體區域並進行 NUL 終止
基本核心庫函式¶
Linux 核心提供了更多基本的實用函式。
位操作¶
-
void set_bit(long nr, volatile unsigned long *addr)¶
原子地設定記憶體中的一位
引數
long nr要設定的位
volatile unsigned long *addr開始計數的地址
描述
這是一個寬鬆的原子操作(沒有隱含的記憶體屏障)。
請注意,nr 可能幾乎任意大;此函式不限於對單個字量進行操作。
-
void clear_bit(long nr, volatile unsigned long *addr)¶
清除記憶體中的一位
引數
long nr要清除的位
volatile unsigned long *addr開始計數的地址
描述
這是一個寬鬆的原子操作(沒有隱含的記憶體屏障)。
-
void change_bit(long nr, volatile unsigned long *addr)¶
切換記憶體中的一位
引數
long nr要更改的位
volatile unsigned long *addr開始計數的地址
描述
這是一個寬鬆的原子操作(沒有隱含的記憶體屏障)。
請注意,nr 可能幾乎任意大;此函式不限於對單個字量進行操作。
-
bool test_and_set_bit(long nr, volatile unsigned long *addr)¶
設定一位並返回其舊值
引數
long nr要設定的位
volatile unsigned long *addr開始計數的地址
描述
這是一個原子的完全有序的操作(隱含完全記憶體屏障)。
-
bool test_and_clear_bit(long nr, volatile unsigned long *addr)¶
清除一位並返回其舊值
引數
long nr要清除的位
volatile unsigned long *addr開始計數的地址
描述
這是一個原子的完全有序的操作(隱含完全記憶體屏障)。
-
bool test_and_change_bit(long nr, volatile unsigned long *addr)¶
更改一位並返回其舊值
引數
long nr要更改的位
volatile unsigned long *addr開始計數的地址
描述
這是一個原子的完全有序的操作(隱含完全記憶體屏障)。
-
void ___set_bit(unsigned long nr, volatile unsigned long *addr)¶
設定記憶體中的一位
引數
unsigned long nr要設定的位
volatile unsigned long *addr開始計數的地址
描述
與 set_bit() 不同,此函式是非原子的。如果在同一記憶體區域上併發呼叫它,則效果可能是隻有一個操作成功。
-
void ___clear_bit(unsigned long nr, volatile unsigned long *addr)¶
清除記憶體中的一位
引數
unsigned long nr要清除的位
volatile unsigned long *addr開始計數的地址
描述
與 clear_bit() 不同,此函式是非原子的。如果在同一記憶體區域上併發呼叫它,則效果可能是隻有一個操作成功。
-
void ___change_bit(unsigned long nr, volatile unsigned long *addr)¶
切換記憶體中的一位
引數
unsigned long nr要更改的位
volatile unsigned long *addr開始計數的地址
描述
與 change_bit() 不同,此函式是非原子的。如果在同一記憶體區域上併發呼叫它,則效果可能是隻有一個操作成功。
-
bool ___test_and_set_bit(unsigned long nr, volatile unsigned long *addr)¶
設定一位並返回其舊值
引數
unsigned long nr要設定的位
volatile unsigned long *addr開始計數的地址
描述
此操作是非原子的。如果此操作的兩個例項發生競爭,一個例項可能看似成功,但實際上失敗。
-
bool ___test_and_clear_bit(unsigned long nr, volatile unsigned long *addr)¶
清除一位並返回其舊值
引數
unsigned long nr要清除的位
volatile unsigned long *addr開始計數的地址
描述
此操作是非原子的。如果此操作的兩個例項發生競爭,一個例項可能看似成功,但實際上失敗。
-
bool ___test_and_change_bit(unsigned long nr, volatile unsigned long *addr)¶
更改一位並返回其舊值
引數
unsigned long nr要更改的位
volatile unsigned long *addr開始計數的地址
描述
此操作是非原子的。如果此操作的兩個例項發生競爭,一個例項可能看似成功,但實際上失敗。
-
bool _test_bit(unsigned long nr, volatile const unsigned long *addr)¶
確定是否設定了某個位
引數
unsigned long nr要測試的位號
const volatile unsigned long *addr開始計數的地址
-
bool _test_bit_acquire(unsigned long nr, volatile const unsigned long *addr)¶
使用獲取語義確定是否設定了某個位
引數
unsigned long nr要測試的位號
const volatile unsigned long *addr開始計數的地址
-
void clear_bit_unlock(long nr, volatile unsigned long *addr)¶
清除記憶體中的一位,用於解鎖
引數
long nr要設定的位
volatile unsigned long *addr開始計數的地址
描述
此操作是原子的,並提供釋放屏障語義。
-
void __clear_bit_unlock(long nr, volatile unsigned long *addr)¶
清除記憶體中的一位
引數
long nr要清除的位
volatile unsigned long *addr開始計數的地址
描述
這是一個非原子操作,但意味著在記憶體操作之前釋放屏障。如果其他 CPU 無法併發修改字中的其他位,則可以使用它進行解鎖。
-
bool test_and_set_bit_lock(long nr, volatile unsigned long *addr)¶
設定一位並返回其舊值,用於鎖定
引數
long nr要設定的位
volatile unsigned long *addr開始計數的地址
描述
如果返回值為 0,則此操作是原子的,並提供獲取屏障語義。它可用於實現位鎖。
-
bool xor_unlock_is_negative_byte(unsigned long mask, volatile unsigned long *addr)¶
XOR 記憶體中的單個位元組,並測試它是否為負數,用於解鎖。
引數
unsigned long mask更改在此掩碼中設定的位。
volatile unsigned long *addr包含要更改的位元組的字的地址。
描述
更改由 addr 指向的字中的某些位 0-6。此操作是原子的,並提供釋放屏障語義。用於最佳化一些通常與解鎖或寫回結束配對的 folio 操作。位 7 用作 PG_waiters 以指示是否有人在等待解鎖。
返回
是否設定了位元組的最高位。
點陣圖操作¶
點陣圖提供一個位數組,使用一個無符號長整型陣列實現。 給定點陣圖中有效位的數量_不需要_是 BITS_PER_LONG 的精確倍數。
點陣圖的最後一個,部分使用的字中可能未使用的位是“無關緊要的”。 該實現沒有特別努力地將它們保持為零。 它確保它們的值不會影響任何操作的結果。 返回布林值(例如,bitmap_empty)或標量(例如,bitmap_weight)結果的點陣圖操作會小心地過濾掉這些未使用的位,以避免影響其結果。
在小端架構上,點陣圖的位元組順序更自然。 有關此順序的最佳解釋,請參見大端標頭檔案 include/asm-ppc64/bitops.h 和 include/asm-s390/bitops.h。
linux/types.h 中的 DECLARE_BITMAP(name,bits) 宏可用於宣告一個名為 “name” 的陣列,該陣列具有足夠的無符號長整型來包含從 0 到 “bits” - 1 的所有位位置。
在點陣圖是單個無符號長整型的情況下,可用的點陣圖操作及其大致含義如下
當 `nbits` 在編譯時已知且最多為 `BITS_PER_LONG` 時,生成的程式碼效率更高。
bitmap_zero(dst, nbits) *dst = 0UL
bitmap_fill(dst, nbits) *dst = ~0UL
bitmap_copy(dst, src, nbits) *dst = *src
bitmap_and(dst, src1, src2, nbits) *dst = *src1 & *src2
bitmap_or(dst, src1, src2, nbits) *dst = *src1 | *src2
bitmap_xor(dst, src1, src2, nbits) *dst = *src1 ^ *src2
bitmap_andnot(dst, src1, src2, nbits) *dst = *src1 & ~(*src2)
bitmap_complement(dst, src, nbits) *dst = ~(*src)
bitmap_equal(src1, src2, nbits) Are *src1 and *src2 equal?
bitmap_intersects(src1, src2, nbits) Do *src1 and *src2 overlap?
bitmap_subset(src1, src2, nbits) Is *src1 a subset of *src2?
bitmap_empty(src, nbits) Are all bits zero in *src?
bitmap_full(src, nbits) Are all bits set in *src?
bitmap_weight(src, nbits) Hamming Weight: number set bits
bitmap_weight_and(src1, src2, nbits) Hamming Weight of and'ed bitmap
bitmap_weight_andnot(src1, src2, nbits) Hamming Weight of andnot'ed bitmap
bitmap_set(dst, pos, nbits) Set specified bit area
bitmap_clear(dst, pos, nbits) Clear specified bit area
bitmap_find_next_zero_area(buf, len, pos, n, mask) Find bit free area
bitmap_find_next_zero_area_off(buf, len, pos, n, mask, mask_off) as above
bitmap_shift_right(dst, src, n, nbits) *dst = *src >> n
bitmap_shift_left(dst, src, n, nbits) *dst = *src << n
bitmap_cut(dst, src, first, n, nbits) Cut n bits from first, copy rest
bitmap_replace(dst, old, new, mask, nbits) *dst = (*old & ~(*mask)) | (*new & *mask)
bitmap_scatter(dst, src, mask, nbits) *dst = map(dense, sparse)(src)
bitmap_gather(dst, src, mask, nbits) *dst = map(sparse, dense)(src)
bitmap_remap(dst, src, old, new, nbits) *dst = map(old, new)(src)
bitmap_bitremap(oldbit, old, new, nbits) newbit = map(old, new)(oldbit)
bitmap_onto(dst, orig, relmap, nbits) *dst = orig relative to relmap
bitmap_fold(dst, orig, sz, nbits) dst bits = orig bits mod sz
bitmap_parse(buf, buflen, dst, nbits) Parse bitmap dst from kernel buf
bitmap_parse_user(ubuf, ulen, dst, nbits) Parse bitmap dst from user buf
bitmap_parselist(buf, dst, nbits) Parse bitmap dst from kernel buf
bitmap_parselist_user(buf, dst, nbits) Parse bitmap dst from user buf
bitmap_find_free_region(bitmap, bits, order) Find and allocate bit region
bitmap_release_region(bitmap, pos, order) Free specified bit region
bitmap_allocate_region(bitmap, pos, order) Allocate specified bit region
bitmap_from_arr32(dst, buf, nbits) Copy nbits from u32[] buf to dst
bitmap_from_arr64(dst, buf, nbits) Copy nbits from u64[] buf to dst
bitmap_to_arr32(buf, src, nbits) Copy nbits from buf to u32[] dst
bitmap_to_arr64(buf, src, nbits) Copy nbits from buf to u64[] dst
bitmap_get_value8(map, start) Get 8bit value from map at start
bitmap_set_value8(map, value, start) Set 8bit value to map at start
bitmap_read(map, start, nbits) Read an nbits-sized value from
map at start
bitmap_write(map, value, start, nbits) Write an nbits-sized value to
map at start
請注意,`bitmap_zero()` 和 `bitmap_fill()` 在無符號長整型區域上操作,也就是說,點陣圖後面的位直到無符號長整型邊界也會被清零或填充。考慮使用 `bitmap_clear()` 或 `bitmap_set()` 來分別顯式地進行清零或填充。
此外,asm/bitops.h 中的以下操作也適用於點陣圖。
set_bit(bit, addr) *addr |= bit
clear_bit(bit, addr) *addr &= ~bit
change_bit(bit, addr) *addr ^= bit
test_bit(bit, addr) Is bit set in *addr?
test_and_set_bit(bit, addr) Set bit and return old value
test_and_clear_bit(bit, addr) Clear bit and return old value
test_and_change_bit(bit, addr) Change bit and return old value
find_first_zero_bit(addr, nbits) Position first zero bit in *addr
find_first_bit(addr, nbits) Position first set bit in *addr
find_next_zero_bit(addr, nbits, bit)
Position next zero bit in *addr >= bit
find_next_bit(addr, nbits, bit) Position next set bit in *addr >= bit
find_next_and_bit(addr1, addr2, nbits, bit)
Same as find_next_bit, but in
(*addr1 & *addr2)
-
void __bitmap_shift_right(unsigned long *dst, const unsigned long *src, unsigned shift, unsigned nbits)¶
點陣圖中位的邏輯右移
引數
unsigned long *dst目標點陣圖
const unsigned long *src源點陣圖
unsigned shift移動的位數
unsigned nbits點陣圖大小,以位為單位
描述
右移(除法)意味著將位從 MS -> LS 位方向移動。零被饋送到空出的 MS 位置,並且從底部移出的 LS 位會丟失。
-
void __bitmap_shift_left(unsigned long *dst, const unsigned long *src, unsigned int shift, unsigned int nbits)¶
點陣圖中位的邏輯左移
引數
unsigned long *dst目標點陣圖
const unsigned long *src源點陣圖
unsigned int shift移動的位數
unsigned int nbits點陣圖大小,以位為單位
描述
左移(乘法)意味著將位從 LS -> MS 方向移動。零被饋送到空出的 LS 位位置,並且從頂部移出的 MS 位會丟失。
-
void bitmap_cut(unsigned long *dst, const unsigned long *src, unsigned int first, unsigned int cut, unsigned int nbits)¶
從點陣圖中刪除位區域並右移剩餘位
引數
unsigned long *dst目標點陣圖,可能與 src 重疊
const unsigned long *src源點陣圖
unsigned int first要刪除的區域的起始位
unsigned int cut要刪除的位數
unsigned int nbits點陣圖大小,以位為單位
描述
僅當 src 的第 n 位被設定並且 n 小於 first 時,才設定 dst 的第 n 位;或者,如果對於任何 m 使得 first <= n < nbits,並且 m = n + cut,則 src 的第 m 位被設定。
用圖片表示,例如對於大端 32 位體系結構
src 點陣圖是
31 63
| |
10000000 11000001 11110010 00010101 10000000 11000001 01110010 00010101
| | | |
16 14 0 32
如果 cut 為 3,並且 first 為 14,則 src 中位 14-16 被切除,並且 dst 是
31 63
| |
10110000 00011000 00110010 00010101 00010000 00011000 00101110 01000010
| | |
14 (bit 17 0 32
from @src)
請注意,dst 和 src 可能部分或全部重疊。
這是以顯而易見的方式實現的,對於每個移動的位都有一個移位和進位步驟。最佳化留給編譯器作為練習。
-
unsigned long bitmap_find_next_zero_area_off(unsigned long *map, unsigned long size, unsigned long start, unsigned int nr, unsigned long align_mask, unsigned long align_offset)¶
查詢一個連續對齊的零區域
引數
unsigned long *map搜尋的基礎地址
unsigned long size點陣圖大小,以位為單位
unsigned long start開始搜尋的位號
unsigned int nr我們要查詢的零位的數量
unsigned long align_mask零區域的對齊掩碼
unsigned long align_offset零區域的對齊偏移量。
描述
align_mask 應該比 2 的冪小 1; 效果是此函式找到的所有零區域的位偏移量加上 align_offset 是該 2 的冪的倍數。
-
void bitmap_remap(unsigned long *dst, const unsigned long *src, const unsigned long *old, const unsigned long *new, unsigned int nbits)¶
將一對點陣圖定義的對映應用於另一個位圖
引數
unsigned long *dst重新對映的結果
const unsigned long *src要重新對映的子集
const unsigned long *old定義對映的域
const unsigned long *new定義對映的範圍
unsigned int nbits每個點陣圖中的位數
描述
讓 old 和 new 定義位位置的對映,使得 old 中第 n 個設定位的任何位置都對映到 new 中第 n 個設定位的。在更一般的情況下,允許 new 的權重 'w' 小於 old 的權重,將 old 中第 n 個設定位的位置對映到 new 中第 m 個設定位的位置,其中 m == n % w。
如果 old 和 new 點陣圖中的任何一個為空,或者如果 src 和 dst 指向相同的位置,則此例程將 src 複製到 dst。
old 中未設定位的位置對映到它們自身(恆等對映)。
將上述指定的對映應用於 src,並將結果放入 dst 中,清除先前在 dst 中設定的任何位。
例如,假設 old 設定了位 4 到 7,而 new 設定了位 12 到 15。 這定義了位位置 4 到 12、5 到 13、6 到 14 和 7 到 15 的對映,以及所有其他位位置不變。 所以如果說 src 進入這個例程時設定了位 1、5 和 7,那麼 dst 應該離開時設定了位 1、13 和 15。
-
int bitmap_bitremap(int oldbit, const unsigned long *old, const unsigned long *new, int bits)¶
將一對點陣圖定義的對映應用於單個位
引數
int oldbit要對映的位位置
const unsigned long *old定義對映的域
const unsigned long *new定義對映的範圍
int bits每個點陣圖中的位數
描述
讓 old 和 new 定義位位置的對映,使得 old 中第 n 個設定位的任何位置都對映到 new 中第 n 個設定位的。在更一般的情況下,允許 new 的權重 'w' 小於 old 的權重,將 old 中第 n 個設定位的位置對映到 new 中第 m 個設定位的位置,其中 m == n % w。
old 中未設定位的位置對映到它們自身(恆等對映)。
將上述指定的對映應用於位位置 oldbit,返回新的位位置。
例如,假設 old 設定了位 4 到 7,而 new 設定了位 12 到 15。 這定義了位位置 4 到 12、5 到 13、6 到 14 和 7 到 15 的對映,以及所有其他位位置不變。 所以如果說 oldbit 是 5,那麼這個例程返回 13。
-
void bitmap_from_arr32(unsigned long *bitmap, const u32 *buf, unsigned int nbits)¶
將 u32 位陣列的內容複製到點陣圖
引數
unsigned long *bitmap無符號長整型陣列,目標點陣圖
const u32 *bufu32 陣列(主機位元組序),源點陣圖
unsigned int nbitsbitmap 中的位數
-
void bitmap_to_arr32(u32 *buf, const unsigned long *bitmap, unsigned int nbits)¶
將點陣圖的內容複製到 u32 位陣列
引數
u32 *bufu32 陣列(主機位元組序),目標點陣圖
const unsigned long *bitmap無符號長整型陣列,源點陣圖
unsigned int nbitsbitmap 中的位數
-
void bitmap_from_arr64(unsigned long *bitmap, const u64 *buf, unsigned int nbits)¶
將 u64 位陣列的內容複製到點陣圖
引數
unsigned long *bitmap無符號長整型陣列,目標點陣圖
const u64 *bufu64 陣列(主機位元組序),源點陣圖
unsigned int nbitsbitmap 中的位數
-
void bitmap_to_arr64(u64 *buf, const unsigned long *bitmap, unsigned int nbits)¶
將點陣圖的內容複製到 u64 位陣列
引數
u64 *bufu64 陣列(主機位元組序),目標點陣圖
const unsigned long *bitmap無符號長整型陣列,源點陣圖
unsigned int nbitsbitmap 中的位數
-
int bitmap_pos_to_ord(const unsigned long *buf, unsigned int pos, unsigned int nbits)¶
查詢點陣圖中給定位置的設定位的序號
引數
const unsigned long *buf指向點陣圖的指標
unsigned int posbuf 中的位位置 (0 <= pos < nbits)
unsigned int nbitsbuf 中有效位位置的數量
描述
將 buf (長度為 nbits) 中位置 pos 處的位對映到它是哪個設定位的序號。 如果未設定或如果 pos 不是有效的位位置,則對映到 -1。
例如,如果僅在 buf 中設定了位 4 到 7,則 pos 值 4 到 7 將分別對映到 0 到 3,其他 pos 值將對映到 -1。 當 pos 值 7 在此示例中對映到(返回)ord 值 3 時,這意味著位 7 是 buf 中第 3 個(從第 0 個開始)設定的位。
位位置 0 到 bits 是 buf 中的有效位置。
-
void bitmap_onto(unsigned long *dst, const unsigned long *orig, const unsigned long *relmap, unsigned int bits)¶
相對於另一個位圖轉換一個位圖
引數
unsigned long *dst生成的轉換後的點陣圖
const unsigned long *orig原始的未轉換的點陣圖
const unsigned long *relmap相對於哪個點陣圖轉換
unsigned int bits每個點陣圖中的位數
描述
設定 dst 的第 n 位,當且僅當存在一些 m,使得 relmap 的第 n 位被設定,orig 的第 m 位被設定,並且 relmap 的第 n 位也是 relmap 的第 m 個 _設定_ 位。 (如果您第一次閱讀時就理解了上一句話,那麼您目前的職位有點屈才了。)
換句話說,使用對映 {
在 orig 中,任何高於位號 W 的設定位(其中 W 是 relmap 的權重(設定位數))都不會對映到任何地方。 特別是,如果對於 orig 中設定的所有位 m,m >= W,那麼 dst 最終將為空。 在不希望出現這種空結果的情況下,避免它的一種方法是使用下面的 bitmap_fold() 運算子,首先將 orig 點陣圖摺疊到它自身上,以便其所有設定位 x 都在範圍 0 <= x < W 中。 bitmap_fold() 運算子透過為 orig 中設定的每個位 (m) 設定 dst 中的位 (m % W) 來實現這一點。
- bitmap_onto() 的示例 [1]
假設 relmap 設定了位 30-39,而 orig 設定了位 1、3、5、7、9 和 11。 然後,從此例程返回時,dst 將設定位 31、33、35、37 和 39。
當 orig 中的第 0 位被設定時,意味著開啟 dst 中對應的位,該位對應於 relmap 中第一個被開啟的位(如果有的話)。 由於上面的例子中第 0 位是關閉的,所以我們在 dst 中保持該位(第 30 位)關閉。
當 orig 中的第 1 位被設定時(如上面的例子所示),意味著開啟 dst 中對應的位,該位對應於 relmap 中第二個被開啟的位。 在上面的例子中,relmap 中第二個被開啟的位是第 31 位,所以我們打開了 dst 中的第 31 位。
類似地,我們打開了 dst 中的第 33、35、37 和 39 位,因為它們是 relmap 中第 4、6、8 和 10 個被設定的位,並且 orig 的第 4、6、8 和 10 位(即第 3、5、7 和 9 位)也被設定了。
當 orig 中的第 11 位被設定時,意味著開啟 dst 中對應的位,該位對應於 relmap 中第十二個被開啟的位。 在上面的例子中,relmap 中只有十個位被開啟(30..39),因此 orig 中的第 11 位被設定對 dst 沒有影響。
- bitmap_fold() + bitmap_onto() 的示例 [2]
假設 relmap 有這十個位被設定
40 41 42 43 45 48 53 61 74 95
(對於好奇的人,這是 40 加上斐波那契數列的前十項。)
此外,假設我們使用以下程式碼,呼叫
bitmap_fold()然後呼叫 bitmap_onto,如上所述,以避免 dst 結果為空的可能性unsigned long *tmp; // a temporary bitmap's bits bitmap_fold(tmp, orig, bitmap_weight(relmap, bits), bits); bitmap_onto(dst, tmp, relmap, bits);
然後,下表顯示了對於各種 orig,dst 的各種值將會是什麼。 我列出了每個設定位的從零開始的位置。 tmp 列顯示了中間結果,該結果是透過使用
bitmap_fold()將 orig 點陣圖對十(relmap 的權重)取模計算得出的。
如果 orig 或 relmap 中的任何一個是空的(沒有設定位),則 dst 將返回為空。
如果(如上所述)orig 中唯一設定的位位於 m 位置,其中 m >= W(其中 W 是 relmap 的權重),則 dst 將再次返回為空。
dst 中未被上述規則設定的所有位都將被清除。
-
void bitmap_fold(unsigned long *dst, const unsigned long *orig, unsigned int sz, unsigned int nbits)¶
將較大的點陣圖摺疊成較小的點陣圖,對指定的大小取模
引數
unsigned long *dst生成的較小點陣圖
const unsigned long *orig原始的較大點陣圖
unsigned int sz指定的大小
unsigned int nbits每個點陣圖中的位數
描述
對於 orig 中的每個位 oldbit,在 dst 中設定位 oldbit mod sz。 清除 dst 中的所有其他位。 請參閱 bitmap_onto() 的註釋和示例 [2],以瞭解為什麼以及如何使用此方法。
-
unsigned long bitmap_find_next_zero_area(unsigned long *map, unsigned long size, unsigned long start, unsigned int nr, unsigned long align_mask)¶
查詢一個連續對齊的零區域
引數
unsigned long *map搜尋的基礎地址
unsigned long size點陣圖大小,以位為單位
unsigned long start開始搜尋的位號
unsigned int nr我們要查詢的零位的數量
unsigned long align_mask零區域的對齊掩碼
描述
align_mask 應該是 2 的冪減 1; 效果是此函式找到的所有零區域的位偏移量都是該 2 的冪的倍數。 align_mask 為 0 表示不需要對齊。
-
bool bitmap_or_equal(const unsigned long *src1, const unsigned long *src2, const unsigned long *src3, unsigned int nbits)¶
檢查兩個點陣圖的或運算是否等於第三個點陣圖
引數
const unsigned long *src1指向點陣圖 1 的指標
const unsigned long *src2指向將與點陣圖 1 進行或運算的點陣圖 2 的指標
const unsigned long *src3指向點陣圖 3 的指標。 與 *src1 | *src2 的結果進行比較
unsigned int nbits每個點陣圖中的位數
返回
如果 (*src1 | *src2) == *src3,則為 True,否則為 False
-
void bitmap_scatter(unsigned long *dst, const unsigned long *src, const unsigned long *mask, unsigned int nbits)¶
根據給定的掩碼分散點陣圖
引數
unsigned long *dst分散的點陣圖
const unsigned long *src收集的點陣圖
const unsigned long *mask表示要分配給分散點陣圖中的位的掩碼
unsigned int nbits每個點陣圖中的位數
描述
根據給定的 mask 分散具有順序位的點陣圖。
或以二進位制形式 src mask dst 0000000001011010 0001001100010011 0000001100000010
(位 0、1、2、3、4、5 被複制到位 0、1、4、8、9、12)
操作的更“視覺化”的描述
src: 0000000001011010
||||||
+------+|||||
| +----+||||
| |+----+|||
| || +-+||
| || | ||
mask: ...v..vv...v..vv
...0..11...0..10
dst: 0000001100000010
bitmap_scatter() 和 bitmap_gather() 之間存在關係。 請參閱 bitmap_gather() 以瞭解點陣圖收集的詳細操作。 TL;DR:bitmap_gather() 可以被視為 bitmap_scatter() 操作的“反向”。
示例
如果 src 點陣圖 = 0x005a,且 mask = 0x1313,則 dst 將為 0x0302。
-
void bitmap_gather(unsigned long *dst, const unsigned long *src, const unsigned long *mask, unsigned int nbits)¶
根據給定的掩碼收集點陣圖
引數
unsigned long *dst收集的點陣圖
const unsigned long *src分散的點陣圖
const unsigned long *mask表示要從分散點陣圖中提取的位的掩碼
unsigned int nbits每個點陣圖中的位數
描述
根據給定的 mask 收集具有稀疏位的點陣圖。
或以二進位制形式 src mask dst 0000001100000010 0001001100010011 0000000000011010
(位 0、1、4、8、9、12 被複制到位 0、1、2、3、4、5)
操作的更“視覺化”的描述
mask: ...v..vv...v..vv
src: 0000001100000010
^ ^^ ^ 0
| || | 10
| || > 010
| |+--> 1010
| +--> 11010
+----> 011010
dst: 0000000000011010
bitmap_gather() 和 bitmap_scatter() 之間存在關係。 請參閱 bitmap_scatter() 以瞭解點陣圖分散的詳細操作。 TL;DR:bitmap_scatter() 可以被視為 bitmap_gather() 操作的“反向”。
假設 scattered 是使用 bitmap_scatter(scattered, src, mask, n) 計算得出的。 操作 bitmap_gather(result, scattered, mask, n) 會導致結果等於或等效於 src。
結果可能是“等效的”,因為 bitmap_scatter() 和 bitmap_gather() 不是雙射的。 結果和 src 值是等效的,因為呼叫 bitmap_scatter(res, src, mask, n) 和呼叫 bitmap_scatter(res, result, mask, n) 將導致相同的 res 值。
示例
如果 src 點陣圖 = 0x0302,且 mask = 0x1313,則 dst 將為 0x001a。
-
void bitmap_release_region(unsigned long *bitmap, unsigned int pos, int order)¶
釋放已分配的點陣圖區域
引數
unsigned long *bitmap對應於點陣圖的無符號長整型陣列
unsigned int pos要釋放的位區域的起始位置
int order要釋放的區域大小(位數的以 2 為底的對數)
描述
這是 __bitmap_find_free_region() 的補充,並釋放找到的區域(透過在點陣圖中清除它)。
-
int bitmap_allocate_region(unsigned long *bitmap, unsigned int pos, int order)¶
分配點陣圖區域
引數
unsigned long *bitmap對應於點陣圖的無符號長整型陣列
unsigned int pos要分配的位區域的起始位置
int order區域大小(位數的以 2 為底的對數)
描述
分配(設定位)點陣圖的指定區域。
返回
成功時返回 0,如果指定的區域不是空閒的(並非所有位都為零),則返回 -EBUSY。
-
int bitmap_find_free_region(unsigned long *bitmap, unsigned int bits, int order)¶
查詢連續對齊的記憶體區域
引數
unsigned long *bitmap對應於點陣圖的無符號長整型陣列
unsigned int bits點陣圖中位的數量
int order要查詢的區域大小(位數的以 2 為底的對數)
描述
在 bitmap 中查詢一個空閒(零)位區域,該點陣圖有 bits 位,並分配它們(將它們設定為 1)。 僅考慮長度為 2 的冪(order)的區域,該區域與 2 的冪對齊,這使得搜尋演算法更快。
返回
已分配區域在點陣圖中的位偏移量,或者失敗時為 -errno。
-
BITMAP_FROM_U64¶
BITMAP_FROM_U64 (n)
以適合點陣圖的格式表示 u64 值。
引數
nu64 值
描述
Linux 點陣圖在內部是無符號長整型陣列,即在 32 位環境中是 32 位整數,在 64 位環境中是 64 位整數。
在 Linux ABI 中,有四種位元組序和字長的組合:LE64、BE64、LE32 和 BE32。
在 64 位核心上,64 位 LE 和 BE 數字自然地在點陣圖中排序,因此不需要任何特殊處理。
在 32 位核心上,32 位 LE ABI 在記憶體中將 64 位數的低字排在高字之前,而 32 位 BE 將高字排在低字之前。 另一方面,位圖表示為 32 位字的陣列,因此位 N 的位置可以計算為:字 #(N/32) 和該字中的位 #(N``32``)。 例如,位 #42 位於第二個字的第 10 個位置。 它匹配 32 位 LE ABI,我們可以簡單地讓編譯器像通常那樣將 64 位值儲存在記憶體中。 但是對於 BE,我們需要手動交換高字和低字。
考慮到所有這些,宏 BITMAP_FROM_U64() 顯式地重新排序 u64 的高位部分和低位部分。 對於 LE32,它不執行任何操作,對於 BE 環境,它會交換高字和低字,正如點陣圖所期望的那樣。
-
void bitmap_from_u64(unsigned long *dst, u64 mask)¶
檢查並交換 u64 中的字。
引數
unsigned long *dst目標點陣圖
u64 mask源點陣圖
描述
在 32 位大端核心中,當使用 (u32 *)(:c:type:`val`)[*] 讀取 u64 掩碼時,我們將得到錯誤的字。 也就是說,(u32 *)(:c:type:`val`)[0] 獲取高 32 位,但我們期望 u64 的低 32 位。
-
unsigned long bitmap_read(const unsigned long *map, unsigned long start, unsigned long nbits)¶
從記憶體區域讀取 n 位的值
引數
const unsigned long *map點陣圖記憶體區域的地址
unsigned long startn 位值的位偏移量
unsigned long nbits值的位數,非零,最大為 BITS_PER_LONG
返回
位於 map 記憶體區域內 start 位偏移量處的 nbits 位的值。 對於 nbits = 0 和 nbits > BITS_PER_LONG,返回值未定義。
-
void bitmap_write(unsigned long *map, unsigned long value, unsigned long start, unsigned long nbits)¶
在記憶體區域中寫入 n 位的值
引數
unsigned long *map點陣圖記憶體區域的地址
unsigned long value要寫入的值,限制為 nbits
unsigned long startn 位值的位偏移量
unsigned long nbits值的位數,非零,最大為 BITS_PER_LONG。
描述
如果像 nbits 那樣實現了 bitmap_write(),則會呼叫 nbits 次 __assign_bit(),即忽略超出 nbits 的位
- for (bit = 0; bit < nbits; bit++)
__assign_bit(start + bit, bitmap, val & BIT(bit));
對於 nbits == 0 和 nbits > BITS_PER_LONG 的情況,不執行任何寫入操作。
命令列解析¶
-
int get_option(char **str, int *pint)¶
從選項字串解析整數
引數
char **str選項字串
int *pint(可選輸出) 從 str 解析的整數值
從選項字串讀取一個整數;如果可用,也接受隨後的逗號。
當 pint 為 NULL 時,該函式可以用作字串中當前選項的驗證器。
返回值:0 - 字串中沒有整數 1 - 找到整數,沒有後續逗號 2 - 找到整數,包括後續逗號 3 - 找到連字元,表示範圍
沒有整數的前導連字元不是整數情況,但為了簡化,我們消耗它。
-
char *get_options(const char *str, int nints, int *ints)¶
將字串解析為整數列表
引數
const char *str要解析的字串
int nints整數陣列的大小
int *ints整數陣列(必須至少為一個元素留出空間)
此函式解析包含逗號分隔的整數列表、連字元分隔的 _正_ 整數範圍或兩者的組合的字串。 當陣列已滿或無法從字串中檢索到更多數字時,解析停止。
當 nints 為 0 時,該函式僅驗證給定的 str 並返回如下所述的可解析整數的數量。
返回
第一個元素由範圍中收集的整數的數量填充。 其餘的是從 str 解析的內容。
返回值是導致解析結束的字串中的字元(如果 str 完全可解析,則通常為空終止符)。
-
unsigned long long memparse(const char *ptr, char **retptr)¶
將帶有記憶體字尾的字串解析為數字
引數
const char *ptr解析開始的位置
char **retptr(輸出) 解析完成後指向下一個字元的可選指標
將字串解析為數字。儲存在 ptr 處的數字可能帶有 K、M、G、T、P、E 字尾。
錯誤指標¶
-
IS_ERR_VALUE¶
IS_ERR_VALUE (x)
檢測錯誤指標。
-
void *ERR_PTR(long error)¶
建立錯誤指標。
引數
long error負錯誤程式碼。
描述
將 error 編碼為指標值。使用者應將結果視為不透明的,不要假設有關錯誤編碼方式的任何資訊。
返回
一個指標,其值中編碼了 error。
-
long PTR_ERR(__force const void *ptr)¶
從錯誤指標提取錯誤程式碼。
引數
__force const void *ptr一個錯誤指標。
返回
ptr 中的錯誤程式碼。
-
bool IS_ERR(__force const void *ptr)¶
檢測錯誤指標。
引數
__force const void *ptr要檢查的指標。
返回
如果 ptr 是錯誤指標,則為 true,否則為 false。
-
bool IS_ERR_OR_NULL(__force const void *ptr)¶
檢測錯誤指標或空指標。
-
void *ERR_CAST(__force const void *ptr)¶
將錯誤值指標顯式轉換為另一種指標型別
引數
__force const void *ptr要轉換的指標。
描述
以一種明確表明正在進行的方式,將錯誤值指標顯式轉換為另一種指標型別。
-
int PTR_ERR_OR_ZERO(__force const void *ptr)¶
如果指標具有錯誤程式碼,則從中提取錯誤程式碼。
引數
__force const void *ptr一個潛在的錯誤指標。
描述
可以在返回錯誤程式碼的函式內部使用的便捷函式,用於傳播作為錯誤指標接收的錯誤。例如,return PTR_ERR_OR_ZERO(ptr); 替換
if (IS_ERR(ptr))
return PTR_ERR(ptr);
else
return 0;
返回
如果 ptr 是錯誤指標,則返回 ptr 中的錯誤程式碼;否則返回 0。
排序¶
-
void sort_r(void *base, size_t num, size_t size, cmp_r_func_t cmp_func, swap_r_func_t swap_func, const void *priv)¶
對元素陣列進行排序
引數
void *base指向要排序的資料的指標
size_t num元素數量
size_t size每個元素的大小
cmp_r_func_t cmp_func指向比較函式的指標
swap_r_func_t swap_func指向交換函式的指標或 NULL
const void *priv傳遞給比較函式的第三個引數
描述
此函式對給定的陣列執行堆排序。如果需要執行超出記憶體複製的操作(例如,修復指標或輔助資料),您可以提供 swap_func 函式,但內建的交換避免了緩慢的 retpoline,因此速度明顯更快。
比較函式必須遵守特定的數學屬性,以確保正確和穩定的排序: - 反對稱性:cmp_func(a, b) 必須返回與 cmp_func(b, a) 相反的符號。 - 傳遞性:如果 cmp_func(a, b) <= 0 且 cmp_func(b, c) <= 0,則 cmp_func(a, c) <= 0。
平均和最壞情況下的排序時間均為 O(n log n)。雖然快速排序平均速度稍快,但它存在可利用的 O(n*n) 最壞情況行為和額外的記憶體要求,使其不太適合核心使用。
-
void sort_r_nonatomic(void *base, size_t num, size_t size, cmp_r_func_t cmp_func, swap_r_func_t swap_func, const void *priv)¶
對元素陣列進行排序,帶有 cond_resched
引數
void *base指向要排序的資料的指標
size_t num元素數量
size_t size每個元素的大小
cmp_r_func_t cmp_func指向比較函式的指標
swap_r_func_t swap_func指向交換函式的指標或 NULL
const void *priv傳遞給比較函式的第三個引數
描述
與 sort_r 相同,但對於較大的陣列,首選此函式,因為它會定期執行 cond_resched()。
-
void list_sort(void *priv, struct list_head *head, list_cmp_func_t cmp)¶
對列表進行排序
引數
void *priv私有資料,對
list_sort()不透明,傳遞給 cmpstruct list_head *head要排序的列表
list_cmp_func_t cmp元素比較函式
描述
如果 a 應排在 b 之後(如果希望升序排序,則為 “a > b”),則比較函式 cmp 必須返回 > 0,如果 a 應排在 b 之前或應保留其原始順序,則返回 <= 0。它總是使用輸入中第一個出現的元素 a 呼叫,並且 list_sort 是一種穩定排序,因此沒有必要區分 a < b 和 a == b 的情況。
比較函式必須遵守特定的數學屬性,以確保正確和穩定的排序: - 反對稱性:cmp(a, b) 必須返回與 cmp(b, a) 相反的符號。 - 傳遞性:如果 cmp(a, b) <= 0 且 cmp(b, c) <= 0,則 cmp(a, c) <= 0。
這與兩種樣式的 cmp 函式相容: - 返回 <0 / =0 / >0 的傳統樣式,或 - 返回布林值 0/1。後者提供了在比較中節省幾個週期的機會(例如,在 block/blk-mq.c 中由 plug_ctx_cmp() 使用)。
編寫多字比較的好方法是
if (a->high != b->high)
return a->high > b->high;
if (a->middle != b->middle)
return a->middle > b->middle;
return a->low > b->low;
此歸併排序儘可能渴望,同時始終執行至少 2:1 平衡合併。給定兩個大小為 2^k 的掛起子列表,只要我們有 2^k 個後續元素,它們就會合併為大小為 2^(k+1) 的列表。
因此,只要 3*2^k 個元素可以放入快取中,它就會避免快取抖動。不如完全渴望的自下而上歸併排序那麼好,但它確實減少了 0.2*n 次比較,因此在所有內容都適合 L1 的常見情況下速度更快。
合併由“count”控制,即掛起列表中的元素數量。這是一個非常簡單的程式碼,但相當微妙。
每次我們遞增“count”時,我們都會設定一位(位 k)並清除位 k-1 .. 0。每次發生這種情況(除了每次位數的第一次,當 count 遞增到 2^k 時),我們將兩個大小為 2^k 的列表合併為一個大小為 2^(k+1) 的列表。
當 count 達到 2^k 的奇數倍時,即當我們在較小列表中掛起 2^k 個元素時,會準確發生此合併,因此可以安全地合併兩個大小為 2^k 的列表。
在此發生兩次後,我們建立了兩個大小為 2^(k+1) 的列表,這些列表將在我們建立第三個大小為 2^(k+1) 的列表之前合併為大小為 2^(k+2) 的列表,因此永遠不會超過兩個掛起列表。
大小為 2^k 的掛起列表的數量由“count”的位 k 的狀態加上兩個額外的資訊確定
位 k-1 的狀態(當 k == 0 時,認為位 -1 始終設定),以及
高階位是零還是非零(即 count >= 2^(k+1))。
我們區分六種狀態。“x”表示一些任意位,“y”表示一些任意非零位: 0: 00x:大小為 2^k 的 0 個掛起列表;大小 < 2^k 的 x 個掛起列表 1: 01x:大小為 2^k 的 0 個掛起列表;大小 < 2^k 的 2^(k-1) + x 個掛起列表 2: x10x:大小為 2^k 的 0 個掛起列表;大小 < 2^k 的 2^k + x 個掛起列表 3: x11x:大小為 2^k 的 1 個掛起列表;大小 < 2^k 的 2^(k-1) + x 個掛起列表 4: y00x:大小為 2^k 的 1 個掛起列表;大小 < 2^k 的 2^k + x 個掛起列表 5: y01x:大小為 2^k 的 2 個掛起列表;大小 < 2^k 的 2^(k-1) + x 個掛起列表(合併並迴圈回到狀態 2)
我們在 2->3 和 4->5 轉換中獲得大小為 2^k 的列表(因為在更高有效位非零時設定了位 k-1),並在 5->2 轉換中合併它們。特別注意,就在 5->2 轉換之前,所有較低階位都是 11(狀態 3),因此每個較小的大小都有一個列表。
當我們到達輸入的末尾時,我們將所有掛起列表從最小到最大合併。如果您處理上述案例 2 到 5,您可以看到我們與大小為 2^k 的列表合併的元素數量從 2^(k-1)(當 x == 0 時的案例 3 和 5)到 2^(k+1) - 1(當 x == 2^(k-1) - 1 時的案例 5 的第二次合併)不等。
文字搜尋¶
簡介
文字搜尋基礎設施為線性和非線性資料提供文字搜尋功能。 各個搜尋演算法在模組中實現並由使用者選擇。
架構
User
+----------------+
| finish()|<--------------(6)-----------------+
|get_next_block()|<--------------(5)---------------+ |
| | Algorithm | |
| | +------------------------------+
| | | init() find() destroy() |
| | +------------------------------+
| | Core API ^ ^ ^
| | +---------------+ (2) (4) (8)
| (1)|----->| prepare() |---+ | |
| (3)|----->| find()/next() |-----------+ |
| (7)|----->| destroy() |----------------------+
+----------------+ +---------------+
(1) User configures a search by calling textsearch_prepare() specifying
the search parameters such as the pattern and algorithm name.
(2) Core requests the algorithm to allocate and initialize a search
configuration according to the specified parameters.
(3) User starts the search(es) by calling textsearch_find() or
textsearch_next() to fetch subsequent occurrences. A state variable
is provided to the algorithm to store persistent variables.
(4) Core eventually resets the search offset and forwards the find()
request to the algorithm.
(5) Algorithm calls get_next_block() provided by the user continuously
to fetch the data to be searched in block by block.
(6) Algorithm invokes finish() after the last call to get_next_block
to clean up any leftovers from get_next_block. (Optional)
(7) User destroys the configuration by calling textsearch_destroy().
(8) Core notifies the algorithm to destroy algorithm specific
allocations. (Optional)
用法
在執行搜尋之前,必須透過呼叫
textsearch_prepare()來建立配置,指定搜尋演算法、要查詢的模式和標誌。作為標誌,您可以設定 TS_IGNORECASE 以執行不區分大小寫的匹配。但這可能會降低演算法的效能,因此您應該自行承擔使用它的風險。返回的配置可以任意次數地使用,甚至可以並行使用,只要為每個例項提供單獨的 struct ts_state 變數。實際搜尋是透過呼叫
textsearch_find_continuous()來執行線性資料搜尋,或者透過提供自己的 get_next_block() 實現並呼叫textsearch_find()來執行。如果未找到匹配項,這兩個函式都返回模式的第一次出現的位置,或者返回 UINT_MAX。無論資料的線性如何,都可以透過呼叫textsearch_next()來查詢後續出現的位置。完成使用配置後,必須透過 textsearch_destroy 將其返回。
示例
int pos;
struct ts_config *conf;
struct ts_state state;
const char *pattern = "chicken";
const char *example = "We dance the funky chicken";
conf = textsearch_prepare("kmp", pattern, strlen(pattern),
GFP_KERNEL, TS_AUTOLOAD);
if (IS_ERR(conf)) {
err = PTR_ERR(conf);
goto errout;
}
pos = textsearch_find_continuous(conf, &state, example, strlen(example));
if (pos != UINT_MAX)
panic("Oh my god, dancing chickens at %d\n", pos);
textsearch_destroy(conf);
-
int textsearch_register(struct ts_ops *ops)¶
註冊一個 textsearch 模組
引數
struct ts_ops *ops操作查詢表
描述
文字搜尋模組必須呼叫此函式來宣告它們的存在。指定的 &**ops** 必須將 name 設定為唯一的識別符號,並且必須實現回撥函式 find()、init()、get_pattern() 和 get_pattern_len()。
如果另一個模組已經註冊了相同的名稱,則返回 0 或 -EEXISTS。
-
int textsearch_unregister(struct ts_ops *ops)¶
登出一個 textsearch 模組
引數
struct ts_ops *ops操作查詢表
描述
文字搜尋模組必須呼叫此函式來宣告它們已消失,例如當模組被解除安裝時。ops 引數必須與註冊期間的引數相同。
成功時返回 0,如果未找到匹配的 textsearch 註冊,則返回 -ENOENT。
-
unsigned int textsearch_find_continuous(struct ts_config *conf, struct ts_state *state, const void *data, unsigned int len)¶
在連續/線性資料中搜索模式
引數
struct ts_config *conf搜尋配置
struct ts_state *state搜尋狀態
const void *data要搜尋的資料
unsigned int len資料的長度
描述
textsearch_find() 的簡化版本,用於連續/線性資料。呼叫 textsearch_next() 來檢索後續匹配項。
返回模式首次出現的位置,如果未找到任何匹配項,則返回 UINT_MAX。
-
struct ts_config *textsearch_prepare(const char *algo, const void *pattern, unsigned int len, gfp_t gfp_mask, int flags)¶
準備搜尋
引數
const char *algo搜尋演算法的名稱
const void *pattern模式資料
unsigned int len模式長度
gfp_t gfp_mask分配掩碼
int flags搜尋標誌
描述
查詢搜尋演算法模組,併為指定的模式建立新的文字搜尋配置。
根據指定的引數返回新的文字搜尋配置或 ERR_PTR()。如果傳遞零長度模式,此函式將返回 EINVAL。
注意
- 各種搜尋演算法之間的模式格式可能不相容。
各種搜尋演算法之間的模式格式可能不相容。
-
void textsearch_destroy(struct ts_config *conf)¶
銷燬搜尋配置
引數
struct ts_config *conf搜尋配置
描述
釋放配置的所有引用並釋放記憶體。
-
unsigned int textsearch_next(struct ts_config *conf, struct ts_state *state)¶
繼續搜尋模式
引數
struct ts_config *conf搜尋配置
struct ts_state *state搜尋狀態
描述
繼續搜尋以查詢模式的更多出現。必須呼叫 textsearch_find() 來查詢第一次出現以重置狀態。
返回模式的下一次出現的位置,如果未找到任何匹配項,則返回 UINT_MAX。
-
unsigned int textsearch_find(struct ts_config *conf, struct ts_state *state)¶
開始搜尋模式
引數
struct ts_config *conf搜尋配置
struct ts_state *state搜尋狀態
描述
返回模式首次出現的位置,如果未找到任何匹配項,則返回 UINT_MAX。
-
void *textsearch_get_pattern(struct ts_config *conf)¶
返回模式的頭部
引數
struct ts_config *conf搜尋配置
-
unsigned int textsearch_get_pattern_len(struct ts_config *conf)¶
返回模式的長度
引數
struct ts_config *conf搜尋配置
Linux 中的 CRC 和數學函式¶
算術溢位檢查¶
-
check_add_overflow¶
check_add_overflow (a, b, d)
計算加法並進行溢位檢查
引數
a第一個加數
b第二個加數
d儲存和的指標
描述
如果發生迴繞,則返回 true,否則返回 false。
無論是否發生迴繞,**d** 都儲存嘗試加法的結果。
-
wrapping_add¶
wrapping_add (type, a, b)
有意執行迴繞加法
引數
type計算結果的型別
a第一個加數
b第二個加數
描述
返回可能迴繞的加法,而不會觸發任何可能啟用的迴繞清理程式。
-
wrapping_assign_add¶
wrapping_assign_add (var, offset)
有意執行迴繞遞增賦值
引數
var要遞增的變數
offset要新增的量
描述
將 **var** 遞增 **offset**,並進行迴繞。返回 **var** 的結果值。不會觸發任何迴繞清理程式。
返回 **var** 的新值。
-
check_sub_overflow¶
check_sub_overflow (a, b, d)
計算減法並進行溢位檢查
引數
a被減數;要從中減去的值
b減數;要從 **a** 中減去的值
d儲存差的指標
描述
如果發生迴繞,則返回 true,否則返回 false。
**d** 儲存嘗試減法的結果,無論是否發生迴繞。
-
wrapping_sub¶
wrapping_sub (type, a, b)
有意執行迴繞減法
引數
type計算結果的型別
a被減數;要從中減去的值
b減數;要從 **a** 中減去的值
描述
返回可能迴繞的減法,而不會觸發任何可能啟用的迴繞清理程式。
-
wrapping_assign_sub¶
wrapping_assign_sub (var, offset)
有意執行迴繞遞減賦值
引數
var要遞減的變數
offset要減去的量
描述
將 **var** 遞減 **offset**,並進行迴繞。返回 **var** 的結果值。不會觸發任何迴繞清理程式。
返回 **var** 的新值。
-
check_mul_overflow¶
check_mul_overflow (a, b, d)
計算乘法並進行溢位檢查
引數
a第一個因子
b第二個因子
d儲存積的指標
描述
如果發生迴繞,則返回 true,否則返回 false。
**d** 儲存嘗試乘法的結果,無論是否發生迴繞。
-
wrapping_mul¶
wrapping_mul (type, a, b)
有意執行迴繞乘法
引數
type計算結果的型別
a第一個因子
b第二個因子
描述
返回可能迴繞的乘法,而不會觸發任何可能啟用的迴繞清理程式。
-
check_shl_overflow¶
check_shl_overflow (a, s, d)
計算左移值並檢查溢位
引數
a要移位的值
s要左移多少位
d儲存結果的位置的指標
描述
計算 **\*d** = (**a** << **s**)
如果“**\*d**”無法儲存結果,或者“**a** << **s**”沒有意義,則返回 true。示例條件
當儲存在 **\*d** 中時,“**a** << **s**”會導致位丟失。
“**s**”是垃圾(例如,負數)或太大,以至於保證“**a** << **s**”的結果為 0。
“**a**”是負數。
如果存在任何符號位,“**a** << **s**”會在“**\*d**”中設定符號位。
“**\*d**”將儲存嘗試移位的結果,但如果返回 true,則不被認為是“可以安全使用”。
-
overflows_type¶
overflows_type (n, T)
用於檢查值、變數或資料型別之間的溢位的輔助函式
引數
n要檢查的源常量值或變數
T建議儲存 **x** 的目標變數或資料型別
描述
比較 **x** 表示式,以確定它是否可以安全地放入 **T** 中型別的儲存中。 **x** 和 **T** 可以具有不同的型別。如果 **x** 是常量表達式,它也會解析為常量表達式。
返回
如果可能發生溢位,則為 true,否則為 false。
-
castable_to_type¶
castable_to_type (n, T)
類似於 __same_type(),但也允許強制轉換的文字
引數
n變數或常量值
T變數或資料型別
描述
與 __same_type() 宏不同,這允許將常量值作為第一個引數。如果此值不會溢位到第二個引數型別的賦值中,則返回 true。否則,這會回退到 __same_type()。
-
size_t size_mul(size_t factor1, size_t factor2)¶
計算 size_t 乘法,並在 SIZE_MAX 處飽和
引數
size_t factor1第一個因子
size_t factor2第二個因子
返回
計算 **factor1** * **factor2**,兩者都提升為 size_t,任何溢位都會導致返回值變為 SIZE_MAX。左值必須是 size_t,以避免隱式型別轉換。
-
size_t size_add(size_t addend1, size_t addend2)¶
計算 size_t 加法,並在 SIZE_MAX 處飽和
引數
size_t addend1第一個加數
size_t addend2第二個加數
返回
計算 **addend1** + **addend2**,兩者都提升為 size_t,任何溢位都會導致返回值變為 SIZE_MAX。左值必須是 size_t,以避免隱式型別轉換。
-
size_t size_sub(size_t minuend, size_t subtrahend)¶
計算 size_t 減法,並在 SIZE_MAX 處飽和
引數
size_t minuend要從中減去的值
size_t subtrahend要從 **minuend** 中減去的值
返回
計算 **minuend** - **subtrahend**,兩者都提升為 size_t,任何溢位都會導致返回值變為 SIZE_MAX。為了與 size_add() 和 size_mul() 輔助函式組合,兩個引數都不能是 SIZE_MAX(否則結果將被強制為 SIZE_MAX)。左值必須是 size_t,以避免隱式型別轉換。
-
array_size¶
array_size (a, b)
計算二維陣列的大小。
引數
a第一維
b第二維
描述
計算二維陣列的大小:**a** * **b**。
返回
表示陣列所需的位元組數,如果溢位,則為 SIZE_MAX。
-
array3_size¶
array3_size (a, b, c)
計算三維陣列的大小。
引數
a第一維
b第二維
c第三維
描述
計算三維陣列的大小:**a** * **b** * **c**。
返回
表示陣列所需的位元組數,如果溢位,則為 SIZE_MAX。
-
flex_array_size¶
flex_array_size (p, member, count)
計算封閉結構中靈活陣列成員的大小。
引數
p指向結構的指標。
member靈活陣列成員的名稱。
count陣列中的元素數。
描述
計算 **p** 結構的末尾處 **count** 個 **member** 元素的靈活陣列的大小。
返回
所需的位元組數,如果溢位,則為 SIZE_MAX。
-
struct_size¶
struct_size (p, member, count)
計算帶有尾隨靈活陣列的結構的大小。
引數
p指向結構的指標。
member陣列成員的名稱。
count陣列中的元素數。
描述
計算 **p** 結構後跟 **count** 個 **member** 元素陣列所需的記憶體大小。
返回
所需的位元組數,如果溢位,則為 SIZE_MAX。
-
struct_size_t¶
struct_size_t (type, member, count)
計算帶有尾隨靈活陣列的結構的大小
引數
type結構型別名稱。
member陣列成員的名稱。
count陣列中的元素數。
描述
計算 **type** 結構後跟 **count** 個 **member** 元素陣列所需的記憶體大小。如果可能,最好使用 struct_size(),以保持計算與型別 **type** 的特定例項變數相關聯。
返回
所需的位元組數,如果溢位,則為 SIZE_MAX。
-
__DEFINE_FLEX¶
__DEFINE_FLEX (type, name, member, count, trailer...)
用於
DEFINE_FLEX()系列的輔助宏。使呼叫方宏能夠傳遞任意尾隨表示式
引數
type結構型別名稱,包括“struct”關鍵字。
name要定義的變數的名稱。
member陣列成員的名稱。
count陣列中的元素數;必須是編譯時常量。
trailer...用於屬性和/或初始值設定項的尾隨表示式。
-
_DEFINE_FLEX¶
_DEFINE_FLEX (type, name, member, count, initializer...)
用於
DEFINE_FLEX()系列的輔助宏。使呼叫方宏能夠傳遞(不同的)initializer。
引數
type結構型別名稱,包括“struct”關鍵字。
name要定義的變數的名稱。
member陣列成員的名稱。
count陣列中的元素數;必須是編譯時常量。
initializer...初始化表示式(例如,至少傳遞 = { })。
-
DEFINE_RAW_FLEX¶
DEFINE_RAW_FLEX (type, name, member, count)
定義一個具有尾隨可變陣列的結構體的棧上例項,當它沒有 __counted_by 註釋時。
引數
type結構型別名稱,包括“struct”關鍵字。
name要定義的變數的名稱。
member陣列成員的名稱。
count陣列中的元素數;必須是編譯時常量。
描述
定義一個清零的、具有尾隨可變陣列的 **type** 結構體的棧上例項。之後使用 __struct_size( **name** ) 來獲取其編譯時大小。使用 __member_size( **name->member** ) 來獲取 **name** 成員的編譯時大小。使用 STACK_FLEX_ARRAY_SIZE( **name** , **member** ) 來獲取陣列 **member** 中元素的編譯時數量。
-
DEFINE_FLEX¶
DEFINE_FLEX (TYPE, NAME, MEMBER, COUNTER, COUNT)
定義一個具有尾隨可變陣列的結構體的棧上例項。
引數
TYPE結構型別名稱,包括“struct”關鍵字。
NAME要定義的變數的名稱。
MEMBER陣列成員的名稱。
COUNTER__counted_by 成員的名稱。
COUNT陣列中的元素數;必須是編譯時常量。
描述
定義一個清零的、具有尾隨可變陣列的 **TYPE** 結構體的棧上例項。之後使用 __struct_size( **NAME** ) 來獲取其編譯時大小。使用 __member_size( **NAME->member** ) 來獲取 **NAME** 成員的編譯時大小。使用 STACK_FLEX_ARRAY_SIZE( **name** , **member** ) 來獲取陣列 **member** 中元素的編譯時數量。
-
STACK_FLEX_ARRAY_SIZE¶
STACK_FLEX_ARRAY_SIZE (name, array)
用於
DEFINE_FLEX()系列的輔助宏。返回 **array** 中的元素數量。
引數
name在
DEFINE_RAW_FLEX()/DEFINE_FLEX()中定義的變數的名稱。array陣列成員的名稱。
CRC 函式¶
-
uint8_t crc4(uint8_t c, uint64_t x, int bits)¶
計算值的 4 位 crc。
引數
uint8_t c起始 crc4
uint64_t x要校驗和的值
int bits要校驗和的 **x** 中的位數
描述
返回 **x** 的 crc4 值,使用多項式 0b10111。
**x** 值被視為左對齊,並且在 crc 計算中忽略高於 **bits** 的位。
-
u8 crc7_be(u8 crc, const u8 *buffer, size_t len)¶
更新資料緩衝區的 CRC7
引數
u8 crc先前的 CRC7 值
const u8 *buffer資料指標
size_t len緩衝區中的位元組數
上下文
任何
描述
返回更新後的 CRC7 值。 CRC7 在位元組中左對齊(lsbit 始終為 0),因為這使得計算更容易,並且所有呼叫者都希望它採用這種形式。
-
void crc8_populate_msb(u8 table[CRC8_TABLE_SIZE], u8 polynomial)¶
以反向位順序填充給定多項式的 crc 表。
引數
u8 table[CRC8_TABLE_SIZE]要填充的表。
u8 polynomial要填充表的的多項式。
-
void crc8_populate_lsb(u8 table[CRC8_TABLE_SIZE], u8 polynomial)¶
以常規位順序填充給定多項式的 crc 表。
引數
u8 table[CRC8_TABLE_SIZE]要填充的表。
u8 polynomial要填充表的的多項式。
-
u8 crc8(const u8 table[CRC8_TABLE_SIZE], const u8 *pdata, size_t nbytes, u8 crc)¶
計算給定輸入資料的 crc8。
引數
const u8 table[CRC8_TABLE_SIZE]用於計算的 crc 表。
const u8 *pdata指向資料緩衝區的指標。
size_t nbytes資料緩衝區中的位元組數。
u8 crc先前返回的 crc8 值。
-
u16 crc16(u16 crc, const u8 *p, size_t len)¶
計算資料緩衝區的 CRC-16
引數
u16 crc先前的 CRC 值
const u8 *p資料指標
size_t len緩衝區中的位元組數
描述
返回更新的 CRC 值。
-
u32 crc32_generic_shift(u32 crc, size_t len, u32 polynomial)¶
以對數時間將 **len** 個 0 位元組附加到 crc
引數
u32 crc原始的小端 CRC(即 lsbit 是 x^31 係數)
size_t len位元組數。 **crc** 乘以 x^(8***len**)
u32 polynomial用於將結果減少到 32 位的模數。
描述
可以透過計算緩衝區各個範圍上的 CRC,然後將它們相加來並行化 CRC 計算。 這會將給定的 CRC 移動 8*len 位(即產生與將 len 個零位元組附加到資料相同的效果),時間與 log(len) 成正比。
-
u16 crc_ccitt(u16 crc, u8 const *buffer, size_t len)¶
重新計算資料緩衝區的 CRC(CRC-CCITT 變體)
引數
u16 crc先前的 CRC 值
u8 const *buffer資料指標
size_t len緩衝區中的位元組數
-
u16 crc_itu_t(u16 crc, const u8 *buffer, size_t len)¶
計算資料緩衝區的 CRC-ITU-T
引數
u16 crc先前的 CRC 值
const u8 *buffer資料指標
size_t len緩衝區中的位元組數
描述
返回更新後的 CRC 值
以 2 為底的對數和冪函式¶
-
bool is_power_of_2(unsigned long n)¶
檢查一個值是否為 2 的冪
引數
unsigned long n要檢查的值
描述
確定某個值是否為 2 的冪,其中零不被視為 2 的冪。
返回
如果 **n** 是 2 的冪,則為 true,否則為 false。
-
unsigned long __roundup_pow_of_two(unsigned long n)¶
向上舍入到最接近的 2 的冪
引數
unsigned long n要向上舍入的值
-
unsigned long __rounddown_pow_of_two(unsigned long n)¶
向下舍入到最接近的 2 的冪
引數
unsigned long n要向下舍入的值
-
const_ilog2¶
const_ilog2 (n)
32 位或 64 位常量無符號值的以 2 為底的對數
引數
n引數
描述
在 sparse 期望一個真常量表達式的地方使用它,例如,用於陣列索引。
-
ilog2¶
ilog2 (n)
32 位或 64 位無符號值的以 2 為底的對數
引數
n引數
描述
具有常量能力的以 2 為底的對數計算 - 這可以用於從常量資料初始化全域性變數,因此需要大量的二元運算子構造
根據 sizeof(n) 選擇適當大小的最佳化版本
-
roundup_pow_of_two¶
roundup_pow_of_two (n)
將給定值向上舍入到最接近的 2 的冪
引數
n引數
描述
將給定值向上舍入到最接近的 2 的冪 - 當 n == 0 時,結果是未定義的 - 這可以用於從常量資料初始化全域性變數
-
rounddown_pow_of_two¶
rounddown_pow_of_two (n)
將給定值向下舍入到最接近的 2 的冪
引數
n引數
描述
將給定值向下舍入到最接近的 2 的冪 - 當 n == 0 時,結果是未定義的 - 這可以用於從常量資料初始化全域性變數
-
order_base_2¶
order_base_2 (n)
計算引數的(向上舍入的)以 2 為底的階數
引數
n引數
描述
- 此例程計算的前幾個值
ob2(0) = 0 ob2(1) = 0 ob2(2) = 1 ob2(3) = 2 ob2(4) = 2 ob2(5) = 3 ... 等等。
-
bits_per¶
bits_per (n)
計算引數所需的位數
引數
n引數
描述
這具有常量能力,可以用於編譯時初始化,例如位域。
此例程計算的前幾個值: bf(0) = 1 bf(1) = 1 bf(2) = 2 bf(3) = 2 bf(4) = 3 ... 等等。
整數對數和冪函式¶
-
unsigned int intlog2(u32 value)¶
計算值的 log2;結果左移 24 位
引數
u32 value該值(必須 != 0)
描述
要使用合理的值,您可以使用以下方法
intlog2(value) = intlog2(value * 2^x) - x * 2^24
一些用例示例
intlog2(8) 將給出 3 << 24 = 3 * 2^24
intlog2(9) 將給出 3 << 24 + ... = 3.16... * 2^24
intlog2(1.5) = intlog2(3) - 2^24 = 0.584... * 2^24
返回
log2(value) * 2^24
-
unsigned int intlog10(u32 value)¶
計算值的 log10;結果左移 24 位
引數
u32 value該值(必須 != 0)
描述
要使用合理的值,您可以使用以下方法
intlog10(value) = intlog10(value * 10^x) - x * 2^24
一個用例示例
intlog10(1000) 將給出 3 << 24 = 3 * 2^24
由於實現 intlog10(1000) 可能不完全是 3 * 2^24
檢視 intlog2 以獲取類似的示例
返回
log10(value) * 2^24
-
u64 int_pow(u64 base, unsigned int exp)¶
計算給定底數和指數的指數
引數
u64 base將提高到給定冪的底數
unsigned int exp要提高到的冪
描述
計算:pow(base, exp),即 **base** 提高到 **exp** 次冪
-
unsigned long int_sqrt(unsigned long x)¶
計算整數平方根
引數
unsigned long x要計算平方根的整數
描述
計算:floor(sqrt(x))
-
u32 int_sqrt64(u64 x)¶
當需要最小 64 位輸入時,強烈型別的 int_sqrt 函式。
引數
u64 x用於計算平方根的 64 位整數
除法函式¶
-
do_div¶
do_div (n, base)
返回 2 個值:計算餘數並更新新的被除數
引數
nuint64_t 被除數(將被更新)
baseuint32_t 除數
描述
摘要:uint32_t remainder = n % base; n = n / base;
返回
(uint32_t)remainder
注意
宏引數 n 會被多次計算,小心副作用!
-
u64 div_u64_rem(u64 dividend, u32 divisor, u32 *remainder)¶
帶 32 位除數的無符號 64 位除法,並返回餘數
引數
u64 dividend無符號 64 位被除數
u32 divisor無符號 32 位除數
u32 *remainder指向無符號 32 位餘數的指標
返回
設定 *remainder,然後返回 被除數 / 除數
描述
通常由 32 位架構提供,以提供最佳化的 64 位除法。
-
s64 div_s64_rem(s64 dividend, s32 divisor, s32 *remainder)¶
帶 32 位除數的有符號 64 位除法,並返回餘數
引數
s64 dividend有符號 64 位被除數
s32 divisor有符號 32 位除數
s32 *remainder指向有符號 32 位餘數的指標
返回
設定 *remainder,然後返回 被除數 / 除數
-
u64 div64_u64_rem(u64 dividend, u64 divisor, u64 *remainder)¶
帶 64 位除數的無符號 64 位除法,並返回餘數
引數
u64 dividend無符號 64 位被除數
u64 divisor無符號 64 位除數
u64 *remainder指向無符號 64 位餘數的指標
返回
設定 *remainder,然後返回 被除數 / 除數
-
u64 div64_u64(u64 dividend, u64 divisor)¶
帶 64 位除數的無符號 64 位除法
引數
u64 dividend無符號 64 位被除數
u64 divisor無符號 64 位除數
返回
被除數 / 除數
-
s64 div64_s64(s64 dividend, s64 divisor)¶
帶 64 位除數的有符號 64 位除法
引數
s64 dividend有符號 64 位被除數
s64 divisor有符號 64 位除數
返回
被除數 / 除數
-
u64 div_u64(u64 dividend, u32 divisor)¶
帶 32 位除數的無符號 64 位除法
引數
u64 dividend無符號 64 位被除數
u32 divisor無符號 32 位除數
描述
這是最常見的 64 位除法,如果可能,應該使用它,因為許多 32 位架構可以比完整的 64 位除法更好地最佳化這個變體。
返回
被除數 / 除數
-
s64 div_s64(s64 dividend, s32 divisor)¶
帶 32 位除數的有符號 64 位除法
引數
s64 dividend有符號 64 位被除數
s32 divisor有符號 32 位除數
返回
被除數 / 除數
-
DIV64_U64_ROUND_UP¶
DIV64_U64_ROUND_UP (ll, d)
帶 64 位除數的無符號 64 位除法,向上舍入
引數
ll無符號 64 位被除數
d無符號 64 位除數
描述
將無符號 64 位被除數除以無符號 64 位除數並向上舍入。
返回
被除數 / 除數,向上舍入
-
DIV_U64_ROUND_UP¶
DIV_U64_ROUND_UP (ll, d)
帶 32 位除數的無符號 64 位除法,向上舍入
引數
ll無符號 64 位被除數
d無符號 32 位除數
描述
將無符號 64 位被除數除以無符號 32 位除數並向上舍入。
返回
被除數 / 除數,向上舍入
-
DIV64_U64_ROUND_CLOSEST¶
DIV64_U64_ROUND_CLOSEST (dividend, divisor)
帶 64 位除數的無符號 64 位除法,舍入到最接近的整數
引數
dividend無符號 64 位被除數
divisor無符號 64 位除數
描述
將無符號 64 位被除數除以無符號 64 位除數並舍入到最接近的整數。
返回
被除數 / 除數,舍入到最接近的整數
-
DIV_U64_ROUND_CLOSEST¶
DIV_U64_ROUND_CLOSEST (dividend, divisor)
帶 32 位除數的無符號 64 位除法,舍入到最接近的整數
引數
dividend無符號 64 位被除數
divisor無符號 32 位除數
描述
將無符號 64 位被除數除以無符號 32 位除數並舍入到最接近的整數。
返回
被除數 / 除數,舍入到最接近的整數
-
DIV_S64_ROUND_CLOSEST¶
DIV_S64_ROUND_CLOSEST (dividend, divisor)
帶 32 位除數的有符號 64 位除法,舍入到最接近的整數
引數
dividend有符號 64 位被除數
divisor有符號 32 位除數
描述
將有符號 64 位被除數除以有符號 32 位除數並舍入到最接近的整數。
返回
被除數 / 除數,舍入到最接近的整數
-
u64 roundup_u64(u64 x, u32 y)¶
將 64 位值向上舍入到下一個指定的 32 位倍數
引數
u64 x要向上舍入的值
u32 y要向上舍入到的 32 位倍數
描述
將 x 舍入到 y 的下一個倍數。對於 32 位 x 值,請參閱 roundup 和更快的 round_up(),適用於 2 的冪。
返回
向上舍入的值。
-
unsigned long gcd(unsigned long a, unsigned long b)¶
計算並返回 2 個無符號長整型的最大公約數
引數
unsigned long a第一個值
unsigned long b第二個值
UUID/GUID¶
-
void generate_random_uuid(unsigned char uuid[16])¶
生成一個隨機 UUID
引數
unsigned char uuid[16]將生成的 UUID 放入何處
描述
隨機 UUID 介面
用於建立啟動 ID 或檔案系統 UUID/GUID,但對於其他核心驅動程式也很有用。
-
bool uuid_is_valid(const char *uuid)¶
檢查 UUID 字串是否有效
引數
const char *uuid要檢查的 UUID 字串
描述
- 它檢查 UUID 字串是否符合格式
xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
其中 x 是一個十六進位制數字。
返回
如果輸入是有效的 UUID 字串,則為 true。
核心 IPC 機制¶
IPC 實用程式¶
-
int ipc_init(void)¶
初始化 ipc 子系統
引數
void無引數
描述
初始化各種 sysv ipc 資源(訊號量、訊息和共享記憶體)。
一個回撥例程被註冊到記憶體熱插拔通知鏈中:由於 msgmni 擴充套件到 lowmem,因此在成功新增/刪除記憶體後,將呼叫此回撥例程以重新計算 msmgni。
-
void ipc_init_ids(struct ipc_ids *ids)¶
初始化 ipc 識別符號
引數
struct ipc_ids *idsipc 識別符號集
描述
設定用於 ipc 識別符號範圍的序列範圍(限制在 ipc_mni 以下),然後初始化金鑰雜湊表和 ids idr。
-
void ipc_init_proc_interface(const char *path, const char *header, int ids, int (*show)(struct seq_file*, void*))¶
使用 seq_file 介面為 sysipc 型別建立一個 proc 介面。
引數
const char *pathprocfs 中的路徑
const char *header要在檔案開頭列印的橫幅。
int ids要迭代的 ipc id 表。
int (*show)(struct seq_file *, void *)show 例程。
-
struct kern_ipc_perm *ipc_findkey(struct ipc_ids *ids, key_t key)¶
在 ipc 識別符號集中查詢金鑰
引數
struct ipc_ids *idsipc 識別符號集
key_t key要查詢的金鑰
描述
如果找到,則返回指向 ipc 結構的鎖定指標,否則返回 NULL。如果找到金鑰,則 ipc 指向擁有的 ipc 結構
使用 writer ipc_ids.rwsem 持有來呼叫。
-
int ipc_addid(struct ipc_ids *ids, struct kern_ipc_perm *new, int limit)¶
新增一個 ipc 識別符號
引數
struct ipc_ids *idsipc 識別符號集
struct kern_ipc_perm *new新的 ipc 許可權集
int limit已使用 id 的數量限制
描述
向 ipc ids idr 新增一個條目“new”。許可權物件被初始化,並設定第一個空閒條目,並返回分配的索引。“new”條目在成功時以鎖定狀態返回。
如果失敗,則該條目未被鎖定,並返回一個負錯誤程式碼。呼叫者必須使用 ipc_rcu_putref() 來釋放識別符號。
使用 writer ipc_ids.rwsem 持有來呼叫。
-
int ipcget_new(struct ipc_namespace *ns, struct ipc_ids *ids, const struct ipc_ops *ops, struct ipc_params *params)¶
建立一個新的 ipc 物件
引數
struct ipc_namespace *nsipc 名稱空間
struct ipc_ids *idsipc 識別符號集
const struct ipc_ops *ops要呼叫的實際建立例程
struct ipc_params *params其引數
描述
當金鑰為 IPC_PRIVATE 時,sys_msgget、sys_semget() 和 sys_shmget() 會呼叫此例程。
-
int ipc_check_perms(struct ipc_namespace *ns, struct kern_ipc_perm *ipcp, const struct ipc_ops *ops, struct ipc_params *params)¶
檢查 ipc 物件的安全和許可權
引數
struct ipc_namespace *nsipc 名稱空間
struct kern_ipc_perm *ipcpipc 許可權集合
const struct ipc_ops *ops要呼叫的實際安全例程
struct ipc_params *params其引數
描述
當鍵不是 IPC_PRIVATE 並且該鍵已存在於 ds IDR 中時,sys_msgget()、sys_semget() 和 sys_shmget() 會呼叫此例程。
成功時,返回 ipc id。
呼叫時會持有 ipc_ids.rwsem 和 ipcp->lock。
-
int ipcget_public(struct ipc_namespace *ns, struct ipc_ids *ids, const struct ipc_ops *ops, struct ipc_params *params)¶
獲取一個 ipc 物件或建立一個新的 ipc 物件
引數
struct ipc_namespace *nsipc 名稱空間
struct ipc_ids *idsipc 識別符號集
const struct ipc_ops *ops要呼叫的實際建立例程
struct ipc_params *params其引數
描述
當鍵不是 IPC_PRIVATE 時,sys_msgget、sys_semget() 和 sys_shmget() 會呼叫此例程。如果找不到該鍵,則會新增一個新條目;如果找到該鍵,則會進行一些許可權/安全檢查。
成功時,返回 ipc id。
-
void ipc_kht_remove(struct ipc_ids *ids, struct kern_ipc_perm *ipcp)¶
從鍵雜湊表中刪除一個 ipc
引數
struct ipc_ids *idsipc 識別符號集
struct kern_ipc_perm *ipcp包含要刪除的鍵的 ipc perm 結構
描述
在此函式被呼叫之前,會持有 ipc_ids.rwsem(作為寫入者)和此 ID 的自旋鎖,並且在退出時保持鎖定。
-
int ipc_search_maxidx(struct ipc_ids *ids, int limit)¶
搜尋分配的最高索引
引數
struct ipc_ids *idsipc 識別符號集
int limit分配的最高索引的已知上限
描述
該函式確定 **ids** 中分配的最高索引。它旨在在需要更新 ids->max_idx 時呼叫。當刪除當前最高索引 ipc 物件時,更新 ids->max_idx 是必要的。如果沒有分配 ipc 物件,則返回 -1。
ipc_ids.rwsem 需要由呼叫者持有。
-
void ipc_rmid(struct ipc_ids *ids, struct kern_ipc_perm *ipcp)¶
刪除一個 ipc 識別符號
引數
struct ipc_ids *idsipc 識別符號集
struct kern_ipc_perm *ipcp包含要刪除的識別符號的 ipc perm 結構
描述
在此函式被呼叫之前,會持有 ipc_ids.rwsem(作為寫入者)和此 ID 的自旋鎖,並且在退出時保持鎖定。
-
void ipc_set_key_private(struct ipc_ids *ids, struct kern_ipc_perm *ipcp)¶
將現有 ipc 的鍵切換到 IPC_PRIVATE
引數
struct ipc_ids *idsipc 識別符號集
struct kern_ipc_perm *ipcp包含要修改的鍵的 ipc perm 結構
描述
在此函式被呼叫之前,會持有 ipc_ids.rwsem(作為寫入者)和此 ID 的自旋鎖,並且在退出時保持鎖定。
-
int ipcperms(struct ipc_namespace *ns, struct kern_ipc_perm *ipcp, short flag)¶
檢查 ipc 許可權
引數
struct ipc_namespace *nsipc 名稱空間
struct kern_ipc_perm *ipcpipc 許可權集合
short flag所需的許可權集合
描述
檢查使用者、組、其他使用者對 ipc 資源的訪問許可權。如果允許,則返回 0
**flag** 最有可能為 0 或 <linux/stat.h> 中的 S_...UGO
-
void kernel_to_ipc64_perm(struct kern_ipc_perm *in, struct ipc64_perm *out)¶
將核心 ipc 許可權轉換為使用者許可權
引數
struct kern_ipc_perm *in核心許可權
struct ipc64_perm *out新樣式的 ipc 許可權
描述
將核心物件 **in** 轉換為一組許可權描述,以便返回給使用者空間 (**out**)。
-
void ipc64_perm_to_ipc_perm(struct ipc64_perm *in, struct ipc_perm *out)¶
將新的 ipc 許可權轉換為舊的 ipc 許可權
引數
struct ipc64_perm *in新樣式的 ipc 許可權
struct ipc_perm *out舊樣式的 ipc 許可權
描述
將新樣式的許可權物件 **in** 轉換為一個相容性物件,並將其儲存到 **out** 指標中。
-
struct kern_ipc_perm *ipc_obtain_object_idr(struct ipc_ids *ids, int id)¶
在 ipc ids idr 中查詢一個 id,並返回關聯的 ipc 物件。
引數
struct ipc_ids *idsipc 識別符號集
int id要查詢的 ipc id
描述
在 RCU 臨界區內呼叫。退出時 ipc 物件未鎖定。
-
struct kern_ipc_perm *ipc_obtain_object_check(struct ipc_ids *ids, int id)¶
與
ipc_obtain_object_idr()類似,但也檢查 ipc 物件序列號。
引數
struct ipc_ids *idsipc 識別符號集
int id要查詢的 ipc id
描述
在 RCU 臨界區內呼叫。退出時 ipc 物件未鎖定。
-
int ipcget(struct ipc_namespace *ns, struct ipc_ids *ids, const struct ipc_ops *ops, struct ipc_params *params)¶
通用的 sys_*get() 程式碼
引數
struct ipc_namespace *ns名稱空間
struct ipc_ids *idsipc 識別符號集
const struct ipc_ops *ops要在 ipc 物件建立、許可權檢查和進一步檢查時呼叫的操作
struct ipc_params *params先前操作所需的引數。
描述
sys_msgget()、sys_semget() 和 sys_shmget() 呼叫的通用例程。
-
int ipc_update_perm(struct ipc64_perm *in, struct kern_ipc_perm *out)¶
更新 ipc 物件的許可權
引數
struct ipc64_perm *in作為輸入給定的許可權。
struct kern_ipc_perm *out要設定的 ipc 的許可權。
-
struct kern_ipc_perm *ipcctl_obtain_check(struct ipc_namespace *ns, struct ipc_ids *ids, int id, int cmd, struct ipc64_perm *perm, int extra_perm)¶
檢索 ipc 物件並檢查許可權
引數
struct ipc_namespace *nsipc 名稱空間
struct ipc_ids *ids要在其中查詢 ipc 的 id 表
int id要檢索的 ipc 的 id
int cmd要檢查的 cmd
struct ipc64_perm *perm要設定的許可權
int extra_permmsq 使用的一個額外的許可權引數
描述
此函式為某些 IPC_XXX cmd 執行一些常見的審計和許可權檢查,並從 semctl_down、shmctl_down 和 msgctl_down 呼叫。
- 它
使用給定 id 在給定表中檢索 ipc 物件。
根據給定的 cmd 執行一些審計和許可權檢查
返回指向 ipc 物件的指標,否則返回相應的錯誤。
呼叫時持有 rwsem 和 rcu 讀鎖。
-
int ipc_parse_version(int *cmd)¶
ipc 呼叫版本
引數
int *cmd指向命令的指標
描述
對於新的 IPC 樣式,返回 IPC_64;對於舊的 IPC 樣式,返回 IPC_OLD。 **cmd** 值從編碼命令和版本轉換為僅命令程式碼。
-
struct kern_ipc_perm *sysvipc_find_ipc(struct ipc_ids *ids, loff_t *pos)¶
基於 seq pos 查詢並鎖定 ipc 結構
引數
struct ipc_ids *idsipc 識別符號集
loff_t *pos預期位置
描述
該函式基於序列檔案位置 **pos** 查詢 ipc 結構。如果在位置 **pos** 處沒有 ipc 結構,則選擇後繼者。如果找到一個結構,則鎖定它(同時鎖定 rcu_read_lock() 和 ipc_lock_object()),並且將 **pos** 設定為定位找到的 ipc 結構所需的位置。如果未找到任何內容(即 EOF),則 **pos** 不會被修改。
該函式返回找到的 ipc 結構,或者在 EOF 時返回 NULL。
FIFO 緩衝區¶
kfifo 介面¶
-
DECLARE_KFIFO_PTR¶
DECLARE_KFIFO_PTR (fifo, type)
宣告一個 fifo 指標物件的宏
引數
fifo宣告的 fifo 的名稱
typefifo 元素的型別
-
DECLARE_KFIFO¶
DECLARE_KFIFO (fifo, type, size)
宣告一個 fifo 物件的宏
引數
fifo宣告的 fifo 的名稱
typefifo 元素的型別
sizefifo 中的元素數量,這必須是 2 的冪
-
INIT_KFIFO¶
INIT_KFIFO (fifo)
初始化由 DECLARE_KFIFO 宣告的 fifo
引數
fifo宣告的 fifo 資料型別的名稱
-
DEFINE_KFIFO¶
DEFINE_KFIFO (fifo, type, size)
定義並初始化一個 fifo 的宏
引數
fifo宣告的 fifo 資料型別的名稱
typefifo 元素的型別
sizefifo 中的元素數量,這必須是 2 的冪
注意
該宏可用於全域性和本地 fifo 資料型別變數。
-
kfifo_initialized¶
kfifo_initialized (fifo)
檢查 fifo 是否已初始化
引數
fifo要檢查的 fifo 的地址
描述
如果 fifo 已初始化,則返回 true,否則返回 false。假設 fifo 之前為 0。
-
kfifo_esize¶
kfifo_esize (fifo)
返回 fifo 管理的元素的大小
引數
fifo要使用的 fifo 的地址
-
kfifo_recsize¶
kfifo_recsize (fifo)
返回記錄長度欄位的大小
引數
fifo要使用的 fifo 的地址
-
kfifo_size¶
kfifo_size (fifo)
返回 fifo 的元素大小
引數
fifo要使用的 fifo 的地址
-
kfifo_reset¶
kfifo_reset (fifo)
刪除整個 fifo 內容
-
kfifo_reset_out¶
kfifo_reset_out (fifo)
跳過 FIFO 內容
引數
fifo要使用的 fifo 的地址
注意
使用 kfifo_reset_out() 是安全的,前提是它只從讀取執行緒呼叫,並且只有一個併發讀取器。否則,它是危險的,必須以與 kfifo_reset() 相同的方式處理。
-
kfifo_len¶
kfifo_len (fifo)
返回 FIFO 中已用元素的數量
引數
fifo要使用的 fifo 的地址
-
kfifo_is_empty¶
kfifo_is_empty (fifo)
如果 FIFO 為空,則返回 true
引數
fifo要使用的 fifo 的地址
-
kfifo_is_empty_spinlocked¶
kfifo_is_empty_spinlocked (fifo, lock)
如果 FIFO 為空,則返回 true,使用自旋鎖進行鎖定
引數
fifo要使用的 fifo 的地址
lock用於鎖定的自旋鎖
-
kfifo_is_empty_spinlocked_noirqsave¶
kfifo_is_empty_spinlocked_noirqsave (fifo, lock)
如果 FIFO 為空,則返回 true,使用自旋鎖進行鎖定,不停用中斷
引數
fifo要使用的 fifo 的地址
lock用於鎖定的自旋鎖
-
kfifo_is_full¶
kfifo_is_full (fifo)
如果 FIFO 已滿,則返回 true
引數
fifo要使用的 fifo 的地址
-
kfifo_avail¶
kfifo_avail (fifo)
返回 FIFO 中未使用的元素的數量
引數
fifo要使用的 fifo 的地址
-
kfifo_skip_count¶
kfifo_skip_count (fifo, count)
跳過輸出資料
引數
fifo要使用的 fifo 的地址
count要跳過的資料計數
-
kfifo_skip¶
kfifo_skip (fifo)
跳過輸出資料
引數
fifo要使用的 fifo 的地址
-
kfifo_peek_len¶
kfifo_peek_len (fifo)
獲取下一個 FIFO 記錄的大小
引數
fifo要使用的 fifo 的地址
描述
此函式返回下一個 FIFO 記錄的大小,以位元組為單位。
-
kfifo_alloc¶
kfifo_alloc (fifo, size, gfp_mask)
動態分配一個新的 FIFO 緩衝區
引數
fifo指向 FIFO 的指標
sizefifo 中的元素數量,這必須是 2 的冪
gfp_maskget_free_pages 掩碼,傳遞給
kmalloc()
描述
此宏動態分配一個新的 FIFO 緩衝區。
元素的數量將向上舍入為 2 的冪。FIFO 將透過 kfifo_free() 釋放。如果沒有錯誤,則返回 0,否則返回一個錯誤程式碼。
-
kfifo_free¶
kfifo_free (fifo)
釋放 FIFO
引數
fifo要釋放的 FIFO
-
kfifo_init¶
kfifo_init (fifo, buffer, size)
使用預先分配的緩衝區初始化 FIFO
引數
fifo要分配緩衝區的 FIFO
buffer要使用的預先分配的緩衝區
size內部緩衝區的大小,這必須是 2 的冪
描述
此宏使用預先分配的緩衝區初始化 FIFO。
元素的數量將向上舍入為 2 的冪。如果沒有錯誤,則返回 0,否則返回一個錯誤程式碼。
-
kfifo_put¶
kfifo_put (fifo, val)
將資料放入 FIFO
引數
fifo要使用的 fifo 的地址
val要新增的資料
描述
此宏將給定的值複製到 FIFO 中。如果 FIFO 已滿,則返回 0。否則,它返回已處理元素的數量。
請注意,只有單個併發讀取器和單個併發寫入器,您不需要額外的鎖定即可使用這些宏。
-
kfifo_get¶
kfifo_get (fifo, val)
從 FIFO 獲取資料
引數
fifo要使用的 fifo 的地址
val儲存資料的地址
描述
此宏從 FIFO 讀取資料。如果 FIFO 為空,則返回 0。否則,它返回已處理元素的數量。
請注意,只有單個併發讀取器和單個併發寫入器,您不需要額外的鎖定即可使用這些宏。
-
kfifo_peek¶
kfifo_peek (fifo, val)
從 FIFO 獲取資料而不刪除
引數
fifo要使用的 fifo 的地址
val儲存資料的地址
描述
這從 FIFO 讀取資料而不從 FIFO 中刪除它。如果 FIFO 為空,則返回 0。否則,它返回已處理元素的數量。
請注意,只有單個併發讀取器和單個併發寫入器,您不需要額外的鎖定即可使用這些宏。
-
kfifo_in¶
kfifo_in (fifo, buf, n)
將資料放入 FIFO
引數
fifo要使用的 fifo 的地址
buf要新增的資料
n要新增的元素的數量
描述
此宏將給定的緩衝區複製到 FIFO 中,並返回複製的元素的數量。
請注意,只有單個併發讀取器和單個併發寫入器,您不需要額外的鎖定即可使用這些宏。
-
kfifo_in_spinlocked¶
kfifo_in_spinlocked (fifo, buf, n, lock)
將資料放入 FIFO,使用自旋鎖進行鎖定
引數
fifo要使用的 fifo 的地址
buf要新增的資料
n要新增的元素的數量
lock指向用於鎖定的自旋鎖的指標
描述
此宏將給定的值緩衝區複製到 FIFO 中,並返回複製的元素的數量。
-
kfifo_in_spinlocked_noirqsave¶
kfifo_in_spinlocked_noirqsave (fifo, buf, n, lock)
將資料放入 FIFO,使用自旋鎖進行鎖定,不停用中斷
引數
fifo要使用的 fifo 的地址
buf要新增的資料
n要新增的元素的數量
lock指向用於鎖定的自旋鎖的指標
描述
這是 kfifo_in_spinlocked() 的一個變體,但使用 spin_lock/unlock() 進行鎖定,並且不停用中斷。
-
kfifo_out¶
kfifo_out (fifo, buf, n)
從 FIFO 獲取資料
引數
fifo要使用的 fifo 的地址
buf指向儲存緩衝區的指標
n要獲取的元素的最大數量
描述
此宏從 FIFO 獲取一些資料,並返回複製的元素的數量。
請注意,只有單個併發讀取器和單個併發寫入器,您不需要額外的鎖定即可使用這些宏。
-
kfifo_out_spinlocked¶
kfifo_out_spinlocked (fifo, buf, n, lock)
從 FIFO 獲取資料,使用自旋鎖進行鎖定
引數
fifo要使用的 fifo 的地址
buf指向儲存緩衝區的指標
n要獲取的元素的最大數量
lock指向用於鎖定的自旋鎖的指標
描述
此宏從 FIFO 獲取資料,並返回複製的元素的數量。
-
kfifo_out_spinlocked_noirqsave¶
kfifo_out_spinlocked_noirqsave (fifo, buf, n, lock)
從 FIFO 獲取資料,使用自旋鎖進行鎖定,不停用中斷
引數
fifo要使用的 fifo 的地址
buf指向儲存緩衝區的指標
n要獲取的元素的最大數量
lock指向用於鎖定的自旋鎖的指標
描述
這是 kfifo_out_spinlocked() 的一個變體,它使用 spin_lock/unlock() 進行鎖定,並且不停用中斷。
-
kfifo_from_user¶
kfifo_from_user (fifo, from, len, copied)
將一些來自使用者空間的資料放入 FIFO
引數
fifo要使用的 fifo 的地址
from指向要新增的資料的指標
len要新增的資料的長度
copied指向輸出變數的指標,用於儲存複製的位元組數
描述
此宏從 **from** 將最多 **len** 個位元組複製到 FIFO 中,具體取決於可用空間,並返回 -EFAULT/0。
請注意,只有單個併發讀取器和單個併發寫入器,您不需要額外的鎖定即可使用這些宏。
-
kfifo_to_user¶
kfifo_to_user (fifo, to, len, copied)
將資料從 FIFO 複製到使用者空間
引數
fifo要使用的 fifo 的地址
to必須將資料複製到哪裡
len目標緩衝區的大小
copied指向輸出變數的指標,用於儲存複製的位元組數
描述
此宏從 FIFO 將最多 **len** 個位元組複製到 **to** 緩衝區,並返回 -EFAULT/0。
請注意,只有單個併發讀取器和單個併發寫入器,您不需要額外的鎖定即可使用這些宏。
-
kfifo_dma_in_prepare_mapped¶
kfifo_dma_in_prepare_mapped (fifo, sgl, nents, len, dma)
設定用於 DMA 輸入的散列表
引數
fifo要使用的 fifo 的地址
sgl指向散列表陣列的指標
nents散列表陣列中的條目數
len要傳輸的元素的數量
dma要填充到 **sgl** 中的對映的 DMA 地址
描述
此宏填充用於 DMA 輸入的散列表。它返回散列表陣列中的條目數。
請注意,只有單個併發讀取器和單個併發寫入器,您不需要額外的鎖定即可使用這些宏。
-
kfifo_dma_in_finish¶
kfifo_dma_in_finish (fifo, len)
完成 DMA IN 操作
引數
fifo要使用的 fifo 的地址
len要接收的位元組數
描述
此宏完成 DMA IN 操作。in 計數器將由 len 引數更新。不會進行錯誤檢查。
請注意,只有單個併發讀取器和單個併發寫入器,您不需要額外的鎖定即可使用這些宏。
-
kfifo_dma_out_prepare_mapped¶
kfifo_dma_out_prepare_mapped (fifo, sgl, nents, len, dma)
設定用於 DMA 輸出的散列表
引數
fifo要使用的 fifo 的地址
sgl指向散列表陣列的指標
nents散列表陣列中的條目數
len要傳輸的元素的數量
dma要填充到 **sgl** 中的對映的 DMA 地址
描述
此宏填充用於 DMA 輸出的散列表,最多傳輸 **len** 個位元組。它返回散列表陣列中的條目數。零表示沒有可用空間,並且未填充散列表。
請注意,只有單個併發讀取器和單個併發寫入器,您不需要額外的鎖定即可使用這些宏。
-
kfifo_dma_out_finish¶
kfifo_dma_out_finish (fifo, len)
完成 DMA OUT 操作
引數
fifo要使用的 fifo 的地址
len傳輸的位元組數
描述
此宏完成 DMA OUT 操作。out 計數器將由 len 引數更新。不會進行錯誤檢查。
請注意,只有單個併發讀取器和單個併發寫入器,您不需要額外的鎖定即可使用這些宏。
-
kfifo_out_peek¶
kfifo_out_peek (fifo, buf, n)
從 FIFO 獲取一些資料
引數
fifo要使用的 fifo 的地址
buf指向儲存緩衝區的指標
n要獲取的元素的最大數量
描述
此宏從 FIFO 獲取資料,並返回複製的元素的數量。資料不會從 FIFO 中刪除。
請注意,只有單個併發讀取器和單個併發寫入器,您不需要額外的鎖定即可使用這些宏。
-
kfifo_out_linear¶
kfifo_out_linear (fifo, tail, n)
獲取可用資料的尾部/偏移量
引數
fifo要使用的 fifo 的地址
tail指向要儲存尾部值的無符號整數的指標
n要指向的元素的最大數量
描述
此宏獲取 FIFO 緩衝區中可用資料的偏移量(尾部),並返回可用元素的數量。它返回到資料結尾或緩衝區結尾的可用計數。因此,它可以用於線性資料處理(如 memcpy() of ( **fifo->data** + **tail**) with 返回的計數)。
請注意,只有單個併發讀取器和單個併發寫入器,您不需要額外的鎖定即可使用這些宏。
-
kfifo_out_linear_ptr¶
kfifo_out_linear_ptr (fifo, ptr, n)
獲取指向可用資料的指標
引數
fifo要使用的 fifo 的地址
ptr指向要儲存指向尾部的指標的資料的指標
n要指向的元素的最大數量
描述
與 kfifo_out_linear() 類似,此宏獲取 FIFO 緩衝區中可用資料的指標,並返回可用元素的數量。它返回到可用資料結尾或緩衝區結尾的可用計數。因此,它可以用於線性資料處理(如 memcpy() of **ptr** with 返回的計數)。
請注意,只有單個併發讀取器和單個併發寫入器,您不需要額外的鎖定即可使用這些宏。
繼電器介面支援¶
繼電器介面支援旨在為工具和設施提供一種有效的機制,以便將大量資料從核心空間傳遞到使用者空間。
繼電器介面¶
-
int relay_buf_full(struct rchan_buf *buf)¶
布林值,通道緩衝區是否已滿?
引數
struct rchan_buf *buf通道緩衝區
如果緩衝區已滿,則返回 1,否則返回 0。
-
void relay_reset(struct rchan *chan)¶
重置通道
引數
struct rchan *chan通道
這具有擦除所有通道緩衝區中的所有資料,並以其初始狀態重新啟動通道的效果。緩衝區不會被釋放,因此任何對映仍然有效。
注意。應注意,在進行此呼叫時,該通道實際上沒有被任何東西使用。
-
struct rchan *relay_open(const char *base_filename, struct dentry *parent, size_t subbuf_size, size_t n_subbufs, const struct rchan_callbacks *cb, void *private_data)¶
建立一個新的繼電器通道
引數
const char *base_filename要建立的檔案的基本名稱
struct dentry *parent父目錄的目錄項,根目錄或緩衝區的
NULLsize_t subbuf_size子緩衝區的大小
size_t n_subbufs子緩衝區的數量
const struct rchan_callbacks *cb客戶端回撥函式
void *private_data使用者定義的資料
如果成功,則返回通道指標,否則返回
NULL。使用指定的大小和屬性為每個 CPU 建立一個通道緩衝區。建立的通道緩衝區檔案將命名為 base_filename0...base_filenameN-1。檔案許可權將為
S_IRUSR。
-
size_t relay_switch_subbuf(struct rchan_buf *buf, size_t length)¶
切換到新的子緩衝區
引數
struct rchan_buf *buf通道緩衝區
size_t length當前事件的大小
如果緩衝區已滿,則返回傳入的長度,否則返回 0。
執行子緩衝區切換任務,例如呼叫回撥函式、更新填充計數、喚醒讀取器等。
-
void relay_subbufs_consumed(struct rchan *chan, unsigned int cpu, size_t subbufs_consumed)¶
更新緩衝區的已消耗子緩衝區計數
引數
struct rchan *chan通道
unsigned int cpu要更新的通道緩衝區關聯的 CPU
size_t subbufs_consumed要新增到當前緩衝區計數的子緩衝區數量
新增到通道緩衝區已消耗的子緩衝區計數。 subbufs_consumed 應該是新消耗的子緩衝區的數量,而不是總共消耗的數量。
注意:如果通道模式為“overwrite”,則核心客戶端無需呼叫此函式。
-
void relay_close(struct rchan *chan)¶
關閉通道
引數
struct rchan *chan通道
關閉所有通道緩衝區並釋放通道。
-
void relay_flush(struct rchan *chan)¶
關閉通道
引數
struct rchan *chan通道
重新整理所有通道緩衝區,即強制緩衝區切換。
-
int relay_mmap_buf(struct rchan_buf *buf, struct vm_area_struct *vma)¶
將通道緩衝區 mmap 到程序地址空間
引數
struct rchan_buf *bufrelay 通道緩衝區
struct vm_area_struct *vma描述要對映的記憶體的 vm_area_struct
如果成功則返回 0,出錯則返回負數
呼叫者應已獲取 mmap_lock。
-
void *relay_alloc_buf(struct rchan_buf *buf, size_t *size)¶
分配通道緩衝區
引數
struct rchan_buf *buf緩衝區結構體
size_t *size緩衝區的總大小
返回指向結果緩衝區的指標,如果失敗則返回
NULL。傳入的大小將被頁對齊(如果尚未對齊)。
-
struct rchan_buf *relay_create_buf(struct rchan *chan)¶
分配並初始化通道緩衝區
引數
struct rchan *chanrelay 通道
如果成功,則返回通道緩衝區,否則返回
NULL。
引數
struct kref *kref包含 relay 通道的目標核心引用
只能從
kref_put()呼叫。
-
void relay_destroy_buf(struct rchan_buf *buf)¶
銷燬 rchan_buf 結構體和關聯的緩衝區
引數
struct rchan_buf *buf緩衝區結構體
引數
struct kref *kref包含 relay 緩衝區的目標核心引用
從檔案系統中移除該檔案,同時釋放 rchan_buf_struct 和通道緩衝區。 只能從
kref_put()呼叫。
-
int relay_buf_empty(struct rchan_buf *buf)¶
布林值,通道緩衝區是否為空?
引數
struct rchan_buf *buf通道緩衝區
如果緩衝區為空,則返回 1,否則返回 0。
-
void wakeup_readers(struct irq_work *work)¶
喚醒等待通道的讀取器
引數
struct irq_work *work包含通道緩衝區
此函式用於延遲讀取器喚醒
-
void __relay_reset(struct rchan_buf *buf, unsigned int init)¶
重置通道緩衝區
引數
struct rchan_buf *buf通道緩衝區
unsigned int init如果是首次初始化,則為 1
有關效果的說明,請參見
relay_reset()。
-
void relay_close_buf(struct rchan_buf *buf)¶
關閉通道緩衝區
引數
struct rchan_buf *buf通道緩衝區
將緩衝區標記為已完成,並恢復預設回撥函式。當放棄最後一個引用時,通道緩衝區和通道緩衝區資料結構會自動釋放。
引數
struct inode *inodeinode
struct file *filp檔案
增加通道緩衝區引用計數。
引數
struct file *filp檔案
struct vm_area_struct *vma描述要對映的內容的 vma
呼叫
relay_mmap_buf()將檔案對映到使用者空間。
引數
struct file *filp檔案
poll_table *waitpoll 表
Poll 實現。
引數
struct inode *inodeinode
struct file *filp檔案
減少通道引用計數,因為檔案系統不再使用它。
-
size_t relay_file_read_subbuf_avail(size_t read_pos, struct rchan_buf *buf)¶
返回子緩衝區中可用的位元組數
引數
size_t read_pos檔案讀取位置
struct rchan_buf *bufrelay 通道緩衝區
-
size_t relay_file_read_start_pos(struct rchan_buf *buf)¶
查詢第一個可讀取的位元組
引數
struct rchan_buf *bufrelay 通道緩衝區
如果 read_pos 位於填充的中間,則返回第一個實際可用位元組的位置,否則返回原始值。
-
size_t relay_file_read_end_pos(struct rchan_buf *buf, size_t read_pos, size_t count)¶
返回新的讀取位置
引數
struct rchan_buf *bufrelay 通道緩衝區
size_t read_pos檔案讀取位置
size_t count要讀取的位元組數
模組支援¶
核心模組自動載入¶
-
int __request_module(bool wait, const char *fmt, ...)¶
嘗試載入核心模組
引數
bool wait等待(或不等待)操作完成
const char *fmt模組名稱的 printf 風格格式字串
...格式字串中指定的引數
描述
使用使用者模式模組載入器載入模組。 如果成功,該函式返回零;如果失敗,則返回負數的 errno 程式碼或來自“modprobe”的正退出程式碼。 請注意,成功載入模組並不意味著該模組沒有解除安裝並因自身錯誤而退出。 呼叫者必須檢查他們請求的服務現在是否可用,而不是盲目地呼叫它。
如果停用了模組自動載入支援,則此函式只返回 -ENOENT。
模組除錯¶
啟用 CONFIG_MODULE_STATS 可以啟用模組除錯統計資訊,這些統計資訊對於監視和根本原因分析模組載入中的記憶體壓力問題很有用。 這些統計資訊有助於我們改進生產工作負載。
當前支援的模組除錯統計資訊有助於跟蹤模組載入失敗,以便改進核心模組自動載入的使用 (request_module()) 或與使用者空間的互動。 提供的統計資訊用於跟蹤 finit_module() 路徑中的所有可能失敗以及在此過程空間中浪費的記憶體。 每個失敗計數器都與一種模組載入失敗型別相關聯,已知這種失敗會導致一定數量的記憶體分配丟失。 在最壞的情況下,載入模組將在 3 步記憶體分配過程後失敗
使用 kernel_read_file_from_fd() 分配的記憶體
模組解壓縮處理從 kernel_read_file_from_fd() 讀取的檔案,並使用
vmap()將解壓縮的模組對映到新的本地緩衝區,該緩衝區表示從使用者空間傳遞的解壓縮模組的副本。 kernel_read_file_from_fd() 中的緩衝區會立即釋放。layout_and_allocate() 為最終位置分配空間,如果模組已成功處理,我們將把模組儲存在該位置。
如果在這些三種不同的分配之後發生失敗,則只會遞增一個計數器,其中包含在此失敗期間釋放的已分配位元組的總和。 同樣,如果模組載入僅在步驟 b) 之後失敗,則將使用單獨的計數器,併為這兩個分配期間釋放且未使用的位元組數遞增該計數器。
虛擬記憶體空間可能會受到限制,例如,在 x86 上,虛擬記憶體大小預設為 128 MiB。 我們應盡力限制和避免在可能的情況下浪費虛擬記憶體分配。 這些模組除錯統計資訊有助於評估由於模組載入失敗而在啟動時浪費了多少記憶體。
所有計數器都設計為增量式的。 使用原子計數器是為了保持簡單並避免延遲和死鎖。
dup_failed_modules - 跟蹤重複的失敗模組¶
由於已在處理或已載入名稱相同的現有模組而未能載入的模組的連結列表。 finit_module() 系統呼叫會導致大量虛擬記憶體分配。 在最壞的情況下,finit_module() 系統呼叫最終可以分配虛擬記憶體 3 次
kernel_read_file_from_fd() 呼叫使用 vmalloc()
可選的模組解壓縮使用
vmap()layout_and allocate() 可以使用 vzalloc() 或 vmalloc 的特定於體系結構的版本來處理需要特殊許可權的 ELF 部分
實際上,在今天的典型啟動中,大多數 finit_module() 呼叫都失敗了,原因是具有相同名稱的模組已載入或即將被處理。 分配給這些失敗模組的所有虛擬記憶體都將被釋放,而沒有實際用途。
為了幫助解決此問題,dup_failed_modules 使我們能夠跟蹤由於模組已載入或正在被處理而未能載入的模組。 我們只有兩個可以使此類呼叫失敗的點,我們在下面列出了它們以及虛擬記憶體分配呼叫的數量
FAIL_DUP_MOD_BECOMING:在 layout_and_allocate() 之前的 early_mod_check() 結束時。 - 使用模組解壓縮:2 個虛擬記憶體分配呼叫 - 不使用模組解壓縮:1 個虛擬記憶體分配呼叫
FAIL_DUP_MOD_LOAD:在 add_unformed_module() 上 layout_and_allocate() 之後 - 使用模組解壓縮:3 個虛擬記憶體分配呼叫 - 不使用模組解壓縮:2 個虛擬記憶體分配呼叫
我們應努力使此列表儘可能小。 如果此列表不為空,則反映了核心或使用者空間中可能存在的工作或最佳化。
模組統計資訊 debugfs 計數器¶
模組載入期間浪費的虛擬記憶體分配空間總量可以透過將總和相加來計算
invalid_kread_bytes + invalid_decompress_bytes + invalid_becoming_bytes + invalid_mod_bytes
以下 debugfs 計數器可用於檢查模組載入失敗
total_mod_size:我們在此係統上處理過的所有模組使用的總位元組數
total_text_size:我們在此係統上處理過的 .text 和 .init.text ELF 部分大小的總位元組數
invalid_kread_bytes: 由於初始的 kernel_read_file_from_fd() 失敗而分配然後釋放的位元組數。 kernel_read_file_from_fd() 使用 vmalloc()。 通常情況下,除非您的系統處於記憶體壓力之下,否則不應發生這種情況。
invalid_decompress_bytes: 由於模組解壓縮路徑中使用
vmap()的記憶體分配而分配和釋放的位元組數。 通常情況下,除非您的系統處於記憶體壓力之下,否則不應發生這種情況。invalid_becoming_bytes: 用於讀取核心模組,在將模組新增到 **modules** 連結串列之前,使用者空間希望我們讀取的位元組總數。 如果我們在成功呼叫 kernel_read_file_from_fd() 之後,以及在我們為模組分配私有記憶體(如果模組成功載入,則會保留)之前進行了檢查,則可能會發生這些故障。 這種失敗最常見的原因是使用者空間正在爭相載入尚未載入的模組。 第一個成功呼叫 add_unformed_module() 的模組會將模組新增到我們的
modules列表中,並且後續載入同名模組的操作將在 early_mod_check() 的末尾報錯。 在 early_mod_check() 末尾檢查 module_patient_check_exists() 可以防止對已在處理的模組在 layout_and_allocate() 上進行重複分配。 這些重複失敗的模組是非致命的,但通常表明使用者空間尚未看到使用者空間中的模組已載入,並且不必要地嘗試在核心有機會開始處理先前的請求之前載入模組。 儘管重複失敗可能不是致命的,但我們應該積極地嘗試減少 vmalloc() 的壓力,因此理想情況下,啟動後,這個值應儘可能接近 0。 如果使用了模組解壓縮,我們還將壓縮模組的初始 kernel_read_file_from_fd() 的成本新增到此計數器。 如果未使用模組解壓縮,則該值表示 kernel_read_file_from_fd() 呼叫中用於此類失敗的總分配和釋放的位元組數。 這些失敗可能發生,因為
module_sig_check() - 模組簽名檢查
elf_validity_cache_copy() - 某些 ELF 驗證問題
early_mod_check()
黑名單
無法重寫節頭
版本魔數
即時補丁要求未透過檢查
檢測到該模組已存在
invalid_mod_bytes: 這些是由於我們對使用者空間傳遞給我們的模組進行了所有健全性檢查,以及在我們首次檢查該模組是否唯一之後發生的故障而分配和釋放的位元組總數。 如果我們在使用 layout_and_allocate() 為模組分配空間後檢測到該模組已載入,則模組仍然可能無法載入,我們在作為即時模組處理並執行其初始化例程之前進行此檢查。 請注意,如果發生此類故障,也意味著相應的 kernel_read_file_from_fd() 記憶體空間也被釋放且未使用,因此我們將此計數器增加模組大小的兩倍。 此外,如果您使用了模組解壓縮,則壓縮模組的大小也會新增到此計數器。
modcount:我們在核心生命週期中載入了多少模組
failed_kreads:有多少模組因 kernel_read_file_from_fd() 失敗而失敗
failed_decompress:我們有多少次失敗的模組解壓縮嘗試。 除非您的壓縮/解壓縮可能已損壞,否則這些情況實際上不應該發生。
failed_becoming:在 kernel_read_file_from_fd() 之後,但在我們使用 layout_and_allocate() 為其分配記憶體之前,有多少模組失敗。 如果您成功驗證模組併為其呼叫 layout_and_allocate(),則此計數器永遠不會遞增。
failed_load_modules:一旦我們使用 layout_and_allocate() 為我們的模組分配了私有空間,有多少模組失敗。 希望這些失敗大部分已經得到處理。 理論上,此處可能仍然存在競爭,但這僅僅意味著核心已開始併發處理兩個執行緒,直到 early_mod_check(),並且一個執行緒獲勝。 這些失敗是核心或使用者空間正在做一些非常愚蠢的事情,或者可以改進的良好跡象。 我們應該努力修復這些問題,但修復它們可能並不容易。 最近的一個例子是為頻率模組產生的模組請求,正在為系統上的每個 CPU 發出單獨的模組請求。
模組間支援¶
有關更多資訊,請參閱 kernel/module/ 中的檔案。
硬體介面¶
DMA 通道¶
-
int request_dma(unsigned int dmanr, const char *device_id)¶
請求並保留系統 DMA 通道
引數
unsigned int dmanrDMA 通道號
const char * device_id保留裝置 ID 字串,用於 /proc/dma
-
void free_dma(unsigned int dmanr)¶
釋放保留的系統 DMA 通道
引數
unsigned int dmanrDMA 通道號
資源管理¶
-
struct resource *request_resource_conflict(struct resource *root, struct resource *new)¶
請求並保留 I/O 或記憶體資源
引數
struct resource *root根資源描述符
struct resource *new呼叫者所需的資源描述符
描述
成功時返回 0,錯誤時返回衝突資源。
-
int find_next_iomem_res(resource_size_t start, resource_size_t end, unsigned long flags, unsigned long desc, struct resource *res)¶
查詢覆蓋 [**start**..**end**] 部分的最低 iomem 資源。
引數
resource_size_t start搜尋到的資源的起始地址
resource_size_t end相同資源的結束地址
unsigned long flags資源必須具有的標誌
unsigned long desc資源必須具有的描述符
struct resource *res如果找到資源,則返回 ptr
描述
如果找到資源,則返回 0,並且 **res 會被覆蓋為 [**start**..**end**] 範圍內的資源部分; 如果未找到資源,則返回 -ENODEV。 對於無效引數,返回 -EINVAL。
呼叫者必須指定 **start**、**end**、**flags** 和 **desc**(可以是 IORES_DESC_NONE)。
-
int reallocate_resource(struct resource *root, struct resource *old, resource_size_t newsize, struct resource_constraint *constraint)¶
在給定範圍和對齊方式的資源樹中分配一個槽。 如果無法在當前位置重新分配新大小,則將重新定位資源。
引數
struct resource *root根資源描述符
struct resource *old呼叫者所需的資源描述符
resource_size_t newsize資源描述符的新大小
struct resource_constraint *constraint要滿足的記憶體範圍和對齊方式約束。
-
struct resource *lookup_resource(struct resource *root, resource_size_t start)¶
透過資源起始地址查詢現有資源
引數
struct resource *root根資源描述符
resource_size_t start資源起始地址
描述
如果找到資源,則返回指向該資源的指標,否則返回 NULL
-
struct resource *insert_resource_conflict(struct resource *parent, struct resource *new)¶
在資源樹中插入資源
引數
struct resource *parent新資源的父資源
struct resource *new要插入的新資源
描述
成功時返回 0,如果無法插入資源,則返回衝突資源。
當沒有發生衝突時,此函式等效於 request_resource_conflict。 如果發生衝突,並且衝突資源完全適合新資源的範圍,則會插入新資源,並且衝突資源將成為新資源的子資源。
此函式適用於資源生產者,例如 FW 模組和匯流排驅動程式。
-
resource_size_t resource_alignment(struct resource *res)¶
計算資源的對齊方式
引數
struct resource *res資源指標
描述
成功時返回對齊方式,失敗時返回 0(無效對齊方式)。
-
void release_mem_region_adjustable(resource_size_t start, resource_size_t size)¶
釋放先前保留的記憶體區域
引數
resource_size_t start資源起始地址
resource_size_t size資源區域大小
描述
此介面適用於記憶體熱刪除。 請求的區域將從當前繁忙的記憶體資源中釋放。 請求的區域必須完全匹配或適合單個繁忙資源條目。 在後一種情況下,剩餘的資源將相應地進行調整。 繁忙記憶體資源的現有子資源在請求中必須是不可變的。
注意
在確認它們是有效用例後,可以支援其他釋放條件,例如重疊區域。
當繁忙的記憶體資源被拆分為兩個條目時,程式碼假定所有子資源都保留在較低地址的條目中以簡化操作。 必要時增強此邏輯。
-
void merge_system_ram_resource(struct resource *res)¶
將系統 RAM 資源標記為可合併,並嘗試將其與相鄰的可合併資源合併
引數
struct resource *res資源描述符
描述
此介面適用於記憶體熱插拔,驅動程式透過 add_memory*() 添加了大量連續的系統 ram 資源,並且對實際的資源邊界不感興趣(例如,它可能與 DIMM 相關)。 僅考慮標記為可合併、具有相同父資源且沒有任何子資源的資源。 所有可合併的資源在請求期間必須是不可變的。
注意
呼叫者必須確保在此呼叫之後不再使用指向標記為可合併的資源的任何指標 - 該資源可能會被釋放,並且該指標可能會失效!
release_mem_region_adjustable()將根據記憶體熱拔出的需求進行拆分
-
int request_resource(struct resource *root, struct resource *new)¶
請求並保留 I/O 或記憶體資源
引數
struct resource *root根資源描述符
struct resource *new呼叫者所需的資源描述符
描述
成功時返回 0,錯誤時返回負錯誤程式碼。
-
int release_resource(struct resource *old)¶
釋放先前保留的資源
引數
struct resource *old資源指標
-
int walk_iomem_res_desc(unsigned long desc, unsigned long flags, u64 start, u64 end, void *arg, int (*func)(struct resource*, void*))¶
遍歷 iomem 資源,並使用匹配的資源範圍呼叫 func()。 *
引數
unsigned long descI/O 資源描述符。 使用 IORES_DESC_NONE 跳過 **desc** 檢查。
unsigned long flagsI/O 資源標誌
u64 start起始地址
u64 end結束地址
void *arg回撥 **func** 的函式引數
int (*func)(struct resource *, void *)為每個合格的資源區域呼叫的回撥函式
描述
所有與 start、end 重疊,並且還匹配 flags 和 desc 的記憶體範圍都是有效的候選範圍。
注意
對於新的描述符搜尋,請在 <linux/ioport.h> 中定義一個新的 IORES_DESC,並將其設定在目標資源條目的“desc”中。
-
int region_intersects(resource_size_t start, size_t size, unsigned long flags, unsigned long desc)¶
確定區域與已知資源的交集
引數
resource_size_t start區域起始地址
size_t size區域大小
unsigned long flags資源標誌(在 iomem_resource 中)
unsigned long desc資源描述符(在 iomem_resource 中)或 IORES_DESC_NONE
描述
檢查指定的區域是否部分重疊或完全覆蓋由 **flags** 和 **desc**(可選,使用 IORES_DESC_NONE)標識的資源。 如果區域與 **flags**/ **desc** 不重疊,則返回 REGION_DISJOINT;如果區域與 **flags**/ **desc** 和另一個資源重疊,則返回 REGION_MIXED;如果區域與 **flags**/ **desc** 重疊,且沒有其他定義的資源,則返回 REGION_INTERSECTS。 請注意,在指定區域與 RAM 和未定義的記憶體空洞重疊的情況下,也會返回 REGION_INTERSECTS。
記憶體重新對映函式使用 region_intersect() 來確保使用者沒有重新對映 RAM,並且它比逐頁遍歷資源表的速度快得多。
-
int find_resource_space(struct resource *root, struct resource *new, resource_size_t size, struct resource_constraint *constraint)¶
在資源樹中查詢空閒空間
引數
struct resource *root根資源描述符
struct resource *new等待空閒資源空間的資源描述符
resource_size_t size空閒空間的最小大小
struct resource_constraint *constraint要滿足的範圍和對齊方式約束
描述
在滿足範圍和對齊方式 **constraints** 的資源樹中,在 **root** 下查詢空閒空間。
返回
0- 如果成功,則會更改 **new** 成員 start、end 和 flags。-EBUSY- 如果未找到空閒空間。
-
int allocate_resource(struct resource *root, struct resource *new, resource_size_t size, resource_size_t min, resource_size_t max, resource_size_t align, resource_alignf alignf, void *alignf_data)¶
根據指定的範圍和對齊方式,在資源樹中分配一個空槽。如果資源已經被分配,則會重新分配一個新的大小。
引數
struct resource *root根資源描述符
struct resource *new呼叫者所需的資源描述符
resource_size_t size請求的資源區域大小
resource_size_t min分配的最小邊界
resource_size_t max分配的最大邊界
resource_size_t align請求的對齊方式,以位元組為單位
resource_alignf alignf對齊函式,可選,如果不為 NULL 則呼叫
void *alignf_data傳遞給 alignf 函式的任意資料
-
int insert_resource(struct resource *parent, struct resource *new)¶
將資源插入資源樹中
引數
struct resource *parent新資源的父資源
struct resource *new要插入的新資源
描述
成功返回 0,如果無法插入資源,則返回 -EBUSY。
此函式適用於資源生產者,例如 FW 模組和匯流排驅動程式。
-
void insert_resource_expand_to_fit(struct resource *root, struct resource *new)¶
將資源插入資源樹中
引數
struct resource *root根資源描述符
struct resource *new要插入的新資源
描述
將資源插入資源樹中,如果需要,可以擴充套件它以包含任何衝突的資源。
-
int remove_resource(struct resource *old)¶
移除資源樹中的資源
引數
struct resource *old要移除的資源
描述
成功返回 0,如果資源無效,則返回 -EINVAL。
此函式移除之前由 insert_resource() 或 insert_resource_conflict() 插入的資源,並將子資源(如果有)上移到它們之前的位置。insert_resource() 和 insert_resource_conflict() 插入一個新資源,並將任何衝突的資源下移到新資源的子資源。
insert_resource()、insert_resource_conflict() 和 remove_resource() 適用於資源的生產者,例如 FW 模組和匯流排驅動程式。
-
int adjust_resource(struct resource *res, resource_size_t start, resource_size_t size)¶
修改資源的起始地址和大小
引數
struct resource *res要修改的資源
resource_size_t start新的起始值
resource_size_t size新的大小
描述
給定一個現有資源,將其起始地址和大小更改為與引數匹配。成功返回 0,如果無法適應,則返回 -EBUSY。資源的現有子資源假定為不可變的。
-
struct resource *__request_region(struct resource *parent, resource_size_t start, resource_size_t n, const char *name, int flags)¶
建立一個新的繁忙資源區域
引數
struct resource *parent父資源描述符
resource_size_t start資源起始地址
resource_size_t n資源區域大小
const char *name保留呼叫者的 ID 字串
int flagsIO 資源標誌
-
void __release_region(struct resource *parent, resource_size_t start, resource_size_t n)¶
釋放先前保留的資源區域
引數
struct resource *parent父資源描述符
resource_size_t start資源起始地址
resource_size_t n資源區域大小
描述
所描述的資源區域必須與當前繁忙區域匹配。
-
int devm_request_resource(struct device *dev, struct resource *root, struct resource *new)¶
請求並保留 I/O 或記憶體資源
引數
struct device *dev請求資源的裝置
struct resource *root從中請求資源的資源樹的根
struct resource *new要請求的資源的描述符
描述
這是 request_resource() 的裝置管理版本。通常不需要顯式釋放此函式請求的資源,因為它會在裝置與其驅動程式取消繫結時得到處理。 如果由於某種原因需要顯式釋放資源(例如,由於排序問題),驅動程式必須呼叫 devm_release_resource(),而不是常規的 release_resource()。
當在任何現有資源和新請求的資源之間檢測到衝突時,將列印一條錯誤訊息。
成功返回 0,失敗返回負錯誤程式碼。
引數
struct device *dev釋放資源的裝置
struct resource *new要釋放的資源的描述符
描述
釋放先前使用 devm_request_resource() 請求的資源。
-
struct resource *devm_request_free_mem_region(struct device *dev, struct resource *base, unsigned long size)¶
查詢裝置私有記憶體的空閒區域
引數
struct device *dev用於繫結資源的裝置結構體
struct resource *base要查詢的資源樹
unsigned long size要新增的裝置記憶體的大小(以位元組為單位)
描述
此函式嘗試找到足夠大的物理地址空閒範圍來包含新資源,以便以後可以將其熱插拔為 ZONE_DEVICE 記憶體,而 ZONE_DEVICE 記憶體又分配結構體頁面。
-
struct resource *alloc_free_mem_region(struct resource *base, unsigned long size, unsigned long align, const char *name)¶
相對於 base 查詢空閒區域
引數
struct resource *base將成為新資源父節點的資源
unsigned long size要從 base 分配的記憶體大小(以位元組為單位)
unsigned long align分配的對齊要求
const char *name資源名稱
描述
像 CXL 這樣的匯流排,可以動態例項化新的記憶體區域,需要一種方法來為這些區域分配物理地址空間。 分配並插入新資源以覆蓋 base 跨度內未被 base 的子資源宣告的空閒範圍。
MTRR 處理¶
-
int arch_phys_wc_add(unsigned long base, unsigned long size)¶
新增 WC MTRR 並在 PAT 不可用時處理錯誤
引數
unsigned long base物理基地址
unsigned long size區域大小
描述
如果 PAT 可用,則不執行任何操作。 如果 PAT 不可用,它會嘗試新增一個覆蓋從 base 開始的 size 位元組的 WC MTRR,如果失敗,則記錄一個錯誤。
被呼叫者應該在等效的二次方邊界上提供二次方大小。
驅動程式必須儲存返回值以傳遞給 mtrr_del_wc_if_needed,但驅動程式不應嘗試解釋該返回值。
安全框架¶
-
int security_init(void)¶
初始化安全框架
引數
void無引數
描述
應該在核心初始化序列的早期呼叫此函式。
-
void security_add_hooks(struct security_hook_list *hooks, int count, const struct lsm_id *lsmid)¶
將模組鉤子新增到鉤子列表。
引數
struct security_hook_list *hooks要新增的鉤子
int count要新增的鉤子數
const struct lsm_id *lsmid安全模組的標識資訊
描述
每個 LSM 必須向基礎架構註冊其鉤子。
-
int lsm_blob_alloc(void **dest, size_t size, gfp_t gfp)¶
分配一個複合 blob
引數
void **destblob 的目標
size_t sizeblob 的大小
gfp_t gfp分配型別
描述
為所有模組分配一個 blob
返回 0,如果無法分配記憶體,則返回 -ENOMEM。
引數
struct cred *cred需要 blob 的 cred
gfp_t gfp分配型別
描述
為所有模組分配 cred blob
返回 0,如果無法分配記憶體,則返回 -ENOMEM。
引數
struct cred *cred需要 blob 的 cred
描述
為所有模組分配 cred blob
引數
struct file *file需要 blob 的 file
描述
為所有模組分配 file blob
返回 0,如果無法分配記憶體,則返回 -ENOMEM。
引數
struct inode *inode需要 blob 的 inode
gfp_t gfp分配標誌
描述
為所有模組分配 inode blob
返回 0,如果無法分配記憶體,則返回 -ENOMEM。
-
int lsm_task_alloc(struct task_struct *task)¶
分配一個組合任務blob
引數
struct task_struct *task需要blob的任務
描述
為所有模組分配任務blob
返回 0,如果無法分配記憶體,則返回 -ENOMEM。
-
int lsm_ipc_alloc(struct kern_ipc_perm *kip)¶
分配一個組合ipc blob
引數
struct kern_ipc_perm *kip需要blob的ipc
描述
為所有模組分配ipc blob
返回 0,如果無法分配記憶體,則返回 -ENOMEM。
引數
struct key *key需要blob的key
描述
為所有模組分配key blob
返回 0,如果無法分配記憶體,則返回 -ENOMEM。
-
int lsm_msg_msg_alloc(struct msg_msg *mp)¶
分配一個組合msg_msg blob
引數
struct msg_msg *mp需要blob的msg_msg
描述
為所有模組分配ipc blob
返回 0,如果無法分配記憶體,則返回 -ENOMEM。
-
int lsm_bdev_alloc(struct block_device *bdev)¶
分配一個組合block_device blob
引數
struct block_device *bdev需要blob的block_device
描述
為所有模組分配block_device blob
返回 0,如果無法分配記憶體,則返回 -ENOMEM。
-
void lsm_early_task(struct task_struct *task)¶
在初始化期間分配一個組合任務blob
引數
struct task_struct *task需要blob的任務
描述
為所有模組分配任務blob
-
int lsm_superblock_alloc(struct super_block *sb)¶
分配一個組合superblock blob
引數
struct super_block *sb需要blob的superblock
描述
為所有模組分配superblock blob
返回 0,如果無法分配記憶體,則返回 -ENOMEM。
-
int lsm_fill_user_ctx(struct lsm_ctx __user *uctx, u32 *uctx_len, void *val, size_t val_len, u64 id, u64 flags)¶
填充一個使用者空間lsm_ctx結構
引數
struct lsm_ctx __user *uctx要填充的使用者空間LSM上下文
u32 *uctx_len可用的uctx大小(輸入),已使用的uctx大小(輸出)
void *val新的LSM上下文值
size_t val_len新的LSM上下文值的大小
u64 idLSM id
u64 flagsLSM定義的標誌
描述
填充使用者空間 lsm_ctx 結構中的所有欄位。 如果 **uctx** 為 NULL,則只需計算透過 **utc_len** 輸出的所需大小並返回成功。
成功時返回 0,如果使用者空間緩衝區不夠大,則返回 -E2BIG,如果複製錯誤,則返回 -EFAULT,如果無法分配記憶體,則返回 -ENOMEM。
-
int security_binder_set_context_mgr(const struct cred *mgr)¶
檢查是否可以成為 binder ctx mgr
引數
const struct cred *mgr當前 binder 程序的任務憑據
描述
檢查是否允許 **mgr** 成為 binder 上下文管理器。
返回
如果授予許可權,則返回 0。
-
int security_binder_transaction(const struct cred *from, const struct cred *to)¶
檢查是否允許 binder 事務
引數
const struct cred *from傳送程序
const struct cred *to接收程序
描述
檢查是否允許 **from** 呼叫到 **to** 的 binder 事務呼叫。
返回
如果授予許可權,則返回 0。
-
int security_binder_transfer_binder(const struct cred *from, const struct cred *to)¶
檢查是否允許 binder 傳輸
引數
const struct cred *from傳送程序
const struct cred *to接收程序
描述
檢查是否允許 **from** 將 binder 引用傳輸到 **to**。
返回
如果授予許可權,則返回 0。
-
int security_binder_transfer_file(const struct cred *from, const struct file *file)¶
檢查是否允許 binder 檔案傳輸
引數
const struct cred *from傳送程序
const struct cred *to接收程序
const struct file *file正在傳輸的檔案
描述
檢查是否允許 **from** 將 **file** 傳輸到 **to**。
返回
如果授予許可權,則返回 0。
-
int security_ptrace_access_check(struct task_struct *child, unsigned int mode)¶
檢查是否允許跟蹤
引數
struct task_struct *child目標程序
unsigned int modePTRACE_MODE 標誌
描述
允許當前程序跟蹤 **child** 程序之前,檢查許可權。 安全模組也可能希望在 execve 期間的 set_security 或 apply_creds 掛鉤中執行程序跟蹤檢查,如果在 binprm_security_ops 的 bprm_set_creds 掛鉤中的 execve 期間的跟蹤檢查期間程序正在被跟蹤並且其安全屬性將被 execve 更改。
返回
如果授予許可權,則返回 0。
-
int security_ptrace_traceme(struct task_struct *parent)¶
檢查是否允許跟蹤
引數
struct task_struct *parent跟蹤程序
描述
在允許當前程序向 **parent** 程序呈現自己進行跟蹤之前,檢查 **parent** 程序是否具有足夠的許可權來跟蹤當前程序。
返回
如果授予許可權,則返回 0。
-
int security_capget(const struct task_struct *target, kernel_cap_t *effective, kernel_cap_t *inheritable, kernel_cap_t *permitted)¶
獲取程序的 capability 集合
引數
const struct task_struct *target目標程序
kernel_cap_t *effective有效 capability 集合
kernel_cap_t *inheritable可繼承 capability 集合
kernel_cap_t *permitted允許的 capability 集合
描述
獲取 **target** 程序的 **effective**、**inheritable** 和 **permitted** capability 集合。 該鉤子還可以執行許可權檢查,以確定是否允許當前程序檢視 **target** 程序的 capability 集合。
返回
如果成功獲取 capability 集合,則返回 0。
-
int security_capset(struct cred *new, const struct cred *old, const kernel_cap_t *effective, const kernel_cap_t *inheritable, const kernel_cap_t *permitted)¶
設定程序的 capability 集合
引數
struct cred *new目標程序的新憑據
const struct cred *old目標程序的當前憑據
const kernel_cap_t *effective有效 capability 集合
const kernel_cap_t *inheritable可繼承 capability 集合
const kernel_cap_t *permitted允許的 capability 集合
描述
為當前程序設定 **effective**、**inheritable** 和 **permitted** capability 集合。
返回
如果授予許可權,則返回 0 並更新 **new**。
-
int security_capable(const struct cred *cred, struct user_namespace *ns, int cap, unsigned int opts)¶
檢查程序是否具有必要的 capability
引數
const struct cred *cred要檢查的憑據
struct user_namespace *ns使用者名稱空間
int cap請求的 capability
unsigned int optscapability 檢查選項
描述
檢查 **tsk** 程序是否在指示的憑據中具有 **cap** capability。 **cap** 包含 capability <include/linux/capability.h>。 **opts** 包含 capability 檢查的選項 <include/linux/security.h>。
返回
如果授予 capability,則返回 0。
-
int security_quotactl(int cmds, int type, int id, const struct super_block *sb)¶
檢查是否允許此 fs 的 quotactl() 系統呼叫
引數
int cmds命令
int typetype
int idid
const struct super_block *sb檔案系統
描述
檢查是否允許此 **sb** 的 quotactl 系統呼叫。
返回
如果授予許可權,則返回 0。
引數
struct dentry *dentrydentry
描述
檢查是否允許 **dentry** 的 QUOTAON。
返回
如果授予許可權,則返回 0。
-
int security_syslog(int type)¶
檢查是否允許訪問核心訊息環
引數
int typeSYSLOG_ACTION_* 型別
描述
在訪問核心訊息環或將日誌記錄更改為控制檯之前檢查許可權。 有關 **type** 值的說明,請參見 syslog(2) 手冊頁。
返回
如果授予許可權,則返回 0。
-
int security_settime64(const struct timespec64 *ts, const struct timezone *tz)¶
檢查是否允許更改系統時間
引數
const struct timespec64 *ts新時間
const struct timezone *tz時區
描述
檢查更改系統時間的許可權。struct timespec64 定義在 <include/linux/time64.h> 中,timezone 定義在 <include/linux/time.h> 中。
返回
如果授予許可權,則返回 0。
-
int security_vm_enough_memory_mm(struct mm_struct *mm, long pages)¶
檢查是否允許分配新的記憶體對映
引數
struct mm_struct *mmmm 結構體
long pages頁數
描述
檢查分配新的虛擬對映的許可權。如果所有 LSM 都返回正值,則將使用 cap_sys_admin 設定呼叫 __vm_enough_memory()。如果至少有一個 LSM 返回 0 或負值,則將使用 cap_sys_admin 清除呼叫 __vm_enough_memory()。
返回
- 如果 LSM 基礎架構授予呼叫者許可權,則返回 0。
呼叫者。
-
int security_bprm_creds_for_exec(struct linux_binprm *bprm)¶
準備 exec() 的憑據
引數
struct linux_binprm *bprm二進位制程式資訊
描述
如果 prepare_exec_creds 中的設定沒有為執行 bprm->file 正確設定 bprm->cred->security,請更新 LSM 的 bprm->cred->security 部分,使其成為 commit_creds 需要為新程式安裝的部分。此 hook 也可以選擇性地檢查許可權(例如,用於安全域之間的轉換)。如果應設定 AT_SECURE 以請求 libc 啟用安全模式,則此 hook 必須將 bprm->secureexec 設定為 1。bprm 包含 linux_binprm 結構。
如果使用 AT_EXECVE_CHECK 標誌呼叫 execveat(2),則會設定 bprm->is_check。即使執行永遠不會真正發生並且將始終刪除 bprm,結果也必須與沒有此標誌的結果相同。
此 hook 不得更改 current->cred,僅更改 bprm->cred。
返回
如果 hook 成功並且授予許可權,則返回 0。
-
int security_bprm_creds_from_file(struct linux_binprm *bprm, const struct file *file)¶
根據檔案更新 linux_binprm 憑據
引數
struct linux_binprm *bprm二進位制程式資訊
const struct file *file關聯檔案
描述
如果 file 是 setpcap、suid、sgid 或以其他方式標記為在 exec 時更改許可權的檔案,請更新 bprm->cred 以反映該更改。 這是在找到將要執行的二進位制檔案而沒有直譯器之後呼叫的。 這可確保憑據不會來自二進位制檔案需要重新開啟的指令碼,該指令碼在重新開啟時可能最終成為完全不同的檔案。 此 hook 也可以選擇性地檢查許可權(例如,用於安全域之間的轉換)。 如果應設定 AT_SECURE 以請求 libc 啟用安全模式,則此 hook 必須將 bprm->secureexec 設定為 1。此 hook 必須將應該從 current->personality 清除的任何個性標誌新增到 bprm->per_clear。 bprm 包含 linux_binprm 結構。
返回
如果 hook 成功並且授予許可權,則返回 0。
-
int security_bprm_check(struct linux_binprm *bprm)¶
調節二進位制處理程式搜尋
引數
struct linux_binprm *bprm二進位制程式資訊
描述
此 hook 調節二進位制處理程式搜尋將要開始的點。它允許檢查在前面的 creds_for_exec 呼叫中設定的 bprm->cred->security 值。argv 列表和 envp 列表可以在 bprm 中可靠地使用。在單個 execve 期間,可能會多次呼叫此 hook。bprm 包含 linux_binprm 結構。
返回
如果 hook 成功並且授予許可權,則返回 0。
-
void security_bprm_committing_creds(const struct linux_binprm *bprm)¶
在 exec() 期間為程序安裝憑據
引數
const struct linux_binprm *bprm二進位制程式資訊
描述
準備安裝由 execve 操作轉換的程序的新安全屬性,該屬性基於 current->cred 指向的舊憑據和 bprm_creds_for_exec hook 在 bprm->cred 中設定的資訊。bprm 指向 linux_binprm 結構。此 hook 是對程序執行狀態更改的好地方,例如關閉當屬性更改時不再授予訪問許可權的開啟的檔案描述符。這將在 commit_creds() 之前立即呼叫。
-
void security_bprm_committed_creds(const struct linux_binprm *bprm)¶
在 exec() 期間完成憑據安裝後進行清理
引數
const struct linux_binprm *bprm二進位制程式資訊
描述
完成安裝由 execve 操作轉換的程序的新安全屬性後進行清理。此時,新憑據已設定為 current->cred。bprm 指向 linux_binprm 結構。此 hook 是對程序執行狀態更改的好地方,例如清除不可繼承的訊號狀態。這將在 commit_creds() 之後立即呼叫。
-
int security_fs_context_submount(struct fs_context *fc, struct super_block *reference)¶
初始化 fc->security
引數
struct fs_context *fc新檔案系統上下文
struct super_block *reference用於子掛載/重新掛載的 dentry 引用
描述
填充新 fs_context 的 ->security 欄位。
返回
成功時返回 0,失敗時返回負錯誤程式碼。
-
int security_fs_context_dup(struct fs_context *fc, struct fs_context *src_fc)¶
複製 fs_context LSM blob
引數
struct fs_context *fc目標檔案系統上下文
struct fs_context *src_fc原始檔系統上下文
描述
分配安全結構並將其附加到 sc->security。此指標由呼叫者初始化為 NULL。 fc 指示新的檔案系統上下文。 src_fc 指示原始檔案系統上下文。
返回
成功返回 0,失敗返回負錯誤程式碼。
-
int security_fs_context_parse_param(struct fs_context *fc, struct fs_parameter *param)¶
配置檔案系統上下文
引數
struct fs_context *fc檔案系統上下文
struct fs_parameter *param檔案系統引數
描述
使用者空間提供了一個引數來配置超級塊。LSM 可以使用該引數或將其返回給呼叫者以供其他地方使用。
返回
- 如果該引數被 LSM 使用,則應返回 0,如果該引數被
返回給呼叫者,則返回 -ENOPARAM,否則返回負錯誤程式碼。
-
int security_sb_alloc(struct super_block *sb)¶
分配 super_block LSM blob
引數
struct super_block *sb檔案系統超級塊
描述
分配安全結構並將其附加到 sb->s_security 欄位。分配結構時,s_security 欄位將初始化為 NULL。 sb 包含要修改的 super_block 結構。
返回
如果操作成功,則返回 0。
-
void security_sb_delete(struct super_block *sb)¶
釋放 super_block LSM 關聯的物件
引數
struct super_block *sb檔案系統超級塊
描述
釋放與超級塊關聯的物件(例如,inodes)。 sb 包含正在釋放的 super_block 結構。
-
void security_sb_free(struct super_block *sb)¶
釋放 super_block LSM blob
引數
struct super_block *sb檔案系統超級塊
描述
取消分配並清除 sb->s_security 欄位。 sb 包含要修改的 super_block 結構。
-
int security_sb_kern_mount(const struct super_block *sb)¶
檢查是否允許核心掛載
引數
const struct super_block *sb檔案系統超級塊
描述
如果許可權允許,則掛載此 sb。
返回
如果授予許可權,則返回 0。
-
int security_sb_show_options(struct seq_file *m, struct super_block *sb)¶
輸出超級塊的掛載選項
引數
struct seq_file *m輸出檔案
struct super_block *sb檔案系統超級塊
描述
顯示(在 m 上列印)此 sb 的掛載選項。
返回
成功時返回 0,失敗時返回負值。
引數
struct dentry *dentry超級塊控制代碼
描述
在獲取 mnt 掛載點的檔案系統統計資訊之前檢查許可權。 dentry 是檔案系統的超級塊上的控制代碼。
返回
如果授予許可權,則返回 0。
-
int security_sb_mount(const char *dev_name, const struct path *path, const char *type, unsigned long flags, void *data)¶
檢查掛載檔案系統的許可權
引數
const char *dev_name檔案系統後備裝置
const struct path *path掛載點
const char *type檔案系統型別
unsigned long flags掛載標誌
void *data檔案系統特定資料
描述
在 dev_name 指定的物件掛載到 nd 命名的掛載點上之前檢查許可權。對於普通掛載,如果檔案系統型別需要裝置,則 dev_name 標識裝置。對於重新掛載(flags & MS_REMOUNT),dev_name 無關緊要。對於環回/繫結掛載(flags & MS_BIND),dev_name 標識要掛載的物件的路徑名。
返回
如果授予許可權,則返回 0。
-
int security_sb_umount(struct vfsmount *mnt, int flags)¶
檢查解除安裝檔案系統的許可權
引數
struct vfsmount *mnt已掛載的檔案系統
int flags解除安裝標誌
描述
在解除安裝 mnt 檔案系統之前檢查許可權。
返回
如果授予許可權,則返回 0。
-
int security_sb_pivotroot(const struct path *old_path, const struct path *new_path)¶
檢查旋轉 rootfs 的許可權
引數
const struct path *old_path當前 rootfs 的新位置
const struct path *new_path新 rootfs 的位置
描述
在旋轉根檔案系統之前檢查許可權。
返回
如果授予許可權,則返回 0。
-
int security_move_mount(const struct path *from_path, const struct path *to_path)¶
檢查移動掛載的許可權
引數
const struct path *from_path源掛載點
const struct path *to_path目標掛載點
描述
在移動掛載之前檢查許可權。
返回
如果授予許可權,則返回 0。
引數
const struct path *path檔案路徑
u64 mask事件掩碼
unsigned int obj_type檔案路徑型別
描述
在由 **mask** 定義的事件上,在 **path** 處的物件上,其型別由 **obj_type** 定義,檢查設定監視器之前是否具有許可權。
返回
如果授予許可權,則返回 0。
引數
struct inode *inodeinode
gfp_t gfp分配標誌
描述
分配安全結構並將其附加到 **inode->i_security**。當分配 inode 結構時,i_security 欄位初始化為 NULL。
返回
如果操作成功,則返回 0。
引數
struct inode *inodeinode
描述
釋放與 **inode** 關聯的任何 LSM 資源,儘管由於 inode 的 RCU 保護,可能要等到當前 RCU 寬限期過後才能完全釋放這些資源。
LSM 必須注意,儘管存在於對 security_inode_free() 的呼叫中,**inode** 仍然可以在 VFS 路徑遍歷中被引用,並且可能會在呼叫 security_inode_free() 期間或之後對 security_inode_permission() 進行呼叫。因此,inode->i_security 欄位透過 call_rcu() 回撥釋放,並且任何需要在 security_inode_permission() 中使用 inode 狀態的 LSM 都應該只在 inode_free_security_rcu() LSM 鉤子回撥中釋放該狀態。
-
int security_inode_init_security_anon(struct inode *inode, const struct qstr *name, const struct inode *context_inode)¶
初始化匿名 inode
引數
struct inode *inodeinode
const struct qstr *name匿名 inode 類
const struct inode *context_inode可選的相關 inode
描述
為新的匿名 inode 設定 incore 安全欄位,並返回安全模組是否允許建立 inode。
返回
成功返回 0,如果安全模組拒絕建立此 inode,則返回 -EACCES,或者在其他錯誤時返回其他 -errno。
引數
struct mnt_idmap *idmap掛載的 idmap
struct dentry *dentry新檔案
描述
在建立常規檔案後更新 inode 安全欄位。
引數
const struct path *dir父目錄
struct dentry *dentry要刪除的目錄
描述
檢查刪除目錄的許可權。
返回
如果授予許可權,則返回 0。
-
int security_path_symlink(const struct path *dir, struct dentry *dentry, const char *old_name)¶
檢查是否允許建立符號連結
引數
const struct path *dir父目錄
struct dentry *dentry符號連結
const char *old_name檔案路徑名
描述
檢查建立指向檔案的符號連結的許可權。
返回
如果授予許可權,則返回 0。
-
int security_path_link(struct dentry *old_dentry, const struct path *new_dir, struct dentry *new_dentry)¶
檢查是否允許建立硬連結
引數
struct dentry *old_dentry現有檔案
const struct path *new_dir新的父目錄
struct dentry *new_dentry新連結
描述
在建立指向檔案的新硬連結之前檢查許可權。
返回
如果授予許可權,則返回 0。
引數
const struct path *path檔案
描述
在截斷 path 指示的檔案之前檢查許可權。請注意,也可以基於已開啟的檔案來檢查截斷許可權,使用 security_file_truncate() 鉤子。
返回
如果授予許可權,則返回 0。
引數
const struct path *path檔案
umode_t mode新模式
描述
檢查更改檔案 **path** 模式的許可權。新模式在 **mode** 中指定,它是 <include/uapi/linux/stat.h> 中的常量位掩碼。
返回
如果授予許可權,則返回 0。
引數
const struct path *path檔案
kuid_t uid檔案所有者
kgid_t gid檔案組
描述
檢查更改檔案或目錄的所有者/組的許可權。
返回
如果授予許可權,則返回 0。
引數
const struct path *path目錄
描述
檢查更改根目錄的許可權。
返回
如果授予許可權,則返回 0。
-
void security_inode_post_create_tmpfile(struct mnt_idmap *idmap, struct inode *inode)¶
更新新 tmpfile 的 inode 安全性
引數
struct mnt_idmap *idmap掛載的 idmap
struct inode *inode新 tmpfile 的 inode
描述
建立 tmpfile 後更新 inode 安全資料。
-
int security_inode_link(struct dentry *old_dentry, struct inode *dir, struct dentry *new_dentry)¶
檢查是否允許建立硬連結
引數
struct dentry *old_dentry現有檔案
struct inode *dir新的父目錄
struct dentry *new_dentry新連結
描述
在建立指向檔案的新硬連結之前檢查許可權。
返回
如果授予許可權,則返回 0。
引數
struct inode *dir父目錄
struct dentry *dentry檔案
描述
檢查刪除指向檔案的硬連結的許可權。
返回
如果授予許可權,則返回 0。
-
int security_inode_symlink(struct inode *dir, struct dentry *dentry, const char *old_name)¶
檢查是否允許建立符號連結
引數
struct inode *dir父目錄
struct dentry *dentry符號連結
const char *old_name現有檔名
描述
檢查建立指向檔案的符號連結的許可權。
返回
如果授予許可權,則返回 0。
引數
struct inode *dir父目錄
struct dentry *dentry要刪除的目錄
描述
檢查刪除目錄的許可權。
返回
如果授予許可權,則返回 0。
-
int security_inode_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, dev_t dev)¶
檢查是否允許建立特殊檔案
引數
struct inode *dir父目錄
struct dentry *dentry新檔案
umode_t mode新檔案模式
dev_t dev裝置號
描述
檢查建立特殊檔案(或透過 mknod 系統呼叫建立的套接字或 fifo 檔案)時的許可權。請注意,如果 mknod 操作是為常規檔案完成的,那麼將呼叫 create 鉤子,而不是此鉤子。
返回
如果授予許可權,則返回 0。
-
int security_inode_rename(struct inode *old_dir, struct dentry *old_dentry, struct inode *new_dir, struct dentry *new_dentry, unsigned int flags)¶
檢查是否允許重新命名檔案
引數
struct inode *old_dir舊檔案的父目錄
struct dentry *old_dentry舊檔案
struct inode *new_dir新檔案的父目錄
struct dentry *new_dentry新檔案
unsigned int flags標誌
描述
檢查重新命名檔案或目錄的許可權。
返回
如果授予許可權,則返回 0。
引數
struct dentry *dentry連結
描述
檢查讀取符號連結的許可權。
返回
如果授予許可權,則返回 0。
引數
struct dentry *dentry連結 dentry
struct inode *inode連結 inode
bool rcu如果在 RCU 步行模式下為真
描述
在查詢路徑名時,檢查跟隨符號連結的許可權。 如果 rcu 為真,則 inode 不穩定。
返回
如果授予許可權,則返回 0。
引數
struct inode *inodeinode
int mask訪問掩碼
描述
在訪問 inode 之前檢查許可權。 此鉤子由現有的 Linux 許可權函式呼叫,因此安全模組可以使用它為現有的 Linux 許可權檢查提供額外的檢查。 請注意,此鉤子在開啟檔案時(以及許多其他操作)呼叫,而 file_security_ops 許可權鉤子在執行實際的讀/寫操作時呼叫。
返回
如果授予許可權,則返回 0。
-
void security_inode_post_setattr(struct mnt_idmap *idmap, struct dentry *dentry, int ia_valid)¶
在 setattr 操作後更新 inode
引數
struct mnt_idmap *idmap掛載的 idmap
struct dentry *dentry檔案
int ia_valid設定的檔案屬性
描述
成功設定檔案屬性後,更新 inode 安全欄位。
引數
const struct path *path檔案
描述
在獲取檔案屬性之前檢查許可權。
返回
如果授予許可權,則返回 0。
-
int security_inode_setxattr(struct mnt_idmap *idmap, struct dentry *dentry, const char *name, const void *value, size_t size, int flags)¶
檢查是否允許設定檔案 xattrs
引數
struct mnt_idmap *idmap掛載的 idmap
struct dentry *dentry檔案
const char *namexattr 名稱
const void *valuexattr 值
size_t sizexattr 值的長度
int flags標誌
描述
此鉤子在 dentry 上設定擴充套件屬性 (xattrs) 之前執行所需的許可權檢查。 重要的是要注意,在我們呼叫主要 LSM 實現之前,我們有一些額外的邏輯來檢測是否需要在 LSM 層執行額外的 capability 檢查。
通常,我們在執行各種 LSM 鉤子實現之前強制執行 capability 檢查,但是如果 LSM 想要避免此 capability 檢查,它可以註冊一個 'inode_xattr_skipcap' 鉤子,併為它想要避免 capability 檢查的 xattrs 返回值 1,讓 LSM 完全負責強制執行特定 xattr 的訪問控制。 如果所有啟用的 LSM 都不註冊 'inode_xattr_skipcap' 鉤子,或者返回 0(預設返回值),則仍會執行 capability 檢查。 如果未註冊任何 'inode_xattr_skipcap' 鉤子,則會執行 capability 檢查。
返回
如果授予許可權,則返回 0。
-
int security_inode_set_acl(struct mnt_idmap *idmap, struct dentry *dentry, const char *acl_name, struct posix_acl *kacl)¶
檢查是否允許設定 posix acls
引數
struct mnt_idmap *idmap掛載的 idmap
struct dentry *dentry檔案
const char *acl_nameacl 名稱
struct posix_acl *kaclacl 結構
描述
在設定 posix acls 之前檢查許可權,kacl 中的 posix acls 由 acl_name 標識。
返回
如果授予許可權,則返回 0。
-
void security_inode_post_set_acl(struct dentry *dentry, const char *acl_name, struct posix_acl *kacl)¶
從 posix acls 設定更新 inode 安全性
引數
struct dentry *dentry檔案
const char *acl_nameacl 名稱
struct posix_acl *kaclacl 結構
描述
成功在 dentry 上設定 posix acls 後,更新 inode 安全資料。 kacl 中的 posix acls 由 acl_name 標識。
-
int security_inode_get_acl(struct mnt_idmap *idmap, struct dentry *dentry, const char *acl_name)¶
檢查是否允許讀取 posix acls
引數
struct mnt_idmap *idmap掛載的 idmap
struct dentry *dentry檔案
const char *acl_nameacl 名稱
描述
在獲取 osix acls 之前檢查許可權,posix acls 由 acl_name 標識。
返回
如果授予許可權,則返回 0。
-
int security_inode_remove_acl(struct mnt_idmap *idmap, struct dentry *dentry, const char *acl_name)¶
檢查是否允許刪除 posix acl
引數
struct mnt_idmap *idmap掛載的 idmap
struct dentry *dentry檔案
const char *acl_nameacl 名稱
描述
在刪除 posix acls 之前檢查許可權,posix acls 由 acl_name 標識。
返回
如果授予許可權,則返回 0。
-
void security_inode_post_remove_acl(struct mnt_idmap *idmap, struct dentry *dentry, const char *acl_name)¶
rm posix acls 後更新 inode 安全性
引數
struct mnt_idmap *idmap掛載的 idmap
struct dentry *dentry檔案
const char *acl_nameacl 名稱
描述
成功從 idmap 中的 dentry 中刪除 posix acls 後,更新 inode 安全資料。 posix acls 由 acl_name 標識。
-
void security_inode_post_setxattr(struct dentry *dentry, const char *name, const void *value, size_t size, int flags)¶
在 setxattr 操作後更新 inode
引數
struct dentry *dentry檔案
const char *namexattr 名稱
const void *valuexattr 值
size_t sizexattr 值大小
int flags標誌
描述
成功執行 setxattr 操作後,更新 inode 安全欄位。
引數
struct dentry *dentry檔案
const char *namexattr 名稱
描述
在獲取由 name 標識的 dentry 的擴充套件屬性之前檢查許可權。
返回
如果授予許可權,則返回 0。
引數
struct dentry *dentry檔案
描述
在獲取 dentry 的擴充套件屬性名稱列表之前檢查許可權。
返回
如果授予許可權,則返回 0。
-
int security_inode_removexattr(struct mnt_idmap *idmap, struct dentry *dentry, const char *name)¶
檢查是否允許刪除 xattr
引數
struct mnt_idmap *idmap掛載的 idmap
struct dentry *dentry檔案
const char *namexattr 名稱
描述
此鉤子在 dentry 上設定擴充套件屬性 (xattrs) 之前執行所需的許可權檢查。 重要的是要注意,在我們呼叫主要 LSM 實現之前,我們有一些額外的邏輯來檢測是否需要在 LSM 層執行額外的 capability 檢查。
通常,我們在執行各種 LSM 鉤子實現之前強制執行 capability 檢查,但是如果 LSM 想要避免此 capability 檢查,它可以註冊一個 'inode_xattr_skipcap' 鉤子,併為它想要避免 capability 檢查的 xattrs 返回值 1,讓 LSM 完全負責強制執行特定 xattr 的訪問控制。 如果所有啟用的 LSM 都不註冊 'inode_xattr_skipcap' 鉤子,或者返回 0(預設返回值),則仍會執行 capability 檢查。 如果未註冊任何 'inode_xattr_skipcap' 鉤子,則會執行 capability 檢查。
返回
如果授予許可權,則返回 0。
-
void security_inode_post_removexattr(struct dentry *dentry, const char *name)¶
在 removexattr op 之後更新 inode
引數
struct dentry *dentry檔案
const char *namexattr 名稱
描述
成功執行 removexattr 操作後更新 inode。
-
int security_inode_need_killpriv(struct dentry *dentry)¶
檢查是否需要
security_inode_killpriv()
引數
struct dentry *dentry關聯的 dentry
描述
當 inode 已更改時呼叫,以確定是否應呼叫 security_inode_killpriv()。
返回
- 如果發生錯誤導致 inode 更改操作中止,則返回 <0,如果
不需要呼叫
security_inode_killpriv(),則返回 0,如果需要呼叫security_inode_killpriv(),則返回 >0。
引數
struct mnt_idmap *idmap掛載的 idmap
struct dentry *dentry關聯的 dentry
描述
正在刪除 dentry 的 setuid 位。 刪除類似的安全標籤。 使用 dentry->d_inode->i_mutex 持有鎖呼叫。
返回
- 成功時返回 0。 如果返回錯誤,則操作
導致刪除 setuid 位的操作失敗。
-
int security_inode_getsecurity(struct mnt_idmap *idmap, struct inode *inode, const char *name, void **buffer, bool alloc)¶
獲取 inode 的 xattr 安全標籤
引數
struct mnt_idmap *idmap掛載的 idmap
struct inode *inodeinode
const char *namexattr 名稱
void **buffer安全標籤緩衝區
bool alloc分配標誌
描述
透過 buffer 檢索與 inode 的 name 關聯的安全標籤的擴充套件屬性表示形式的副本。 請注意,name 是刪除安全字首後屬性名稱的其餘部分。 alloc 用於指定呼叫是透過緩衝區返回一個值還是僅返回值的長度。
返回
成功時返回緩衝區的大小。
-
int security_inode_setsecurity(struct inode *inode, const char *name, const void *value, size_t size, int flags)¶
設定inode的xattr安全標籤
引數
struct inode *inodeinode
const char *namexattr 名稱
const void *value安全標籤
size_t size安全標籤的長度
int flags標誌
描述
從擴充套件屬性值 **value** 為 **inode** 設定與 **name** 關聯的安全標籤。 **size** 指示 **value** 的大小(以位元組為單位)。**flags** 可以是 XATTR_CREATE、XATTR_REPLACE 或 0。請注意,**name** 是移除 security. 字首後屬性名稱的其餘部分。
返回
成功返回 0。
引數
struct inode *inodeinode
struct lsm_prop *prop要返回的lsm特定資訊
描述
獲取與節點關聯的lsm特定資訊。
-
int security_kernfs_init_security(struct kernfs_node *kn_dir, struct kernfs_node *kn)¶
為kernfs節點初始化LSM上下文
引數
struct kernfs_node *kn_dir父kernfs節點
struct kernfs_node *kn要初始化的kernfs節點
描述
根據新建立的kernfs節點自身及其父節點的屬性,初始化其安全上下文。
返回
如果授予許可權,則返回 0。
引數
struct file *file檔案
int mask請求的許可權
描述
在訪問開啟的檔案之前檢查檔案許可權。此鉤子由讀取或寫入檔案的各種操作呼叫。安全模組可以使用此鉤子對這些操作執行額外的檢查,例如,重新驗證使用許可權以支援許可權括號或策略更改。請注意,此鉤子在執行實際的讀取/寫入操作時使用,而 inode_security_ops 鉤子在開啟檔案時(以及許多其他操作)呼叫。雖然此鉤子可用於重新驗證各種讀取或寫入檔案的系統呼叫操作的許可權,但它不能解決記憶體對映檔案的許可權重新驗證問題。如果安全模組需要此類重新驗證,則必須單獨處理。
返回
如果授予許可權,則返回 0。
引數
struct file *file檔案
描述
分配一個安全結構並將其附加到 file->f_security 欄位。首次建立結構時,安全欄位初始化為 NULL。
返回
如果鉤子成功並且授予許可權,則返回 0。
引數
struct file *file檔案
描述
在釋放對檔案的最後一個引用之前執行操作。
引數
struct file *file檔案
描述
取消分配並釋放儲存在 file->f_security 中的任何安全結構。
引數
struct file *file檔案
unsigned long prot核心應用的保護
unsigned long flags標誌
描述
檢查mmap操作的許可權。 **file** 可以為 NULL,例如,如果對映匿名記憶體。
返回
如果授予許可權,則返回 0。
-
int security_mmap_addr(unsigned long addr)¶
檢查是否允許mmap一個地址
引數
unsigned long addr地址
描述
檢查 **addr** 處 mmap 操作的許可權。
返回
如果授予許可權,則返回 0。
-
int security_file_mprotect(struct vm_area_struct *vma, unsigned long reqprot, unsigned long prot)¶
檢查是否允許更改記憶體保護
引數
struct vm_area_struct *vma記憶體區域
unsigned long reqprot應用程式請求的保護
unsigned long prot核心應用的保護
描述
在更改記憶體訪問許可權之前檢查許可權。
返回
如果授予許可權,則返回 0。
引數
struct file *file檔案
unsigned int cmd鎖定操作 (例如 F_RDLCK, F_WRLCK)
描述
在執行檔案鎖定操作之前檢查許可權。請注意,此鉤子同時調解 flock 和 fcntl 樣式的鎖。
返回
如果授予許可權,則返回 0。
引數
struct file *file檔案
unsigned int cmdfcntl 命令
unsigned long arg命令引數
描述
在允許對檔案 **file** 執行由 **cmd** 指定的檔案操作之前檢查許可權。請注意,**arg** 有時表示使用者空間指標;在其他情況下,它可能是一個簡單的整數值。當 **arg** 表示使用者空間指標時,安全模組永遠不應使用它。
返回
如果授予許可權,則返回 0。
引數
struct file *file檔案
描述
將所有者安全資訊(通常來自 current->security)儲存在 file->f_security 中,以供 send_sigiotask 鉤子稍後使用。
呼叫此鉤子時會持有 file->f_owner.lock。
返回
成功返回 0。
-
int security_file_send_sigiotask(struct task_struct *tsk, struct fown_struct *fown, int sig)¶
檢查是否允許傳送 SIGIO/SIGURG
引數
struct task_struct *tsk目標任務
struct fown_struct *fown訊號傳送者
int sig要傳送的訊號,如果為 0 則傳送 SIGIO
描述
檢查檔案所有者 **fown** 向程序 **tsk** 傳送 SIGIO 或 SIGURG 的許可權。請注意,此鉤子有時從中斷中呼叫。請注意,fown_struct,**fown**,永遠不在 struct file 的上下文之外,因此總是可以獲取檔案結構(和相關的安全資訊):container_of(fown, struct file, f_owner)。
返回
如果授予許可權,則返回 0。
引數
struct file *file正在接收的檔案
描述
此鉤子允許安全模組控制程序透過套接字 IPC 接收開啟的檔案描述符的能力。
返回
如果授予許可權,則返回 0。
引數
struct file *file
描述
儲存 open-time 許可權檢查狀態,以便稍後在 file_permission 上使用,如果自 inode_permission 以來有任何更改,則重新檢查訪問。
我們可以透過檢查 file->f_flags & __FMODE_EXEC 來檢查檔案是否為執行而開啟(例如 execve(2) 呼叫),無論是直接還是間接(例如 ELF 的 ld.so)。
返回
如果授予許可權,則返回 0。
引數
struct file *file檔案
描述
在截斷檔案之前檢查許可權,即使用 ftruncate。請注意,截斷許可權也可以基於路徑進行檢查,使用 **path_truncate** 鉤子。
返回
如果授予許可權,則返回 0。
-
int security_task_alloc(struct task_struct *task, unsigned long clone_flags)¶
分配任務的LSM blob
引數
struct task_struct *task任務
unsigned long clone_flags指示正在共享的內容的標誌
描述
處理與任務相關的資源的分配。
返回
成功返回零,失敗返回負值。
-
void security_task_free(struct task_struct *task)¶
釋放任務的LSM blob和相關資源
引數
struct task_struct *task任務
描述
處理與任務相關的資源的釋放。請注意,這可以從中斷上下文中呼叫。
引數
struct cred *cred憑證
gfp_t gfpgfp 標誌
描述
僅分配足夠的記憶體並附加到 **cred**,以便 cred_transfer() 不會得到 ENOMEM。
返回
成功時返回 0,失敗時返回負值。
引數
struct cred *cred憑證
描述
取消分配並清除一組憑證中的 cred->security 欄位。
-
int security_prepare_creds(struct cred *new, const struct cred *old, gfp_t gfp)¶
準備一組新的憑證
引數
struct cred *new新的憑證
const struct cred *old原始憑證
gfp_t gfpgfp 標誌
描述
透過從舊集合複製資料來準備一組新的憑證。
返回
成功時返回 0,失敗時返回負值。
-
void security_transfer_creds(struct cred *new, const struct cred *old)¶
傳輸憑證
引數
struct cred *new目標憑證
const struct cred *old原始憑證
描述
將資料從原始憑證傳輸到新的憑證。
-
int security_kernel_act_as(struct cred *new, u32 secid)¶
設定核心憑據以充當 secid
引數
struct cred *new憑證
u32 secidsecid
描述
設定核心服務的憑據以充當(主觀上下文)。當前任務必須是提名 secid 的任務。
返回
成功時返回 0。
引數
struct cred *new目標憑證
struct inode *inode引用 inode
描述
在一組憑據中設定檔案建立上下文,使其與指定 inode 的客觀上下文相同。當前任務必須是提名 inode 的任務。
返回
成功時返回 0。
-
int security_kernel_module_request(char *kmod_name)¶
檢查是否允許載入模組
引數
char *kmod_name模組名稱
描述
允許觸發核心自動向上呼叫使用者空間,以便使用者空間載入具有給定名稱的核心模組的能力。
返回
成功時返回 0。
-
int security_task_fix_setuid(struct cred *new, const struct cred *old, int flags)¶
使用新的使用者 ID 屬性更新 LSM
引數
struct cred *new更新的憑據
const struct cred *old正在替換的憑據
int flagsLSM_SETID_* 標誌值
描述
在設定當前程序的一個或多個使用者身份屬性後,更新模組的狀態。 flags 引數指示哪個 set*uid 系統呼叫呼叫了此鉤子。如果 new 是將要安裝的一組憑據。應該對此進行修改,而不是對 current->cred 進行修改。
返回
成功返回 0。
-
int security_task_fix_setgid(struct cred *new, const struct cred *old, int flags)¶
使用新的組 ID 屬性更新 LSM
引數
struct cred *new更新的憑據
const struct cred *old正在替換的憑據
int flagsLSM_SETID_* 標誌值
描述
在設定當前程序的一個或多個組身份屬性後,更新模組的狀態。 flags 引數指示哪個 set*gid 系統呼叫呼叫了此鉤子。 new 是將要安裝的一組憑據。應該對此進行修改,而不是對 current->cred 進行修改。
返回
成功返回 0。
-
int security_task_fix_setgroups(struct cred *new, const struct cred *old)¶
使用新的補充組更新 LSM
引數
struct cred *new更新的憑據
const struct cred *old正在替換的憑據
描述
在設定當前程序的補充組身份屬性後,更新模組的狀態。 new 是將要安裝的一組憑據。應該對此進行修改,而不是對 current->cred 進行修改。
返回
成功返回 0。
-
int security_task_setpgid(struct task_struct *p, pid_t pgid)¶
檢查是否允許設定 pgid
引數
struct task_struct *p正在修改的任務
pid_t pgid新的 pgid
描述
在將程序 p 的程序組識別符號設定為 pgid 之前,檢查許可權。
返回
如果授予許可權,則返回 0。
-
int security_task_getpgid(struct task_struct *p)¶
檢查是否允許獲取 pgid
引數
struct task_struct *p任務
描述
在獲取程序 p 的程序組識別符號之前,檢查許可權。
返回
如果授予許可權,則返回 0。
-
int security_task_getsid(struct task_struct *p)¶
檢查是否允許獲取會話 ID
引數
struct task_struct *p任務
描述
在獲取程序 p 的會話識別符號之前,檢查許可權。
返回
如果授予許可權,則返回 0。
-
int security_task_setnice(struct task_struct *p, int nice)¶
檢查是否允許設定任務的 nice 值
引數
struct task_struct *p目標任務
int nicenice 值
描述
在將 p 的 nice 值設定為 nice 之前,檢查許可權。
返回
如果授予許可權,則返回 0。
-
int security_task_setioprio(struct task_struct *p, int ioprio)¶
檢查是否允許設定任務的 ioprio
引數
struct task_struct *p目標任務
int ioprioioprio 值
描述
在將 p 的 ioprio 值設定為 ioprio 之前,檢查許可權。
返回
如果授予許可權,則返回 0。
-
int security_task_getioprio(struct task_struct *p)¶
檢查是否允許獲取任務的 ioprio
引數
struct task_struct *p任務
描述
在獲取 p 的 ioprio 值之前,檢查許可權。
返回
如果授予許可權,則返回 0。
-
int security_task_prlimit(const struct cred *cred, const struct cred *tcred, unsigned int flags)¶
檢查是否允許獲取/設定資源限制
引數
const struct cred *cred當前任務憑據
const struct cred *tcred目標任務憑據
unsigned int flagsLSM_PRLIMIT_* 標誌位,指示獲取/設定/兩者
描述
在獲取和/或設定另一個任務的資源限制之前,檢查許可權。
返回
如果授予許可權,則返回 0。
-
int security_task_setrlimit(struct task_struct *p, unsigned int resource, struct rlimit *new_rlim)¶
檢查是否允許設定新的 rlimit 值
引數
struct task_struct *p目標任務的組領導者
unsigned int resource正在設定其限制的資源
struct rlimit *new_rlim新的資源限制
描述
在將程序 p 的 resource 的資源限制設定為 new_rlim 之前,檢查許可權。可以透過取消引用 (p->signal->rlim + resource) 來檢查舊的資源限制值。
返回
如果授予許可權,則返回 0。
-
int security_task_setscheduler(struct task_struct *p)¶
檢查是否允許設定排程策略/引數
引數
struct task_struct *p目標任務
描述
在設定程序 p 的排程策略和/或引數之前,檢查許可權。
返回
如果授予許可權,則返回 0。
-
int security_task_getscheduler(struct task_struct *p)¶
檢查是否允許獲取排程資訊
引數
struct task_struct *p目標任務
描述
在獲取程序 p 的排程資訊之前,檢查許可權。
返回
如果授予許可權,則返回 0。
-
int security_task_movememory(struct task_struct *p)¶
檢查是否允許移動記憶體
引數
struct task_struct *p任務
描述
在移動程序 p 擁有的記憶體之前,檢查許可權。
返回
如果授予許可權,則返回 0。
-
int security_task_kill(struct task_struct *p, struct kernel_siginfo *info, int sig, const struct cred *cred)¶
檢查是否允許傳送訊號
引數
struct task_struct *p目標程序
struct kernel_siginfo *info訊號資訊
int sig訊號值
const struct cred *cred訊號傳送者的憑據,如果 current 為 NULL
描述
在向 p 傳送訊號 sig 之前,檢查許可權。 info 可以是 NULL、常量 1 或指向 kernel_siginfo 結構的指標。如果 info 是 1 或 SI_FROMKERNEL(info) 為真,則應將該訊號視為來自核心,並且通常應允許。 SIGIO 訊號由 file_security_ops 中的 send_sigiotask 鉤子單獨處理。
返回
如果授予許可權,則返回 0。
-
int security_task_prctl(int option, unsigned long arg2, unsigned long arg3, unsigned long arg4, unsigned long arg5)¶
檢查是否允許 prctl 操作
引數
int option操作
unsigned long arg2引數
unsigned long arg3引數
unsigned long arg4引數
unsigned long arg5引數
描述
在對當前程序執行程序控制操作之前,檢查許可權。
返回
- 如果沒有人想處理此操作,則返回 -ENOSYS,任何其他值
導致 prctl() 立即返回該值。
引數
struct task_struct *p任務
struct inode *inodeinode
描述
根據關聯任務的安全屬性設定 inode 的安全屬性,例如,對於 /proc/pid inodes。
引數
const struct cred *cred準備好的憑據
描述
在建立新的使用者名稱空間之前,檢查許可權。
返回
成功時返回 0,否則返回 < 0 錯誤程式碼。
-
int security_ipc_permission(struct kern_ipc_perm *ipcp, short flag)¶
檢查是否允許 sysv ipc 訪問
引數
struct kern_ipc_perm *ipcpipc 許可權結構
short flag請求的許可權
描述
檢查訪問 IPC 的許可權。
返回
如果授予許可權,則返回 0。
-
void security_ipc_getlsmprop(struct kern_ipc_perm *ipcp, struct lsm_prop *prop)¶
獲取 sysv ipc 物件 LSM 資料
引數
struct kern_ipc_perm *ipcpipc 許可權結構
struct lsm_prop *prop指向 lsm 資訊的指標
描述
獲取與 ipc 物件關聯的 lsm 資訊。
-
int security_msg_msg_alloc(struct msg_msg *msg)¶
分配一個 sysv ipc 訊息 LSM blob
引數
struct msg_msg *msg訊息結構
描述
分配一個安全結構體,並將其附加到 msg->security 欄位。首次建立該結構體時,security 欄位初始化為 NULL。
返回
如果操作成功且許可權被授予,則返回 0。
-
void security_msg_msg_free(struct msg_msg *msg)¶
釋放一個 sysv ipc 訊息 LSM blob
引數
struct msg_msg *msg訊息結構
描述
釋放此訊息的安全結構體。
-
int security_msg_queue_alloc(struct kern_ipc_perm *msq)¶
分配一個 sysv ipc 訊息佇列 LSM blob
引數
struct kern_ipc_perm *msqsysv ipc 許可權結構
描述
分配一個安全結構體,並將其附加到 msg。首次建立該結構體時,security 欄位初始化為 NULL。
返回
如果操作成功且許可權被授予,則返回 0。
-
void security_msg_queue_free(struct kern_ipc_perm *msq)¶
釋放一個 sysv ipc 訊息佇列 LSM blob
引數
struct kern_ipc_perm *msqsysv ipc 許可權結構
描述
釋放訊息佇列的 security 欄位 perm->security。
-
int security_msg_queue_associate(struct kern_ipc_perm *msq, int msqflg)¶
檢查是否允許訊息佇列操作
引數
struct kern_ipc_perm *msqsysv ipc 許可權結構
int msqflg操作標誌
描述
透過 msgget 系統呼叫請求訊息佇列時,檢查許可權。僅當為現有訊息佇列返回訊息佇列識別符號時才呼叫此鉤子,而不是建立新訊息佇列時。
返回
如果授予許可權,則返回 0。
-
int security_msg_queue_msgctl(struct kern_ipc_perm *msq, int cmd)¶
檢查是否允許訊息佇列操作
引數
struct kern_ipc_perm *msqsysv ipc 許可權結構
int cmd操作
描述
當要在具有許可權的訊息佇列上執行 cmd 指定的訊息控制操作時,檢查許可權。
返回
如果授予許可權,則返回 0。
-
int security_msg_queue_msgsnd(struct kern_ipc_perm *msq, struct msg_msg *msg, int msqflg)¶
檢查是否允許傳送 sysv ipc 訊息
引數
struct kern_ipc_perm *msqsysv ipc 許可權結構
struct msg_msg *msg訊息
int msqflg操作標誌
描述
在訊息 msg 排隊到 msq 中指定的具有許可權的訊息佇列之前,檢查許可權。
返回
如果授予許可權,則返回 0。
-
int security_msg_queue_msgrcv(struct kern_ipc_perm *msq, struct msg_msg *msg, struct task_struct *target, long type, int mode)¶
檢查是否允許接收 sysv ipc 訊息
引數
struct kern_ipc_perm *msqsysv ipc 許可權結構
struct msg_msg *msg訊息
struct task_struct *target目標任務
long type請求的訊息型別
int mode操作標誌
描述
在從訊息佇列中刪除訊息 msg 之前,檢查許可權。 target 任務結構包含一個指向將接收訊息的程序的指標(當執行內聯接收時,不等於當前程序)。
返回
如果授予許可權,則返回 0。
-
int security_shm_alloc(struct kern_ipc_perm *shp)¶
分配一個 sysv shm LSM blob
引數
struct kern_ipc_perm *shpsysv ipc 許可權結構
描述
分配一個安全結構體,並將其附加到 shp 安全欄位。首次建立該結構體時,security 欄位初始化為 NULL。
返回
如果操作成功且許可權被授予,則返回 0。
-
void security_shm_free(struct kern_ipc_perm *shp)¶
釋放一個 sysv shm LSM blob
引數
struct kern_ipc_perm *shpsysv ipc 許可權結構
描述
釋放記憶體段的安全結構體 perm->security。
-
int security_shm_associate(struct kern_ipc_perm *shp, int shmflg)¶
檢查是否允許 sysv shm 操作
引數
struct kern_ipc_perm *shpsysv ipc 許可權結構
int shmflg操作標誌
描述
透過 shmget 系統呼叫請求共享記憶體區域時,檢查許可權。僅當為現有區域返回共享記憶體區域識別符號時才呼叫此鉤子,而不是建立新的共享記憶體區域時。
返回
如果授予許可權,則返回 0。
-
int security_shm_shmctl(struct kern_ipc_perm *shp, int cmd)¶
檢查是否允許 sysv shm 操作
引數
struct kern_ipc_perm *shpsysv ipc 許可權結構
int cmd操作
描述
當要在 shp 中具有許可權的共享記憶體區域上執行 cmd 指定的共享記憶體控制操作時,檢查許可權。
返回
如果授予許可權,則返回 0。
-
int security_shm_shmat(struct kern_ipc_perm *shp, char __user *shmaddr, int shmflg)¶
檢查是否允許 sysv shm 附加操作
引數
struct kern_ipc_perm *shpsysv ipc 許可權結構
char __user *shmaddr要附加的記憶體區域的地址
int shmflg操作標誌
描述
在允許 shmat 系統呼叫將具有許可權 shp 的共享記憶體段附加到呼叫程序的資料段之前,檢查許可權。附加地址由 shmaddr 指定。
返回
如果授予許可權,則返回 0。
-
int security_sem_alloc(struct kern_ipc_perm *sma)¶
分配一個 sysv 訊號量 LSM blob
引數
struct kern_ipc_perm *smasysv ipc 許可權結構
描述
分配一個安全結構體,並將其附加到 sma 安全欄位。首次建立該結構體時,security 欄位初始化為 NULL。
返回
如果操作成功且許可權被授予,則返回 0。
-
void security_sem_free(struct kern_ipc_perm *sma)¶
釋放一個 sysv 訊號量 LSM blob
引數
struct kern_ipc_perm *smasysv ipc 許可權結構
描述
釋放訊號量的安全結構體 sma->security。
-
int security_sem_associate(struct kern_ipc_perm *sma, int semflg)¶
檢查是否允許 sysv 訊號量操作
引數
struct kern_ipc_perm *smasysv ipc 許可權結構
int semflg操作標誌
描述
透過 semget 系統呼叫請求訊號量時,檢查許可權。僅當為現有訊號量返回訊號量識別符號時才呼叫此鉤子,而不是建立新訊號量時。
返回
如果授予許可權,則返回 0。
-
int security_sem_semctl(struct kern_ipc_perm *sma, int cmd)¶
檢查是否允許 sysv 訊號量操作
引數
struct kern_ipc_perm *smasysv ipc 許可權結構
int cmd操作
描述
當要在訊號量上執行 cmd 指定的訊號量操作時,檢查許可權。
返回
如果授予許可權,則返回 0。
-
int security_sem_semop(struct kern_ipc_perm *sma, struct sembuf *sops, unsigned nsops, int alter)¶
檢查是否允許 sysv 訊號量操作
引數
struct kern_ipc_perm *smasysv ipc 許可權結構
struct sembuf *sops要執行的操作
unsigned nsops操作的數量
int alter指示將進行更改的標誌
描述
在對訊號量整合員執行操作之前,檢查許可權。如果 alter 標誌非零,則可以修改訊號量集。
返回
如果授予許可權,則返回 0。
-
int security_getselfattr(unsigned int attr, struct lsm_ctx __user *uctx, u32 __user *size, u32 flags)¶
讀取當前程序的 LSM 屬性。
引數
unsigned int attr要返回哪個屬性
struct lsm_ctx __user *uctx資訊的使用者空間目標,或 NULL
u32 __user *size指向可用於接收資料的可用空間大小的指標
u32 flags特殊處理選項。 LSM_FLAG_SINGLE 表示僅報告與傳遞的 ctx 中標識的 LSM 關聯的屬性。
描述
uctx 的 NULL 值可用於獲取屬性的數量和資料的大小。
成功時返回找到的屬性的數量,錯誤時返回負值。 size 重置為資料的總大小。如果 size 不足以包含資料,則返回 -E2BIG。
-
int security_setselfattr(unsigned int attr, struct lsm_ctx __user *uctx, u32 size, u32 flags)¶
設定當前程序的 LSM 屬性。
引數
unsigned int attr要設定哪個屬性
struct lsm_ctx __user *uctx資訊的使用者空間來源
u32 size資料的大小
u32 flags為將來使用保留,必須為 0
描述
設定當前程序的 LSM 屬性。 LSM、屬性和新值包含在 uctx 中。
成功時返回 0,如果輸入不一致則返回 -EINVAL,如果使用者緩衝區不可訪問則返回 -EFAULT,如果大小太大則返回 E2BIG,或者返回 LSM 特定故障。
-
int security_getprocattr(struct task_struct *p, int lsmid, const char *name, char **value)¶
讀取任務的屬性
引數
struct task_struct *p任務
int lsmidLSM 標識
const char *name屬性名稱
char **value屬性值
描述
讀取任務 p 的屬性 name,如果允許,將其儲存到 value 中。
返回
成功時返回 value 的長度,否則返回負值。
-
int security_setprocattr(int lsmid, const char *name, void *value, size_t size)¶
設定任務的屬性
引數
int lsmidLSM 標識
const char *name屬性名稱
void *value屬性值
size_t size屬性值大小
描述
如果允許,將當前任務的屬性 name 寫入(設定)為 value,大小為 size。
返回
成功時返回寫入的位元組數,否則返回負值。
-
int security_post_notification(const struct cred *w_cred, const struct cred *cred, struct watch_notification *n)¶
檢查是否可以釋出監視通知
引數
const struct cred *w_cred設定監視任務的憑據
const struct cred *cred觸發監視任務的憑據
struct watch_notification *n通知
描述
檢查是否可以將監視通知釋出到特定佇列。
返回
如果授予許可權,則返回 0。
引數
struct key *key要監視的金鑰
描述
檢查是否允許程序監視來自金鑰或金鑰環的事件通知。
返回
如果授予許可權,則返回 0。
引數
struct sock *sk傳送套接字
struct sk_buff *skbnetlink訊息
描述
儲存netlink訊息的安全資訊,以便在處理訊息時可以執行許可權檢查。可以使用netlink_skb_parms結構的eff_cap欄位儲存安全資訊。還可以用於提供對訊息傳輸的細粒度控制。
返回
- 如果成功儲存資訊並允許傳輸訊息,則返回0。
允許傳輸。
-
int security_socket_create(int family, int type, int protocol, int kern)¶
檢查是否允許建立新套接字
引數
int family協議族
int type通訊型別
int protocol請求的協議
int kern如果請求核心套接字,則設定為1
描述
在建立新套接字之前檢查許可權。
返回
如果授予許可權,則返回 0。
-
int security_socket_post_create(struct socket *sock, int family, int type, int protocol, int kern)¶
初始化新建立的套接字
引數
struct socket *sock套接字
int family協議族
int type通訊型別
int protocol請求的協議
int kern如果請求核心套接字,則設定為1
描述
此鉤子允許模組更新或分配每個套接字的安全結構。 請注意,安全欄位未直接新增到套接字結構中,而是將套接字安全資訊儲存在關聯的 inode 中。 通常,inode alloc_security 鉤子會將安全資訊分配並附加到 SOCK_INODE(sock)->i_security。 此鉤子可用於使用在分配 inode 時無法獲得的附加資訊來更新 SOCK_INODE(sock)->i_security 欄位。
返回
如果授予許可權,則返回 0。
引數
struct socket *sock套接字
struct sockaddr *address請求的繫結地址
int addrlen地址的長度
描述
在執行套接字協議層繫結操作並將套接字 sock 繫結到 address 引數中指定的地址之前,檢查許可權。
返回
如果授予許可權,則返回 0。
-
int security_socket_connect(struct socket *sock, struct sockaddr *address, int addrlen)¶
檢查是否允許套接字連線操作
引數
struct socket *sock套接字
struct sockaddr *address遠端連線點的地址
int addrlen地址的長度
描述
在套接字協議層連線操作嘗試將套接字 sock 連線到遠端地址 address 之前,檢查許可權。
返回
如果授予許可權,則返回 0。
引數
struct socket *sock套接字
int backlog連線佇列大小
描述
在套接字協議層偵聽操作之前檢查許可權。
返回
如果授予許可權,則返回 0。
引數
struct socket *sock偵聽套接字
struct socket *newsock新建立的連線套接字
描述
在接受新連線之前檢查許可權。 請注意,已建立新套接字 newsock 並已將某些資訊複製到該套接字,但實際上尚未執行接受操作。
返回
如果授予許可權,則返回 0。
引數
struct socket *sock傳送套接字
struct msghdr *msg要傳送的訊息
int size訊息大小
描述
在將訊息傳輸到另一個套接字之前檢查許可權。
返回
如果授予許可權,則返回 0。
-
int security_socket_recvmsg(struct socket *sock, struct msghdr *msg, int size, int flags)¶
檢查是否允許接收訊息
引數
struct socket *sock接收套接字
struct msghdr *msg要接收的訊息
int size訊息大小
int flags操作標誌
描述
在從套接字接收訊息之前檢查許可權。
返回
如果授予許可權,則返回 0。
引數
struct socket *sock套接字
描述
在讀取套接字物件的本地地址(名稱)之前檢查許可權。
返回
如果授予許可權,則返回 0。
引數
struct socket *sock套接字
描述
在讀取套接字物件的遠端地址(名稱)之前檢查許可權。
返回
如果授予許可權,則返回 0。
引數
struct socket *sock套接字
int level選項的協議級別
int optname選項名稱
描述
在檢索與套接字 sock 關聯的選項之前檢查許可權。
返回
如果授予許可權,則返回 0。
引數
struct socket *sock套接字
int level選項的協議級別
int optname選項名稱
描述
在設定與套接字 sock 關聯的選項之前檢查許可權。
返回
如果授予許可權,則返回 0。
引數
struct socket *sock套接字
int how指示如何處理傳送和接收的標誌
描述
檢查是否允許關閉套接字 sock 上連線的全部或部分。
返回
如果授予許可權,則返回 0。
-
int security_socket_getpeersec_stream(struct socket *sock, sockptr_t optval, sockptr_t optlen, unsigned int len)¶
獲取遠端對等方標籤
引數
struct socket *sock套接字
sockptr_t optval目標緩衝區
sockptr_t optlen複製到緩衝區中的對等方標籤的大小
unsigned int len目標緩衝區的最大大小
描述
此鉤子允許安全模組透過 getsockopt SO_GETPEERSEC 為使用者空間提供 unix 或連線的 tcp 套接字的對等套接字安全狀態。 對於 tcp 套接字,如果套接字與 ipsec SA 相關聯,這可能是有意義的。
返回
- 如果一切正常,則返回 0,否則,返回典型的 getsockopt 返回值。
價值觀。
引數
struct sock *sock需要 blob 的套接字
gfp_t gfp分配模式
描述
為所有模組分配套接字 blob
返回 0,如果無法分配記憶體,則返回 -ENOMEM。
引數
struct sock *sk套接字
int family協議族
gfp_t prioritygfp 標誌
描述
分配並將安全結構附加到 sk->sk_security 欄位,該欄位用於在本地流套接字之間複製安全屬性。
返回
成功時返回 0,失敗時返回錯誤。
引數
struct sock *sk套接字
描述
取消分配安全結構。
-
void security_inet_csk_clone(struct sock *newsk, const struct request_sock *req)¶
基於 request_sock 設定新的 sock LSM 狀態
引數
struct sock *newsk新的 sock
const struct request_sock *req連線 request_sock
描述
使用 req 中的 LSM 狀態來設定 sock 的 LSM 狀態。
引數
struct sock *sk擁有的 MPTCP 套接字
struct sock *ssk新的子流
描述
更新給定 MPTCP 子流的標籤,使其與擁有的 MPTCP 套接字的標籤匹配。這個鉤子必須在透過 security_socket_create() 和 security_socket_post_create() LSM 鉤子建立和初始化套接字之後呼叫。
返回
成功返回 0,失敗返回負錯誤程式碼。
-
int security_xfrm_policy_clone(struct xfrm_sec_ctx *old_ctx, struct xfrm_sec_ctx **new_ctxp)¶
克隆 xfrm 策略 LSM 狀態
引數
struct xfrm_sec_ctx *old_ctxxfrm 安全上下文
struct xfrm_sec_ctx **new_ctxp目標 xfrm 安全上下文
描述
在 new_ctxp 中分配一個安全結構,其中包含來自 old_ctx 結構的資訊。
返回
如果操作成功,則返回 0。
-
int security_xfrm_policy_delete(struct xfrm_sec_ctx *ctx)¶
檢查是否允許刪除 xfrm 策略
引數
struct xfrm_sec_ctx *ctxxfrm 安全上下文
描述
授權刪除 SPD 條目。
返回
如果授予許可權,則返回 0。
-
int security_xfrm_state_alloc_acquire(struct xfrm_state *x, struct xfrm_sec_ctx *polsec, u32 secid)¶
分配一個 xfrm 狀態 LSM blob
引數
struct xfrm_state *x正在新增到 SAD 的 xfrm 狀態
struct xfrm_sec_ctx *polsec關聯策略的安全上下文
u32 secid來自流的 secid
描述
為 x->security 欄位分配一個安全結構;當分配 xfrm_state 時,該安全欄位初始化為 NULL。將上下文設定為與 secid 對應。
返回
如果操作成功,則返回 0。
-
void security_xfrm_state_free(struct xfrm_state *x)¶
釋放 xfrm 狀態
引數
struct xfrm_state *xxfrm 狀態
描述
取消分配 x->security。
-
int security_xfrm_policy_lookup(struct xfrm_sec_ctx *ctx, u32 fl_secid)¶
檢查是否允許使用 xfrm 策略
引數
struct xfrm_sec_ctx *ctx目標 xfrm 安全上下文
u32 fl_secid用於授權訪問的流 secid
描述
檢查當流選擇 xfrm_policy 以處理資料包上的 XFRM 時是否允許該操作。 該鉤子在選擇每個套接字策略或通用 xfrm 策略時呼叫。
返回
- 如果授予許可權,則返回 0,否則返回 -ESRCH,或其他錯誤返回 -errno。
其他錯誤。
-
int security_xfrm_state_pol_flow_match(struct xfrm_state *x, struct xfrm_policy *xp, const struct flowi_common *flic)¶
檢查 xfrm 是否匹配
引數
struct xfrm_state *x要匹配的 xfrm 狀態
struct xfrm_policy *xp要檢查是否匹配的 xfrm 策略
const struct flowi_common *flic要檢查是否匹配的流。
描述
檢查 xp 和 flic 是否與 x 匹配。
返回
如果存在匹配,則返回 1。
引數
struct sk_buff *skbxfrm 資料包
u32 *secidsecid
描述
解碼 skb 中的資料包,並在 secid 中返回安全標籤。
返回
如果所有使用的 xfrm 具有相同的 secid,則返回 0。
-
int security_key_alloc(struct key *key, const struct cred *cred, unsigned long flags)¶
分配並初始化核心金鑰 LSM blob
引數
struct key *key金鑰
const struct cred *cred憑證
unsigned long flags分配標誌
描述
允許分配金鑰並分配安全資料。請注意,此時尚未為金鑰分配序列號。
返回
如果授予許可權,則返回 0,否則返回 -ve 錯誤。
引數
struct key *key金鑰
描述
銷燬通知;釋放安全資料。
-
int security_key_permission(key_ref_t key_ref, const struct cred *cred, enum key_need_perm need_perm)¶
檢查是否允許核心金鑰操作
引數
key_ref_t key_ref金鑰引用
const struct cred *cred請求訪問的參與者的憑據
enum key_need_perm need_perm請求的許可權
描述
檢視是否授予程序對金鑰的特定操作許可權。
返回
如果授予許可權,則返回 0,否則返回 -ve 錯誤。
引數
struct key *key金鑰
char **buffer安全標籤緩衝區
描述
獲取附加到金鑰的安全上下文的文字表示形式,以便於處理 KEYCTL_GETSECURITY。此函式分配 NUL 終止字串的儲存空間,呼叫者應釋放它。
返回
- 返回 buffer 的長度(包括終止 NUL),如果發生錯誤則返回 -ve。
如果金鑰未分配安全標籤,則也可能返回 0(以及 NULL 緩衝區指標)。
-
void security_key_post_create_or_update(struct key *keyring, struct key *key, const void *payload, size_t payload_len, unsigned long flags, bool create)¶
金鑰建立或更新通知
引數
struct key *keyring金鑰所連結到的金鑰環
struct key *key已建立或更新的金鑰
const void *payload用於例項化或更新金鑰的資料
size_t payload_len有效負載的長度
unsigned long flags金鑰標誌
bool create指示金鑰是建立還是更新的標誌
描述
通知呼叫者金鑰的建立或更新。
-
int security_audit_rule_init(u32 field, u32 op, char *rulestr, void **lsmrule, gfp_t gfp)¶
分配並初始化 LSM 審計規則結構
引數
u32 field審計操作
u32 op規則運算子
char *rulestr規則上下文
void **lsmrule審計規則結構的接收緩衝區
gfp_t gfp用於 kmalloc 的 GFP 標誌
描述
分配並初始化 LSM 審計規則結構。
返回
- 如果已成功設定 lsmrule,則返回 0,如果規則無效,則返回 -EINVAL。
規則無效。
-
int security_audit_rule_known(struct audit_krule *krule)¶
檢查審計規則是否包含 LSM 欄位
引數
struct audit_krule *krule審計規則
描述
指定給定的 krule 是否包含任何與當前 LSM 相關的欄位。
返回
如果找到關係,則返回 1,否則返回 0。
-
void security_audit_rule_free(void *lsmrule)¶
釋放 LSM 審計規則結構
引數
void *lsmrule審計規則結構
描述
取消分配先前由 audit_rule_init() 分配的 LSM 審計規則結構。
-
int security_audit_rule_match(struct lsm_prop *prop, u32 field, u32 op, void *lsmrule)¶
檢查標籤是否與審計規則匹配
引數
struct lsm_prop *prop安全標籤
u32 fieldLSM 審計欄位
u32 op匹配運算子
void *lsmrule審計規則
描述
確定給定的 secid 是否與先前經 security_audit_rule_known() 批准的規則匹配。
返回
- 如果 secid 與規則匹配,則返回 1,如果不匹配,則返回 0,如果失敗,則返回 -ERRNO。
失敗。
-
int security_bpf(int cmd, union bpf_attr *attr, unsigned int size, bool kernel)¶
檢查是否允許 bpf 系統呼叫操作
引數
int cmd命令
union bpf_attr *attrbpf 屬性
unsigned int sizesize
bool kernel呼叫是否源自核心
描述
在將屬性複製到核心後,對所有 bpf 系統呼叫執行初始檢查。實際的安全模組可以實現自己的規則來檢查它們需要的特定命令。
返回
如果授予許可權,則返回 0。
-
int security_bpf_map(struct bpf_map *map, fmode_t fmode)¶
檢查是否允許訪問 bpf map
引數
struct bpf_map *mapbpf map
fmode_t fmode模式
描述
在核心為 eBPF map 生成並返回檔案描述符時進行檢查。
返回
如果授予許可權,則返回 0。
-
int security_bpf_prog(struct bpf_prog *prog)¶
檢查是否允許訪問 bpf 程式
引數
struct bpf_prog *progbpf 程式
描述
在核心為 eBPF 程式生成並返回檔案描述符時進行檢查。
返回
如果授予許可權,則返回 0。
-
int security_bpf_map_create(struct bpf_map *map, union bpf_attr *attr, struct bpf_token *token, bool kernel)¶
檢查是否允許建立 BPF map
引數
struct bpf_map *mapBPF map 物件
union bpf_attr *attr用於建立 BPF map 的 BPF 系統呼叫屬性
struct bpf_token *token用於授予使用者訪問許可權的 BPF 令牌
bool kernel呼叫是否源自核心
描述
在核心建立新的 BPF map 時進行檢查。這也是為需要它們的 LSM 分配 LSM blob 的地方。
返回
成功時返回 0,失敗時返回錯誤。
-
int security_bpf_prog_load(struct bpf_prog *prog, union bpf_attr *attr, struct bpf_token *token, bool kernel)¶
檢查是否允許載入 BPF 程式
引數
struct bpf_prog *progBPF 程式物件
union bpf_attr *attr用於建立 BPF 程式的 BPF 系統呼叫屬性
struct bpf_token *token用於授予使用者訪問 BPF 子系統許可權的 BPF 令牌
bool kernel呼叫是否源自核心
描述
當核心載入 BPF 程式並分配相關的 BPF 程式物件時,執行訪問控制檢查。此鉤子還負責為 BPF 程式分配任何所需的 LSM 狀態。
返回
成功時返回 0,失敗時返回錯誤。
-
int security_bpf_token_create(struct bpf_token *token, union bpf_attr *attr, const struct path *path)¶
檢查是否允許建立 BPF 令牌
引數
struct bpf_token *tokenBPF 令牌物件
union bpf_attr *attr用於建立 BPF 令牌的 BPF 系統呼叫屬性
const struct path *path指向從中建立 BPF 令牌的 BPF FS 掛載點的路徑
描述
當核心從 BPF FS 例項例項化新的 BPF 令牌物件時進行檢查。這也是可以為 LSM 分配 LSM blob 的地方。
返回
成功時返回 0,失敗時返回錯誤。
-
int security_bpf_token_cmd(const struct bpf_token *token, enum bpf_cmd cmd)¶
檢查是否允許 BPF 令牌委託請求的 BPF 系統呼叫命令
引數
const struct bpf_token *tokenBPF 令牌物件
enum bpf_cmd cmd請求由 BPF 令牌委託的 BPF 系統呼叫命令
描述
當核心決定提供的 BPF 令牌是否應允許委託請求的 BPF 系統呼叫命令時進行檢查。
返回
成功時返回 0,失敗時返回錯誤。
-
int security_bpf_token_capable(const struct bpf_token *token, int cap)¶
檢查是否允許 BPF 令牌委託請求的 BPF 相關 capability
引數
const struct bpf_token *tokenBPF 令牌物件
int cap請求由 BPF 令牌委託的 capability
描述
當核心決定提供的 BPF 令牌是否應允許委託請求的 BPF 相關 capability 時進行檢查。
返回
成功時返回 0,失敗時返回錯誤。
-
void security_bpf_map_free(struct bpf_map *map)¶
釋放 bpf map 的 LSM blob
引數
struct bpf_map *mapbpf map
描述
清理儲存在 bpf map 中的安全資訊。
-
void security_bpf_prog_free(struct bpf_prog *prog)¶
釋放 BPF 程式的 LSM blob
引數
struct bpf_prog *progBPF 程式結構
描述
清理儲存在 BPF 程式中的安全資訊。
-
void security_bpf_token_free(struct bpf_token *token)¶
釋放 BPF 令牌的 LSM blob
引數
struct bpf_token *tokenBPF 令牌結構
描述
清理儲存在 BPF 令牌中的安全資訊。
-
int security_perf_event_open(int type)¶
檢查是否允許 perf event open
引數
int type事件型別
描述
檢查是否允許 type 型別的 perf_event_open 系統呼叫。
返回
如果授予許可權,則返回 0。
-
int security_perf_event_alloc(struct perf_event *event)¶
分配 perf event LSM blob
引數
struct perf_event *eventperf event
描述
分配並儲存 perf_event 安全資訊。
返回
成功時返回 0,失敗時返回錯誤。
-
void security_perf_event_free(struct perf_event *event)¶
釋放 perf event LSM blob
引數
struct perf_event *eventperf event
描述
釋放(free)perf_event 安全資訊。
-
int security_perf_event_read(struct perf_event *event)¶
檢查是否允許讀取 perf event 標籤
引數
struct perf_event *eventperf event
描述
如果允許,讀取 perf_event 安全資訊。
返回
如果授予許可權,則返回 0。
-
int security_perf_event_write(struct perf_event *event)¶
檢查是否允許寫入 perf event 標籤
引數
struct perf_event *eventperf event
描述
如果允許,寫入 perf_event 安全資訊。
返回
如果授予許可權,則返回 0。
-
int security_uring_override_creds(const struct cred *new)¶
檢查是否允許覆蓋憑據
引數
const struct cred *new新的憑證
描述
檢查執行 io_uring 操作的當前任務是否允許使用 new 覆蓋其憑據。
返回
如果授予許可權,則返回 0。
-
int security_uring_sqpoll(void)¶
檢查是否允許 IORING_SETUP_SQPOLL
引數
void無引數
描述
檢查是否允許當前任務生成一個 io_uring 輪詢執行緒 (IORING_SETUP_SQPOLL)。
返回
如果授予許可權,則返回 0。
-
int security_uring_cmd(struct io_uring_cmd *ioucmd)¶
檢查是否允許 io_uring 直通命令
引數
struct io_uring_cmd *ioucmd命令
描述
檢查是否允許執行 file_operations uring_cmd。
返回
如果授予許可權,則返回 0。
-
int security_uring_allowed(void)¶
檢查是否允許 io_uring_setup()
引數
void無引數
描述
檢查是否允許當前任務呼叫 io_uring_setup()。
返回
如果授予許可權,則返回 0。
-
void security_initramfs_populated(void)¶
通知 LSM 已載入 initramfs
引數
void無引數
描述
告知 LSM initramfs 已被解壓縮到 rootfs 中。
-
struct dentry *securityfs_create_file(const char *name, umode_t mode, struct dentry *parent, void *data, const struct file_operations *fops)¶
在 securityfs 檔案系統中建立一個檔案
引數
const char *name指向包含要建立的檔名的字串的指標。
umode_t mode檔案應具有的許可權
struct dentry *parent指向此檔案的父 dentry 的指標。如果設定,這應為目錄 dentry。如果此引數為
NULL,則將在 securityfs 檔案系統的根目錄中建立檔案。void *data指向呼叫者稍後想要訪問的內容的指標。inode.i_private 指標將在 open() 呼叫中指向此值。
const struct file_operations *fops指向應用於此檔案的 struct file_operations 的指標。
描述
此函式在 securityfs 中建立一個具有給定 name 的檔案。
如果成功,此函式將返回指向 dentry 的指標。當要刪除檔案時,必須將此指標傳遞給 securityfs_remove() 函式(如果您的模組被解除安裝,則不會發生自動清理,您需要自行負責)。如果發生錯誤,該函式將返回錯誤值(透過 ERR_PTR)。
如果 securityfs 未在核心中啟用,則返回 -ENODEV 值。
-
struct dentry *securityfs_create_dir(const char *name, struct dentry *parent)¶
在 securityfs 檔案系統中建立一個目錄
引數
const char *name指向包含要建立的目錄名稱的字串的指標。
struct dentry *parent指向此檔案的父 dentry 的指標。如果設定,這應為目錄 dentry。如果此引數為
NULL,則將在 securityfs 檔案系統的根目錄中建立該目錄。
描述
此函式在 securityfs 中建立一個具有給定 name 的目錄。
如果成功,此函式將返回指向 dentry 的指標。當要刪除檔案時,必須將此指標傳遞給 securityfs_remove() 函式(如果您的模組被解除安裝,則不會發生自動清理,您需要自行負責)。如果發生錯誤,該函式將返回錯誤值(透過 ERR_PTR)。
如果 securityfs 未在核心中啟用,則返回 -ENODEV 值。
-
struct dentry *securityfs_create_symlink(const char *name, struct dentry *parent, const char *target, const struct inode_operations *iops)¶
在 securityfs 檔案系統中建立一個符號連結
引數
const char *name指向包含要建立的符號連結名稱的字串的指標。
struct dentry *parent指向符號連結的父 dentry 的指標。如果設定,這應為目錄 dentry。如果此引數為
NULL,則將在 securityfs 檔案系統的根目錄中建立該目錄。const char *target指向包含符號連結目標的名稱的字串的指標。如果此引數為
NULL,則需要設定 iops 引數來處理 .readlink 和 .get_link inode_operations。const struct inode_operations *iops指向用於符號連結的 struct inode_operations 的指標。如果此引數為
NULL,則將使用預設的 simple_symlink_inode operations。
描述
此函式在 securityfs 中建立一個具有給定 name 的符號連結。
如果成功,此函式將返回指向 dentry 的指標。當要刪除檔案時,必須將此指標傳遞給 securityfs_remove() 函式(如果您的模組被解除安裝,則不會發生自動清理,您需要自行負責)。如果發生錯誤,該函式將返回錯誤值(透過 ERR_PTR)。
如果 securityfs 未在核心中啟用,則返回 -ENODEV 值。
引數
struct dentry *dentry指向要移除的檔案或目錄的 dentry 的指標。
描述
此函式從 securityfs 中移除檔案或目錄,該檔案或目錄先前是透過呼叫另一個 securityfs 函式(例如 securityfs_create_file() 或其變體)建立的。
必須呼叫此函式才能移除檔案。模組移除時不會自動清理檔案;您需要在此處負責。
引數
struct dentry *dentry指向要移除的檔案或目錄的 dentry 的指標。
描述
此函式遞迴地從 securityfs 中移除檔案或目錄,該檔案或目錄先前是透過呼叫另一個 securityfs 函式(例如 securityfs_create_file() 或其變體)建立的。
審計介面¶
-
struct audit_buffer *audit_log_start(struct audit_context *ctx, gfp_t gfp_mask, int type)¶
獲取審計緩衝區
引數
struct audit_context *ctxaudit_context (可以為 NULL)
gfp_t gfp_mask分配型別
int type審計訊息型別
描述
成功時返回 audit_buffer 指標,失敗時返回 NULL。
獲取審計緩衝區。此例程會執行鎖定以獲取審計緩衝區,但隨後呼叫 audit_log_*format 不需要鎖定。如果任務 (ctx) 是當前在系統呼叫中的任務,則該系統呼叫將被標記為可審計,並且將在系統呼叫退出時寫入審計記錄。如果沒有關聯的任務,則任務上下文 (ctx) 應為 NULL。
-
void audit_log_format(struct audit_buffer *ab, const char *fmt, ...)¶
將訊息格式化到審計緩衝區中。
引數
struct audit_buffer *abaudit_buffer
const char *fmt格式字串
...與 fmt 字串匹配的可選引數
描述
所有工作都在 audit_log_vformat 中完成。
-
void audit_log_end(struct audit_buffer *ab)¶
結束一條審計記錄
引數
struct audit_buffer *abaudit_buffer
描述
我們無法在 irq 上下文中進行 netlink 傳送,因為它會阻塞(最後一個引數 flags 未設定為 MSG_DONTWAIT),因此審計緩衝區放置在一個佇列中,並排程一個 kthread 以在 irq 上下文之外從佇列中移除它們。可以在任何上下文中呼叫。
-
void audit_log(struct audit_context *ctx, gfp_t gfp_mask, int type, const char *fmt, ...)¶
記錄審計記錄
引數
struct audit_context *ctx審計上下文
gfp_t gfp_mask分配型別
int type審計訊息型別
const char *fmt要使用的格式字串
...與格式字串匹配的可變引數
描述
這是一個便利函式,它呼叫 audit_log_start、audit_log_vformat 和 audit_log_end。可以在任何上下文中呼叫。
-
int __audit_filter_op(struct task_struct *tsk, struct audit_context *ctx, struct list_head *list, struct audit_names *name, unsigned long op)¶
操作的通用過濾器助手(syscall/uring/etc)
引數
struct task_struct *tsk關聯的任務
struct audit_context *ctx審計上下文
struct list_head *list審計過濾器列表
struct audit_names *nameaudit_name (可以為 NULL)
unsigned long op當前 syscall/uring_op
描述
使用 ctx、name 和 op(必要時)針對 tsk 執行 list 中指定的 udit 過濾器;呼叫者負責確保在持有 RCU 讀取鎖定時進行呼叫。 name 引數可以為 NULL,但必須指定所有其他引數。如果過濾器找到匹配項,則返回 1/true;如果未找到匹配項,則返回 0/false。
-
void audit_filter_uring(struct task_struct *tsk, struct audit_context *ctx)¶
將過濾器應用於 io_uring 操作
引數
struct task_struct *tsk關聯的任務
struct audit_context *ctx審計上下文
-
void audit_reset_context(struct audit_context *ctx)¶
重置 audit_context 結構
引數
struct audit_context *ctx要重置的 audit_context
描述
audit_context 中的所有欄位都將重置為初始狀態,欄位持有的所有引用都將被刪除,並且私有記憶體將被釋放。當此函式返回時,audit_context 將適合重用,只要傳遞的上下文不是 NULL 或虛擬上下文。
-
int audit_alloc(struct task_struct *tsk)¶
為任務分配審計上下文塊
引數
struct task_struct *tsk任務
描述
過濾任務資訊,並在必要時分配每個任務的審計上下文。這樣做會為指定的任務啟用系統呼叫審計。這是從 copy_process 呼叫的,因此不需要鎖定。
-
void audit_log_uring(struct audit_context *ctx)¶
生成 AUDIT_URINGOP 記錄
引數
struct audit_context *ctx審計上下文
-
void __audit_free(struct task_struct *tsk)¶
釋放每個任務的審計上下文
引數
struct task_struct *tsk要釋放其審計上下文塊的任務
描述
從 copy_process、do_exit 和 io_uring 程式碼呼叫
-
void audit_return_fixup(struct audit_context *ctx, int success, long code)¶
修復 audit_context 中的返回程式碼
引數
struct audit_context *ctxaudit_context
int success指示操作是否成功的 true/false 值
long code操作返回程式碼
描述
如果實際返回程式碼稍後將由特定於 arch 的訊號處理程式修復,我們需要修復審計日誌中的返回程式碼。
-
void __audit_uring_entry(u8 op)¶
為 io_uring 準備核心任務的審計上下文
引數
u8 opio_uring 操作碼
描述
這類似於 audit_syscall_entry(),但旨在由 io_uring 操作使用。此函式應僅從 audit_uring_entry() 呼叫,因為我們依賴於該函式中存在的審計上下文檢查。
-
void __audit_uring_exit(int success, long code)¶
在 io_uring 之後包裝核心任務的審計上下文
引數
int success指示操作是否成功的 true/false 值
long code操作返回程式碼
描述
這類似於 audit_syscall_exit(),但旨在由 io_uring 操作使用。此函式應僅從 audit_uring_exit() 呼叫,因為我們依賴於該函式中存在的審計上下文檢查。
-
void __audit_syscall_entry(int major, unsigned long a1, unsigned long a2, unsigned long a3, unsigned long a4)¶
在 syscall 進入時填寫審計記錄
引數
int major主要的 syscall 型別(函式)
unsigned long a1額外的 syscall 暫存器 1
unsigned long a2額外的 syscall 暫存器 2
unsigned long a3額外的 syscall 暫存器 3
unsigned long a4額外的 syscall 暫存器 4
描述
在 syscall 進入時填寫審計上下文。只有在建立任務時建立了審計上下文,並且狀態或過濾器要求構建審計上下文時才會發生這種情況。如果來自每個任務的過濾器或來自每個 syscall 的過濾器的狀態為 AUDIT_STATE_RECORD,則該記錄將在 syscall 退出時寫入(否則,只有在核心的另一部分請求寫入該記錄時才會寫入)。
-
void __audit_syscall_exit(int success, long return_code)¶
在系統呼叫後釋放審計上下文
引數
int successsyscall 的成功值
long return_codesyscall 的返回值
描述
在系統呼叫後進行清理。如果審計上下文已被標記為可審計(由於過濾器的 AUDIT_STATE_RECORD 狀態,或者由於核心的另一部分寫入了審計訊息),則寫出 syscall 資訊。在所有情況下,釋放從 getname() 儲存的名稱。
-
struct filename *__audit_reusename(__user const char *uptr)¶
使用現有條目的資訊填寫檔名
引數
const __user char *uptr指向路徑名的使用者空間指標
描述
在 audit_names 列表中搜索當前審計上下文。如果存在具有匹配“uptr”的現有條目,則返回與該 audit_name 關聯的檔名。如果不是,則返回 NULL。
-
void __audit_getname(struct filename *name)¶
將名稱新增到列表
引數
struct filename *name要新增的名稱
描述
將名稱新增到此上下文的審計名稱列表中。從 fs/namei.c:getname() 呼叫。
-
void __audit_inode(struct filename *name, const struct dentry *dentry, unsigned int flags)¶
儲存來自查詢的 inode 和裝置
引數
struct filename *name正在審計的名稱
const struct dentry *dentry正在審計的 dentry
unsigned int flags此特定條目的屬性
-
int auditsc_get_stamp(struct audit_context *ctx, struct timespec64 *t, unsigned int *serial)¶
獲取 audit_context 值的本地副本
引數
struct audit_context *ctx任務的 audit_context
struct timespec64 *ttimespec64 用於儲存審計上下文中記錄的時間
unsigned int *serial在審計上下文中記錄的序列值
描述
還會將上下文設定為可審計。
-
void __audit_mq_open(int oflag, umode_t mode, struct mq_attr *attr)¶
記錄 POSIX MQ 開啟的審計資料
引數
int oflag開啟標誌
umode_t mode模式位
struct mq_attr *attr佇列屬性
-
void __audit_mq_sendrecv(mqd_t mqdes, size_t msg_len, unsigned int msg_prio, const struct timespec64 *abs_timeout)¶
為POSIX MQ定時傳送/接收記錄審計資料
引數
mqd_t mqdesMQ 描述符
size_t msg_len訊息長度
unsigned int msg_prio訊息優先順序
const struct timespec64 *abs_timeout訊息超時,使用絕對時間
-
void __audit_mq_notify(mqd_t mqdes, const struct sigevent *notification)¶
為POSIX MQ通知記錄審計資料
引數
mqd_t mqdesMQ 描述符
const struct sigevent *notification通知事件
-
void __audit_mq_getsetattr(mqd_t mqdes, struct mq_attr *mqstat)¶
為POSIX MQ獲取/設定屬性記錄審計資料
引數
mqd_t mqdesMQ 描述符
struct mq_attr *mqstatMQ 標誌
-
void __audit_ipc_obj(struct kern_ipc_perm *ipcp)¶
為 ipc 物件記錄審計資料
引數
struct kern_ipc_perm *ipcpipc 許可權
-
void __audit_ipc_set_perm(unsigned long qbytes, uid_t uid, gid_t gid, umode_t mode)¶
為新的 ipc 許可權記錄審計資料
引數
unsigned long qbytesmsgq 位元組數
uid_t uidmsgq 使用者 ID
gid_t gidmsgq 組 ID
umode_t modemsgq 模式 (許可權)
描述
僅在 audit_ipc_obj() 之後呼叫。
-
int __audit_socketcall(int nargs, unsigned long *args)¶
為 sys_socketcall 記錄審計資料
引數
int nargs引數個數,不應超過 AUDITSC_ARGS。
unsigned long *args引數陣列
-
void __audit_fd_pair(int fd1, int fd2)¶
為管道和socketpair記錄審計資料
引數
int fd1第一個檔案描述符
int fd2第二個檔案描述符
-
int __audit_sockaddr(int len, void *a)¶
為 sys_bind, sys_connect, sys_sendto 記錄審計資料
引數
int len使用者空間中的資料長度
void *a核心空間中的資料地址
描述
成功時返回0,NULL 上下文時返回 NULL,錯誤時返回 < 0。
-
int audit_signal_info_syscall(struct task_struct *t)¶
為 syscalls 記錄 signal 資訊
引數
struct task_struct *t被髮送訊號的任務
描述
如果審計子系統正在終止,記錄執行此操作的任務 (pid) 和 uid。
-
int __audit_log_bprm_fcaps(struct linux_binprm *bprm, const struct cred *new, const struct cred *old)¶
儲存有關載入 bprm 和相關 fcaps 的資訊
引數
struct linux_binprm *bprm指向正在處理的 bprm 的指標
const struct cred *new提議的新憑據
const struct cred *old舊憑據
描述
只需檢查 proc 是否已具有檔案給出的 capabilities,如果沒有,則儲存許可權提升資訊,以便在 syscall 結束時進行後續審計
-Eric
-
void __audit_log_capset(const struct cred *new, const struct cred *old)¶
儲存有關 capset syscall 引數的資訊
引數
const struct cred *new新憑據
const struct cred *old舊 (當前) 憑據
描述
記錄 userspace 傳送給 sys_capset 的引數,以便在適用時由審計系統進行後續列印
-
void audit_core_dumps(long signr)¶
記錄有關異常結束的程序的資訊
引數
long signr訊號值
描述
如果程序以 core dump 結束,則可能存在一些可疑情況,我們應該記錄該事件以進行調查。
-
void audit_seccomp(unsigned long syscall, long signr, int code)¶
記錄有關 seccomp 操作的資訊
引數
unsigned long syscallsyscall 號
long signr訊號值
int codeseccomp 操作
描述
記錄與 seccomp 操作相關的資訊。 不應記錄的 seccomp 操作的事件過濾在 seccomp_log() 中完成。 因此,此函式強制執行獨立於 audit_enabled 和 dummy 上下文狀態的審計,因為即使未使用審計,也應記錄 seccomp 操作。
-
int audit_rule_change(int type, int seq, void *data, size_t datasz)¶
將所有規則應用於指定的 訊息型別
引數
int type審計訊息型別
int seqnetlink 審計訊息序列 (serial) 號
void *datapayload 資料
size_t dataszpayload 資料的大小
引數
struct sk_buff *request_skb我們正在回覆的請求的 skb(用於定位回覆)
int seqnetlink 審計訊息序列 (serial) 號
-
int parent_len(const char *path)¶
查詢路徑名的父部分長度
引數
const char *path要確定長度的路徑名
-
int audit_compare_dname_path(const struct qstr *dname, const char *path, int parentlen)¶
將給定的 dentry 名稱與給定路徑中的最後一個元件進行比較。 返回 0 表示匹配。
引數
const struct qstr *dname我們正在比較的 dentry 名稱
const char *path我們正在比較的完整路徑名
int parentlen如果已知,父級的長度。 在此處傳入 AUDIT_NAME_FULL 表示我們必須計算此值。
會計框架¶
-
long sys_acct(const char __user *name)¶
啟用/停用程序會計
引數
const char __user * name會計記錄的檔名,或者 NULL 以關閉會計
描述
sys_acct() 是實現程序會計所需的唯一系統呼叫。 它採用應寫入會計記錄的檔案的名稱。 如果檔名為 NULL,則將關閉會計。
返回
成功時返回 0,失敗時返回負 errno 值。
-
void acct_collect(long exitcode, int group_dead)¶
將會計資訊收集到 pacct_struct 中
引數
long exitcode任務退出程式碼
int group_dead如果此執行緒是程序中的最後一個執行緒,則不為 0。
-
void acct_process(void)¶
處理退出任務的程序會計
引數
void無引數
塊裝置¶
引數
struct bio *bio要遞增的 bio
unsigned int nbytes要完成的位元組數
描述
這會更新 bi_sector、bi_size 和 bi_idx; 如果要完成的位元組數與 bvec 邊界不對齊,則也會更新最後一個 bvec 上的 bv_len 和 bv_offset。
然後,bio 將表示 io 的剩餘的、未完成的部分。
-
struct folio_iter¶
用於迭代 bio 中所有 folios 的狀態。
定義:
struct folio_iter {
struct folio *folio;
size_t offset;
size_t length;
};
成員
folio我們正在迭代的當前 folio。 最後一個 folio 後為 NULL。
offset當前 folio 中的位元組偏移量。
長度此迭代中的位元組數(不會跨越 folio 邊界)。
-
bio_for_each_folio_all¶
bio_for_each_folio_all (fi, bio)
迭代 bio 中的每個 folio。
引數
fistruct folio_iter,它為每個 folio 更新。bio要迭代的 struct bio。
-
struct bio *bio_next_split(struct bio *bio, int sectors, gfp_t gfp, struct bio_set *bs)¶
從 bio 獲取接下來的 sectors,必要時進行分割
引數
struct bio *bio要分割的 bio
int sectors從 bio 前端分割的扇區數
gfp_t gfpgfp 掩碼
struct bio_set *bs從中分配的 bio 集
返回
一個代表 bio 的接下來的 sectors 的 bio - 如果 bio 小於 sectors,則返回原始 bio,不做修改。
-
unsigned int bio_add_max_vecs(void *kaddr, unsigned int len)¶
將資料新增到 bio 所需的 bio_vecs 的數量
引數
void *kaddr要新增的核心虛擬地址
unsigned int len要新增的位元組長度
描述
計算最壞情況下,需要分配多少 bio_vecs 才能將 [kaddr:len] 中的核心虛擬地址範圍新增到 bio。
引數
struct bio *bio要檢查的 bio
描述
檢查 bio 是否為 zone append 操作。核心塊層程式碼和 end_io 處理程式必須使用此函式,而不是直接使用 REQ_OP_ZONE_APPEND 檢查,因為如果本地不支援,塊層可以將 REQ_OP_ZONE_APPEND 重寫為 REQ_OP_WRITE。
-
void blk_queue_flag_set(unsigned int flag, struct request_queue *q)¶
原子地設定佇列標誌
引數
unsigned int flag要設定的標誌
struct request_queue *q請求佇列
-
void blk_queue_flag_clear(unsigned int flag, struct request_queue *q)¶
原子地清除佇列標誌
引數
unsigned int flag要清除的標誌
struct request_queue *q請求佇列
-
const char *blk_op_str(enum req_op op)¶
返回 REQ_OP_XXX 中的字串 XXX。
引數
enum req_op opREQ_OP_XXX。
描述
集中式塊層函式,用於將 REQ_OP_XXX 轉換為字串格式。在除錯和跟蹤 bio 或請求時很有用。對於無效的 REQ_OP_XXX,它返回字串“UNKNOWN”。
-
void blk_sync_queue(struct request_queue *q)¶
取消佇列上的任何掛起的回撥
引數
struct request_queue *q佇列
描述
塊層可能會在佇列上執行非同步回撥活動,例如在超時後呼叫 unplug 函式。塊裝置可以呼叫 blk_sync_queue 來確保取消任何此類活動,從而允許它釋放回調可能使用的資源。呼叫者必須已經確保其 ->submit_bio 在呼叫此函式之前不會重新新增外掛。
此函式不會取消因電梯或節流程式碼而產生的任何非同步活動。那將需要使用初始化的佇列鎖呼叫 elevator_exit() 和 blkcg_exit_queue()。
-
void blk_set_pm_only(struct request_queue *q)¶
增加 pm_only 計數器
引數
struct request_queue *q請求佇列指標
-
void blk_put_queue(struct request_queue *q)¶
減少 request_queue 引用計數
引數
struct request_queue *q用於減少引用計數的 request_queue 結構
描述
減少 request_queue 的引用計數,並在引用計數達到 0 時釋放它。
-
bool blk_get_queue(struct request_queue *q)¶
增加 request_queue 引用計數
引數
struct request_queue *q用於增加引用計數的 request_queue 結構
描述
增加 request_queue kobject 的引用計數。
上下文
任何上下文。
引數
struct bio *bio描述記憶體和裝置位置的 bio。
描述
這是 submit_bio() 的一個版本,僅應用於由堆疊塊驅動程式重新提交到較低級別驅動程式的 I/O。所有檔案系統和塊層的其他上層使用者都應改用 submit_bio()。
引數
struct bio *bio描述 I/O 的
struct bio
描述
submit_bio() 用於將 I/O 請求提交到塊裝置。它傳遞一個完全設定好的 struct bio,該結構描述了需要完成的 I/O。bio 將被髮送到由 bi_bdev 欄位描述的裝置。
請求的成功/失敗狀態,以及完成通知,透過 bio 中的 ->bi_end_io() 回撥非同步傳遞。在呼叫 ->bi_end_io() 之前,呼叫者不得觸碰 bio。
引數
struct bio *bio要輪詢的 bio
struct io_comp_batch *iobI/O 批處理
unsigned int flags控制行為的 BLK_POLL_* 標誌
描述
輪詢與 bio 關聯的佇列上的完成。返回找到的已完成條目的數量。
注意
呼叫者必須是提交 bio 的上下文,或者在 RCU 臨界區中,以防止釋放 bio。
引數
struct bio *bio要啟動記帳的 bio
描述
返回應傳遞迴 bio_end_io_acct() 的開始時間。
-
int blk_lld_busy(struct request_queue *q)¶
檢查裝置的底層低級別驅動程式是否繁忙
引數
struct request_queue *q正在檢查的裝置的佇列
描述
檢查裝置的底層低級別驅動程式是否繁忙。如果驅動程式想要匯出其繁忙狀態,則必須首先使用 blk_queue_lld_busy() 設定自己的匯出函式。
基本上,此函式僅由請求堆疊驅動程式使用,以在底層裝置繁忙時停止將請求分派到底層裝置。此行為有助於在請求堆疊驅動程式的佇列上進行更多 I/O 合併,並防止在突發 I/O 負載下 I/O 吞吐量下降。
返回
0 - 不繁忙(請求堆疊驅動程式應分派請求) 1 - 繁忙(請求堆疊驅動程式應停止分派請求)
-
void blk_start_plug(struct blk_plug *plug)¶
初始化 blk_plug 並在 task_struct 中跟蹤它
引數
struct blk_plug *plug需要初始化的
struct blk_plug
描述
blk_start_plug()向塊層指示呼叫者打算批次提交多個 I/O 請求。塊層可以使用此提示來延遲從呼叫者提交 I/O,直到呼叫blk_finish_plug()。但是,如果排隊的 I/O 數量超過BLK_MAX_REQUEST_COUNT,或者 I/O 的大小大於BLK_PLUG_FLUSH_SIZE,則塊層可能會選擇在呼叫blk_finish_plug()之前提交請求。如果任務排程(見下文),排隊的 I/O 也可能提前提交。在 task_struct 中跟蹤 blk_plug 將有助於自動重新整理掛起的 I/O,如果任務最終在
blk_start_plug()和blk_finish_plug()之間阻塞。這從效能角度來看很重要,但也確保我們不會死鎖。例如,如果任務正在阻塞以進行記憶體分配,則記憶體回收最終可能想要釋放屬於當前駐留在我們的私有外掛中的請求的頁面。透過在程序進入睡眠狀態時重新整理掛起的 I/O,我們可以避免這種死鎖。
-
void blk_finish_plug(struct blk_plug *plug)¶
標記提交的 I/O 批處理的結束
引數
struct blk_plug *plug傳遞給
blk_start_plug()的struct blk_plug
描述
指示 I/O 提交批處理已完成。此函式必須與對 blk_start_plug() 的初始呼叫配對。目的是允許塊層最佳化 I/O 提交。有關更多資訊,請參閱 blk_start_plug() 的文件。
-
int blk_queue_enter(struct request_queue *q, blk_mq_req_flags_t flags)¶
嘗試增加 q->q_usage_counter
引數
struct request_queue *q請求佇列指標
blk_mq_req_flags_t flagsBLK_MQ_REQ_NOWAIT 和/或 BLK_MQ_REQ_PM
-
int blk_rq_map_user_iov(struct request_queue *q, struct request *rq, struct rq_map_data *map_data, const struct iov_iter *iter, gfp_t gfp_mask)¶
將使用者資料對映到請求,用於直通請求
引數
struct request_queue *q應在其中插入請求的請求佇列
struct request *rq要將資料對映到的請求
struct rq_map_data *map_data指向儲存頁面的 rq_map_data 的指標(如果需要)
const struct iov_iter *iteriovec 迭代器
gfp_t gfp_mask記憶體分配標誌
描述
如果可能,資料將直接對映以實現零複製 I/O。否則,將使用核心反彈緩衝區。
在 I/O 結束時,仍然在程序上下文中時,必須發出匹配的
blk_rq_unmap_user()。
引數
struct bio *biobio 列表的開頭
描述
取消對映先前由 blk_rq_map_user() 對映的 rq。呼叫者必須提供來自 blk_rq_map_user() 返回的原始 rq->bio,因為 I/O 完成可能已更改 rq->bio。
-
int blk_rq_map_kern(struct request *rq, void *kbuf, unsigned int len, gfp_t gfp_mask)¶
為直通請求將核心資料對映到請求。
引數
struct request *rq要填充的請求
void *kbuf核心緩衝區
unsigned int len使用者資料的長度
gfp_t gfp_mask記憶體分配標誌
描述
如果可能,資料將被直接對映。否則,將使用反彈緩衝區。可以多次呼叫以附加多個緩衝區。
-
int blk_register_queue(struct gendisk *disk)¶
向 sysfs 註冊塊層佇列
引數
struct gendisk *disk請求佇列應向 sysfs 註冊的磁碟。
-
void blk_unregister_queue(struct gendisk *disk)¶
blk_register_queue()的對應函式
-
void blk_set_stacking_limits(struct queue_limits *lim)¶
設定堆疊裝置的預設限制
-
int queue_limits_commit_update(struct request_queue *q, struct queue_limits *lim)¶
提交佇列限制的原子更新
引數
struct request_queue *q要更新的佇列
struct queue_limits *lim要應用的限制
描述
將 **lim** 中的限制應用於 q,這些限制是從 queue_limits_start_update() 獲取並由呼叫者更新的。呼叫者必須凍結佇列或確保沒有其他方式的未完成 I/O。
如果成功,則返回 0,否則返回負錯誤程式碼。
-
int queue_limits_commit_update_frozen(struct request_queue *q, struct queue_limits *lim)¶
提交佇列限制的原子更新
引數
struct request_queue *q要更新的佇列
struct queue_limits *lim要應用的限制
描述
將 **lim** 中的限制應用於 q,這些限制是從 queue_limits_start_update() 獲取並由呼叫者使用新值更新的。在更新之前凍結佇列,並在之後解凍佇列。
如果成功,則返回 0,否則返回負錯誤程式碼。
-
int queue_limits_set(struct request_queue *q, struct queue_limits *lim)¶
將佇列限制應用於佇列
引數
struct request_queue *q要更新的佇列
struct queue_limits *lim要應用的限制
描述
將 **lim** 中的限制應用於 q,這些限制是新初始化的。要更新現有限制,請改用 queue_limits_start_update() 和 queue_limits_commit_update()。
如果成功,則返回 0,否則返回負錯誤程式碼。
-
int blk_stack_limits(struct queue_limits *t, struct queue_limits *b, sector_t start)¶
調整堆疊裝置的 queue_limits
引數
struct queue_limits *t堆疊驅動程式限制(頂部裝置)
struct queue_limits *b底層佇列限制(底部,元件裝置)
sector_t start元件裝置內的第一個資料扇區
描述
此函式由 MD 和 DM 等堆疊驅動程式使用,以確保所有元件裝置都具有相容的塊大小和對齊方式。堆疊驅動程式必須提供一個 queue_limits 結構(頂部),然後迭代地為所有元件(底部)裝置呼叫堆疊函式。堆疊函式將嘗試組合這些值並確保正確的對齊方式。
如果頂部和底部 queue_limits 相容,則返回 0。可以調整頂部裝置的塊大小和對齊偏移量,以確保與底部裝置對齊。如果不存在相容的大小和對齊方式,則返回 -1,並且生成的頂部 queue_limits 將設定 misaligned 標誌,以指示 alignment_offset 未定義。
-
void queue_limits_stack_bdev(struct queue_limits *t, struct block_device *bdev, sector_t offset, const char *pfx)¶
調整堆疊裝置的 queue_limits
引數
struct queue_limits *t堆疊驅動程式限制(頂部裝置)
struct block_device *bdev底層塊裝置(底部)
sector_t offset元件裝置內資料起點的偏移量
const char *pfx用於記錄警告的字首
描述
此函式由 MD 和 DM 等堆疊驅動程式使用,以確保所有元件裝置都具有相容的塊大小和對齊方式。堆疊驅動程式必須提供一個 queue_limits 結構(頂部),然後迭代地為所有元件(底部)裝置呼叫堆疊函式。堆疊函式將嘗試組合這些值並確保正確的對齊方式。
-
bool queue_limits_stack_integrity(struct queue_limits *t, struct queue_limits *b)¶
堆疊完整性配置檔案
引數
struct queue_limits *t目標佇列限制
struct queue_limits *b基本佇列限制
描述
檢查 **b** 中的完整性配置檔案是否可以堆疊到目標 **t** 中。如果滿足以下任一條件,則可以堆疊:
尚未堆疊任何完整性資訊
**b** 中的完整性配置檔案與 **t** 中的配置檔案相同
如果可以將 **b** 堆疊到 **t** 中,則返回 true。否則,返回 false 並清除 **t** 中的完整性資訊。
-
void blk_set_queue_depth(struct request_queue *q, unsigned int depth)¶
告訴塊層裝置佇列深度
引數
struct request_queue *q裝置的請求佇列
unsigned int depth佇列深度
-
int blkdev_issue_flush(struct block_device *bdev)¶
排隊重新整理
引數
struct block_device *bdev要發出重新整理的 blockdev
描述
為有問題的塊裝置發出重新整理。
-
int blkdev_issue_discard(struct block_device *bdev, sector_t sector, sector_t nr_sects, gfp_t gfp_mask)¶
排隊丟棄
引數
struct block_device *bdev要發出丟棄的 blockdev
sector_t sector起始扇區
sector_t nr_sects要丟棄的扇區數
gfp_t gfp_mask記憶體分配標誌(對於 bio_alloc)
描述
為有問題的扇區發出丟棄請求。
-
int __blkdev_issue_zeroout(struct block_device *bdev, sector_t sector, sector_t nr_sects, gfp_t gfp_mask, struct bio **biop, unsigned flags)¶
生成多個零填充的寫 bio
引數
struct block_device *bdev要發出的 blockdev
sector_t sector起始扇區
sector_t nr_sects要寫入的扇區數
gfp_t gfp_mask記憶體分配標誌(對於 bio_alloc)
struct bio **biop指向錨 bio 的指標
unsigned flags控制詳細行為
描述
零填充一個塊範圍,可以使用硬體解除安裝,也可以透過將零顯式寫入裝置。
如果裝置使用邏輯塊配置,則如果
flags包含 BLKDEV_ZERO_NOUNMAP,則不會釋放底層空間。如果
flags包含 BLKDEV_ZERO_NOFALLBACK,如果沒有為零填充提供顯式硬體解除安裝,則該函式將返回 -EOPNOTSUPP。
-
int blkdev_issue_zeroout(struct block_device *bdev, sector_t sector, sector_t nr_sects, gfp_t gfp_mask, unsigned flags)¶
零填充一個塊範圍
引數
struct block_device *bdev要寫入的 blockdev
sector_t sector起始扇區
sector_t nr_sects要寫入的扇區數
gfp_t gfp_mask記憶體分配標誌(對於 bio_alloc)
unsigned flags控制詳細行為
描述
零填充一個塊範圍,可以使用硬體解除安裝,也可以透過將零顯式寫入裝置。有關
flags的有效值,請參閱__blkdev_issue_zeroout()。
-
int blk_rq_map_integrity_sg(struct request *rq, struct scatterlist *sglist)¶
將完整性元資料對映到散列表
引數
struct request *rq要對映的請求
struct scatterlist *sglist目標散列表
描述
將請求中的完整性向量對映到散列表中。散列表必須足夠大以容納所有元素。即,使用 blk_rq_count_integrity_sg() 或 rq->nr_integrity_segments 調整大小。
-
int blk_trace_ioctl(struct block_device *bdev, unsigned cmd, char __user *arg)¶
處理與跟蹤關聯的 ioctl
引數
struct block_device *bdev塊裝置
unsigned cmdioctl cmd
char __user *arg引數資料(如果有)
-
void blk_trace_shutdown(struct request_queue *q)¶
停止並清理跟蹤結構
引數
struct request_queue *q與裝置關聯的請求佇列
-
void blk_add_trace_rq(struct request *rq, blk_status_t error, unsigned int nr_bytes, u32 what, u64 cgid)¶
為面向請求的操作新增跟蹤
引數
struct request *rq源請求
blk_status_t error要記錄的返回狀態
unsigned int nr_bytes已完成的位元組數
u32 what操作
u64 cgidcgroup 資訊
描述
記錄針對請求的操作。將記錄 bio 偏移量 + 大小。
-
void blk_add_trace_bio(struct request_queue *q, struct bio *bio, u32 what, int error)¶
為 bio 導向的操作新增跟蹤資訊
引數
struct request_queue *qIO 所在的佇列
struct bio *bio源 bio
u32 what操作
int error錯誤碼(如果存在)
描述
記錄針對 bio 的操作。將記錄 bio 的偏移量 + 大小。
-
void blk_add_trace_bio_remap(void *ignore, struct bio *bio, dev_t dev, sector_t from)¶
為 bio 重新對映操作新增跟蹤資訊
引數
void *ignore跟蹤回撥資料引數(未使用)
struct bio *bio源 bio
dev_t dev源裝置
sector_t from源扇區
描述
在 bio 被重新對映到不同的裝置和/或扇區後呼叫。
-
void blk_add_trace_rq_remap(void *ignore, struct request *rq, dev_t dev, sector_t from)¶
為請求重新對映操作新增跟蹤資訊
引數
void *ignore跟蹤回撥資料引數(未使用)
struct request *rq源請求
dev_t dev目標裝置
sector_t from源扇區
描述
裝置對映器將請求重新對映到其他裝置。為該操作新增跟蹤資訊。
引數
struct device *dev表示此磁碟的裝置
描述
此函式釋放 gendisk 的所有已分配資源。
使用 __device_add_disk() 的驅動程式具有分配了 request_queue 的 gendisk。由於對於這些驅動程式,request_queue 位於 gendisk 的頂部,因此我們還為它們呼叫 blk_put_queue(),我們期望 request_queue 的引用計數在此刻達到 0,因此 request_queue 也將在磁碟之前被釋放。
上下文
可以睡眠
-
unsigned int bdev_count_inflight(struct block_device *part)¶
獲取塊裝置正在進行的 IO 數量。
引數
struct block_device *part塊裝置。
描述
Inflight 在這裡意味著已開始 IO 記帳,對於基於 bio 的塊裝置,從 bdev_start_io_acct() 開始,對於基於 rq 的塊裝置,從 blk_account_io_start() 開始。
-
int __register_blkdev(unsigned int major, const char *name, void (*probe)(dev_t devt))¶
註冊一個新的塊裝置
引數
unsigned int major請求的主裝置號 [1..BLKDEV_MAJOR_MAX-1]。如果 major = 0,則嘗試分配任何未使用的主裝置號。
const char *name新塊裝置的名稱,以零結尾的字串
void (*probe)(dev_t devt)在訪問其預建立的裝置節點時,用於建立磁碟的 pre-devtmpfs / pre-udev 回撥。當 probe 呼叫使用 add_disk() 並且失敗時,驅動程式必須清理資源。此介面可能很快將被移除。
描述
name 在系統中必須是唯一的。
返回值取決於 major 輸入引數
如果在範圍 [1..BLKDEV_MAJOR_MAX-1] 中請求了一個主裝置號,則該函式在成功時返回零,否則返回負錯誤程式碼
如果使用 major = 0 引數請求了任何未使用的主裝置號,則返回值是在範圍 [1..BLKDEV_MAJOR_MAX-1] 中分配的主裝置號,否則返回負錯誤程式碼
有關已分配主裝置號的列表,請參見 Linux 分配的裝置(4.x+ 版本)。
對於任何新程式碼,請使用 register_blkdev 代替。
-
int add_disk_fwnode(struct device *parent, struct gendisk *disk, const struct attribute_group **groups, struct fwnode_handle *fwnode)¶
將磁碟資訊新增到帶有 fwnode 的核心列表中
引數
struct device *parent磁碟的父裝置
struct gendisk *disk每個裝置的劃分資訊
const struct attribute_group **groups其他每個裝置的 sysfs 組
struct fwnode_handle *fwnode附加的磁碟 fwnode
描述
此函式將 disk 中的劃分資訊註冊到核心中。同時將 fwnode 附加到磁碟裝置。
-
int device_add_disk(struct device *parent, struct gendisk *disk, const struct attribute_group **groups)¶
將磁碟資訊新增到核心列表中
引數
struct device *parent磁碟的父裝置
struct gendisk *disk每個裝置的劃分資訊
const struct attribute_group **groups其他每個裝置的 sysfs 組
描述
此函式將 disk 中的劃分資訊註冊到核心中。
-
void blk_mark_disk_dead(struct gendisk *disk)¶
將磁碟標記為死亡
引數
struct gendisk *disk要標記為死亡的磁碟
描述
將磁碟標記為死亡(例如,意外移除)並且不接受任何新的 I/O 到該磁碟。
-
void del_gendisk(struct gendisk *disk)¶
移除 gendisk
引數
struct gendisk *disk要移除的 struct gendisk
描述
移除 gendisk 及其所有相關資源。這將刪除與 gendisk 關聯的分割槽,並登出關聯的 request_queue。
這是對相應 __device_add_disk() 呼叫的計數器。
struct gendisk 的最終移除發生在它的引用計數達到 0 時,使用 put_disk(),如果使用了 __device_add_disk(),則應該在 del_gendisk() 之後呼叫。
存在一些驅動程式,它們依賴於 gendisk 的同步釋放,不應延遲。
上下文
可以睡眠
-
void invalidate_disk(struct gendisk *disk)¶
使磁碟無效
引數
struct gendisk *disk要使其無效的 struct gendisk
描述
用於使磁碟無效的助手函式。它將清理磁碟關聯的緩衝區/頁面快取並重置其內部狀態,以便驅動程式可以重用該磁碟。
上下文
可以睡眠
-
void put_disk(struct gendisk *disk)¶
遞減 gendisk 引用計數
引數
struct gendisk *disk要遞減引用計數的 struct gendisk
描述
這會遞減 struct gendisk 的引用計數。當它達到 0 時,我們將呼叫 disk_release()。
注意
對於 blk-mq 磁碟,在處理 probe 錯誤時(即在呼叫 add_disk() 之前),必須在釋放 tag_set 之前呼叫 put_disk。
上下文
任何上下文,但不得從原子上下文中刪除最後一個引用。
-
void set_disk_ro(struct gendisk *disk, bool read_only)¶
將 gendisk 設定為只讀
引數
struct gendisk *disk要操作的 gendisk
bool read_onlytrue將磁碟設定為只讀,false將磁碟設定為讀/寫
描述
此函式用於指示給定的磁碟裝置是否應設定其只讀標誌。set_disk_ro() 通常由裝置驅動程式使用,以指示底層物理裝置是否受到防寫。
-
int bdev_validate_blocksize(struct block_device *bdev, int block_size)¶
檢查此塊大小是否可接受
引數
struct block_device *bdev要檢查的塊裝置
int block_size要檢查的塊大小
描述
對於不使用緩衝區頭或塊裝置頁面快取的塊裝置使用者,請確保此塊大小可以與該裝置一起使用。
返回
成功時返回零,失敗時返回負錯誤程式碼。
-
int bdev_freeze(struct block_device *bdev)¶
鎖定檔案系統並強制其進入一致狀態
引數
struct block_device *bdev要鎖定的塊裝置
描述
如果在此裝置上找到超級塊,我們將獲取其 s_umount 訊號量,以確保在快照建立完成之前沒有人解除安裝。引用計數器 (bd_fsfreeze_count) 保證只有最後一個解凍程序才能在同時到達多個凍結請求時實際解凍凍結的檔案系統。它在 bdev_freeze() 中計數增加,並在 bdev_thaw() 中計數減少。當它變為 0 時,thaw_bdev() 將實際解凍。
返回
成功時返回零,失敗時返回負錯誤程式碼。
-
int bdev_thaw(struct block_device *bdev)¶
解鎖檔案系統
-
int bd_prepare_to_claim(struct block_device *bdev, void *holder, const struct blk_holder_ops *hops)¶
宣告一個塊裝置
引數
struct block_device *bdev感興趣的塊裝置
void *holder嘗試宣告 bdev 的持有者
const struct blk_holder_ops *hops持有者操作。
描述
宣告 bdev。如果 bdev 已經被另一個持有者宣告,並且另一個宣告正在進行中,則此函式將失敗並等待。返回後,呼叫者擁有 bd_claiming 和 bd_holder[s] 的所有權。
返回
如果可以宣告 bdev,則返回 0,否則返回 -EBUSY。
-
void bd_abort_claiming(struct block_device *bdev, void *holder)¶
中止對塊裝置的宣告
引數
struct block_device *bdev感興趣的塊裝置
void *holder已宣告 bdev 的持有者
描述
當獨佔開啟失敗時,中止對塊裝置的宣告。當實際上不需要獨佔開啟,而我們只需要暫時阻止其他獨佔開啟者時,也可以使用此方法。
引數
struct file *bdev_file開啟塊裝置
描述
放棄對塊裝置的宣告並放入檔案。確保可以在檔案關閉之前回收塊裝置,這是一個延遲操作。
-
int lookup_bdev(const char *pathname, dev_t *dev)¶
透過名稱查詢 struct block_device。
引數
const char *pathname檔案系統中塊裝置的名稱。
dev_t *dev指向塊裝置的 dev_t 的指標(如果找到)。
描述
如果可能,在當前名稱空間中的 pathname 處查詢塊裝置的 dev_t,並在 dev 中返回它。
上下文
可能會睡眠。
返回
成功時返回 0,否則返回負數的 errno。
-
void bdev_mark_dead(struct block_device *bdev, bool surprise)¶
將塊裝置標記為 dead
引數
struct block_device *bdev要操作的塊裝置
bool surprise指示意外移除
描述
告訴檔案系統該裝置或介質已失效。如果 surprise 設定為 true,則裝置或介質已經消失,否則我們正在準備有序移除。
這將呼叫檔案系統,檔案系統通常會同步所有髒資料並寫回 inode,然後使檔案系統上 inode 中的任何快取資料失效。此外,我們還會使塊裝置對映失效。
字元裝置¶
-
int register_chrdev_region(dev_t from, unsigned count, const char *name)¶
註冊一系列裝置號
引數
dev_t from所需裝置號範圍中的第一個;必須包含主裝置號。
unsigned count所需的連續裝置號的數量
const char *name裝置或驅動程式的名稱。
描述
成功時返回值零,失敗時返回負錯誤程式碼。
-
int alloc_chrdev_region(dev_t *dev, unsigned baseminor, unsigned count, const char *name)¶
註冊一系列字元裝置號
引數
dev_t *dev第一個分配的數字的輸出引數
unsigned baseminor請求的小裝置號範圍中的第一個
unsigned count所需的小裝置號的數量
const char *name關聯裝置或驅動程式的名稱
描述
分配一系列字元裝置號。主裝置號將動態選擇,並在 dev 中返回(以及第一個小裝置號)。返回零或負錯誤程式碼。
-
int __register_chrdev(unsigned int major, unsigned int baseminor, unsigned int count, const char *name, const struct file_operations *fops)¶
建立並註冊一個 cdev,佔用一系列小裝置號
引數
unsigned int major主裝置號;0 表示動態分配
unsigned int baseminor請求的小裝置號範圍中的第一個
unsigned int count所需的小裝置號的數量
const char *name此裝置範圍的名稱
const struct file_operations *fops與此裝置關聯的檔案操作
描述
如果 major == 0,則此函式將動態分配一個主裝置號並返回其編號。
如果 major > 0,則此函式將嘗試保留一個具有給定主裝置號的裝置,並在成功時返回零。
失敗時返回 -ve errno。
此裝置的名稱與 /dev 中裝置的名稱無關。它僅有助於跟蹤裝置的不同所有者。如果您的模組名稱只有一種型別的裝置,則在此處使用模組名稱是可以的。
-
void unregister_chrdev_region(dev_t from, unsigned count)¶
登出一系列裝置號
引數
dev_t from要登出的號碼範圍中的第一個
unsigned count要登出的裝置號的數量
描述
此函式將登出一系列 count 裝置號,從 from 開始。呼叫者通常應該是首先分配這些數字的人...
-
void __unregister_chrdev(unsigned int major, unsigned int baseminor, unsigned int count, const char *name)¶
登出並銷燬 cdev
引數
unsigned int major主裝置號
unsigned int baseminor小裝置號範圍中的第一個
unsigned int count此 cdev 佔用的小裝置號的數量
const char *name此裝置範圍的名稱
描述
登出並銷燬佔用由 major、baseminor 和 count 描述的區域的 cdev。此函式撤消了 __register_chrdev() 所做的事情。
-
int cdev_add(struct cdev *p, dev_t dev, unsigned count)¶
將字元裝置新增到系統
引數
struct cdev *p裝置的 cdev 結構
dev_t dev此裝置負責的第一個裝置號
unsigned count與此裝置對應的連續小裝置號的數量
描述
cdev_add() 將由 p 表示的裝置新增到系統,使其立即生效。失敗時返回負錯誤程式碼。
-
void cdev_set_parent(struct cdev *p, struct kobject *kobj)¶
為字元裝置設定父 kobject
引數
struct cdev *pcdev 結構
struct kobject *kobj要獲取引用的 kobject
描述
cdev_set_parent() 設定一個父 kobject,它將被適當地引用,以便在 cdev 之前不會釋放父物件。應在 cdev_add 之前呼叫此函式。
-
int cdev_device_add(struct cdev *cdev, struct device *dev)¶
新增字元裝置及其對應的
struct device,連結
引數
struct cdev *cdevcdev 結構
struct device *dev裝置結構
描述
cdev_device_add() 將由 cdev 表示的字元裝置新增到系統,就像 cdev_add 一樣。然後,它使用 device_add 將 dev 新增到系統。字元裝置的 dev_t 將從 struct device 中獲取,該結構需要首先初始化。此輔助函式正確地獲取對父裝置的引用,因此在釋放對 cdev 的所有引用之前,父裝置不會被釋放。
此助手使用 dev->devt 作為裝置號。如果未設定,它將不會新增 cdev,並且它將等效於 device_add。
只要 struct cdev 和 struct device 是同一結構的成員,並且該結構的生命週期由 struct device 管理,就應該使用此函式。
注意
呼叫者必須假定使用者空間能夠開啟 cdev,並且可以隨時呼叫 cdev fops 回撥,即使此函式失敗也是如此。
引數
struct cdev *cdevcdev 結構
struct device *dev裝置結構
描述
cdev_device_del() 是一個呼叫 cdev_del 和 device_del 的輔助函式。只要使用 cdev_device_add,就應該使用它。
如果未設定 dev->devt,它將不會刪除 cdev,並且它將等效於 device_del。
注意
這保證了關聯的 sysfs 回撥不會執行或可執行,但是,任何已經開啟的 cdev 將保持不變,並且它們的 fops 仍然可以呼叫,即使在此函式返回之後也是如此。
-
void cdev_del(struct cdev *p)¶
從系統中刪除 cdev
引數
struct cdev *p要刪除的 cdev 結構
描述
cdev_del() 從系統中刪除 p,可能會釋放結構本身。
注意
這保證了 cdev 裝置將不再能夠開啟,但是,任何已經開啟的 cdev 將保持不變,並且它們的 fops 仍然可以呼叫,即使在 cdev_del 返回之後也是如此。
-
struct cdev *cdev_alloc(void)¶
分配一個 cdev 結構
引數
void無引數
描述
分配並返回一個 cdev 結構,如果失敗則返回 NULL。
引數
struct cdev *cdev要初始化的結構
const struct file_operations *fops此裝置的檔案操作
描述
初始化 cdev,記住 fops,使其準備好透過 cdev_add() 新增到系統。
時鐘框架¶
時鐘框架定義了程式設計介面,以支援系統時鐘樹的軟體管理。此框架廣泛用於片上系統 (SOC) 平臺,以支援電源管理和可能需要自定義時鐘速率的各種裝置。請注意,這些“時鐘”與計時或即時時鐘 (RTC) 無關,它們每個都有單獨的框架。這些 struct clk 例項可用於管理例如用於將位移入和移出外圍裝置或匯流排,或以其他方式觸發系統硬體中的同步狀態機轉換的 96 MHz 訊號。
電源管理由顯式軟體時鐘門控支援:停用未使用的時鐘,因此係統不會浪費電力來更改未在主動使用的電晶體的狀態。在某些系統上,這可以透過硬體時鐘門控來支援,其中時鐘在不停用軟體的情況下被門控。晶片中已供電但未計時的部分可能能夠保留其最後的狀態。這種低功耗狀態通常稱為保留模式。這種模式仍然會產生洩漏電流,尤其是在更精細的電路幾何形狀中,但對於 CMOS 電路,電力主要由計時狀態更改使用。
電源感知驅動程式僅在其管理的裝置處於活動使用狀態時才啟用其時鐘。此外,系統睡眠狀態通常因哪個時鐘域處於活動狀態而異:雖然“待機”狀態可能允許從幾個活動域喚醒,但“mem”(掛起至 RAM)狀態可能需要更徹底地關閉從更高速度 PLL 和振盪器派生的時鐘,從而限制了可能的喚醒事件源的數量。驅動程式的掛起方法可能需要知道目標睡眠狀態的系統特定時鐘約束。
某些平臺支援可程式設計時鐘發生器。這些可以被各種型別的外部晶片使用,例如其他 CPU、多媒體編解碼器以及對介面計時有嚴格要求的裝置。
-
struct clk_notifier¶
將 clk 與通知器關聯
定義:
struct clk_notifier {
struct clk *clk;
struct srcu_notifier_head notifier_head;
struct list_head node;
};
成員
clk要將通知器與之關聯的 struct clk *
notifier_head此 clk 的 blocking_notifier_head
節點連結串列指標
描述
通知器程式碼維護一個 struct clk_notifier 列表。每當程式碼在特定 clk 上註冊第一個通知器時,就會建立一個條目。該 clk 上的未來通知器將新增到 notifier_head。
-
struct clk_notifier_data¶
要傳遞給通知器回撥的速率資料
定義:
struct clk_notifier_data {
struct clk *clk;
unsigned long old_rate;
unsigned long new_rate;
};
成員
clk正在更改的 struct clk *
old_rate此 clk 的先前速率
new_rate此 clk 的新速率
描述
對於 pre-notifier,old_rate 是 clk 在此速率更改之前的速率,new_rate 是速率將來的值。對於 post-notifier,old_rate 和 new_rate 都設定為 clk 的當前速率(這樣做是為了最佳化實現)。
-
struct clk_bulk_data¶
用於批次 clk 操作的資料。
定義:
struct clk_bulk_data {
const char *id;
struct clk *clk;
};
成員
id時鐘使用者 ID
clkstruct clk * 用於儲存關聯的時鐘
描述
CLK API 提供了一系列 clk_bulk_() API 呼叫,方便需要多個 clk 的使用者。此結構用於管理這些呼叫的資料。
引數
struct clk *clk我們感興趣的速率的時鐘
struct notifier_block *nb帶有回撥函式指標的通知器塊
描述
專家提示:跨通知器鏈進行除錯可能會令人沮喪。確保您的通知器回撥函式在發生故障時列印一個大的警告。
引數
struct clk *clk不再對其頻率感興趣的時鐘
struct notifier_block *nb將被登出的通知塊
-
int devm_clk_notifier_register(struct device *dev, struct clk *clk, struct notifier_block *nb)¶
註冊一個託管的頻率改變通知回撥
引數
struct device *dev時鐘“消費者”的裝置
struct clk *clk我們感興趣的速率的時鐘
struct notifier_block *nb帶有回撥函式指標的通知器塊
描述
成功時返回 0,否則返回 -EERROR
引數
struct clk *clk時鐘源
描述
這獲取以 ppb 為單位表示的時鐘源精度。一個完美時鐘返回 0。
引數
struct clk *clk時鐘訊號源
int degrees訊號偏移的度數
描述
將時鐘訊號的相位移動指定的度數。成功時返回 0,否則返回 -EERROR。
引數
struct clk *clk時鐘訊號源
描述
返回時鐘節點的相位偏移(以度為單位),否則返回 -EERROR。
引數
struct clk *clk時鐘訊號源
unsigned int num要應用的佔空比的分母
unsigned int den要應用的佔空比的分母
描述
按指定比率調整時鐘訊號的佔空比。成功時返回 0,否則返回 -EERROR。
引數
struct clk *clk時鐘訊號源
unsigned int scale應用於將比率表示為整數的縮放因子
描述
返回乘以提供的比例因子的佔空比,否則返回 -EERROR。
-
bool clk_is_match(const struct clk *p, const struct clk *q)¶
檢查兩個 clk 是否指向同一個硬體時鐘
引數
const struct clk *p與 q 比較的 clk
const struct clk *q與 p 比較的 clk
描述
如果兩個 struct clk 指標都指向同一個硬體時鐘節點,則返回 true。換句話說,如果 **p** 和 **q** 共享同一個 struct clk_core 物件,則返回 true。
否則返回 false。請注意,兩個 NULL clk 被視為匹配。
引數
struct clk *clk時鐘源
描述
此函式允許驅動程式獲得對提供者速率的獨佔控制。它可以防止任何其他使用者執行,即使是間接執行,可能改變提供者速率或導致故障的操作
如果在時鐘上多次宣告獨佔權,即使是同一驅動程式,速率實際上也會被鎖定,因為獨佔權無法被搶佔。
不得從原子上下文中呼叫。
返回成功 (0) 或負 errno。
-
int devm_clk_rate_exclusive_get(struct device *dev, struct clk *clk)¶
clk_rate_exclusive_get 的 devm 變體
引數
struct device *dev獨佔權繫結到的裝置
struct clk *clk時鐘源
描述
在 **clk** 上呼叫 clk_rate_exclusive_get() 並在 **dev** 上註冊一個 devm 清理處理程式,以呼叫 clk_rate_exclusive_put()。
不得從原子上下文中呼叫。
引數
struct clk *clk時鐘源
描述
此函式允許驅動程式釋放先前從 clk_rate_exclusive_get() 獲得的獨佔權
呼叫者必須平衡 clk_rate_exclusive_get() 和 clk_rate_exclusive_put() 呼叫的數量。
不得從原子上下文中呼叫。
引數
struct clk *clk時鐘源
描述
這為使用準備時鐘源。
不得從原子上下文中呼叫。
引數
struct clk *clk時鐘源
描述
如果 clk_prepare() 隱式啟用時鐘,實際上使 clk_enable()/clk_disable() 成為空操作,則返回 true,否則返回 false。
這主要與電源管理程式碼相關,其中實際停用時鐘還需要取消準備才能產生任何實際效果。
無論此處返回的值如何,呼叫者都必須始終呼叫 clk_enable() 或 clk_prepare_enable() 及其對應項,以使使用計數正確。
引數
struct clk *clk時鐘源
描述
這會撤消先前準備的時鐘。呼叫者必須平衡準備和取消準備呼叫的數量。
不得從原子上下文中呼叫。
引數
struct device *dev時鐘“消費者”的裝置
const char *id時鐘使用者 ID
描述
返回對應於時鍾生產者的 struct clk,或者包含 errno 的有效 IS_ERR() 條件。該實現使用 **dev** 和 **id** 來確定時鐘消費者,從而確定時鐘生產者。(換句話說,**id** 可能是相同的字串,但 clk_get 可能會根據 **dev** 返回不同的時鐘生產者。)
驅動程式必須假定時鐘源未啟用。
不應從中斷上下文中呼叫 clk_get。
-
int clk_bulk_get(struct device *dev, int num_clks, struct clk_bulk_data *clks)¶
查詢並獲取對時鐘生產者的多個引用。
引數
struct device *dev時鐘“消費者”的裝置
int num_clksclk_bulk_data 的數量
struct clk_bulk_data *clks消費者的 clk_bulk_data 表
描述
此輔助函式允許驅動程式在一個操作中獲取多個 clk 消費者。如果無法獲取任何 clk,則在返回給呼叫者之前,將釋放已獲取的任何 clk。
如果成功獲取 clk_bulk_data 表中指定的所有時鐘,則返回 0,或者返回包含 errno 的有效 IS_ERR() 條件。該實現使用 **dev** 和 **clk_bulk_data.id** 來確定時鐘消費者,從而確定時鐘生產者。返回的時鐘儲存在每個 **clk_bulk_data.clk** 欄位中。
驅動程式必須假定時鐘源未啟用。
不應從中斷上下文中呼叫 clk_bulk_get。
-
int clk_bulk_get_all(struct device *dev, struct clk_bulk_data **clks)¶
查詢並獲取對時鐘生產者的所有可用引用。
引數
struct device *dev時鐘“消費者”的裝置
struct clk_bulk_data **clks指向消費者的 clk_bulk_data 表的指標
描述
此輔助函式允許驅動程式在一個操作中獲取所有 clk 消費者。如果無法獲取任何 clk,則在返回給呼叫者之前,將釋放已獲取的任何 clk。
返回獲取的時鐘數量的正值,同時時鐘引用儲存在 **clks** 欄位中的 clk_bulk_data 表中。如果沒有,則返回 0,如果發生錯誤,則返回負值。
驅動程式必須假定時鐘源未啟用。
不應從中斷上下文中呼叫 clk_bulk_get。
-
int clk_bulk_get_optional(struct device *dev, int num_clks, struct clk_bulk_data *clks)¶
查詢並獲取對時鐘生產者的多個引用
引數
struct device *dev時鐘“消費者”的裝置
int num_clksclk_bulk_data 的數量
struct clk_bulk_data *clks消費者的 clk_bulk_data 表
描述
行為與 clk_bulk_get() 相同,除非沒有時鐘生產者。在這種情況下,該函式不會返回 -ENOENT,而是返回 0,對於無法確定時鐘生產者的 clk,則返回 NULL。
-
int devm_clk_bulk_get(struct device *dev, int num_clks, struct clk_bulk_data *clks)¶
託管獲取多個 clk 消費者
引數
struct device *dev時鐘“消費者”的裝置
int num_clksclk_bulk_data 的數量
struct clk_bulk_data *clks消費者的 clk_bulk_data 表
描述
成功時返回 0,失敗時返回 errno。
此輔助函式允許驅動程式在一個操作中獲取多個 clk 消費者並進行管理,當裝置未繫結時,clk 將自動釋放。
-
int devm_clk_bulk_get_optional(struct device *dev, int num_clks, struct clk_bulk_data *clks)¶
獲取多個可選的消費者時鐘(託管的)
引數
struct device *dev時鐘“消費者”的裝置
int num_clksclk_bulk_data 的數量
struct clk_bulk_data *clks指向消費者的 clk_bulk_data 表的指標
描述
行為與 devm_clk_bulk_get() 相同,除非沒有時鐘生產者。在這種情況下,函式不會返回 -ENOENT,而是為給定的時鐘返回 NULL。假設 clk_bulk_data 中的所有時鐘都是可選的。
如果成功獲取 clk_bulk_data 表中指定的所有時鐘,或者對於任何 clk 沒有可用的 clk 提供者,則返回 0,否則返回包含 errno 的有效 IS_ERR() 條件。該實現使用 dev 和 clk_bulk_data.id 來確定時鐘消費者,從而確定時鐘生產者。返回的時鐘儲存在每個 clk_bulk_data.clk 欄位中。
驅動程式必須假定時鐘源未啟用。
不應從中斷上下文中呼叫 clk_bulk_get。
-
int devm_clk_bulk_get_all(struct device *dev, struct clk_bulk_data **clks)¶
託管獲取多個 clk 消費者
引數
struct device *dev時鐘“消費者”的裝置
struct clk_bulk_data **clks指向消費者的 clk_bulk_data 表的指標
描述
返回獲取的時鐘數量的正值,同時時鐘引用儲存在 **clks** 欄位中的 clk_bulk_data 表中。如果沒有,則返回 0,如果發生錯誤,則返回負值。
此輔助函式允許驅動程式在一個操作中獲取多個 clk 消費者並進行管理,當裝置未繫結時,clk 將自動釋放。
-
int devm_clk_bulk_get_all_enabled(struct device *dev, struct clk_bulk_data **clks)¶
獲取並啟用消費者的所有時鐘(託管的)
引數
struct device *dev時鐘“消費者”的裝置
struct clk_bulk_data **clks指向消費者的 clk_bulk_data 表的指標
描述
返回獲取的時鐘數量的正值,同時時鐘引用儲存在 **clks** 欄位中的 clk_bulk_data 表中。如果沒有,則返回 0,如果發生錯誤,則返回負值。
此輔助函式允許驅動程式獲取消費者的所有時鐘,並在一次操作中啟用它們,並進行管理。當裝置取消繫結時,clks 將自動停用和釋放。
引數
struct device *dev時鐘“消費者”的裝置
const char *id時鐘使用者 ID
上下文
可能會睡眠。
返回
與時鐘生產者相對應的 struct clk,或包含 errno 的有效 IS_ERR() 條件。該實現使用 dev 和 id 來確定時鐘消費者,從而確定時鐘生產者。(也就是說,id 可能是相同的字串,但 clk_get 可能會根據 dev 返回不同的時鐘生產者。)
描述
驅動程式必須假設時鐘源既未準備好也未啟用。
當裝置從匯流排取消繫結時,時鐘將自動釋放。
引數
struct device *dev時鐘“消費者”的裝置
const char *id時鐘使用者 ID
上下文
可能會睡眠。
返回
與時鐘生產者相對應的 struct clk,或包含 errno 的有效 IS_ERR() 條件。該實現使用 dev 和 id 來確定時鐘消費者,從而確定時鐘生產者。(也就是說,id 可能是相同的字串,但 clk_get 可能會根據 dev 返回不同的時鐘生產者。)
描述
返回的 clk(如果有效)已準備好。但是,驅動程式必須假定時鐘未啟用。
當裝置從匯流排取消繫結時,時鐘將自動取消準備並釋放。
-
struct clk *devm_clk_get_enabled(struct device *dev, const char *id)¶
devm_clk_get()+ clk_prepare_enable()
引數
struct device *dev時鐘“消費者”的裝置
const char *id時鐘使用者 ID
上下文
可能會睡眠。
返回
與時鐘生產者相對應的 struct clk,或包含 errno 的有效 IS_ERR() 條件。該實現使用 dev 和 id 來確定時鐘消費者,從而確定時鐘生產者。(也就是說,id 可能是相同的字串,但 clk_get 可能會根據 dev 返回不同的時鐘生產者。)
描述
返回的 clk(如果有效)已準備好並啟用。
當裝置從匯流排取消繫結時,時鐘將自動停用、取消準備並釋放。
引數
struct device *dev時鐘“消費者”的裝置
const char *id時鐘使用者 ID
上下文
可能會睡眠。
返回
與時鐘生產者相對應的 struct clk,或包含 errno 的有效 IS_ERR() 條件。該實現使用 dev 和 id 來確定時鐘消費者,從而確定時鐘生產者。如果未找到此類 clk,則它將返回 NULL,該值充當虛擬 clk。這是與 devm_clk_get() 相比唯一的區別。
描述
驅動程式必須假設時鐘源既未準備好也未啟用。
當裝置從匯流排取消繫結時,時鐘將自動釋放。
引數
struct device *dev時鐘“消費者”的裝置
const char *id時鐘使用者 ID
上下文
可能會睡眠。
返回
與時鐘生產者相對應的 struct clk,或包含 errno 的有效 IS_ERR() 條件。該實現使用 dev 和 id 來確定時鐘消費者,從而確定時鐘生產者。如果未找到此類 clk,則它將返回 NULL,該值充當虛擬 clk。這是與 devm_clk_get_prepared() 相比唯一的區別。
描述
返回的 clk(如果有效)已準備好。但是,驅動程式必須假定時鐘未啟用。
當裝置從匯流排取消繫結時,時鐘將自動取消準備並釋放。
-
struct clk *devm_clk_get_optional_enabled(struct device *dev, const char *id)¶
devm_clk_get_optional()+ clk_prepare_enable()
引數
struct device *dev時鐘“消費者”的裝置
const char *id時鐘使用者 ID
上下文
可能會睡眠。
返回
與時鐘生產者相對應的 struct clk,或包含 errno 的有效 IS_ERR() 條件。該實現使用 dev 和 id 來確定時鐘消費者,從而確定時鐘生產者。如果未找到此類 clk,則它將返回 NULL,該值充當虛擬 clk。這是與 devm_clk_get_enabled() 相比唯一的區別。
描述
返回的 clk(如果有效)已準備好並啟用。
當裝置從匯流排取消繫結時,時鐘將自動停用、取消準備並釋放。
-
struct clk *devm_clk_get_optional_enabled_with_rate(struct device *dev, const char *id, unsigned long rate)¶
devm_clk_get_optional()+clk_set_rate()+ clk_prepare_enable()
引數
struct device *dev時鐘“消費者”的裝置
const char *id時鐘使用者 ID
unsigned long rate新的時鐘頻率
上下文
可能會睡眠。
返回
與時鐘生產者相對應的 struct clk,或包含 errno 的有效 IS_ERR() 條件。該實現使用 dev 和 id 來確定時鐘消費者,從而確定時鐘生產者。如果未找到此類 clk,則它將返回 NULL,該值充當虛擬 clk。這是與 devm_clk_get_enabled() 相比唯一的區別。
描述
返回的 clk(如果有效)已準備好、啟用並設定了速率。
當裝置從匯流排取消繫結時,時鐘將自動停用、取消準備並釋放。
-
struct clk *devm_get_clk_from_child(struct device *dev, struct device_node *np, const char *con_id)¶
從子節點查詢並獲取對時鐘生產者的託管引用。
引數
struct device *dev時鐘“消費者”的裝置
struct device_node *np指向時鐘消費者節點的指標
const char *con_id時鐘使用者 ID
描述
此函式解析時鐘,並使用它們透過使用 np 和 con_id 從註冊的時鐘提供者列表中查詢 struct clk
當裝置從匯流排取消繫結時,時鐘將自動釋放。
引數
struct clk *clk時鐘源
描述
如果無法啟用/停用時鐘,則應返回成功。
可以從原子上下文中呼叫。
返回成功 (0) 或負 errno。
-
int clk_bulk_enable(int num_clks, const struct clk_bulk_data *clks)¶
通知系統何時應執行這組 clk。
引數
int num_clksclk_bulk_data 的數量
const struct clk_bulk_data *clks消費者的 clk_bulk_data 表
描述
可以從原子上下文中呼叫。
返回成功 (0) 或負 errno。
引數
struct clk *clk時鐘源
描述
通知系統驅動程式不再需要時鐘源,可以關閉。
可以從原子上下文中呼叫。
實現細節:如果時鐘源在多個驅動程式之間共享,則 clk_enable() 呼叫必須與相同數量的 clk_disable() 呼叫保持平衡,才能停用時鐘源。
-
void clk_bulk_disable(int num_clks, const struct clk_bulk_data *clks)¶
通知系統何時不再需要這組 clk。
引數
int num_clksclk_bulk_data 的數量
const struct clk_bulk_data *clks消費者的 clk_bulk_data 表
描述
通知系統驅動程式不再需要一組 clk,可以關閉。
可以從原子上下文中呼叫。
實現細節:如果這組 clk 在多個驅動程式之間共享,則 clk_bulk_enable() 呼叫必須與相同數量的 clk_bulk_disable() 呼叫保持平衡,才能停用時鐘源。
引數
struct clk *clk時鐘源
引數
struct clk *clk時鐘源
注意
驅動程式必須確保在此時鐘源上進行的所有 clk_enable 呼叫在呼叫此函式之前都透過 clk_disable 呼叫保持平衡。
描述
不應從中斷上下文中呼叫 clk_put。
-
void clk_bulk_put(int num_clks, struct clk_bulk_data *clks)¶
“釋放”時鐘源
引數
int num_clksclk_bulk_data 的數量
struct clk_bulk_data *clks消費者的 clk_bulk_data 表
注意
驅動程式必須確保在此時鐘源上進行的所有 clk_bulk_enable 呼叫在呼叫此函式之前都透過 clk_bulk_disable 呼叫保持平衡。
描述
不應從中斷上下文中呼叫 clk_bulk_put。
-
void clk_bulk_put_all(int num_clks, struct clk_bulk_data *clks)¶
“釋放”所有時鐘源
引數
int num_clksclk_bulk_data 的數量
struct clk_bulk_data *clks消費者的 clk_bulk_data 表
注意
驅動程式必須確保在此時鐘源上進行的所有 clk_bulk_enable 呼叫在呼叫此函式之前都透過 clk_bulk_disable 呼叫保持平衡。
描述
不應在中斷上下文中呼叫 clk_bulk_put_all。
引數
struct device *dev用於獲取時鐘的裝置
struct clk *clk使用
devm_clk_get()獲取的時鐘源
注意
驅動程式必須確保在此時鐘源上進行的所有 clk_enable 呼叫在呼叫此函式之前都透過 clk_disable 呼叫保持平衡。
描述
不應從中斷上下文中呼叫 clk_put。
引數
struct clk *clk時鐘源
unsigned long rate所需的時鐘速率,單位為 Hz
描述
這回答了問題“如果我將 **rate** 傳遞給 clk_set_rate(),我最終會得到什麼樣的時鐘速率?”,而不會以任何方式更改硬體。換句話說
rate = clk_round_rate(clk, r);
和
clk_set_rate(clk, r); rate = clk_get_rate(clk);
是等效的,只是前者不會以任何方式修改時鐘硬體。
返回四捨五入的時鐘速率,單位為 Hz,或負的 errno。
引數
struct clk *clk時鐘源
unsigned long rate所需的時鐘速率,單位為 Hz
描述
更新速率從最頂層受影響的時鐘開始,然後沿著樹向下走到需要更新的最底層時鐘。
返回成功 (0) 或負 errno。
引數
struct clk *clk時鐘源
unsigned long rate所需的時鐘速率,單位為 Hz
描述
此輔助函式允許驅動程式原子地設定生產者的速率並宣告對生產者速率控制的獨佔權。
它本質上是 clk_set_rate() 和 clk_rate_exclusite_get() 的組合。呼叫者必須透過呼叫 clk_rate_exclusive_put() 來平衡此呼叫。
返回成功 (0) 或負 errno。
引數
const struct clk *clk時鐘源
const struct clk *parent父時鐘源
描述
驅動程式可以使用此函式來檢查一個時鐘是否可以成為另一個時鐘的父時鐘,而無需實際更改父時鐘。
如果 **parent** 是 **clk** 的可能父時鐘,則返回 true;否則返回 false。
引數
struct clk *clk時鐘源
unsigned long min所需的最小時鐘速率,單位為 Hz,包含
unsigned long max所需的最大時鐘速率,單位為 Hz,包含
描述
返回成功 (0) 或負 errno。
引數
struct clk *clk時鐘源
unsigned long rate所需的最小時鐘速率,單位為 Hz,包含
描述
返回成功 (0) 或負 errno。
引數
struct clk *clk時鐘源
unsigned long rate所需的最大時鐘速率,單位為 Hz,包含
描述
返回成功 (0) 或負 errno。
引數
struct clk *clk時鐘源
struct clk *parent父時鐘源
描述
返回成功 (0) 或負 errno。
-
struct clk *clk_get_sys(const char *dev_id, const char *con_id)¶
根據裝置名稱獲取時鐘
引數
const char *dev_id裝置名稱
const char *con_id連線 ID
描述
返回與時鐘生產者對應的 struct clk,或包含 errno 的有效 IS_ERR() 條件。該實現使用 **dev_id** 和 **con_id** 來確定時鐘消費者,從而確定時鐘生產者。與 clk_get() 相比,此函式使用裝置名稱而不是裝置本身進行標識。
驅動程式必須假定時鐘源未啟用。
不應在中斷上下文中呼叫 clk_get_sys。
-
int clk_save_context(void)¶
儲存時鐘上下文以進行斷電
引數
void無引數
描述
儲存時鐘暫存器的上下文,以用於暫存器內容將丟失的電源狀態。發生在掛起程式碼深處,因此不需要鎖定。
-
void clk_restore_context(void)¶
斷電後恢復時鐘上下文
引數
void無引數
描述
這發生在所有時鐘都啟用的情況下。發生在恢復程式碼深處,因此不需要鎖定。
引數
struct clk *clk時鐘源
描述
返回成功 (0) 或負 errno。
引數
struct device *dev時鐘“消費者”的裝置
const char *id時鐘使用者 ID
描述
其行為與 clk_get() 相同,只是在沒有時鐘生產者的情況下。在這種情況下,該函式不是返回 -ENOENT,而是返回 NULL。
同步原語¶
讀取-複製更新 (RCU)¶
-
bool same_state_synchronize_rcu(unsigned long oldstate1, unsigned long oldstate2)¶
兩個舊狀態值是否相同?
引數
unsigned long oldstate1第一個舊狀態值。
unsigned long oldstate2第二個舊狀態值。
描述
這兩個舊狀態值必須從 get_state_synchronize_rcu()、start_poll_synchronize_rcu() 或 get_completed_synchronize_rcu() 之一獲取。如果兩個值相同,則返回 **true**;否則返回 **false**。這允許其生存期由舊狀態值跟蹤的結構將這些值推送到列表標頭,從而使這些結構稍微小一些。
-
bool rcu_trace_implies_rcu_gp(void)¶
RCU 任務跟蹤寬限期是否意味著 RCU 寬限期?
引數
void無引數
描述
作為實現的意外,RCU 任務跟蹤寬限期也充當 RCU 寬限期。但是,這隨時可能更改。依賴此意外的程式碼必須呼叫此函式以驗證此意外是否仍在發生。
已發出警告!
-
cond_resched_tasks_rcu_qs¶
cond_resched_tasks_rcu_qs ()
向 RCU 報告潛在的靜止狀態
描述
此宏類似於 cond_resched(),不同之處在於,即使 cond_resched() 機制已關閉,它也被定義為向 RCU 任務報告潛在的靜止狀態,正如某些 PREEMPTION 核心所倡導的那樣。
-
rcu_softirq_qs_periodic¶
rcu_softirq_qs_periodic (old_ts)
報告 RCU 和 RCU 任務靜止狀態
引數
old_ts處理開始時的節拍數。
描述
此幫助程式用於長時間執行的 softirq 處理程式,例如網路中的 NAPI 執行緒。呼叫者應在 softirq 處理程式的開頭初始化作為 **old_ts** 傳遞的變數。頻繁呼叫時,此宏將在此後每 100 毫秒呼叫一次 rcu_softirq_qs(),這將提供 RCU 和 RCU 任務靜止狀態。請注意,此宏會修改其 old_ts 引數。
由於已停用 softirq 的程式碼區域充當 RCU 讀取端臨界區,因此應在啟用 softirq(和搶佔)的情況下呼叫此宏。
當定義了 CONFIG_PREEMPT_RT 時,不需要此宏。RT 核心將有更多機會呼叫 schedule() 呼叫並提供必要的靜止狀態。相比之下,僅呼叫 cond_resched() 不會達到相同的效果,因為 cond_resched() 不提供 RCU 任務靜止狀態。
-
RCU_LOCKDEP_WARN¶
RCU_LOCKDEP_WARN (c, s)
如果滿足指定的條件,則發出 lockdep splat
引數
c要檢查的條件
s資訊性訊息
描述
這會在檢查 (c) 之前檢查 debug_lockdep_rcu_enabled(),以防止由於 lockdep 尚未初始化而導致的早期引導 splat,並在檢查 (c) 之後重新檢查它,以防止由於 lockdep 被停用而導致的誤報 splat。有關更多詳細資訊,請參見 提交 3066820034b5dd(“rcu:拒絕 RCU_LOCKDEP_WARN() 誤報”)。
-
lockdep_assert_in_rcu_read_lock¶
lockdep_assert_in_rcu_read_lock ()
-
lockdep_assert_in_rcu_read_lock_bh¶
lockdep_assert_in_rcu_read_lock_bh ()
如果未受
rcu_read_lock_bh()保護,則發出警告描述
如果啟用了 lockdep 並且沒有生效的
rcu_read_lock_bh(),則會觸發 splat。請注意,local_bh_disable() 及其同類函式在這裡是不夠的,而是需要實際的rcu_read_lock_bh()。
-
lockdep_assert_in_rcu_read_lock_sched¶
lockdep_assert_in_rcu_read_lock_sched ()
如果未受
rcu_read_lock_sched()保護,則發出警告。描述
如果啟用了 lockdep 並且沒有生效的
rcu_read_lock_sched(),則會觸發 splat。請注意,preempt_disable() 及其同類函式在這裡是不夠的,而是需要實際的rcu_read_lock_sched()。
-
lockdep_assert_in_rcu_reader¶
lockdep_assert_in_rcu_reader ()
如果不在某種型別的 RCU 讀取器中,則發出警告。
描述
如果啟用了 lockdep 並且沒有任何型別的 RCU 讀取器生效,則會觸發 splat。請注意,受 preempt_disable、local_bh_disable() 和 local_irq_disable() 等保護的程式碼區域都符合 RCU 讀取器的條件。
請注意,這永遠不會在未同時使用 PREEMPT_COUNT 構建的 PREEMPT_NONE 或 PREEMPT_VOLUNTARY 核心中觸發。但是,如果您啟用了 lockdep,那麼最好也啟用 PREEMPT_COUNT。
-
unrcu_pointer¶
unrcu_pointer (p)
將指標標記為不受 RCU 保護。
引數
p需要失去其 __rcu 屬性的指標。
描述
將 p 從 __rcu 指標轉換為 __kernel 指標。這允許將 __rcu 指標與 xchg() 及其同類函式一起使用。
-
RCU_INITIALIZER¶
RCU_INITIALIZER (v)
靜態初始化一個受 RCU 保護的全域性變數。
引數
v要靜態初始化的值。
-
rcu_assign_pointer¶
rcu_assign_pointer (p, v)
賦值給受 RCU 保護的指標。
引數
p要賦值的指標。
v要賦值(釋出)的值。
描述
將指定的值賦值給指定的受 RCU 保護的指標,確保任何併發的 RCU 讀取器都將看到任何先前的初始化。
在需要它們的架構(即大多數架構)上插入記憶體屏障,並防止編譯器在指標賦值後重新排序初始化結構體的程式碼。更重要的是,此呼叫記錄了哪些指標將被 RCU 讀取端程式碼取消引用。
在某些特殊情況下,您可以使用 RCU_INIT_POINTER() 代替 rcu_assign_pointer()。RCU_INIT_POINTER() 速度更快,因為它不限制 CPU 或編譯器。也就是說,當您應該使用 rcu_assign_pointer() 時使用 RCU_INIT_POINTER() 是一件非常糟糕的事情,會導致難以診斷的記憶體損壞。因此,請務必小心。有關詳細資訊,請參閱 RCU_INIT_POINTER() 註釋頭。
請注意,儘管看起來如此,rcu_assign_pointer() 僅評估其每個引數一次。其中一個“額外的”評估在 typeof() 中,另一個僅對 sparse (__CHECKER__) 可見,它們都不會實際執行引數。與大多數 cpp 宏一樣,這種僅執行引數一次的屬性非常重要,因此在更改 rcu_assign_pointer() 及其呼叫的其他宏時,請務必小心。
-
rcu_replace_pointer¶
rcu_replace_pointer (rcu_ptr, ptr, c)
替換 RCU 指標,返回其舊值。
引數
rcu_ptrRCU 指標,其舊值將被返回。
ptr常規指標
c取消引用將發生的 lockdep 條件。
描述
執行替換,其中 rcu_ptr 是 RCU 註釋的指標,而 c 是傳遞給用於讀取該指標的 rcu_dereference_protected() 呼叫的 lockdep 引數。將返回 rcu_ptr 的舊值,並且 rcu_ptr 將設定為 ptr。
-
rcu_access_pointer¶
rcu_access_pointer (p)
獲取 RCU 指標,不進行取消引用。
引數
p要讀取的指標
描述
返回指定 RCU 保護的指標的值,但省略 RCU 讀取端臨界區中的 lockdep 檢查。當訪問此指標的值,但不取消引用指標時,這很有用,例如,當針對 NULL 測試 RCU 保護的指標時。雖然 rcu_access_pointer() 也可用於更新端鎖阻止指標的值更改的情況,但您應該為此用例改用 rcu_dereference_protected()。在 RCU 讀取端臨界區中,幾乎沒有理由使用 rcu_access_pointer()。
通常最好直接測試 rcu_access_pointer() 返回值,以避免以後不注意的更改引入意外的取消引用。換句話說,將 rcu_access_pointer() 返回值分配給區域性變數會導致事故發生。
當對指標的讀取端訪問已至少在一個寬限期前刪除時,也可以使用 rcu_access_pointer(),例如在釋放資料的 RCU 回撥的上下文中,或者在 synchronize_rcu() 返回之後。在寬限期過去後拆除多連結結構時,這可能很有用。但是,通常首選 rcu_dereference_protected() 用於此用例。
-
rcu_dereference_check¶
rcu_dereference_check (p, c)
帶有除錯檢查的 rcu_dereference。
引數
p取消引用之前要讀取的指標。
c取消引用將發生的條件。
描述
執行 rcu_dereference(),但檢查取消引用將發生的條件是否正確。通常,這些條件指示此時應保持的各種鎖定條件。如果滿足條件,則檢查應返回 true。包含對 RCU 讀取端臨界區 (rcu_read_lock()) 中的隱式檢查。
例如
bar = rcu_dereference_check(foo->bar, lockdep_is_held(
foo->lock));
可用於向 lockdep 指示只有在持有 rcu_read_lock() 或持有替換 foo->bar 處的 bar 結構所需的鎖時,才可以取消引用 foo->bar。
請注意,條件列表還可以包括何時不需要持有鎖的指示,例如在目標結構的初始化或銷燬期間。
- bar = rcu_dereference_check(foo->bar, lockdep_is_held(
foo->lock) ||atomic_read(
foo->usage) == 0);
在需要它們的架構(當前僅 Alpha)上插入記憶體屏障,防止編譯器重新獲取(併合並獲取),更重要的是,準確地記錄哪些指標受 RCU 保護,並檢查指標是否已註釋為 __rcu。
-
rcu_dereference_bh_check¶
rcu_dereference_bh_check (p, c)
帶有除錯檢查的 rcu_dereference_bh。
引數
p取消引用之前要讀取的指標。
c取消引用將發生的條件。
描述
這是 rcu_dereference_check() 的 RCU-bh 對應項。但是,請注意,從 v5.0 核心開始,vanilla RCU 寬限期除了等待由 rcu_read_lock() 和 rcu_read_unlock() 標記的程式碼區域之外,還等待 local_bh_disable() 程式碼區域。這意味著 synchronize_rcu()、call_rcu 及其同類函式不僅考慮了 rcu_read_lock(),還考慮了 rcu_read_lock_bh()。
-
rcu_dereference_sched_check¶
rcu_dereference_sched_check (p, c)
帶有除錯檢查的 rcu_dereference_sched。
引數
p取消引用之前要讀取的指標。
c取消引用將發生的條件。
描述
這是 rcu_dereference_check() 的 RCU-sched 對應項。但是,請注意,從 v5.0 核心開始,vanilla RCU 寬限期除了等待由 rcu_read_lock() 和 rcu_read_unlock() 標記的程式碼區域之外,還等待 preempt_disable() 程式碼區域。這意味著 synchronize_rcu()、call_rcu 及其同類函式不僅考慮了 rcu_read_lock(),還考慮了 rcu_read_lock_sched()。
-
rcu_dereference_protected¶
rcu_dereference_protected (p, c)
在阻止更新時獲取 RCU 指標。
引數
p取消引用之前要讀取的指標。
c取消引用將發生的條件。
描述
返回指定 RCU 保護的指標的值,但省略 READ_ONCE()。這在更新端鎖阻止指標的值更改的情況下很有用。請注意,此原語不阻止編譯器重複此引用或將其與其他引用組合,因此不應在沒有適當鎖的保護的情況下使用它。
此函式僅供更新端使用。僅在受 rcu_read_lock() 保護時使用此函式會導致不頻繁但非常糟糕的故障。
-
rcu_dereference¶
rcu_dereference (p)
獲取 RCU 保護的指標以進行取消引用。
-
rcu_dereference_bh¶
rcu_dereference_bh (p)
獲取受 RCU-bh 保護的指標以進行取消引用。
-
rcu_dereference_sched¶
rcu_dereference_sched (p)
獲取受 RCU-sched 保護的指標以進行取消引用。
-
rcu_pointer_handoff¶
rcu_pointer_handoff (p)
將指標從 RCU 移交給其他機制。
引數
p要移交的指標
描述
這只是一個恆等函式,但它記錄了指標從 RCU 移交給其他同步機制的位置,例如引用計數或鎖定。在 C11 中,它將對映到 kill_dependency()。它可以按如下方式使用。
rcu_read_lock();
p = rcu_dereference(gp);
long_lived = is_long_lived(p);
if (long_lived) {
if (!atomic_inc_not_zero(p->refcnt))
long_lived = false;
else
p = rcu_pointer_handoff(p);
}
rcu_read_unlock();
-
void rcu_read_lock(void)¶
標記 RCU 讀取端臨界區的開始。
引數
void無引數
描述
如果在其他 CPU 位於 RCU 讀取端臨界區中時在一個 CPU 上呼叫 synchronize_rcu(),則保證 synchronize_rcu() 會阻塞,直到所有其他 CPU 退出其臨界區之後。類似地,如果在其他 CPU 位於 RCU 讀取端臨界區中時在一個 CPU 上呼叫 call_rcu(),則相應的 RCU 回撥的呼叫會延遲到所有其他 CPU 退出其臨界區之後。
synchronize_rcu() 和 call_rcu() 都還會等待停用搶佔的程式碼區域,包括停用中斷或軟中斷的程式碼區域。
但是,請注意,允許 RCU 回撥與新的 RCU 讀取端臨界區併發執行。發生這種情況的一種方式是透過以下事件序列:(1)CPU 0 進入 RCU 讀取端臨界區,(2)CPU 1 呼叫 call_rcu() 以註冊 RCU 回撥,(3)CPU 0 退出 RCU 讀取端臨界區,(4)CPU 2 進入 RCU 讀取端臨界區,(5)呼叫 RCU 回撥。這是合法的,因為與 call_rcu() 併發執行的 RCU 讀取端臨界區(因此可能引用相應的 RCU 回撥會釋放的某些內容)在呼叫相應的 RCU 回撥之前已完成。
RCU 讀取端臨界區可以巢狀。任何延遲操作都將延遲到最外層的 RCU 讀取端臨界區完成。
您可以透過遵循以下規則來避免閱讀和理解下一段:不要將任何會在 !PREEMPTION 核心中阻塞的內容放入 rcu_read_lock() RCU 讀取端臨界區中。但是,如果您想要完整的故事,請繼續閱讀!
在不可搶佔的 RCU 實現(純 TREE_RCU 和 TINY_RCU)中,在 RCU 讀取端臨界區中阻塞是非法的。在 CONFIG_PREEMPTION 核心構建中的可搶佔 RCU 實現 (PREEMPT_RCU) 中,RCU 讀取端臨界區可能會被搶佔,但顯式阻塞是非法的。最後,在即時(帶有 -rt 補丁集)核心構建中的可搶佔 RCU 實現中,RCU 讀取端臨界區可能會被搶佔,並且它們也可能會阻塞,但僅在獲取受優先順序繼承約束的自旋鎖時。
-
void rcu_read_unlock(void)¶
標記 RCU 讀取端臨界區的結束。
引數
void無引數
描述
在幾乎所有情況下,rcu_read_unlock() 都不會死鎖。由於當停用中斷時呼叫 rcu_read_unlock() 時執行的靜止狀態延遲,這種死鎖免疫性也擴充套件到排程程式的執行佇列和優先順序繼承自旋鎖。
有關更多資訊,請參閱 rcu_read_lock()。
-
void rcu_read_lock_bh(void)¶
標記 RCU-bh 臨界區的開始。
引數
void無引數
描述
這等效於 rcu_read_lock(),但也會停用軟中斷。請注意,任何停用軟中斷的其他操作也可以用作 RCU 讀取端臨界區。但是,請注意,此等效性僅適用於 v5.0 及更高版本。在 v5.0 之前,rcu_read_lock() 和 rcu_read_lock_bh() 是不相關的。
請注意,rcu_read_lock_bh() 和與之匹配的 rcu_read_unlock_bh() 必須在同一上下文中發生。例如,如果匹配的 rcu_read_lock_bh() 是從其他任務呼叫的,則從一個任務呼叫 rcu_read_unlock_bh() 是非法的。
-
void rcu_read_unlock_bh(void)¶
標記軟中斷(softirq)專用 RCU 臨界區的結束
-
void rcu_read_lock_sched(void)¶
標記 RCU-sched 臨界區的開始
引數
void無引數
描述
這等效於 rcu_read_lock(),但也停用了搶佔。 讀端臨界區也可以由任何停用搶佔的操作引入,包括 local_irq_disable() 及其類似函式。 但是,請注意,與 rcu_read_lock() 的等效性僅適用於 v5.0 及更高版本。 在 v5.0 之前,rcu_read_lock() 和 rcu_read_lock_sched() 是不相關的。
請注意,rcu_read_lock_sched() 和與之匹配的 rcu_read_unlock_sched() 必須在同一上下文中發生。例如,如果匹配的 rcu_read_lock_sched() 是從 NMI 處理程式呼叫的,則從程序上下文中呼叫 rcu_read_unlock_sched() 是非法的。
-
void rcu_read_unlock_sched(void)¶
標記 RCU-classic 臨界區的結束
-
RCU_INIT_POINTER¶
RCU_INIT_POINTER (p, v)
初始化一個 RCU 保護的指標
引數
p要初始化的指標。
v指標要初始化的值。
描述
在特殊情況下初始化 RCU 保護的指標,在這些情況下,讀取者不需要 CPU 或編譯器的排序約束。 這些特殊情況是
使用
RCU_INIT_POINTER()將指標置為 NULL *或*呼叫者已採取必要的步驟來防止 RCU 讀取者併發訪問此指標 *或*
引用資料結構已經透過編譯時或透過
rcu_assign_pointer()暴露給讀取者 *並且*自那時以來,您沒有對此結構進行 *任何* 對讀取者可見的更改 *或*
允許從其新位置訪問此結構的讀取者看到該結構的舊狀態。(例如,更改是對統計計數器或其他不需要精確同步的狀態進行的。)
未能遵循這些關於使用 RCU_INIT_POINTER() 的規則將導致難以診斷的記憶體損壞。 就像在崩潰轉儲中結構看起來沒問題一樣,但是任何併發的 RCU 讀取者都可能看到引用資料結構的預初始化值。 因此,請非常小心地使用 RCU_INIT_POINTER()!!!
如果您正在建立一個由單個外部到結構的 RCU 保護的指標訪問的 RCU 保護的連結結構,則可以使用 RCU_INIT_POINTER() 初始化內部 RCU 保護的指標,但是在完全初始化連結結構的可讀取部分 *之後*,必須使用 rcu_assign_pointer() 初始化外部到結構的指標。
請注意,與 rcu_assign_pointer() 不同,RCU_INIT_POINTER() 不提供 CPU 或編譯器的排序保證。
-
RCU_POINTER_INITIALIZER¶
RCU_POINTER_INITIALIZER (p, v)
靜態初始化 RCU 保護的指標
引數
p要初始化的指標。
v指標要初始化的值。
描述
結構欄位中 RCU 保護的指標的 GCC 風格初始化。
-
kfree_rcu¶
kfree_rcu (ptr, rhf)
在寬限期後 kfree 物件。
引數
ptr用於雙引數呼叫的 kfree 指標。
rhfptr 型別中 struct rcu_head 的名稱。
描述
許多 rcu 回撥函式只是對基本結構呼叫 kfree()。 這些函式很簡單,但是它們的大小會累積起來,而且當它們在核心模組中使用時,該模組必須在模組解除安裝時呼叫高延遲的 rcu_barrier() 函式。
kfree_rcu() 函式處理此問題。 為了使通用回撥函式處理 rcu_head 的不同偏移量,回撥需要確定被釋放物件的起始地址,該起始地址可以是大型 kmalloc 或 vmalloc 分配。 為了允許簡單地將指標向下對齊到頁邊界,只能容納最大 4095 位元組的偏移量。 如果偏移量大於 4095 位元組,則會在 kvfree_rcu_arg_2() 中生成編譯時錯誤。 如果觸發此錯誤,您可以回退到使用 call_rcu() 或重新排列結構以將 rcu_head 結構定位到前 4096 個位元組中。
要釋放的物件可以透過 kmalloc() 或 kmem_cache_alloc() 分配。
請注意,允許的偏移量將來可能會減小。
BUILD_BUG_ON 檢查不得涉及任何函式呼叫,因此此處在宏中進行檢查。
-
kfree_rcu_mightsleep¶
kfree_rcu_mightsleep (ptr)
在寬限期後 kfree 物件。
引數
ptr用於單引數呼叫的 kfree 指標。
描述
對於無頭變體,僅傳遞一個引數,即一個必須在寬限期後釋放的指標。 因此,語義是
kfree_rcu_mightsleep(ptr);
其中 ptr 是要透過 kvfree() 釋放的指標。
請注意,允許從必須遵循 might_sleep() 註釋的上下文中以無頭方式釋放。 否則,請切換並在 ptr 型別中嵌入 rcu_head 結構。
-
void rcu_head_init(struct rcu_head *rhp)¶
初始化 rcu_head 以用於
rcu_head_after_call_rcu()
引數
struct rcu_head *rhp要初始化的 rcu_head 結構。
描述
如果您打算呼叫 rcu_head_after_call_rcu() 以測試給定的 rcu_head 結構是否已經傳遞給 call_rcu(),那麼您還必須在分配該結構後立即呼叫此 rcu_head_init() 函式。 對此函式的呼叫不得與對 call_rcu()、rcu_head_after_call_rcu() 或回撥呼叫的呼叫競爭。
-
bool rcu_head_after_call_rcu(struct rcu_head *rhp, rcu_callback_t f)¶
此 rcu_head 是否已傳遞給
call_rcu()?
引數
struct rcu_head *rhp要測試的 rcu_head 結構。
rcu_callback_t f與 rhp 一起傳遞給
call_rcu()的函式。
描述
如果 rhp 已使用 func 傳遞給 call_rcu(),則返回 true,否則返回 false。 在任何其他情況下都會發出警告,包括 rhp 在寬限期後已經被呼叫的情況。 對此函式的呼叫不得與回撥呼叫競爭。 避免此類競爭的一種方法是將對 rcu_head_after_call_rcu() 的呼叫放在 RCU 讀取端臨界區中,該臨界區包含包含 rhp 的結構的指標的讀取端提取。
-
void rcu_softirq_qs(void)¶
在軟中斷處理中提供一組 RCU 靜止狀態
引數
void無引數
描述
標記 RCU、Tasks RCU 和 Tasks Trace RCU 的靜止狀態。 這是一個特殊用途的函式,用於軟中斷基礎設施,也可能用於偶爾長時間執行的軟中斷處理程式。
請注意,從 RCU 的角度來看,呼叫 rcu_softirq_qs() 等效於暫時完全啟用搶佔。 例如,給定以下程式碼
local_bh_disable();
do_something();
rcu_softirq_qs(); // A
do_something_else();
local_bh_enable(); // B
與 do_something() 的呼叫併發開始的對 synchronize_rcu() 的呼叫將保證僅等待到執行到達語句 A。如果沒有 rcu_softirq_qs(),則相同的 synchronize_rcu() 將改為保證等待到執行到達語句 B。
-
bool rcu_watching_snap_stopped_since(struct rcu_data *rdp, int snap)¶
自指定的 snap 以來,RCU 是否停止監視給定的 CPU?
引數
struct rcu_data *rdp與要檢查 EQS 的 CPU 對應的 rcu_data。
int snapCPU 不在 EQS 中時拍攝的 rcu_watching 快照。
描述
如果與 rdp 對應的 CPU 自 snap 以來在擴充套件靜止狀態中花費了一些時間,則返回 true。 請注意,這不會檢查它是否 /仍然/ 在 EQS 中,只是檢查它自 snap 以來是否經歷過 EQS。
這旨在用於迴圈中,等待 CPU 經歷 EQS。
-
int rcu_is_cpu_rrupt_from_idle(void)¶
檢視是否從空閒狀態“中斷”
引數
void無引數
描述
如果當前 CPU 處於空閒狀態,並且正在執行第一級(非巢狀)中斷,或者直接從空閒狀態執行,則返回 true。
呼叫者必須至少停用 IRQ。
-
void rcu_irq_exit_check_preempt(void)¶
驗證是否可以進行排程
引數
void無引數
-
void __rcu_irq_enter_check_tick(void)¶
如果 RCU 需要,則在 CPU 上啟用排程程式時鐘。
引數
void無引數
描述
當 CPU 從 nohz_full 使用者空間執行進入核心時,排程程式時鐘通常不會啟用。 畢竟,nohz_full 使用者空間執行是 RCU 靜止狀態,並且在核心中執行的時間非常短。 除非當然不是。 並且不難導致大型系統在核心中迴圈數十秒甚至數分鐘,這會導致許多問題,包括 RCU CPU 停止警告。
因此,如果 nohz_full CPU 未能及時報告靜止狀態,則 RCU 寬限期 kthread 會設定該 CPU 的 ->rcu_urgent_qs 標誌,並期望下一個中斷或異常會呼叫此函式,這將開啟排程程式時鐘,這將使 RCU 能夠檢測到該 CPU 的靜止狀態,例如,由於 CONFIG_PREEMPT=n 核心中的 cond_resched() 呼叫。 一旦報告了此 CPU 的靜止狀態,將停用該時鐘。
當然,在經過仔細調整的系統中,可能永遠不會發生中斷或異常。 在這種情況下,RCU 寬限期 kthread 最終會導致發生中斷或異常。 但是,在控制不太嚴格的環境中,此函式允許 RCU 在不建立其他無用中斷的情況下獲得所需內容。
-
notrace bool rcu_is_watching(void)¶
是否允許在當前 CPU 上使用 RCU 讀取端臨界區?
引數
void無引數
描述
如果 RCU 正在監視正在執行的 CPU,則返回 true,否則返回 false。 true 返回值表示此 CPU 可以安全地進入 RCU 讀取端臨界區。
儘管從核心的大多數部分呼叫 rcu_is_watching() 將返回 true,但也有重要的例外情況。 例如,如果當前 CPU 位於其空閒迴圈的深處、在核心進入/退出程式碼中或處於離線狀態,則 rcu_is_watching() 將返回 false。
使 notrace,因為它可能被 ftrace 的內部函式呼叫,並且使此 notrace 可以消除不必要的遞迴呼叫。
-
void rcu_set_gpwrap_lag(unsigned long lag_gps)¶
設定 RCU GP 序列溢位滯後值。
引數
unsigned long lag_gps將溢位滯後設定為此多個寬限期的計數器值,rcutorture 使用該值快速強制 gpwrap 情況。 lag_gps = 0 表示我們將其重置回啟動時間值。
-
void call_rcu_hurry(struct rcu_head *head, rcu_callback_t func)¶
將 RCU 回撥排隊,以便在寬限期後呼叫,並在這樣做時將所有延遲迴調(包括新的回撥)重新整理到主 ->cblist。
引數
struct rcu_head *head用於對 RCU 更新進行排隊的結構。
rcu_callback_t func在寬限期後呼叫的實際回撥函式
描述
回撥函式將在完整的寬限期結束後的一段時間呼叫,換句話說,在所有預先存在的 RCU 讀取端臨界區都已完成之後。
如果你不希望回撥函式被延遲很長時間才執行(這種情況可能發生在記憶體壓力不大、負載較輕或基本空閒的系統上),請使用此 API 而不是 call_rcu()。此函式會以犧牲額外功耗為代價,使回撥函式儘快被呼叫。除此之外,此函式與 call_rcu() 完全相同,並且重用 call_rcu() 的邏輯。有關記憶體排序和其他功能的更多詳細資訊,請參閱 call_rcu()。
-
void call_rcu(struct rcu_head *head, rcu_callback_t func)¶
將 RCU 回撥函式排隊,以便在寬限期結束後呼叫。預設情況下,回撥是“懶惰的”,並且對主 ->cblist 保持隱藏,以防止過早啟動寬限期。如果您希望寬限期儘快開始,請使用
call_rcu_hurry()。
引數
struct rcu_head *head用於對 RCU 更新進行排隊的結構。
rcu_callback_t func在寬限期後呼叫的實際回撥函式
描述
回撥函式將在完整的寬限期結束後的一段時間被呼叫,換句話說,在所有先前存在的 RCU 讀取端臨界區都已完成後。但是,回撥函式很可能與在呼叫 call_rcu() 後啟動的 RCU 讀取端臨界區併發執行。
從回撥函式內部重新發布 RCU 回撥,可能會使用不同的回撥函式,這是完全合法的。指定的函式將在另一個完整的寬限期結束後被呼叫。此用例在形式上類似於從其自身處理程式中重新發布計時器的常見做法。
RCU 讀取端臨界區由 rcu_read_lock() 和 rcu_read_unlock() 分隔,並且可以巢狀。此外,但僅在 v5.0 及更高版本中,停用中斷、搶佔或軟中斷的程式碼區域也充當 RCU 讀取端臨界區。這包括硬體中斷處理程式、軟中斷處理程式和 NMI 處理程式。
請注意,所有 CPU 必須同意寬限期已擴充套件到所有先前存在的 RCU 讀取端臨界區之外。在具有多個 CPU 的系統上,這意味著當呼叫“func()”時,保證每個 CPU 自其最後一個 RCU 讀取端臨界區結束以來都已執行完整的記憶體屏障,該 RCU 讀取端臨界區的開始先於呼叫 call_rcu()。這也意味著每個執行 RCU 讀取端臨界區的 CPU,該臨界區繼續超出“func()”的開始,必須在 call_rcu() 之後但在該 RCU 讀取端臨界區的開始之前執行記憶體屏障。請注意,這些保證包括離線、空閒或以使用者模式執行的 CPU,以及在核心中執行的 CPU。
此外,如果 CPU A 呼叫了 call_rcu(),並且 CPU B 呼叫了 resulting RCU 回撥函式“func()”,則保證 CPU A 和 CPU B 在呼叫 call_rcu() 和呼叫“func()”之間的時間間隔內執行完整的記憶體屏障——即使 CPU A 和 CPU B 是同一個 CPU(但同樣只有在系統有多個 CPU 的情況下)。
此處描述了這些記憶體排序保證的實現:TREE_RCU 的寬限期記憶體排序之旅。
特別是對於 call_rcu()(與其他 call_rcu*() 函式相反),在以 CONFIG_RCU_LAZY=y 構建的核心中,call_rcu() 可能會延遲數秒,然後才開始對應回撥所需的寬限期。這種延遲可以顯著提高低利用率電池供電裝置的能效。為了避免這種延遲,在對延遲敏感的核心程式碼中,請使用 call_rcu_hurry()。
-
void synchronize_rcu(void)¶
等待寬限期結束。
引數
void無引數
描述
在完整的寬限期結束後的一段時間,控制權將返回給呼叫者,換句話說,在所有當前執行的 RCU 讀取端臨界區都已完成後。但是,請注意,從 synchronize_rcu() 返回後,呼叫者很可能與在 synchronize_rcu() 等待時開始的新的 RCU 讀取端臨界區併發執行。
RCU 讀取端臨界區由 rcu_read_lock() 和 rcu_read_unlock() 分隔,並且可以巢狀。此外,但僅在 v5.0 及更高版本中,停用中斷、搶佔或軟中斷的程式碼區域也充當 RCU 讀取端臨界區。這包括硬體中斷處理程式、軟中斷處理程式和 NMI 處理程式。
請注意,此保證意味著進一步的記憶體排序保證。在具有多個 CPU 的系統上,當 synchronize_rcu() 返回時,保證每個 CPU 自其最後一個 RCU 讀取端臨界區結束以來都已執行完整的記憶體屏障,該 RCU 讀取端臨界區的開始先於呼叫 synchronize_rcu()。此外,每個具有 RCU 讀取端臨界區的 CPU,該臨界區超出 synchronize_rcu() 的返回,保證在 synchronize_rcu() 的開始之後和該 RCU 讀取端臨界區的開始之前執行完整的記憶體屏障。請注意,這些保證包括離線、空閒或以使用者模式執行的 CPU,以及在核心中執行的 CPU。
此外,如果 CPU A 呼叫了 synchronize_rcu(),它在 CPU B 上返回到其呼叫者,則保證 CPU A 和 CPU B 在執行 synchronize_rcu() 期間執行完整的記憶體屏障——即使 CPU A 和 CPU B 是同一個 CPU(但同樣只有在系統有多個 CPU 的情況下)。
此處描述了這些記憶體排序保證的實現:TREE_RCU 的寬限期記憶體排序之旅。
-
void get_completed_synchronize_rcu_full(struct rcu_gp_oldstate *rgosp)¶
返回一個完全預先完成的輪詢狀態 Cookie
引數
struct rcu_gp_oldstate *rgosp放置狀態 Cookie 的位置
描述
將一個值儲存到 rgosp 中,該值將始終被諸如 poll_state_synchronize_rcu_full() 之類的函式視為寬限期已完成的 Cookie。
-
unsigned long get_state_synchronize_rcu(void)¶
快照當前 RCU 狀態
引數
void無引數
描述
返回一個 Cookie,該 Cookie 由後續對 cond_synchronize_rcu() 或 poll_state_synchronize_rcu() 的呼叫使用,以確定在此期間是否經過了完整的寬限期。
-
void get_state_synchronize_rcu_full(struct rcu_gp_oldstate *rgosp)¶
快照 RCU 狀態,包括正常和加速
引數
struct rcu_gp_oldstate *rgosp放置組合的正常/加速寬限期狀態的位置
描述
將正常和加速的寬限期狀態放置在 rgosp 中。可以將此狀態值傳遞給後續對 cond_synchronize_rcu_full() 或 poll_state_synchronize_rcu_full() 的呼叫,以確定在此期間是否經過寬限期(無論是正常還是加速)。rcu_gp_oldstate 結構佔用的記憶體是 unsigned long 的兩倍,但保證可以看到所有寬限期。相比之下,組合狀態佔用的記憶體較少,但有時無法考慮寬限期。
這不能保證所需的寬限期實際開始。
-
unsigned long start_poll_synchronize_rcu(void)¶
快照並啟動 RCU 寬限期
引數
void無引數
描述
返回一個 Cookie,該 Cookie 由後續對 cond_synchronize_rcu() 或 poll_state_synchronize_rcu() 的呼叫使用,以確定在此期間是否經過了完整的寬限期。如果所需的寬限期尚未計劃開始,則通知 RCU 核心需要該寬限期。
-
void start_poll_synchronize_rcu_full(struct rcu_gp_oldstate *rgosp)¶
獲取完整快照並啟動 RCU 寬限期
引數
struct rcu_gp_oldstate *rgosp來自
get_state_synchronize_rcu_full()或start_poll_synchronize_rcu_full()的值
描述
將正常和加速的寬限期狀態放置在 *rgos 中。可以將此狀態值傳遞給後續對 cond_synchronize_rcu_full() 或 poll_state_synchronize_rcu_full() 的呼叫,以確定在此期間是否經過寬限期(無論是正常還是加速)。如果所需的寬限期尚未計劃開始,則通知 RCU 核心需要該寬限期。
-
bool poll_state_synchronize_rcu(unsigned long oldstate)¶
指定的 RCU 寬限期是否已完成?
引數
unsigned long oldstate來自
get_state_synchronize_rcu()或start_poll_synchronize_rcu()的值
描述
如果自獲得 oldstate 的先前呼叫以來,已經過了完整的 RCU 寬限期,則返回 true,否則返回 false。如果返回 false,則呼叫者有責任稍後呼叫此函式,直到它返回 true。或者,呼叫者可以顯式等待寬限期,例如,透過將 oldstate 傳遞給 cond_synchronize_rcu() 或 cond_synchronize_rcu_expedited(),或者透過直接呼叫 synchronize_rcu() 或 synchronize_rcu_expedited()。
是的,此函式不考慮計數器迴繞。但是計數器迴繞是無害的。如果計數器迴繞,我們已經等待超過 10 億個寬限期(在 64 位系統上更多!)。那些需要將舊狀態值保持很長時間(即使在 32 位系統上也是幾個小時)的人員應該偶爾檢查它們,並重新整理它們或設定一個標誌,指示寬限期已完成。或者,他們可以使用 get_completed_synchronize_rcu() 來獲得保證完成的寬限期狀態。
此外,由於 oldstate 將正常和加速寬限期的寬限期狀態壓縮為單個 unsigned long,因此當 synchronize_rcu() 與 synchronize_rcu_expedited() 併發執行時,它可能會錯過寬限期。如果這是不可接受的,請改為使用這些輪詢 API 的 _full() 變體。
此函式提供與在提供 oldstate 的函式呼叫時呼叫並在該函式結束時返回的 synchronize_rcu() 提供的相同的記憶體排序保證。
-
bool poll_state_synchronize_rcu_full(struct rcu_gp_oldstate *rgosp)¶
指定的 RCU 寬限期是否已完成?
引數
struct rcu_gp_oldstate *rgosp來自
get_state_synchronize_rcu_full()或start_poll_synchronize_rcu_full()的值
描述
如果自獲得 rgosp 的先前呼叫以來,已經過了完整的 RCU 寬限期,則返回 **true*,否則返回 false。如果返回 false,則呼叫者有責任稍後呼叫此函式,直到它返回 true。或者,呼叫者可以顯式等待寬限期,例如,透過將 rgosp 傳遞給 cond_synchronize_rcu() 或透過直接呼叫 synchronize_rcu()。
是的,此函式不考慮計數器迴繞。但是計數器迴繞是無害的。如果計數器迴繞,我們已經等待超過 10 億個寬限期(在 64 位系統上更多!)。那些需要將 rcu_gp_oldstate 值保持很長時間(即使在 32 位系統上也是幾個小時)的人員應該偶爾檢查它們,並重新整理它們或設定一個標誌,指示寬限期已完成。或者,他們可以使用 get_completed_synchronize_rcu_full() 來獲得保證完成的寬限期狀態。
此函式提供與在提供 rgosp 的函式呼叫時呼叫並在該函式結束時返回的 synchronize_rcu() 提供的相同的記憶體排序保證。並且此保證要求檢查根 rcu_node 結構的 ->gp_seq 欄位,而不是 rcu_state 結構的欄位。問題在於,剛剛結束的寬限期的回撥可以在更新根 rcu_node 結構的 ->gp_seq 欄位的時間與更新 rcu_state 結構的 ->gp_seq 欄位的時間之間被呼叫。因此,如果要使單個 synchronize_rcu() 導致後續的 poll_state_synchronize_rcu_full() 返回 true,則需要輪詢根 rcu_node 結構。
-
void cond_synchronize_rcu(unsigned long oldstate)¶
有條件地等待 RCU 寬限期
引數
unsigned long oldstate來自
get_state_synchronize_rcu()、start_poll_synchronize_rcu()或start_poll_synchronize_rcu_expedited()的值
描述
如果自先前呼叫 get_state_synchronize_rcu() 或 start_poll_synchronize_rcu() 以來,已經過了完整的 RCU 寬限期,則直接返回。否則,呼叫 synchronize_rcu() 以等待完整的寬限期。
是的,此函式不考慮計數器迴繞。但是計數器迴繞是無害的。如果計數器迴繞,我們已經等待超過 20 億個寬限期(在 64 位系統上更多!),因此等待幾個額外的寬限期應該沒有問題。
此函式提供與在提供 oldstate 的函式呼叫時呼叫並在該函式結束時返回的 synchronize_rcu() 提供的相同的記憶體排序保證。
-
void cond_synchronize_rcu_full(struct rcu_gp_oldstate *rgosp)¶
有條件地等待 RCU 寬限期
引數
struct rcu_gp_oldstate *rgosp來自
get_state_synchronize_rcu_full()、start_poll_synchronize_rcu_full()或start_poll_synchronize_rcu_expedited_full()的值
描述
如果自呼叫 get_state_synchronize_rcu_full()、start_poll_synchronize_rcu_full() 或 start_poll_synchronize_rcu_expedited_full()(從中獲取了 rgosp)以來,已經過了一個完整的 RCU 寬限期,則直接返回。否則,呼叫 synchronize_rcu() 等待一個完整的寬限期。
是的,此函式不考慮計數器迴繞。但是計數器迴繞是無害的。如果計數器迴繞,我們已經等待超過 20 億個寬限期(在 64 位系統上更多!),因此等待幾個額外的寬限期應該沒有問題。
此函式提供的記憶體排序保證與呼叫提供 rgosp 的函式時呼叫,並在該函式結束時返回的 synchronize_rcu() 所提供的記憶體排序保證相同。
-
void rcu_barrier(void)¶
等待所有正在進行的
call_rcu()回撥完成。
引數
void無引數
描述
請注意,此原語不一定等待 RCU 寬限期完成。例如,如果系統中任何地方都沒有排隊的 RCU 回撥,則 rcu_barrier() 有權立即返回,無需等待任何事情,更不用說 RCU 寬限期了。
-
void rcu_barrier_throttled(void)¶
執行
rcu_barrier(),但限制為每秒一次
引數
void無引數
描述
這可以被認為是 rcu_barrier() 周圍的防護欄,允許不受限制的使用者空間使用,至少假設硬體的 try_cmpxchg() 是健壯的。使用此函式,系統範圍內每秒最多呼叫一次 rcu_barrier(),這意味著呼叫者可能會不必要地等待一到三秒。
這旨在供測試套件使用,以避免 OOM,透過在啟動下一個測試之前重新整理先前測試中的 RCU 回撥。有關更多資訊,請參見 rcutree.do_rcu_barrier 模組引數。
為什麼不簡單地使 rcu_barrier() 更具可伸縮性?這可能是最終的端點,但暫時讓我們保持簡單。請注意,模組引數基礎結構序列化對給定 .set() 函式的呼叫,但是如果可能同時呼叫 .set(),我們已經準備好了!
-
void synchronize_rcu_expedited(void)¶
暴力 RCU 寬限期
引數
void無引數
描述
等待 RCU 寬限期,但加快它。基本思想是 IPI 所有非空閒、非nohz 的線上 CPU。IPI 處理程式檢查 CPU 是否處於 RCU 臨界區,如果是,則設定一個標誌,該標誌導致最外層的 rcu_read_unlock() 報告 RCU-preempt 的靜止狀態,或要求排程程式為 RCU-sched 提供幫助。另一方面,如果 CPU 不在 RCU 讀取側臨界區中,則 IPI 處理程式會立即報告靜止狀態。
儘管與以前的加速實現相比,這是一個很大的改進,但它對即時工作負載仍然不友好,因此不建議用於任何型別的常見情況程式碼。實際上,如果您在迴圈中使用 synchronize_rcu_expedited(),請重構您的程式碼以批次更新,然後改用單個 synchronize_rcu()。
這具有與 synchronize_rcu() 相同的語義(但比它更殘酷)。
-
unsigned long start_poll_synchronize_rcu_expedited(void)¶
快照當前 RCU 狀態並啟動加速寬限期
引數
void無引數
描述
返回一個 cookie,傳遞給對 cond_synchronize_rcu()、cond_synchronize_rcu_expedited() 或 poll_state_synchronize_rcu() 的呼叫,允許它們確定是否在此期間已經過任何型別的寬限期。如果所需的加速寬限期尚未計劃啟動,則啟動該寬限期。
-
void start_poll_synchronize_rcu_expedited_full(struct rcu_gp_oldstate *rgosp)¶
獲取完整快照並啟動加速寬限期
引數
struct rcu_gp_oldstate *rgosp放置寬限期狀態快照的位置
描述
將正常和加速寬限期狀態放置在 rgosp 中。此狀態值可以傳遞給稍後對 cond_synchronize_rcu_full() 或 poll_state_synchronize_rcu_full() 的呼叫,以確定在此期間是否已經過寬限期(無論是正常寬限期還是加速寬限期)。如果所需的加速寬限期尚未計劃啟動,則啟動該寬限期。
-
void cond_synchronize_rcu_expedited(unsigned long oldstate)¶
有條件地等待加速的 RCU 寬限期
引數
unsigned long oldstate來自
get_state_synchronize_rcu()、start_poll_synchronize_rcu()或start_poll_synchronize_rcu_expedited()的值
描述
如果自先前呼叫 get_state_synchronize_rcu()、start_poll_synchronize_rcu() 或 start_poll_synchronize_rcu_expedited() 以來,已經過任何型別的完整 RCU 寬限期,則直接返回。否則,呼叫 synchronize_rcu_expedited() 等待一個完整的寬限期。
是的,此函式不考慮計數器迴繞。但是計數器迴繞是無害的。如果計數器迴繞,我們已經等待超過 20 億個寬限期(在 64 位系統上更多!),因此等待幾個額外的寬限期應該沒有問題。
此函式提供與在提供 oldstate 的函式呼叫時呼叫並在該函式結束時返回的 synchronize_rcu() 提供的相同的記憶體排序保證。
-
void cond_synchronize_rcu_expedited_full(struct rcu_gp_oldstate *rgosp)¶
有條件地等待加速的 RCU 寬限期
引數
struct rcu_gp_oldstate *rgosp來自
get_state_synchronize_rcu_full()、start_poll_synchronize_rcu_full()或start_poll_synchronize_rcu_expedited_full()的值
描述
如果自呼叫 get_state_synchronize_rcu_full()、start_poll_synchronize_rcu_full() 或 start_poll_synchronize_rcu_expedited_full()(從中獲取了 rgosp)以來,已經過了一個完整的 RCU 寬限期,則直接返回。否則,呼叫 synchronize_rcu_expedited() 等待一個完整的寬限期。
是的,此函式不考慮計數器迴繞。但是計數器迴繞是無害的。如果計數器迴繞,我們已經等待超過 20 億個寬限期(在 64 位系統上更多!),因此等待幾個額外的寬限期應該沒有問題。
此函式提供的記憶體排序保證與呼叫提供 rgosp 的函式時呼叫,並在該函式結束時返回的 synchronize_rcu() 所提供的記憶體排序保證相同。
-
bool rcu_read_lock_held_common(bool *ret)¶
我們是否可能位於 RCU-sched 讀取側臨界區?
引數
bool *ret如果無法依賴 lockdep,則提供最佳猜測答案
描述
如果必須忽略 lockdep,則返回 true,在這種情況下,*ret 包含下面描述的最佳猜測。否則返回 false,在這種情況下,*ret 不告訴呼叫者任何內容,呼叫者應改為查閱 lockdep。
如果選擇了 CONFIG_DEBUG_LOCK_ALLOC,則當且僅當在 RCU-sched 讀取側臨界區中時,才將 *ret 設定為非零值。在沒有 CONFIG_DEBUG_LOCK_ALLOC 的情況下,這假定我們位於 RCU-sched 讀取側臨界區中,除非可以證明情況並非如此。請注意,停用搶佔(包括停用 irq)算作 RCU-sched 讀取側臨界區。這對於需要從 RCU-sched 讀取側臨界區中呼叫的函式中的除錯檢查很有用。
檢查 debug_lockdep_rcu_enabled() 以防止在啟動期間和停用 lockdep 時出現誤報。
請注意,如果 CPU 從 RCU 的角度來看處於空閒迴圈中(即:我們位於 ct_idle_enter() 和 ct_idle_exit() 之間的部分中),則即使 CPU 執行了 rcu_read_lock(),rcu_read_lock_held() 也會將 *ret 設定為 false。這樣做的原因是 RCU 忽略處於此類部分的 CPU,將其視為處於擴充套件靜止狀態,因此無論 RCU 呼叫哪些原語,此類 CPU 實際上永遠不會處於 RCU 讀取側臨界區中。這種情況是必需的 --- 我們需要在空閒狀態下保持一個無 RCU 的視窗,CPU 可能會進入低功耗模式。這樣,我們可以注意到啟動寬限期的其他 CPU 的擴充套件靜止狀態。否則,只要我們在空閒任務中執行,就會延遲任何寬限期。
類似地,如果當前 CPU 處於離線狀態,我們將避免宣告持有 RCU 讀取鎖。
-
void rcu_async_hurry(void)¶
使未來的非同步 RCU 回撥不會延遲。
-
void rcu_async_relax(void)¶
使未來的非同步 RCU 回撥延遲。
-
void rcu_expedite_gp(void)¶
加速未來的 RCU 寬限期
-
void rcu_unexpedite_gp(void)¶
取消先前的
rcu_expedite_gp()呼叫
引數
void無引數
描述
撤消先前對 rcu_expedite_gp() 的呼叫。如果通過後續呼叫 rcu_unexpedite_gp() 撤消了所有先前對 rcu_expedite_gp() 的呼叫,並且未設定 rcu_expedited sysfs/boot 引數,則對 synchronize_rcu() 及其相關函式的所有後續呼叫將恢復為正常的非加速行為。
-
int rcu_read_lock_held(void)¶
我們是否可能位於 RCU 讀取側臨界區?
引數
void無引數
描述
如果選擇了 CONFIG_DEBUG_LOCK_ALLOC,則當且僅當在 RCU 讀取側臨界區中時,才返回非零值。在沒有 CONFIG_DEBUG_LOCK_ALLOC 的情況下,這假定我們位於 RCU 讀取側臨界區中,除非可以證明情況並非如此。這對於需要從 RCU 讀取側臨界區中呼叫的函式中的除錯檢查很有用。
檢查 debug_lockdep_rcu_enabled() 以防止在啟動期間和停用 lockdep 時出現誤報。
請注意,rcu_read_lock() 和匹配的 rcu_read_unlock() 必須發生在同一上下文中,例如,如果在 irq 處理程式中呼叫了匹配的 rcu_read_lock(),則在程序上下文中呼叫 rcu_read_unlock() 是非法的。
請注意,如果 CPU 從 RCU 的角度來看是空閒的或離線的,則不允許使用 rcu_read_lock(),因此也要檢查這些情況。
-
int rcu_read_lock_bh_held(void)¶
我們是否可能位於 RCU-bh 讀取側臨界區?
引數
void無引數
描述
檢查是否停用了 bottom half,這涵蓋了 CONFIG_PROVE_RCU 和非 CONFIG_PROVE_RCU 的情況。請注意,如果有人使用 rcu_read_lock_bh(),但稍後啟用了 BH,則 lockdep(如果啟用)將顯示該情況。這對於需要從 RCU 讀取側臨界區中呼叫的函式中的除錯檢查很有用。
檢查 debug_lockdep_rcu_enabled() 以防止在啟動期間出現誤報。
請注意,如果 CPU 從 RCU 的角度來看是空閒的或離線的,則不允許使用 rcu_read_lock_bh(),因此也要檢查這些情況。
-
void wakeme_after_rcu(struct rcu_head *head)¶
寬限期後喚醒任務的回撥函式
引數
struct rcu_head *head指向 rcu_synchronize 結構中的 rcu_head 成員的指標
描述
現在寬限期已過,喚醒相應的任務。
-
void init_rcu_head_on_stack(struct rcu_head *head)¶
初始化用於 debugobjects 的堆疊上的 rcu_head
引數
struct rcu_head *head指向要初始化的 rcu_head 結構的指標
描述
此函式通知 debugobjects 已分配一個新的 rcu_head 結構作為堆疊上的自動變數。對於靜態定義或在堆上動態分配的 rcu_head 結構,不需要此函式。對於 !CONFIG_DEBUG_OBJECTS_RCU_HEAD 核心構建,此函式無效。
-
void destroy_rcu_head_on_stack(struct rcu_head *head)¶
銷燬用於 debugobjects 的堆疊上的 rcu_head
引數
struct rcu_head *head指向要初始化的 rcu_head 結構的指標
描述
此函式通知 debugobjects 堆疊上的 rcu_head 結構即將超出範圍。與 init_rcu_head_on_stack() 一樣,對於靜態定義或在堆上動態分配的 rcu_head 結構,不需要此函式。此外,與 init_rcu_head_on_stack() 一樣,對於 !CONFIG_DEBUG_OBJECTS_RCU_HEAD 核心構建,此函式無效。
-
unsigned long get_completed_synchronize_rcu(void)¶
返回預完成的輪詢狀態 cookie
-
unsigned long get_completed_synchronize_srcu(void)¶
返回預完成的輪詢狀態 cookie
-
bool same_state_synchronize_srcu(unsigned long oldstate1, unsigned long oldstate2)¶
兩個舊狀態值是否相同?
引數
unsigned long oldstate1第一個舊狀態值。
unsigned long oldstate2第二個舊狀態值。
描述
這兩個舊狀態值必須從 get_state_synchronize_srcu()、start_poll_synchronize_srcu() 或 get_completed_synchronize_srcu() 中獲得。如果兩個值相同,則返回 true,否則返回 false。這允許其生命週期由舊狀態值跟蹤的結構將這些值推送到列表頭,從而使這些結構稍微小一些。
-
int srcu_read_lock_held(const struct srcu_struct *ssp)¶
我們可能在 SRCU 讀取端臨界區嗎?
引數
const struct srcu_struct *ssp要檢查的 srcu_struct 結構
描述
如果選擇了 CONFIG_DEBUG_LOCK_ALLOC,則當且僅當在 SRCU 讀取端臨界區中時才返回非零值。在沒有 CONFIG_DEBUG_LOCK_ALLOC 的情況下,這假定我們在 SRCU 讀取端臨界區中,除非它可以證明相反的情況。
檢查 debug_lockdep_rcu_enabled() 以防止在啟動期間和停用 lockdep 時出現誤報。
請注意,SRCU 基於其自己的狀態機,並且不依賴於普通的 RCU,它可以從 CPU 呼叫,該 CPU 從 RCU 的角度來看處於空閒迴圈或離線狀態。
-
srcu_dereference_check¶
srcu_dereference_check (p, ssp, c)
獲取 SRCU 保護的指標以供以後解引用
引數
p要獲取並保護以供以後解引用的指標
ssp指向 srcu_struct 的指標,用於檢查我們是否真的在 SRCU 讀取端臨界區中。
c要檢查的更新端使用的條件
描述
如果啟用了 PROVE_RCU,則在 RCU 讀取端臨界區之外呼叫此函式將導致 RCU 鎖依賴錯誤,除非 c 的計算結果為 1。 c 引數通常是一個包含 lockdep_is_held() 呼叫的邏輯表示式。
-
srcu_dereference¶
srcu_dereference (p, ssp)
獲取 SRCU 保護的指標以供以後解引用
引數
p要獲取並保護以供以後解引用的指標
ssp指向 srcu_struct 的指標,用於檢查我們是否真的在 SRCU 讀取端臨界區中。
描述
使 rcu_dereference_check() 完成繁重的工作。如果啟用了 PROVE_RCU,則在 RCU 讀取端臨界區之外呼叫此函式將導致 RCU 鎖依賴錯誤。
-
srcu_dereference_notrace¶
srcu_dereference_notrace (p, ssp)
此處沒有跟蹤,也沒有鎖依賴呼叫
引數
p要獲取並保護以供以後解引用的指標
ssp指向 srcu_struct 的指標,用於檢查我們是否真的在 SRCU 讀取端臨界區中。
-
int srcu_read_lock(struct srcu_struct *ssp)¶
為受 SRCU 保護的結構註冊一個新的讀取器。
引數
struct srcu_struct *ssp要在其中註冊新讀取器的 srcu_struct。
描述
進入 SRCU 讀取端臨界區。請注意,SRCU 讀取端臨界區可以巢狀。但是,呼叫任何等待同一 srcu_struct 的 SRCU 寬限期的操作(無論是直接還是間接)都是非法的。請注意,間接等待 SRCU 寬限期的一種方法是在呼叫 synchronize_srcu() 或 synchronize_srcu_expedited() 時,獲取其他地方持有的互斥鎖。
srcu_read_lock() 的返回值保證為非負數。此值必須原封不動地傳遞給匹配的 srcu_read_unlock()。請注意,srcu_read_lock() 和匹配的 srcu_read_unlock() 必須在同一上下文中發生,例如,如果在程序上下文中呼叫了匹配的 srcu_read_lock(),則在 irq 處理程式中呼叫 srcu_read_unlock() 是非法的。或者,從一個任務呼叫 srcu_read_unlock(),從另一個任務呼叫匹配的 srcu_read_lock() 也是非法的。
-
struct srcu_ctr __percpu *srcu_read_lock_fast(struct srcu_struct *ssp)¶
為受 SRCU 保護的結構註冊一個新的讀取器。
引數
struct srcu_struct *ssp要在其中註冊新讀取器的 srcu_struct。
描述
進入 SRCU 讀取端臨界區,但適用於輕量級的無 smp_mb() 讀取器。有關更多資訊,請參見 srcu_read_lock()。
如果在 srcu_struct 結構上使用了 srcu_read_lock_fast(),則無論之前、期間還是之後,都不能使用其他任何風格。請注意,對於 _fast srcu_struct 結構,寬限期自動加速已停用,因為自動加速的寬限期會呼叫 synchronize_rcu_expedited()、IPI 以及所有內容。
請注意,只能從 RCU 正在監視的上下文中呼叫 srcu_read_lock_fast(),也就是說,從呼叫 rcu_read_lock() 合法的上下文中。否則,lockdep 將會報錯。
-
struct srcu_ctr __percpu *srcu_down_read_fast(struct srcu_struct *ssp)¶
為受 SRCU 保護的結構註冊一個新的讀取器。
引數
struct srcu_struct *ssp要在其中註冊新讀取器的 srcu_struct。
描述
進入類似訊號量的 SRCU 讀取端臨界區,但適用於輕量級的無 smp_mb() 讀取器。有關更多資訊,請參見 srcu_read_lock_fast() 和 srcu_down_read()。
srcu_down_read_fast() 和 srcu_read_lock_fast() 可以併發使用相同的 srcu_struct。
-
int srcu_read_lock_lite(struct srcu_struct *ssp)¶
為受 SRCU 保護的結構註冊一個新的讀取器。
引數
struct srcu_struct *ssp要在其中註冊新讀取器的 srcu_struct。
描述
進入 SRCU 讀取端臨界區,但適用於輕量級的無 smp_mb() 讀取器。有關更多資訊,請參見 srcu_read_lock()。
如果在 srcu_struct 結構上使用了 srcu_read_lock_lite(),則無論之前、期間還是之後,都不能使用其他任何風格。請注意,對於 _lite srcu_struct 結構,寬限期自動加速已停用,因為自動加速的寬限期會呼叫 synchronize_rcu_expedited()、IPI 以及所有內容。
請注意,只能從 RCU 正在監視的上下文中呼叫 srcu_read_lock_lite(),也就是說,從呼叫 rcu_read_lock() 合法的上下文中。否則,lockdep 將會報錯。
-
int srcu_read_lock_nmisafe(struct srcu_struct *ssp)¶
為受 SRCU 保護的結構註冊一個新的讀取器。
引數
struct srcu_struct *ssp要在其中註冊新讀取器的 srcu_struct。
描述
進入 SRCU 讀取端臨界區,但以 NMI 安全的方式進行。有關更多資訊,請參見 srcu_read_lock()。
如果在 srcu_struct 結構上使用了 srcu_read_lock_nmisafe(),則無論之前、期間還是之後,都不能使用其他任何風格。
-
int srcu_down_read(struct srcu_struct *ssp)¶
為受 SRCU 保護的結構註冊一個新的讀取器。
引數
struct srcu_struct *ssp要在其中註冊新讀取器的 srcu_struct。
描述
進入類似訊號量的 SRCU 讀取端臨界區。請注意,SRCU 讀取端臨界區可以巢狀。但是,呼叫任何等待同一 srcu_struct 的 SRCU 寬限期的操作(無論是直接還是間接)都是非法的。請注意,間接等待 SRCU 寬限期的一種方法是在呼叫 synchronize_srcu() 或 synchronize_srcu_expedited() 時,獲取其他地方持有的互斥鎖。但是,如果您希望 lockdep 幫助您理清這些內容,則應改用 srcu_read_lock()。
srcu_down_read() 的類似訊號量的性質意味著可以從其他一些上下文(例如,從其他一些任務或從 irq 處理程式)呼叫匹配的 srcu_up_read()。但是,既不能從 NMI 處理程式呼叫 srcu_down_read(),也不能從 NMI 處理程式呼叫 srcu_up_read()。
對 srcu_down_read() 的呼叫可以巢狀,類似於對 down_read() 的呼叫可以巢狀的方式。srcu_down_read() 和 srcu_read_lock() 可以併發使用相同的 srcu_struct。
-
void srcu_read_unlock(struct srcu_struct *ssp, int idx)¶
從受 SRCU 保護的結構中登出舊的讀取器。
引數
struct srcu_struct *ssp要在其中登出舊的讀取器的 srcu_struct。
int idx來自相應
srcu_read_lock()的返回值。
描述
退出 SRCU 讀取端臨界區。
-
void srcu_read_unlock_fast(struct srcu_struct *ssp, struct srcu_ctr __percpu *scp)¶
從受 SRCU 保護的結構中登出舊的讀取器。
引數
struct srcu_struct *ssp要在其中登出舊的讀取器的 srcu_struct。
struct srcu_ctr __percpu *scp來自相應
srcu_read_lock_fast()的返回值。
描述
退出輕量級 SRCU 讀取端臨界區。
-
void srcu_up_read_fast(struct srcu_struct *ssp, struct srcu_ctr __percpu *scp)¶
從受 SRCU 保護的結構中登出舊的讀取器。
引數
struct srcu_struct *ssp要在其中登出舊的讀取器的 srcu_struct。
struct srcu_ctr __percpu *scp來自相應
srcu_read_lock_fast()的返回值。
描述
退出 SRCU 讀取端臨界區,但不一定與匹配的 srcu_down_read_fast() 位於同一上下文中。
-
void srcu_read_unlock_lite(struct srcu_struct *ssp, int idx)¶
從受 SRCU 保護的結構中登出舊的讀取器。
引數
struct srcu_struct *ssp要在其中登出舊的讀取器的 srcu_struct。
int idx來自相應
srcu_read_lock_lite()的返回值。
描述
退出輕量級 SRCU 讀取端臨界區。
-
void srcu_read_unlock_nmisafe(struct srcu_struct *ssp, int idx)¶
從受 SRCU 保護的結構中登出舊的讀取器。
引數
struct srcu_struct *ssp要在其中登出舊的讀取器的 srcu_struct。
int idx來自相應
srcu_read_lock_nmisafe()的返回值。
描述
退出 SRCU 讀取端臨界區,但以 NMI 安全的方式進行。
-
void srcu_up_read(struct srcu_struct *ssp, int idx)¶
從受 SRCU 保護的結構中登出舊的讀取器。
引數
struct srcu_struct *ssp要在其中登出舊的讀取器的 srcu_struct。
int idx來自相應
srcu_read_lock()的返回值。
描述
退出 SRCU 讀取側臨界區,但不一定與匹配的 srcu_down_read() 在同一上下文中。
-
void smp_mb__after_srcu_read_unlock(void)¶
確保在 srcu_read_unlock 之後完全排序
引數
void無引數
描述
將前面的 srcu_read_unlock 轉換為雙向記憶體屏障。
在 srcu_read_unlock 之後呼叫此函式,以保證在 smp_mb__after_srcu_read_unlock 之後發生的所有記憶體操作都將在前面的 srcu_read_unlock 之後發生。
-
void smp_mb__after_srcu_read_lock(void)¶
確保在 srcu_read_lock 之後完全排序
引數
void無引數
描述
將前面的 srcu_read_lock 轉換為雙向記憶體屏障。
在 srcu_read_lock 之後呼叫此函式,以保證在 smp_mb__after_srcu_read_lock 之後發生的所有記憶體操作都將在前面的 srcu_read_lock 之後發生。
-
int init_srcu_struct(struct srcu_struct *ssp)¶
初始化一個睡眠-RCU 結構
引數
struct srcu_struct *ssp要初始化的結構。
描述
必須在將給定的 srcu_struct 傳遞給任何其他函式之前,在該 srcu_struct 上呼叫此函式。每個 srcu_struct 代表一個單獨的 SRCU 保護域。
-
bool srcu_readers_active(struct srcu_struct *ssp)¶
如果存在讀取者,則返回 true。否則返回 false
引數
struct srcu_struct *ssp要計算活動讀取者(持有 srcu_read_lock)的 srcu_struct。
描述
請注意,這不是一個原子原語,因此在活動 srcu_struct 上呼叫時可能會出現嚴重錯誤。也就是說,它可以在清理時用作錯誤檢查。
-
void cleanup_srcu_struct(struct srcu_struct *ssp)¶
解構一個睡眠-RCU 結構
引數
struct srcu_struct *ssp要清理的結構。
描述
在使用透過 init_srcu_struct() 初始化的給定 srcu_struct 後,必須呼叫此函式,否則會洩漏記憶體。
-
void call_srcu(struct srcu_struct *ssp, struct rcu_head *rhp, rcu_callback_t func)¶
在 SRCU 寬限期後排隊一個回撥以進行呼叫
引數
struct srcu_struct *ssp將回調排隊的 srcu_struct
struct rcu_head *rhp用於排隊 SRCU 回撥的結構。
rcu_callback_t func在 SRCU 寬限期結束後要呼叫的函式
描述
回撥函式將在完整的 SRCU 寬限期結束後的一段時間內呼叫,換句話說,在所有預先存在的 SRCU 讀取側臨界區完成後。但是,回撥函式很可能與在呼叫 call_srcu() 之後啟動的其他 SRCU 讀取側臨界區同時執行。SRCU 讀取側臨界區由 srcu_read_lock() 和 srcu_read_unlock() 分隔,並且可能是巢狀的。
回撥將從程序上下文中呼叫,但停用了 bh。因此,回撥函式必須快速且不得阻塞。
有關記憶體排序保證的更多詳細資訊,請參見 call_rcu() 的描述。
-
void synchronize_srcu_expedited(struct srcu_struct *ssp)¶
強制 SRCU 寬限期
引數
struct srcu_struct *ssp要同步的 srcu_struct。
描述
等待 SRCU 寬限期過去,但在等待時更積極地進行旋轉,而不是阻塞。
請注意,synchronize_srcu_expedited() 具有與 synchronize_srcu() 相同的死鎖和記憶體排序屬性。
-
void synchronize_srcu(struct srcu_struct *ssp)¶
等待先前的 SRCU 讀取側臨界區完成
引數
struct srcu_struct *ssp要同步的 srcu_struct。
描述
等待兩個索引的計數都降至零。為了避免 synchronize_srcu() 可能發生的飢餓,它首先等待 index=!(ssp->srcu_ctrp - ssp->sda->srcu_ctrs[0]) 的計數降至零,然後翻轉 ->srcu_ctrp 並等待另一個索引的計數。
可以阻塞;必須從程序上下文中呼叫。
請注意,從相應的 SRCU 讀取側臨界區呼叫 synchronize_srcu() 是非法的;這樣做會導致死鎖。但是,從某個其他 srcu_struct 的讀取側臨界區呼叫一個 srcu_struct 上的 synchronize_srcu() 是完全合法的,只要生成的 srcu_struct 圖是無環的。
synchronize_srcu() 隱含了記憶體排序約束。在具有多個 CPU 的系統上,當 synchronize_srcu() 返回時,保證每個 CPU 都執行了一個完整的記憶體屏障,該記憶體屏障自從其最後一個相應的 SRCU 讀取側臨界區結束以來,該臨界區的開始先於對 synchronize_srcu() 的呼叫。此外,具有 SRCU 讀取側臨界區的每個 CPU,該臨界區超出 synchronize_srcu() 的返回,都保證在 synchronize_srcu() 開始之後和該 SRCU 讀取側臨界區開始之前執行了一個完整的記憶體屏障。請注意,這些保證包括離線、空閒或以使用者模式執行的 CPU,以及在核心中執行的 CPU。
此外,如果 CPU A 呼叫了 synchronize_srcu(),該函式返回給 CPU B 上的呼叫者,則保證 CPU A 和 CPU B 都在 synchronize_srcu() 的執行過程中執行了一個完整的記憶體屏障。即使 CPU A 和 CPU B 是同一個 CPU,此保證也適用,但同樣僅當系統具有多個 CPU 時才適用。
當然,這些記憶體排序保證僅在將相同的 srcu_struct 結構傳遞給 synchronize_srcu()、srcu_read_lock() 和 srcu_read_unlock() 時才適用。
這些記憶體排序保證的實現與 synchronize_rcu() 的實現類似。
如果 SRCU 可能處於空閒狀態(由 srcu_should_expedite() 確定),則加速第一個請求。此語義由 Classic SRCU 提供,並被其使用者所依賴,因此 TREE SRCU 也必須提供此語義。請注意,檢測空閒狀態是啟發式的,並且容易出現誤報和漏報。
-
unsigned long get_state_synchronize_srcu(struct srcu_struct *ssp)¶
提供一個寬限期結束 Cookie
引數
struct srcu_struct *ssp要提供 Cookie 的 srcu_struct。
描述
此函式返回一個 Cookie,可以將其傳遞給 poll_state_synchronize_srcu(),如果在此期間經過了完整的寬限期,則該函式將返回 true。呼叫者有責任確保發生寬限期,例如,透過在從 get_state_synchronize_srcu() 返回後呼叫 call_srcu() 來確保。
-
unsigned long start_poll_synchronize_srcu(struct srcu_struct *ssp)¶
提供 Cookie 並啟動寬限期
引數
struct srcu_struct *ssp要提供 Cookie 的 srcu_struct。
描述
此函式返回一個 Cookie,可以將其傳遞給 poll_state_synchronize_srcu(),如果在此期間經過了完整的寬限期,則該函式將返回 true。與 get_state_synchronize_srcu() 不同,此函式還確保啟動任何需要的 SRCU 寬限期。這種便利性確實會帶來 CPU 開銷方面的成本。
-
bool poll_state_synchronize_srcu(struct srcu_struct *ssp, unsigned long cookie)¶
Cookie 的寬限期是否已結束?
引數
struct srcu_struct *ssp要提供 Cookie 的 srcu_struct。
unsigned long cookie從
get_state_synchronize_srcu()或start_poll_synchronize_srcu()返回的值。
描述
此函式獲取從 get_state_synchronize_srcu() 或 start_poll_synchronize_srcu() 返回的 Cookie,如果自建立 Cookie 以來已經過 SRCU 寬限期,則返回 true。
由於 Cookie 的大小有限,因此可能會發生包裝/溢位。在 32 位系統上,這種現象更為明顯,因為 Cookie 是 32 位的,理論上,假設 25 微秒的加速 SRCU 寬限期,大約 14 小時內可能會發生包裝。但是,在 1 毫秒 SRCU 寬限期的情況下,更可能的溢位下限約為 24 天。當然,在 64 位系統中,包裝需要地質時間跨度,即使對於加速的 SRCU 寬限期,也超過 700 萬年。
對於 CONFIG_SMP=n 系統(也具有 CONFIG_PREEMPTION=n)而言,包裝/溢位問題更為嚴重,該系統選擇 Tiny SRCU。這使用一個 16 位的 Cookie,rcutorture 通常在幾分鐘內包裝該 Cookie。如果這證明是一個問題,則此計數器將擴充套件到與 Tree SRCU 相同的大小。
-
void srcu_barrier(struct srcu_struct *ssp)¶
等待所有正在進行的
call_srcu()回撥完成。
引數
struct srcu_struct *ssp在其上等待正在進行的回撥的 srcu_struct。
-
unsigned long srcu_batches_completed(struct srcu_struct *ssp)¶
返回已完成的批次。
引數
struct srcu_struct *ssp在其上報告批次完成情況的 srcu_struct。
描述
報告與已經過的寬限期數量相關聯,但不一定完全相同的批次數量。
-
void hlist_bl_del_rcu(struct hlist_bl_node *n)¶
從雜湊列表中刪除條目,而無需重新初始化
引數
struct hlist_bl_node *n要從雜湊列表中刪除的元素。
注意
在此之後,hlist_bl_unhashed() 在條目上不返回 true,該條目處於未定義狀態。它對於基於 RCU 的無鎖遍歷很有用。
描述
特別是,這意味著我們無法破壞可能仍用於遍歷雜湊列表的前向指標。
呼叫者必須採取任何必要的預防措施(例如持有適當的鎖),以避免與在同一列表上執行的另一個列表變異原語(例如 hlist_bl_add_head_rcu() 或 hlist_bl_del_rcu())競爭。但是,與 _rcu 列表遍歷原語(例如 hlist_bl_for_each_entry())併發執行是完全合法的。
-
void hlist_bl_add_head_rcu(struct hlist_bl_node *n, struct hlist_bl_head *h)¶
引數
struct hlist_bl_node *n要新增到雜湊列表的元素。
struct hlist_bl_head *h要新增到的列表。
描述
將指定的元素新增到指定的 hlist_bl,同時允許競爭遍歷。
呼叫者必須採取任何必要的預防措施(例如持有適當的鎖),以避免與在同一列表上執行的另一個列表變異原語(例如 hlist_bl_add_head_rcu() 或 hlist_bl_del_rcu())競爭。但是,與 _rcu 列表遍歷原語(例如 hlist_bl_for_each_entry_rcu())併發執行是完全合法的,該原語用於防止 Alpha CPU 上的記憶體一致性問題。無論 CPU 的型別如何,列表遍歷原語都必須由 rcu_read_lock() 保護。
-
hlist_bl_for_each_entry_rcu¶
hlist_bl_for_each_entry_rcu (tpos, pos, head, member)
迭代給定型別的 rcu 列表
引數
tpos用作循環遊標的 型別 *。
pos用作循環遊標的
struct hlist_bl_node。head連結串列的頭部。
member結構中的 hlist_bl_node 的名稱。
-
list_tail_rcu¶
list_tail_rcu (head)
返回列表頭的 prev 指標
-
void list_add_rcu(struct list_head *new, struct list_head *head)¶
新增一個新條目到 rcu 保護的連結串列
引數
struct list_head *new要新增的新條目
struct list_head *head在其後新增的列表頭
描述
在指定的頭部之後插入一個新條目。 這對於實現堆疊很有用。
呼叫者必須採取必要的預防措施(例如持有適當的鎖),以避免與同一連結串列上執行的其他連結串列修改原語(例如 list_add_rcu() 或 list_del_rcu())發生競爭。但是,與 _rcu 連結串列遍歷原語(例如 list_for_each_entry_rcu())併發執行是完全合法的。
-
void list_add_tail_rcu(struct list_head *new, struct list_head *head)¶
新增一個新條目到 rcu 保護的連結串列
引數
struct list_head *new要新增的新條目
struct list_head *head在其前新增的列表頭
描述
在指定的頭部之前插入一個新條目。 這對於實現佇列很有用。
呼叫者必須採取必要的預防措施(例如持有適當的鎖),以避免與同一連結串列上執行的其他連結串列修改原語(例如 list_add_tail_rcu() 或 list_del_rcu())發生競爭。但是,與 _rcu 連結串列遍歷原語(例如 list_for_each_entry_rcu())併發執行是完全合法的。
-
void list_del_rcu(struct list_head *entry)¶
從連結串列中刪除條目,無需重新初始化
引數
struct list_head *entry要從列表中刪除的元素。
注意
在此之後,entry 上的 list_empty() 不會返回 true,該條目處於未定義狀態。 它對於基於 RCU 的無鎖遍歷很有用。
描述
特別是,這意味著我們不能汙染可能仍用於遍歷列表的前向指標。
呼叫者必須採取必要的預防措施(例如持有適當的鎖),以避免與同一連結串列上執行的其他連結串列修改原語(例如 list_del_rcu() 或 list_add_rcu())發生競爭。但是,與 _rcu 連結串列遍歷原語(例如 list_for_each_entry_rcu())併發執行是完全合法的。
請注意,不允許呼叫者立即釋放新刪除的條目。相反,必須使用 synchronize_rcu() 或 call_rcu() 來延遲釋放,直到 RCU 寬限期過去。
-
void list_bidir_del_rcu(struct list_head *entry)¶
從連結串列中刪除條目,無需重新初始化
引數
struct list_head *entry要從列表中刪除的元素。
描述
與 list_del_rcu() 相比,不會汙染 prev 指標,因此允許透過 list_bidir_prev_rcu() 進行向後遍歷。
呼叫者必須採取必要的預防措施(例如持有適當的鎖),以避免與同一連結串列上執行的其他連結串列修改原語(例如 list_bidir_del_rcu() 或 list_add_rcu())發生競爭。但是,與 _rcu 連結串列遍歷原語(例如 list_for_each_entry_rcu())併發執行是完全合法的。
請注意,list_del_rcu() 和 list_bidir_del_rcu() 不得在同一連結串列上使用。
請注意,不允許呼叫者立即釋放新刪除的條目。相反,必須使用 synchronize_rcu() 或 call_rcu() 來延遲釋放,直到 RCU 寬限期過去。
注意
在此之後,entry 上的 list_empty() 不會返回 true,因為該條目處於特殊的未定義狀態,該狀態允許基於 RCU 的無鎖反向遍歷。特別是,這意味著我們不能汙染可能仍用於遍歷列表的前向和後向指標。
-
void hlist_del_init_rcu(struct hlist_node *n)¶
從雜湊連結串列中刪除條目,並重新初始化
引數
struct hlist_node *n要從雜湊列表中刪除的元素。
注意
在此之後,節點上的 list_unhashed() 返回 true。如果寫入者需要知道連結串列條目是否仍然被雜湊或已經被取消雜湊,則這對於基於 RCU 的無鎖讀取遍歷很有用。
描述
特別是,這意味著我們不能汙染可能仍用於遍歷雜湊連結串列的前向指標,並且我們只能將 pprev 指標置零,以便在此之後 list_unhashed() 返回 true。
呼叫者必須採取必要的預防措施(例如持有適當的鎖),以避免與同一連結串列上執行的其他連結串列修改原語(例如 hlist_add_head_rcu() 或 hlist_del_rcu())發生競爭。但是,與 _rcu 連結串列遍歷原語(例如 hlist_for_each_entry_rcu())併發執行是完全合法的。
-
void list_replace_rcu(struct list_head *old, struct list_head *new)¶
用新條目替換舊條目
引數
struct list_head *old要替換的元素
struct list_head *new要插入的新元素
描述
從併發讀取者的角度來看,**old** 條目將被 **new** 條目原子地替換。如果有任何併發更新程式,則由呼叫者負責與它們同步。
注意
**old** 不應為空。
-
void __list_splice_init_rcu(struct list_head *list, struct list_head *prev, struct list_head *next, void (*sync)(void))¶
將受 RCU 保護的列表連線到現有列表中。
引數
struct list_head *list要拼接的受 RCU 保護的列表
struct list_head *prev指向現有列表的最後一個元素
struct list_head *next指向現有列表的第一個元素
void (*sync)(void)synchronize_rcu, synchronize_rcu_expedited, ...
描述
由 **prev** 和 **next** 指向的列表可以與此函式併發地進行 RCU 讀取遍歷。
請注意,此函式會阻塞。
重要提示:呼叫者必須採取必要的措施來防止對現有列表進行任何其他更新。原則上,一旦 sync() 開始執行,就可以修改列表。如果必須這樣做,則可以建立基於 call_rcu() 的替代版本。但只有在 - 真正 - 需要時 -- RCU API 成員並不短缺。
-
void list_splice_init_rcu(struct list_head *list, struct list_head *head, void (*sync)(void))¶
將受 RCU 保護的列表拼接到一個現有列表中,專為堆疊設計。
引數
struct list_head *list要拼接的受 RCU 保護的列表
struct list_head *head現有列表中要將第一個列表拼接到的位置
void (*sync)(void)synchronize_rcu, synchronize_rcu_expedited, ...
-
void list_splice_tail_init_rcu(struct list_head *list, struct list_head *head, void (*sync)(void))¶
將受 RCU 保護的列表拼接到一個現有列表中,專為佇列設計。
引數
struct list_head *list要拼接的受 RCU 保護的列表
struct list_head *head現有列表中要將第一個列表拼接到的位置
void (*sync)(void)synchronize_rcu, synchronize_rcu_expedited, ...
-
list_entry_rcu¶
list_entry_rcu (ptr, type, member)
獲取此條目的結構體
引數
ptrstruct list_head指標。type嵌入此結構的結構體型別。
member結構體中 list_head 的名稱。
描述
只要由 rcu_read_lock() 保護,此原語就可以與 _rcu 連結串列修改原語(例如 list_add_rcu())安全地併發執行。
-
list_first_or_null_rcu¶
list_first_or_null_rcu (ptr, type, member)
從連結串列中獲取第一個元素
引數
ptr從中獲取元素的連結串列頭。
type嵌入此結構的結構體型別。
member結構體中 list_head 的名稱。
描述
請注意,如果連結串列為空,則返回 NULL。
只要由 rcu_read_lock() 保護,此原語就可以與 _rcu 連結串列修改原語(例如 list_add_rcu())安全地併發執行。
-
list_next_or_null_rcu¶
list_next_or_null_rcu (head, ptr, type, member)
從列表中獲取下一個元素
引數
head列表的頭部。
ptr從中獲取下一個元素的連結串列頭部。
type嵌入此結構的結構體型別。
member結構體中 list_head 的名稱。
描述
請注意,如果 ptr 位於列表末尾,則返回 NULL。
只要由 rcu_read_lock() 保護,此原語就可以與 _rcu 連結串列修改原語(例如 list_add_rcu())安全地併發執行。
-
list_for_each_entry_rcu¶
list_for_each_entry_rcu (pos, head, member, cond...)
迭代給定型別的 rcu 列表
引數
pos用作循環遊標的 型別 *。
head連結串列的頭部。
member結構體中 list_head 的名稱。
cond...如果從非 RCU 保護呼叫,則為可選的 lockdep 表示式。
描述
只要由 rcu_read_lock() 保護,此連結串列遍歷原語就可以與 _rcu 連結串列修改原語(例如 list_add_rcu())安全地併發執行。
-
list_for_each_entry_srcu¶
list_for_each_entry_srcu (pos, head, member, cond)
迭代給定型別的 rcu 列表
引數
pos用作循環遊標的 型別 *。
head連結串列的頭部。
member結構體中 list_head 的名稱。
cond遍歷列表所需的鎖的 lockdep 表示式。
描述
只要由 srcu_read_lock() 保護,此連結串列遍歷原語就可以與 _rcu 連結串列修改原語(例如 list_add_rcu())安全地併發執行。從讀取端可以將 lockdep 表示式 srcu_read_lock_held() 作為 cond 引數傳遞。
-
list_entry_lockless¶
list_entry_lockless (ptr, type, member)
獲取此條目的結構體
引數
ptrstruct list_head指標。type嵌入此結構的結構體型別。
member結構體中 list_head 的名稱。
描述
此原語可以與 _rcu 連結串列修改原語(例如 list_add_rcu())安全地併發執行,但需要一些隱式 RCU 讀取端保護。一個例子是在一個特殊的異常時間環境中執行,在該環境中停用了搶佔並且無法呼叫 lockdep。另一個例子是當將專案新增到列表中,但從未刪除時。
-
list_for_each_entry_lockless¶
list_for_each_entry_lockless (pos, head, member)
迭代給定型別的 rcu 列表
引數
pos用作循環遊標的 型別 *。
head連結串列的頭部。
member結構體中 list_struct 的名稱。
描述
此原語可以與 _rcu 連結串列修改原語(例如 list_add_rcu())安全地併發執行,但需要一些隱式 RCU 讀取端保護。一個例子是在一個特殊的異常時間環境中執行,在該環境中停用了搶佔並且無法呼叫 lockdep。另一個例子是當將專案新增到列表中,但從未刪除時。
-
list_for_each_entry_continue_rcu¶
list_for_each_entry_continue_rcu (pos, head, member)
繼續迭代給定型別的連結串列
引數
pos用作循環遊標的 型別 *。
head連結串列的頭部。
member結構體中 list_head 的名稱。
描述
繼續迭代給定型別的列表,在當前位置之後繼續,該位置必須在獲取 RCU 讀取鎖時位於列表中。這通常需要您從同一 RCU 讀取端臨界區中先前遍歷列表獲得節點,或者您持有某種非 RCU 引用(例如引用計數)以保持節點活動 * 並且 * 在列表中。
此迭代器類似於 list_for_each_entry_from_rcu(),只是此迭代器從給定位置之後開始,而該迭代器從給定位置開始。
-
list_for_each_entry_from_rcu¶
list_for_each_entry_from_rcu (pos, head, member)
從當前點迭代列表
引數
pos用作循環遊標的 型別 *。
head連結串列的頭部。
member結構體中 list_node 的名稱。
描述
從給定位置開始迭代列表的尾部,該位置必須在獲取 RCU 讀取鎖時位於列表中。這通常需要您從同一 RCU 讀取端臨界區中先前遍歷列表獲得節點,或者您持有某種非 RCU 引用(例如引用計數)以保持節點活動 * 並且 * 在列表中。
此迭代器類似於 list_for_each_entry_continue_rcu(),只是此迭代器從給定位置開始,而該迭代器從給定位置之後的位置開始。
-
void hlist_del_rcu(struct hlist_node *n)¶
從雜湊列表中刪除條目,而無需重新初始化
引數
struct hlist_node *n要從雜湊列表中刪除的元素。
注意
在此之後,entry 上的 list_unhashed() 不會返回 true,該條目處於未定義狀態。它對於基於 RCU 的無鎖遍歷很有用。
描述
特別是,這意味著我們無法破壞可能仍用於遍歷雜湊列表的前向指標。
呼叫者必須採取必要的預防措施(例如持有適當的鎖),以避免與同一連結串列上執行的其他連結串列修改原語(例如 hlist_add_head_rcu() 或 hlist_del_rcu())發生競爭。但是,與 _rcu 連結串列遍歷原語(例如 hlist_for_each_entry())併發執行是完全合法的。
-
void hlist_replace_rcu(struct hlist_node *old, struct hlist_node *new)¶
用新條目替換舊條目
引數
struct hlist_node *old要替換的元素
struct hlist_node *new要插入的新元素
描述
從併發讀取者的角度來看,**old** 條目將被 **new** 條目原子地替換。如果有任何併發更新程式,則由呼叫者負責與它們同步。
-
void hlists_swap_heads_rcu(struct hlist_head *left, struct hlist_head *right)¶
交換 hlist head 指向的列表
引數
struct hlist_head *left左側的 hlist head
struct hlist_head *right右側的 hlist head
描述
- 列表初始狀態為 [left ][node1 ... ] 和
[right ][node2 ... ]
- 列表最終狀態為 [left ][node2 ... ]
[right ][node1 ... ]
-
void hlist_add_head_rcu(struct hlist_node *n, struct hlist_head *h)¶
引數
struct hlist_node *n要新增到雜湊列表的元素。
struct hlist_head *h要新增到的列表。
描述
在允許併發遍歷的情況下,將指定的元素新增到指定的 hlist。
呼叫者必須採取必要的預防措施(例如持有適當的鎖),以避免與另一個列表修改原語(例如 hlist_add_head_rcu() 或 hlist_del_rcu())在同一個列表上競爭。但是,完全可以與 _rcu 列表遍歷原語(例如 hlist_for_each_entry_rcu())併發執行,用於防止 Alpha CPU 上的記憶體一致性問題。無論 CPU 型別如何,列表遍歷原語都必須受到 rcu_read_lock() 的保護。
-
void hlist_add_tail_rcu(struct hlist_node *n, struct hlist_head *h)¶
引數
struct hlist_node *n要新增到雜湊列表的元素。
struct hlist_head *h要新增到的列表。
描述
在允許併發遍歷的情況下,將指定的元素新增到指定的 hlist。
呼叫者必須採取必要的預防措施(例如持有適當的鎖),以避免與另一個列表修改原語(例如 hlist_add_head_rcu() 或 hlist_del_rcu())在同一個列表上競爭。但是,完全可以與 _rcu 列表遍歷原語(例如 hlist_for_each_entry_rcu())併發執行,用於防止 Alpha CPU 上的記憶體一致性問題。無論 CPU 型別如何,列表遍歷原語都必須受到 rcu_read_lock() 的保護。
-
void hlist_add_before_rcu(struct hlist_node *n, struct hlist_node *next)¶
引數
struct hlist_node *n要新增到雜湊列表中的新元素。
struct hlist_node *next在現有元素之前新增新元素。
描述
在允許併發遍歷的情況下,將指定的元素新增到指定的 hlist 中的指定節點之前。
呼叫者必須採取必要的預防措施(例如持有適當的鎖),以避免與另一個列表修改原語(例如 hlist_add_head_rcu() 或 hlist_del_rcu())在同一個列表上競爭。但是,完全可以與 _rcu 列表遍歷原語(例如 hlist_for_each_entry_rcu())併發執行,用於防止 Alpha CPU 上的記憶體一致性問題。
-
void hlist_add_behind_rcu(struct hlist_node *n, struct hlist_node *prev)¶
引數
struct hlist_node *n要新增到雜湊列表中的新元素。
struct hlist_node *prev在現有元素之後新增新元素。
描述
在允許併發遍歷的情況下,將指定的元素新增到指定的 hlist 中的指定節點之後。
呼叫者必須採取必要的預防措施(例如持有適當的鎖),以避免與另一個列表修改原語(例如 hlist_add_head_rcu() 或 hlist_del_rcu())在同一個列表上競爭。但是,完全可以與 _rcu 列表遍歷原語(例如 hlist_for_each_entry_rcu())併發執行,用於防止 Alpha CPU 上的記憶體一致性問題。
-
hlist_for_each_entry_rcu¶
hlist_for_each_entry_rcu (pos, head, member, cond...)
迭代給定型別的 rcu 列表
引數
pos用作循環遊標的 型別 *。
head連結串列的頭部。
member結構體中 hlist_node 的名稱。
cond...如果從非 RCU 保護呼叫,則為可選的 lockdep 表示式。
描述
只要遍歷受到 rcu_read_lock() 的保護,此列表遍歷原語就可以安全地與 _rcu 列表修改原語(例如 hlist_add_head_rcu())併發執行。
-
hlist_for_each_entry_srcu¶
hlist_for_each_entry_srcu (pos, head, member, cond)
迭代給定型別的 rcu 列表
引數
pos用作循環遊標的 型別 *。
head連結串列的頭部。
member結構體中 hlist_node 的名稱。
cond遍歷列表所需的鎖的 lockdep 表示式。
描述
只要遍歷受到 srcu_read_lock() 的保護,此列表遍歷原語就可以安全地與 _rcu 列表修改原語(例如 hlist_add_head_rcu())併發執行。lockdep 表示式 srcu_read_lock_held() 可以作為 cond 引數從讀取端傳遞。
-
hlist_for_each_entry_rcu_notrace¶
hlist_for_each_entry_rcu_notrace (pos, head, member)
迭代給定型別的 rcu 列表(用於跟蹤)
引數
pos用作循環遊標的 型別 *。
head連結串列的頭部。
member結構體中 hlist_node 的名稱。
描述
只要遍歷受到 rcu_read_lock() 的保護,此列表遍歷原語就可以安全地與 _rcu 列表修改原語(例如 hlist_add_head_rcu())併發執行。
這與 hlist_for_each_entry_rcu() 相同,只是它不執行任何 RCU 除錯或跟蹤。
-
hlist_for_each_entry_rcu_bh¶
hlist_for_each_entry_rcu_bh (pos, head, member)
迭代給定型別的 rcu 列表
引數
pos用作循環遊標的 型別 *。
head連結串列的頭部。
member結構體中 hlist_node 的名稱。
描述
只要遍歷受到 rcu_read_lock() 的保護,此列表遍歷原語就可以安全地與 _rcu 列表修改原語(例如 hlist_add_head_rcu())併發執行。
-
hlist_for_each_entry_continue_rcu¶
hlist_for_each_entry_continue_rcu (pos, member)
在當前點之後繼續迭代 hlist
引數
pos用作循環遊標的 型別 *。
member結構體中 hlist_node 的名稱。
-
hlist_for_each_entry_continue_rcu_bh¶
hlist_for_each_entry_continue_rcu_bh (pos, member)
在當前點之後繼續迭代 hlist
引數
pos用作循環遊標的 型別 *。
member結構體中 hlist_node 的名稱。
-
hlist_for_each_entry_from_rcu¶
hlist_for_each_entry_from_rcu (pos, member)
從當前點繼續迭代 hlist
引數
pos用作循環遊標的 型別 *。
member結構體中 hlist_node 的名稱。
-
void hlist_nulls_del_init_rcu(struct hlist_nulls_node *n)¶
從雜湊連結串列中刪除條目,並重新初始化
引數
struct hlist_nulls_node *n要從雜湊列表中刪除的元素。
注意
在此之後,節點上的 hlist_nulls_unhashed() 返回 true。如果寫入方必須知道列表條目是否仍然雜湊或已經取消雜湊,則它對於基於 RCU 的讀取鎖無遍歷非常有用。
描述
特別是,這意味著我們不能汙染可能仍用於遍歷雜湊連結串列的前向指標,並且我們只能將 pprev 指標置零,以便在此之後 list_unhashed() 返回 true。
呼叫者必須採取必要的預防措施(例如持有適當的鎖),以避免與另一個列表修改原語(例如 hlist_nulls_add_head_rcu() 或 hlist_nulls_del_rcu())在同一個列表上競爭。但是,完全可以與 _rcu 列表遍歷原語(例如 hlist_nulls_for_each_entry_rcu())併發執行。
-
hlist_nulls_first_rcu¶
hlist_nulls_first_rcu (head)
返回雜湊列表的第一個元素。
引數
head列表的頭部。
-
hlist_nulls_next_rcu¶
hlist_nulls_next_rcu (node)
返回 node 之後的列表元素。
引數
節點列表的元素。
-
void hlist_nulls_del_rcu(struct hlist_nulls_node *n)¶
從雜湊列表中刪除條目,而無需重新初始化
引數
struct hlist_nulls_node *n要從雜湊列表中刪除的元素。
注意
在此之後,條目上的 hlist_nulls_unhashed() 不會返回 true,該條目處於未定義狀態。它對於基於 RCU 的鎖無遍歷非常有用。
描述
特別是,這意味著我們無法破壞可能仍用於遍歷雜湊列表的前向指標。
呼叫者必須採取必要的預防措施(例如持有適當的鎖),以避免與另一個列表修改原語(例如 hlist_nulls_add_head_rcu() 或 hlist_nulls_del_rcu())在同一個列表上競爭。但是,完全可以與 _rcu 列表遍歷原語(例如 hlist_nulls_for_each_entry())併發執行。
-
void hlist_nulls_add_head_rcu(struct hlist_nulls_node *n, struct hlist_nulls_head *h)¶
引數
struct hlist_nulls_node *n要新增到雜湊列表的元素。
struct hlist_nulls_head *h要新增到的列表。
描述
在允許併發遍歷的情況下,將指定的元素新增到指定的 hlist_nulls。
呼叫者必須採取必要的預防措施(例如持有適當的鎖),以避免與另一個列表修改原語(例如 hlist_nulls_add_head_rcu() 或 hlist_nulls_del_rcu())在同一個列表上競爭。但是,完全可以與 _rcu 列表遍歷原語(例如 hlist_nulls_for_each_entry_rcu())併發執行,用於防止 Alpha CPU 上的記憶體一致性問題。無論 CPU 型別如何,列表遍歷原語都必須受到 rcu_read_lock() 的保護。
-
void hlist_nulls_add_tail_rcu(struct hlist_nulls_node *n, struct hlist_nulls_head *h)¶
引數
struct hlist_nulls_node *n要新增到雜湊列表的元素。
struct hlist_nulls_head *h要新增到的列表。
描述
在允許併發遍歷的情況下,將指定的元素新增到指定的 hlist_nulls。
呼叫者必須採取必要的預防措施(例如持有適當的鎖),以避免與另一個列表修改原語(例如 hlist_nulls_add_head_rcu() 或 hlist_nulls_del_rcu())在同一個列表上競爭。但是,完全可以與 _rcu 列表遍歷原語(例如 hlist_nulls_for_each_entry_rcu())併發執行,用於防止 Alpha CPU 上的記憶體一致性問題。無論 CPU 型別如何,列表遍歷原語都必須受到 rcu_read_lock() 的保護。
-
hlist_nulls_for_each_entry_rcu¶
hlist_nulls_for_each_entry_rcu (tpos, pos, head, member)
迭代給定型別的 rcu 列表
引數
tpos用作循環遊標的 型別 *。
pos要用作迴圈游標的
struct hlist_nulls_node。head列表的頭部。
member結構體中 hlist_nulls_node 的名稱。
描述
需要 barrier() 來確保編譯器不會快取第一個元素 [1],因為此迴圈可以重新啟動 [2] [1] Documentation/memory-barriers.txt 大約第 1533 行 [2] 使用 RCU hlist_nulls 來保護列表和物件 大約第 146 行
-
hlist_nulls_for_each_entry_safe¶
hlist_nulls_for_each_entry_safe (tpos, pos, head, member)
迭代給定型別的連結串列,防止刪除連結串列條目
引數
tpos用作循環遊標的 型別 *。
pos要用作迴圈游標的
struct hlist_nulls_node。head列表的頭部。
member結構體中 hlist_nulls_node 的名稱。
-
bool rcu_sync_is_idle(struct rcu_sync *rsp)¶
是否允許讀取器使用其快速路徑?
引數
struct rcu_sync *rsp指向用於同步的 rcu_sync 結構的指標
描述
如果允許讀取器使用其快速路徑,則返回 true。必須在某種型別的 RCU 讀取端臨界區內呼叫。
-
void rcu_sync_init(struct rcu_sync *rsp)¶
初始化 rcu_sync 結構
引數
struct rcu_sync *rsp指向要初始化的 rcu_sync 結構的指標
-
void rcu_sync_func(struct rcu_head *rhp)¶
管理讀取器對快速路徑訪問的回撥函式
引數
struct rcu_head *rhp指向 rcu_sync 結構中用於同步的 rcu_head 的指標
描述
此函式由 rcu_sync_enter() 和 rcu_sync_exit() 傳遞給 call_rcu() 函式,以便在呼叫 enter/exit 之後的寬限期後呼叫它。
如果它由 rcu_sync_enter() 呼叫,則表示所有讀取器都已切換到慢速路徑。
如果它由 rcu_sync_exit() 呼叫,它會根據在此期間發生的事件採取操作,以便緊密間隔的 rcu_sync_enter() 和 rcu_sync_exit() 對不需要等待寬限期。
如果在寬限期結束前再次呼叫 rcu_sync_enter(),則重置狀態,以便下一個 rcu_sync_exit() 允許讀者返回到他們的快速路徑(在寬限期之後)。 如果在寬限期結束之前,rcu_sync_enter() 及其匹配的 rcu_sync_exit() 都被呼叫,則代表該 rcu_sync_exit() 重新呼叫 call_rcu()。 否則,將所有狀態設定回空閒,以便讀者可以再次使用他們的快速路徑。
-
void rcu_sync_enter(struct rcu_sync *rsp)¶
強制讀者進入慢速路徑
引數
struct rcu_sync *rsp指向用於同步的 rcu_sync 結構的指標
描述
此函式由更新程式使用,這些更新程式需要讀者在更新期間使用慢速路徑。 此函式返回後,所有後續對 rcu_sync_is_idle() 的呼叫都將返回 false,這告訴讀者遠離他們的快速路徑。 稍後呼叫 rcu_sync_exit() 重新啟用讀者快速路徑。
當孤立呼叫時,rcu_sync_enter() 必須等待寬限期,但是,緊密間隔的 rcu_sync_enter() 呼叫可以透過由 rcu_sync_enter()、rcu_sync_exit() 和 rcu_sync_func() 實現的狀態機來最佳化掉寬限期等待。
-
void rcu_sync_exit(struct rcu_sync *rsp)¶
在寬限期後允許讀者返回到快速路徑
引數
struct rcu_sync *rsp指向用於同步的 rcu_sync 結構的指標
描述
此函式由已完成的更新程式使用,因此現在可以允許讀者在經過寬限期後使用他們的快速路徑。 在此寬限期完成後,所有後續對 rcu_sync_is_idle() 的呼叫都將返回 true,這告訴讀者他們可以再次使用他們的快速路徑。
-
void rcu_sync_dtor(struct rcu_sync *rsp)¶
清理 rcu_sync 結構
引數
struct rcu_sync *rsp指向要清理的 rcu_sync 結構的指標
-
struct rcu_tasks_percpu¶
類似於 Tasks-RCU 機制的定義的每個 CPU 元件。
定義:
struct rcu_tasks_percpu {
struct rcu_segcblist cblist;
raw_spinlock_t __private lock;
unsigned long rtp_jiffies;
unsigned long rtp_n_lock_retries;
struct timer_list lazy_timer;
unsigned int urgent_gp;
struct work_struct rtp_work;
struct irq_work rtp_irq_work;
struct rcu_head barrier_q_head;
struct list_head rtp_blkd_tasks;
struct list_head rtp_exit_list;
int cpu;
int index;
struct rcu_tasks *rtpp;
};
成員
cblist回撥列表。
lock鎖定保護每個 CPU 回撥列表。
rtp_jiffies用於統計資訊的 Jiffies 計數器值。
rtp_n_lock_retries粗略的鎖爭用統計資訊。
lazy_timer用於取消延遲迴調的計時器。
urgent_gp額外的非延遲寬限期的數量。
rtp_work用於呼叫回撥的工作佇列。
rtp_irq_work用於延遲喚醒的 IRQ 工作佇列。
barrier_q_head用於屏障操作的 RCU 回撥。
rtp_blkd_tasks作為讀者被阻止的任務列表。
rtp_exit_list位於 do_exit() 後部分的任務列表。
cpu與此條目對應的 CPU 編號。
index此 CPU 在 rcu_tasks 結構的 rtpcp_array 中的索引。
rtpp指向 rcu_tasks 結構的指標。
-
struct rcu_tasks¶
類似於 Tasks-RCU 機制的定義。
定義:
struct rcu_tasks {
struct rcuwait cbs_wait;
raw_spinlock_t cbs_gbl_lock;
struct mutex tasks_gp_mutex;
int gp_state;
int gp_sleep;
int init_fract;
unsigned long gp_jiffies;
unsigned long gp_start;
unsigned long tasks_gp_seq;
unsigned long n_ipis;
unsigned long n_ipis_fails;
struct task_struct *kthread_ptr;
unsigned long lazy_jiffies;
rcu_tasks_gp_func_t gp_func;
pregp_func_t pregp_func;
pertask_func_t pertask_func;
postscan_func_t postscan_func;
holdouts_func_t holdouts_func;
postgp_func_t postgp_func;
call_rcu_func_t call_func;
unsigned int wait_state;
struct rcu_tasks_percpu __percpu *rtpcpu;
struct rcu_tasks_percpu **rtpcp_array;
int percpu_enqueue_shift;
int percpu_enqueue_lim;
int percpu_dequeue_lim;
unsigned long percpu_dequeue_gpseq;
struct mutex barrier_q_mutex;
atomic_t barrier_q_count;
struct completion barrier_q_completion;
unsigned long barrier_q_seq;
unsigned long barrier_q_start;
char *name;
char *kname;
};
成員
cbs_waitRCU 等待允許新的回撥引起 kthread 的注意。
cbs_gbl_lock鎖定保護回撥列表。
tasks_gp_mutex互斥鎖保護寬限期,在啟動中期死區期間需要。
gp_state寬限期的最新狀態轉換(除錯)。
gp_sleep每個寬限期的睡眠以防止 CPU 繫結的迴圈。
init_fract初始退避睡眠間隔。
gp_jiffies上次 gp_state 轉換的時間。
gp_start最近一次寬限期開始的時間,以 jiffies 為單位。
tasks_gp_seq自啟動以來完成的寬限期的數量,位於高位。
n_ipis傳送以鼓勵寬限期結束的 IPI 的數量。
n_ipis_failsIPI 傳送失敗的數量。
kthread_ptr此風格的寬限期/回撥呼叫 kthread。
lazy_jiffies允許回撥延遲的 jiffies 數量。
gp_func此風格的寬限期等待函式。
pregp_func此風格的寬限期前函式(可選)。
pertask_func此風格的每個任務掃描函式(可選)。
postscan_func此風格的任務後掃描函式(可選)。
holdouts_func此風格的保留列表掃描函式(可選)。
postgp_func此風格的寬限期後函式(可選)。
call_func此風格的
call_rcu()等效函式。wait_state同步寬限期等待的任務狀態(預設為 TASK_UNINTERRUPTIBLE)。
rtpcpu此風格的 rcu_tasks_percpu 結構。
rtpcp_array指向 cpu_possible_mask 中 CPU 的 rcu_tasks_percpu 結構的指標陣列。
percpu_enqueue_shift在排隊回撥時,將 CPU ID 向下移動這麼多。
percpu_enqueue_lim用於排隊的每個 CPU 回撥佇列的數量。
percpu_dequeue_lim用於出隊的每個 CPU 回撥佇列的數量。
percpu_dequeue_gpseqRCU 寬限期編號,用於將排隊限制傳播到出隊者。
barrier_q_mutex序列化屏障操作。
barrier_q_count正在等待的佇列數量。
barrier_q_completion屏障等待/喚醒機制。
barrier_q_seq屏障操作的序列號。
barrier_q_start最近一次屏障開始的時間,以 jiffies 為單位。
name此風格的文字名稱。
kname此風格的 kthread 名稱。
-
void call_rcu_tasks(struct rcu_head *rhp, rcu_callback_t func)¶
將 RCU 排隊以呼叫基於任務的寬限期
引數
struct rcu_head *rhp用於對 RCU 更新進行排隊的結構。
rcu_callback_t func在寬限期後呼叫的實際回撥函式
描述
回撥函式將在完整的寬限期結束後一段時間後被呼叫,換句話說,在所有當前正在執行的 RCU 讀取端關鍵部分都已完成後。 call_rcu_tasks() 假設讀取端關鍵部分在自願上下文切換(不是搶佔!)、cond_resched_tasks_rcu_qs()、進入空閒或轉換到使用者模式執行時結束。 因此,沒有類似於 rcu_read_lock() 和 rcu_read_unlock() 的讀取端原語,因為此原語旨在確定所有任務都已透過安全狀態,而不是用於資料結構同步。
有關記憶體排序保證的更多詳細資訊,請參見 call_rcu() 的描述。
-
void synchronize_rcu_tasks(void)¶
等待 rcu-tasks 寬限期過去。
引數
void無引數
描述
在完整的 rcu-tasks 寬限期過去後一段時間後,控制將返回給呼叫者,換句話說,在所有當前正在執行的 rcu-tasks 讀取端關鍵部分都已過去後。 這些讀取端關鍵部分由對 schedule()、cond_resched_tasks_rcu_qs()、空閒執行、使用者空間執行、對 synchronize_rcu_tasks() 的呼叫以及(理論上)cond_resched() 的呼叫分隔。
這是一個非常專門的原語,僅用於跟蹤和其他需要操作函式序言和分析掛鉤的少數情況。 synchronize_rcu_tasks() 函式(尚未)打算從多個 CPU 大量使用。
有關記憶體排序保證的更多詳細資訊,請參見 synchronize_rcu() 的描述。
-
void rcu_barrier_tasks(void)¶
等待正在進行的
call_rcu_tasks()回撥。
引數
void無引數
描述
雖然當前的實現保證等待,但它沒有義務,例如,如果沒有掛起的回撥。
-
void synchronize_rcu_tasks_rude(void)¶
等待粗魯的 rcu-tasks 寬限期
引數
void無引數
描述
在粗魯的 rcu-tasks 寬限期過去後一段時間後,控制將返回給呼叫者,換句話說,在所有當前正在執行的 rcu-tasks 讀取端關鍵部分都已過去後。 這些讀取端關鍵部分由對 schedule()、cond_resched_tasks_rcu_qs()、使用者空間執行(這是一個可排程的上下文)以及(理論上)cond_resched() 的呼叫分隔。
這是一個非常專門的原語,僅用於跟蹤和其他需要操作函式序言和分析掛鉤的少數情況。 synchronize_rcu_tasks_rude() 函式(尚未)打算從多個 CPU 大量使用。
有關記憶體排序保證的更多詳細資訊,請參見 synchronize_rcu() 的描述。
-
void call_rcu_tasks_trace(struct rcu_head *rhp, rcu_callback_t func)¶
將回調跟蹤任務排隊基於寬限期
引數
struct rcu_head *rhp用於對 RCU 更新進行排隊的結構。
rcu_callback_t func在寬限期後呼叫的實際回撥函式
描述
回撥函式將在跟蹤 rcu-tasks 寬限期過去後一段時間後被呼叫,換句話說,在所有當前正在執行的跟蹤 rcu-tasks 讀取端關鍵部分都已完成後。 這些讀取端關鍵部分由對 rcu_read_lock_trace() 和 rcu_read_unlock_trace() 的呼叫分隔。
有關記憶體排序保證的更多詳細資訊,請參見 call_rcu() 的描述。
-
void synchronize_rcu_tasks_trace(void)¶
等待跟蹤 rcu-tasks 寬限期
引數
void無引數
描述
在跟蹤 rcu-tasks 寬限期過去後一段時間後,控制將返回給呼叫者,換句話說,在所有當前正在執行的跟蹤 rcu-tasks 讀取端關鍵部分都已完成後。 這些讀取端關鍵部分由對 rcu_read_lock_trace() 和 rcu_read_unlock_trace() 的呼叫分隔。
這是一個非常專門的原語,僅用於跟蹤和其他需要操作函式序言和分析掛鉤的少數情況。 synchronize_rcu_tasks_trace() 函式(尚未)打算從多個 CPU 大量使用。
有關記憶體排序保證的更多詳細資訊,請參見 synchronize_rcu() 的描述。
-
void rcu_barrier_tasks_trace(void)¶
等待正在進行的
call_rcu_tasks_trace()回撥。
引數
void無引數
描述
雖然當前的實現保證等待,但它沒有義務,例如,如果沒有掛起的回撥。
-
void rcu_cpu_stall_reset(void)¶
重新啟動當前寬限期的停止警告超時
引數
void無引數
描述
為了從呼叫者執行重置請求,停用停止檢測,直到經過 3 個 fqs 迴圈。 這是為了確保載入新的 jiffies。 從 fqs 迴圈執行應該是安全的,因為應該已經過去了足夠的定時器中斷和上下文切換。
呼叫者必須停用硬 IRQ。
-
int rcu_stall_chain_notifier_register(struct notifier_block *n)¶
新增 RCU CPU 停止通知器
引數
struct notifier_block *n要新增的條目。
描述
將 RCU CPU 停止通知器新增到原子通知器鏈。 傳遞給通知器的 action 將是 RCU_STALL_NOTIFY_NORM 或朋友。 data 將是停止的寬限期的持續時間,以 jiffies 為單位,強制轉換為 void* 指標。
成功時返回 0,錯誤時返回 -EEXIST。
-
int rcu_stall_chain_notifier_unregister(struct notifier_block *n)¶
刪除 RCU CPU 停止通知器
引數
struct notifier_block *n要新增的條目。
描述
從原子通知器鏈中刪除 RCU CPU 停止通知器。
成功時返回零,失敗時返回 -ENOENT。
-
void rcu_read_lock_trace(void)¶
標記 RCU 跟蹤讀取端關鍵部分的開始
引數
void無引數
描述
當 synchronize_rcu_tasks_trace() 由一個任務呼叫時,則保證該任務會阻塞,直到所有其他任務退出其讀取端關鍵部分。 同樣,如果在其他任務位於 RCU 讀取端關鍵部分內時在一個任務上呼叫 call_rcu_trace(),則對應 RCU 回撥的呼叫將延遲到所有其他任務退出其關鍵部分之後。
有關更多詳細資訊,請參見 rcu_read_lock() 的文件。
-
void rcu_read_unlock_trace(void)¶
標記 RCU 跟蹤讀取端關鍵部分的結束
引數
void無引數
描述
與先前對 rcu_read_lock_trace() 的呼叫配對,並允許巢狀。如果在沒有匹配的 rcu_read_lock_trace() 的情況下呼叫 rcu_read_unlock_trace() 是禁止的,並且會導致 lockdep 抱怨。
更多細節,請參考 rcu_read_unlock() 的文件。
-
synchronize_rcu_mult¶
synchronize_rcu_mult (...)
併發等待多個寬限期
引數
...要等待的不同寬限期的
call_rcu()函式列表
描述
這個宏併發等待多種型別的 RCU 寬限期。例如,synchronize_rcu_mult(call_rcu, call_rcu_tasks) 將等待併發的 RCU 和 RCU-tasks 寬限期。等待給定的 SRCU 域需要您為該 SRCU 域的 call_srcu() 函式編寫一個包裝函式,該包裝函式提供指向相應 srcu_struct 的指標。
請注意,應使用 call_rcu_hurry() 而不是 call_rcu(),因為在用 CONFIG_RCU_LAZY=y 構建的核心中,call_rcu() 的呼叫與相應 RCU 回撥的呼叫之間的延遲可能長達數秒。
第一個引數告訴 Tiny RCU 的 _wait_rcu_gp() 不要費心等待 RCU。 原因是任何可以呼叫 synchronize_rcu_mult() 的地方都已經是一個完整的寬限期。
-
void rcuref_init(rcuref_t *ref, unsigned int cnt)¶
使用給定的引用計數初始化一個 rcuref 引用計數
引數
rcuref_t *ref指向引用計數的指標
unsigned int cnt初始引用計數通常為“1”
-
unsigned int rcuref_read(rcuref_t *ref)¶
讀取 rcuref 的持有引用計數數量
引數
rcuref_t *ref指向引用計數的指標
返回
持有的引用數量 (0 ... N)。 值 0 並不表示可以安全地排程受此引用計數器保護的物件進行解構。 如果您想知道引用計數器是否已標記為 DEAD(由 rcuref_put() 發出訊號),請使用 rcuread_is_dead()。
-
bool rcuref_is_dead(rcuref_t *ref)¶
檢查 rcuref 是否已被標記為 dead
引數
rcuref_t *ref指向引用計數的指標
返回
如果物件已被標記為 DEAD,則為 True。 這表示先前呼叫 rcuref_put() 在此引用計數器上返回 true,這意味著可以安全地排程受保護物件進行解構。 否則,返回 false。
-
bool rcuref_get(rcuref_t *ref)¶
獲取 rcuref 引用計數上的一個引用
引數
rcuref_t *ref指向引用計數的指標
描述
類似於 atomic_inc_not_zero(),但在 RCUREF_MAXREF 處飽和。
不提供記憶體排序,假設呼叫者已保證物件記憶體穩定(RCU 等)。 它確實提供了一個控制依賴性,從而對未來的儲存進行排序。 請參閱 lib/rcuref.c 中的文件
返回
如果獲取引用的嘗試失敗,則為 False。 當最後一個引用已被放置時會發生這種情況
如果成功獲取了引用,則為 True
-
bool rcuref_put_rcusafe(rcuref_t *ref)¶
釋放一個 rcuref 引用計數 RCU 安全的引用
引數
rcuref_t *ref指向引用計數的指標
描述
提供釋放記憶體排序,以便在之前完成先前的載入和儲存,並在成功時提供獲取排序,以便 free() 必須在之後進行。
可以從上下文中呼叫,這些上下文保證如果遞減丟棄最後一個引用並且慢速路徑與併發的 get() 和 put() 對競爭,則不會發生寬限期,從而併發地釋放物件。 rcu_read_lock()'ed 和原子上下文符合條件。
返回
如果這是最後一個引用,並且將來沒有可能的引用,則為 True。 這向呼叫者發出訊號,表明它可以安全地釋放受引用計數器保護的物件。
如果仍然存在活動引用,或者 put() 與併發的 get()/put() 對競爭,則為 False。 不允許呼叫者釋放受保護的物件。
-
bool rcuref_put(rcuref_t *ref)¶
釋放一個 rcuref 引用計數的引用
引數
rcuref_t *ref指向引用計數的指標
描述
可以從任何上下文呼叫。
提供釋放記憶體排序,以便在之前完成先前的載入和儲存,並在成功時提供獲取排序,以便 free() 必須在之後進行。
返回
如果這是最後一個引用,並且將來沒有可能的引用,則為 True。 這向呼叫者發出訊號,表明它可以安全地排程受引用計數器保護的物件進行解構。
如果仍然存在活動引用,或者 put() 與併發的 get()/put() 對競爭,則為 False。 不允許呼叫者解構受保護的物件。
-
bool same_state_synchronize_rcu_full(struct rcu_gp_oldstate *rgosp1, struct rcu_gp_oldstate *rgosp2)¶
兩個舊狀態值是否相同?
引數
struct rcu_gp_oldstate *rgosp1第一個舊狀態值。
struct rcu_gp_oldstate *rgosp2第二個舊狀態值。
描述
這兩個 old-state 值必須從 get_state_synchronize_rcu_full()、start_poll_synchronize_rcu_full() 或 get_completed_synchronize_rcu_full() 中獲得。 如果這兩個值相同,則返回 true,否則返回 false。 這允許生命週期由 old-state 值跟蹤的結構將這些值推送到列表標頭,從而使這些結構稍微小一些。
請注意,等式是按位判斷的,因此在一個欄位中具有已完成狀態的 rcu_gp_oldstate 結構將與在另一個欄位中具有已完成狀態的結構進行比較而不相等。 畢竟,rcu_gp_oldstate 結構是不透明的,那麼這種情況最初是如何發生的呢?