使用者空間除錯建議

本文件簡要概述了從使用者空間除錯 Linux 核心的常用工具。有關針對驅動程式開發者的除錯建議,請轉到此處。有關一般除錯建議,請參閱一般建議文件

以下部分向您展示了可用的工具。

動態除錯

透過啟用/停用日誌訊息來過濾最終進入核心日誌的內容的機制。

先決條件:CONFIG_DYNAMIC_DEBUG

動態除錯只能針對

  • pr_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

事件和指標的可用性取決於您執行的系統。

有關完整的文件,請參閱https://perf.wiki.kernel.org/index.php/Main_Page

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