Android 10 包含 Android 即時鎖定 Daemon
(llkd
),用於擷取及減少核心死結。llkd
元件提供預設的獨立實作
您也可以將 llkd
程式碼整合到其他服務中,
主迴圈,或做為獨立執行緒。
偵測情境
llkd
有兩種偵測情境:永久 D 或 Z 狀態
堆疊簽章
永久 D 或 Z 狀態
如果執行緒處於 D (無法中斷的睡眠) 或 Z (殭屍) 狀態,但沒有快轉狀態
超過 ro.llk.timeout_ms or ro.llk.[D|Z].timeout_ms
的進度時
llkd
會終止程序 (或父項程序)。如果後續掃描作業顯示
相同的程序會繼續存在,llkd
會確認即時鎖定條件,並
恐慌,為
值。
llkd
包含自拍狗狗,當 llkd
鎖定時發出鬧鐘提醒。監控計時器是
是每次執行主迴圈的預計時間會加倍
ro.llk_sample_ms
。
永久堆疊簽章
針對使用者偵錯版本,llkd
可以使用永久性偵測核心即時鎖定
進行堆疊簽章檢查如果處於 Z 以外任何狀態的執行緒
列出來的 ro.llk.stack
個核心符號超過
ro.llk.timeout_ms
或 ro.llk.stack.timeout_ms
,llkd
會終止程序
(即使有轉寄排程進度)。如果後續掃描作業顯示
相同的程序會繼續存在,llkd
會確認即時鎖定條件,並
恐慌,為
值。
如果有即時鎖定條件,lldk
檢查會持續存在,且
請尋找語句中由 symbol+0x
或 symbol.cfi+0x
組成的字串
/proc/pid/stack
檔案。符號清單位於 ro.llk.stack
和
預設值為以半形逗號分隔的清單
cma_alloc,__get_user_pages,bit_wait_io,wait_on_page_bit_killable
。
符號的使用應該很少,而且使用時間必須夠短,這樣才能在典型系統中
函式在逾時期間的樣本中只會出現一次
ro.llk.stack.timeout_ms
(樣本數為每 ro.llk.check_ms
)。由於缺少
ABA 保護措施的唯一方法,就是避免觸發錯誤觸發的唯一方法。符號
函式必須顯示在呼叫鎖的函式下方,可以形成連續的鎖定。如果
鎖頭位於下方或符號功能中,所有受影響的符號都會出現這個符號
不只是造成鎖定圖文標誌的程式
涵蓋範圍
llkd
的預設實作不會監控 init
、[kthreadd]
或
出現 [kthreadd]
次。針對 llkd
涵蓋 [kthreadd]
產生的執行緒:
- 驅動程式不得處於永久的 D 狀態。
或
- 驅動程式必須具有復原執行緒的機制,才能在執行緒終止時加以復原
外部。舉例來說,請使用
wait_event_interruptible()
而非wait_event()
。
如果符合上述任一條件,llkd
拒絕清單即可調整為
涵蓋核心元件堆疊符號檢查作業涉及額外的程序
拒絕清單,以免封鎖 ptrace
的服務違反政策
作業。
Android 屬性
llkd
會回應多個 Android 屬性 (如下所列)。
- 名為
prop_ms
的屬性以毫秒為單位。 - 屬性如果使用半形逗號 (,) 分隔符,則在屬性前面加上分隔符,
保留預設值,然後視需要加上或減去項目,並可選擇是否加上加號
(+) 和減號 (-) 前置字元。在這些清單中,字串
false
與空白清單同義字,而空白或遺漏項目之餘則 指定的預設值
ro.config.low_ram
裝置設定的記憶體有限。
ro.debuggable
裝置已設定用於使用者偵錯或工程版本。
ro.llk.sysrq_t
如果屬性是 eng
,則預設值為 ro.config.low_ram
或 ro.debuggable
。
如為 true
,請傾印所有執行緒 (sysrq t
)。
ro.llk.enable
允許啟用即時鎖定 Daemon。預設值為 false
。
llk.enable
已針對工程版本評估。預設值為 ro.llk.enable
。
ro.khungtask.enable
允許啟用 [khungtask]
Daemon。預設值為 false
。
khungtask.enable
已針對工程版本評估。預設值為 ro.khungtask.enable
。
ro.llk.mlockall
啟用對 mlockall()
的通話。預設值為 false
。
ro.khungtask.timeout
時間上限為 [khungtask]
。預設值為 12 分鐘。
ro.llk.timeout_ms
時間上限為 D 或 Z。預設值為 10 分鐘。按兩下這個值即可設定
llkd
的鬧鐘監控計時器。
ro.llk.D.timeout_ms
D 時間上限。預設值為 ro.llk.timeout_ms
。
ro.llk.Z.timeout_ms
Z 時間上限。預設值為 ro.llk.timeout_ms
。
ro.llk.stack.timeout_ms
檢查永久堆疊符號的時間上限。預設值為
ro.llk.timeout_ms
。僅在使用者偵錯或 eng 版本上啟用。
ro.llk.check_ms
D 或 Z 的執行緒範例。預設值為兩分鐘。
ro.llk.stack
檢查核心堆疊符號,如果持續存在,可能表示
子系統處於鎖定狀態預設值為
cma_alloc,__get_user_pages,bit_wait_io,wait_on_page_bit_killable
以半形逗號分隔的核心符號清單。這項檢查無法提前安排
ABA (這段期間內每 ro.llk_check_ms
輪詢一次)
ro.llk.stack.timeout_ms
,因此堆疊符號會特別罕見,且
短暫出現 (不太可能持續出現符號)
)。檢查內容是否與「symbol+0x
」相符,或
堆疊展開中的 symbol.cfi+0x
。僅適用於使用者偵錯或工程師
版本對使用者版本的安全性疑慮會導致有限的權限,
防止這項檢查
ro.llk.黑名單.process
llkd
不會監控指定的程序。預設值為 0,1,2
(kernel
,
init
和 [kthreadd]
) 以及程序名稱
init,[kthreadd],[khungtaskd],lmkd,llkd,watchdogd, [watchdogd],[watchdogd/0],...,[watchdogd/get_nprocs-1]
。
程序可以是 comm
、cmdline
或 pid
參照。自動預設值
可能大於目前的屬性大小上限 92。
ro.llk.黑名單.parent
llkd
不會監控具有指定父項的程序。預設
是 0,2,adbd&[setsid]
(kernel
、[kthreadd]
和 adbd
僅適用於殭屍
setsid
)。分隔符 (&) 分隔符表示只忽略父項
以及目標子項程序選擇 AND 符號,因為這個字詞
絕不屬於程序名稱的一部分;然而,殼層中的 setprop
需要
逸出或引用,但這個 init rc
檔案採用
不會發生這個問題父項或目標程序可以是
參照 comm
、cmdline
或 pid
。
ro.llk.黑名單.uid
llkd
不會監控符合指定 UID 的程序。
以半形逗號分隔的 UIS 號碼或名稱清單。預設值為空白或 false
。
ro.llk.黑名單.process.stack
llkd
不會監控即時鎖定堆疊的指定部分程序
簽章。預設值為程序名稱
init,lmkd.llkd,llkd,keystore,ueventd,apexd,logd
。禁止這項政策
違反與封鎖 ptrace
的程序相關的違規事件 (因為
已勾選)。僅在使用者偵錯版本和 eng 版本上啟用。建構詳細資料
請參閱建構 Android。
架構問題
- 屬性長度上限為 92 個字元 (但預設值會忽略此屬性)。
來源的
include/llkd.h
檔案所定義)。 - 內建的
[khungtask]
Daemon 太過籠統,且會佔用驅動程式代碼, 坐在 D 狀態下太久改用 S 會導致工作終止 以及供駕駛人視需要確認。
程式庫介面 (選用)
您可以選擇使用以下項目,將 llkd
併入另一個特殊權限 Daemon 中
libllkd
元件中的下列 C 介面:
#include "llkd.h"
bool llkInit(const char* threadname) /* return true if enabled */
unsigned llkCheckMillseconds(void) /* ms to sleep for next check */
如果提供執行緒名稱,執行緒會自動產生執行緒,否則呼叫端
必須在主迴圈中呼叫 llkCheckMilliseconds
。這個函式會傳回
時間。