使用者空間除錯建議¶
本文件簡要概述了從使用者空間除錯 Linux 核心的常用工具。有關針對驅動程式開發者的除錯建議,請轉到此處。有關一般除錯建議,請參閱一般建議文件。
以下部分向您展示了可用的工具。
動態除錯¶
透過啟用/停用日誌訊息來過濾最終進入核心日誌的內容的機制。
先決條件:CONFIG_DYNAMIC_DEBUG
動態除錯只能針對
dev_dbg()
print_hex_dump_debug()
print_hex_dump_bytes()
因此,該工具的可用性目前非常有限,因為沒有統一的規則將除錯列印新增到程式碼庫中,導致這些列印的實現方式多種多樣。
另外,請注意,大多數除錯語句都以 dprintk() 的變體實現,必須透過相應模組中的引數啟用,動態除錯無法為您完成該步驟。
這是一個示例,它啟用檔案中所有可用的pr_debug()。
$ alias ddcmd='echo $* > /proc/dynamic_debug/control'
$ ddcmd '-p; file v4l2-h264.c +p'
$ grep =p /proc/dynamic_debug/control
drivers/media/v4l2-core/v4l2-h264.c:372 [v4l2_h264]print_ref_list_b =p
"ref_pic_list_b%u (cur_poc %u%c) %s"
drivers/media/v4l2-core/v4l2-h264.c:333 [v4l2_h264]print_ref_list_p =p
"ref_pic_list_p (cur_poc %u%c) %s\n"
何時應該使用它而不是 Ftrace?
當代碼包含有效的列印語句之一(參見上文),或者當您在開發過程中添加了多個
pr_debug()語句時當時間不是問題時,這意味著程式碼中的多個
pr_debug()語句不會導致延遲當您更關心接收特定的日誌訊息,而不是跟蹤函式的呼叫模式時
有關完整文件,請參閱動態除錯
Ftrace¶
先決條件:CONFIG_DYNAMIC_FTRACE
此工具使用 tracefs 檔案系統作為控制檔案和輸出檔案。該檔案系統將掛載為 tracing 目錄,該目錄可以在 /sys/kernel/ 或 /sys/debug/kernel/ 中找到。
除錯時最重要的一些操作是
您可以透過將函式名稱新增到
set_ftrace_filter檔案(它接受在available_filter_functions檔案中找到的任何函式名稱)來執行函式跟蹤,或者您可以透過將它們的名稱新增到set_ftrace_notrace檔案來專門停用某些函式(更多資訊請參見:動態 ftrace)。為了找出呼叫的來源,您可以啟用
options/func_stack_trace下的func_stack_trace選項。透過將所需的函式新增到
set_graph_function檔案(需要配置FUNCTION_GRAPH_RETVAL)可以跟蹤函式呼叫的子函式並顯示返回值;更多資訊請參見帶有函式圖示跟蹤器的動態 ftrace。
有關完整的 Ftrace 文件,請參閱ftrace - 函式跟蹤器
或者您也可以透過使用事件跟蹤來跟蹤特定事件,該事件可以定義如下:建立自定義 Ftrace 跟蹤點。
有關完整的 Ftrace 事件跟蹤文件,請參閱事件跟蹤
讀取 ftrace 日誌¶
可以像讀取任何其他檔案一樣讀取 trace 檔案(cat, tail, head, vim 等),檔案的大小受 buffer_size_kb 的限制(echo 1000 > buffer_size_kb)。trace_pipe 的行為類似於 trace 檔案,但是每當您從檔案中讀取內容時,內容就會被消耗。
Kernelshark¶
一個 GUI 介面,用於將來自 trace-cmd 應用程式輸出的跟蹤視覺化為圖形和列表檢視。
有關完整的文件,請參閱https://kernelshark.org/Documentation.html
Perf & 替代方案¶
上面提到的工具提供了檢查核心程式碼、結果、變數值等的方法。有時您必須先找出要查詢的位置,對於這些情況,一組效能跟蹤工具可以幫助您確定問題範圍。
為什麼要做效能分析?¶
在效能分析是一個很好的第一步,尤其是當
您無法定義問題
您不知道問題發生在何處
執行中的系統不應中斷,或者它是遠端系統,您無法安裝新的模組/核心
如何使用 Linux 工具進行簡單的分析?¶
對於效能分析的開始,您可以從常用工具開始,例如
top/htop/atop(獲取系統負載的概覽,檢視特定程序的峰值)mpstat -P ALL(檢視 CPU 之間的負載分佈)iostat -x(觀察輸入和輸出裝置的利用率和效能)vmstat(系統上記憶體使用情況的概覽)pidstat(類似於vmstat,但按程序劃分,以縮小到目標)strace -tp $PID(一旦您知道程序,您就可以弄清楚它如何與核心通訊)
這些應該有助於充分縮小要檢視的區域。
使用 perf 深入研究¶
perf 工具提供了一系列指標和事件,以進一步縮小問題範圍。
先決條件:在您的系統上構建或安裝 perf
收集統計資料以查詢 /usr 中所有以 gcc 開頭的檔案
# perf stat -d find /usr -name 'gcc*' | wc -l
Performance counter stats for 'find /usr -name gcc*':
1277.81 msec task-clock # 0.997 CPUs utilized
9 context-switches # 7.043 /sec
1 cpu-migrations # 0.783 /sec
704 page-faults # 550.943 /sec
766548897 cycles # 0.600 GHz (97.15%)
798285467 instructions # 1.04 insn per cycle (97.15%)
57582731 branches # 45.064 M/sec (2.85%)
3842573 branch-misses # 6.67% of all branches (97.15%)
281616097 L1-dcache-loads # 220.390 M/sec (97.15%)
4220975 L1-dcache-load-misses # 1.50% of all L1-dcache accesses (97.15%)
<not supported> LLC-loads
<not supported> LLC-load-misses
1.281746009 seconds time elapsed
0.508796000 seconds user
0.773209000 seconds sys
52
事件和指標的可用性取決於您執行的系統。
Perfetto¶
一套用於測量和分析應用程式和系統性能的工具。您可以使用它來
識別瓶頸
最佳化程式碼
使軟體執行得更快、更高效。
perfetto 和 perf 之間有什麼區別?
perf 是 Linux 核心的一部分並專門用於 Linux 核心的工具,並且具有 CLI 使用者介面。
perfetto 跨平臺效能分析堆疊,已將功能擴充套件到使用者空間,並提供 WEB 使用者介面。
有關完整的文件,請參閱https://perfetto.dev/docs/
核心崩潰分析工具¶
要捕獲崩潰轉儲,請使用
Kdump&Kexec。下面您可以找到一些分析資料的建議。有關完整的文件,請參閱Kdump 文件 - 基於 kexec 的崩潰轉儲解決方案
為了找到程式碼中的相應行,您可以使用faddr2line;請注意,您需要啟用
CONFIG_DEBUG_INFO才能使其工作。使用
faddr2line的替代方法是使用objdump(及其用於不同平臺的衍生版本,如aarch64-linux-gnu-objdump)。以此行作為示例
[ +0.000240] rkvdec_device_run+0x50/0x138 [rockchip_vdec].我們可以透過執行找到程式碼的相應行
aarch64-linux-gnu-objdump -dS drivers/staging/media/rkvdec/rockchip-vdec.ko | grep rkvdec_device_run\>: -A 40 0000000000000ac8 <rkvdec_device_run>: ac8: d503201f nop acc: d503201f nop { ad0: d503233f paciasp ad4: a9bd7bfd stp x29, x30, [sp, #-48]! ad8: 910003fd mov x29, sp adc: a90153f3 stp x19, x20, [sp, #16] ae0: a9025bf5 stp x21, x22, [sp, #32] const struct rkvdec_coded_fmt_desc *desc = ctx->coded_fmt_desc; ae4: f9411814 ldr x20, [x0, #560] struct rkvdec_dev *rkvdec = ctx->dev; ae8: f9418015 ldr x21, [x0, #768] if (WARN_ON(!desc)) aec: b4000654 cbz x20, bb4 <rkvdec_device_run+0xec> ret = pm_runtime_resume_and_get(rkvdec->dev); af0: f943d2b6 ldr x22, [x21, #1952] ret = __pm_runtime_resume(dev, RPM_GET_PUT); af4: aa0003f3 mov x19, x0 af8: 52800081 mov w1, #0x4 // #4 afc: aa1603e0 mov x0, x22 b00: 94000000 bl 0 <__pm_runtime_resume> if (ret < 0) { b04: 37f80340 tbnz w0, #31, b6c <rkvdec_device_run+0xa4> dev_warn(rkvdec->dev, "Not good\n"); b08: f943d2a0 ldr x0, [x21, #1952] b0c: 90000001 adrp x1, 0 <rkvdec_try_ctrl-0x8> b10: 91000021 add x1, x1, #0x0 b14: 94000000 bl 0 <_dev_warn> *bad = 1; b18: d2800001 mov x1, #0x0 // #0 ...這意味著,在崩潰轉儲的這一行中
[ +0.000240] rkvdec_device_run+0x50/0x138 [rockchip_vdec]我可以將
0x50作為偏移量,我必須將其新增到相應函式的基本地址,該地址可以在這一行中找到0000000000000ac8 <rkvdec_device_run>:
0xac8 + 0x50 = 0xb18的結果是,當我在函式中搜索該地址時,我會得到以下行*bad = 1; b18: d2800001 mov x1, #0x0
版權所有 ©2024 : Collabora