OpenRemoved_Tina_Linux系統調試使用指南1
概述1.1 編寫目的
1.2 適用范圍
1.3 相關人員
2 調試方法及工具
2.1 內核日志
2.2 GDB2.2.1 介紹
2.2.2 配置
2.2.3 使用
2.2.4 更多用法
2.2.5 注意事項
2.3 gdbserver.
2.3.1 介紹
2.3.2 配置
2.3.3 使用
2.4 coredump.
2.4.1 介紹
2.4.2 配置
2.4.3 配置生成coredump文件.
2.4.4 通過gdb定位問題
2.5 perf
2.5.1 介紹
2.5.2 配置
2.5.3 使用
2.6 strace
2.6.1 介紹
2.6.2 配置
2.6.3 使用
2.7 valgrind.
2.7.1 介紹
2.7.2 配置
2.7.3 使用
2.8 輕量級日志永久轉存.
2.8.1 使能日志轉存.
2.8.1.1 使能內核功能模塊
2.8.1.2 指定分區
2.8.2 獲取奔潰日志.
2.8.2.1 掛載文件系統.
2.8.2.2 讀取文件
2.8.2.3 刪除文件
2.8.3 高級功能配置.
2.8.3.1 分區的空間分布
2.8.3.2 高級功能
OpenRemoved_Tina_Linux系統調試使用指南
1 概述
1.1 編寫目的
本文主要服務于使用Tina軟件平臺的廣大客戶,幫助開發人員方便快速了解Tina平臺系統調試工具。
1.2 適用范圍
本文適用于Tina3.5版本以上軟件平臺;對硬件環境沒有要求,所有Allwinner硬件平臺都適 用。
其中,注意linux-5.4內核上暫未支持pstore功能。
1.3 相關人員
適用Tina平臺的廣大客戶與開發人員。
2 調試方法及工具
2.1 內核日志
內核日志默認打印在env.cfg中配置,文件路徑:
文件一般在芯片方案配置目錄下,例如:
device/config/chips/v853/configs/perf1/linux/env-4.9.cfg
device/config/chips/r528/configs/evb2/env.cfg
?
文件中的loglevel決定打印等級
loglevel=
在進入系統后,有下面方法可以修改打印等級:
echo 8 > /proc/sys/kernel/printk
dmesg -n 8
2.2 GDB
2.2.1 介紹
GDB(GNU symbolic debugger)是GNU開源組織發布的一款調試工具,用于調試由GCC編譯的代碼。它的功能非常強大,使用命令行的調試方式,允許調試復雜的應用程序,給程序開發提供了極大的便利。
2.2.2 配置
Tina SDK中GDB源碼包位于dl目錄下,默認不配置GDB軟件包,使用時需要先選上GDB。配置方法如下。
make menuconfig -->
Development -->
<*> gdb------------------------------------------------------- GNU Debugger
2.2.3 使用
按照上述方法配置好GDB后,重新編譯并燒寫系統,在設備端口運行gdb即可調試應用程序。
gdb
2.2.4 更多用法
gdb調試命令很多,如何使用可以參考:https://www.gnu.org/software/gdb/documentation/
2.2.5 注意事項
調試信息
gdb主要用來調試C/C++的程序。在編譯源碼時必須要把調試信息加到可執行文件中。即編譯參數帶上-g參數。如果沒有-g,將看不見程序的函數名和變量名,代替它們的全是運行時的內存地址。
多線程調試
已運行進程調試
gdb attach -p ,其中pid為需要調試的進程名字。
2.3 gdbserver.
2.3.1 介紹
gdbserver是可以對目標設備上的程序進行遠程調試的軟件。
2.3.2 配置
make menuconfig -->
Development -->
<*> gdbserver................................. Remote server for GNU Debugger
2.3.3 使用
先確定本地回環接口是否打開,如未打開需要先進行網絡配置,在小機端執行以下命令。
ip addr add dev lo 127.0.0.1/32 //設置本地回環地址為127.0.0.
ifconfig lo up //使能端口
在小機端運行gdbserver程序
gdbserver 127.0.0.1:3456 process //3456為目標板端口號,用戶自己定義,process為應用程序名字
在主機端做adb端口映射
adb forward tcp:3456 tcp:3456 //第一個 3456 為主機端口,第二個 3456 為目標板端口
在主機使用gdb
${PC端編譯工具鏈路徑}/arm-openwrt-linux-gnueabi-gdb process
主機端進行進入gdb界面,執行
target remote :
連接正確可開始調試程序,最開始會從_start函數開始,所以可以先執行下邊調試指令,進入 應用程序的main函數進行調試。
b main c
2.4 coredump.
2.4.1 介紹
程序運行過程中異常終止或崩潰,操作系統會將程序當時的內存狀態記錄下來,保存在一個文件中,這種行為就叫做CoreDump。
可以認為CoreDump是內存快照,但實際上,除了內存信息之外,還有些關鍵的程序運行狀態也會同時記錄下來,例如寄存器信息(包括程序指針、棧指針等)、內存管理信息、其他處理器和操作系統狀態和信息。
CoreDump對于調試程序是非常有幫助的,因為對于有些程序錯誤是很難重現的,例如指針異常,而CoreDump文件可以再現程序出錯時的情景。
技巧:man core 可以看到 core dump file 詳細說明。 man 7 signal 可以看到信號詳細說明。
2.4.2 配置
tina根目錄下,make kernel_menuconfig,選中以下配置。 Userspace binary formats --> [*] Enable core dump support 涉及到的內核配置:CONFIG_COREDUMP
2.4.3 配置生成coredump文件.
(1) ulimit -c unlimited; (2) echo ‘core.%e.%p’> /proc/sys/kernel/core_pattern;
(1)表示在異常時產生core dump文件,不對core dump文件的大小進行限制。
(2)指定core dump文件的存儲位置及名稱,表示產生的core文件中將帶有崩潰的程序名、以 及它的進程ID
core_pattern的格式說明: %%單個%字符 %p所dump進程的進程ID %u所dump進程的實際用戶ID %g所dump進程的實際組ID %s導致本次core dump的信號 %t core dump的時間(由 1970 年 1 月 1 日計起的秒數) %h主機名 %e程序文件名 具體可以通過man core查看
技巧: core dump 文件默認存放在 tmp 目錄下,如果有指定目錄 , 注意目錄必須存在, coredump 不支持創建目錄。 /proc/sys/ker-nel/core_uses_pid ,內容為 1 ,一定會加上進程 ID ,即使 core_pattern 中沒有 %p 。
2.4.4 通過gdb定位問題
生成coredump文件后(例如/tmp/core),gdb運行該文件:
./gdb coredump_sample /tmp/core
具體可以查看gdb或者gdbserver章節描述。
2.5 perf
2.5.1 介紹
Perf是從Linux 2.6開始引入的一個profiling工具,通過訪問包括pmu在內的軟硬件性能計數器來分析性能,支持多架構,是目前Kernel的主要性能檢測手段,和Kernel代碼一起發布,所以兼容性良好。
性能瓶頸如果要分類的話,大致可以分為幾個大類: cpu/gpu/mem/storage ,其中gpu用Perf沒法直接探測(這個目前比較好用的工具就只有DS5),storage一般用tracepoint來統計??偟恼f來,Perf還是側重于分析cpu的性能,其他功能都不是很好用。常用的功能有以下幾個。
record:收集profile數據
report:根據profile數據生成統計報告
stat:打印性能計數統計值
top:cpu占有率實時統計
2.5.2 配置
perf工具依賴內核選上PERF_EVENTS等配置,具體配置介紹如下:
支持perf基本功能選項,必須打開: CONFIG_PERF_EVENTS=y CONFIG_HW_PERF_EVENTS=y 支持堆棧跟蹤: CONFIG_FRAME_POINTER=y 支持解析內核和外部包符號,GCC編譯時加上-g選項: CONFIG_KALLSYMS=y 支持TRACEPOINTS: CONFIG_FTRACE=y 支持內核態動態跟蹤: CONFIG_KPROBES=y CONFIG_KPROBE_EVENT=y 支持用戶態動態tracepoint跟蹤: CONFIG_DEBUG_INFO=y //以下配置需要執行make kernel_menuconfig進行配置 支持用戶態動態跟蹤: CONFIG_UPROBES=y CONFIG_UPROBE_EVENTS=y 支持內核態lock跟蹤: CONFIG_LOCKDEP=y kernel lock tracing: CONFIG_LOCK_STAT=y 支持TRACEPOINTS: CONFIG_TRACEPOINTS=y
注意:部分內核不支持用戶態動態跟蹤,例如linux3.4,具體是否支持,內核搜索是否有該配置 選項即可。
上述介紹的配置都是內核的配置,Tina中直接通過make menuconfig可以選上部分配置,配 置方式如下:
tina根目錄下,make menuconfig,選中以下配置: Global build settings ---> [*] Compile the kernel with frame pointers [*] Compile the kernel with symbol table information -*- Compile the kernel with tracing support [*] Compile the kernel with kprobes support Development ---> <*> perf............. Linux performance monitoring tool
選上上述配置之后編譯即可,部分使用者需要修改 perf編譯工具的編譯參數,可配置pack- age/devel/perf/Makefile中MAKE_FLAGS參數,修改其中的NO_XXX=1。修改之后會新 增依賴,相應的先編譯依賴再編譯perf。
2.5.3 使用
root@TinaLinux:/# perf stat /bin/perftest Starting convolution! thread = 4 ,count = 2 Finished convolution! Time consumed 20 seconds. Performance counter stats for '/bin/perftest': 20236.937258 task-clock # 0.994 CPUs utilized 2404 context-switches # 0.119 K/sec 0 CPU-migrations # 0.000 K/sec 1572 page-faults # 0.078 K/sec 24241775385 cycles # 1.198 GHz stalled-cycles-frontend stalled-cycles-backend 7514299585 instructions # 0.31 insns per cycle 621110448 branches # 30.692 M/sec 1134868 branch-misses # 0.18% of all branches 20.352726051 seconds time elapsed
2.6 strace
2.6.1 介紹
Strace通過ptrace系統調用來跟蹤進程調用syscall的情況。
2.6.2 配置
tina根目錄下, 運行make menuconfig,選擇 Utilities ---> <*> strace............................ System call tracer
2.6.3 使用
strace啟動程序的同時用strace跟蹤。
strace -p pid對于已經啟動的程序通過-p參數attach上去。
2.7 valgrind.
2.7.1 介紹
Valgrind是一套Linux下,開放源代碼(GPLv2)的仿真調試工具的集合。由內核(core)以及基于內核的其他調試工具組成。內核類似于一個框架(framework),它模擬了一個CPU環境,并提供服務給其他工具;而其他工具則類似于插件(plug-in),利用內核提供的服務完成各種特定的內存調試任務。Valgrind包括以下工具,Tina平臺使用較多的工具是memcheck,用來檢查應用程序內存泄漏情況。
Memcheck:內存使用情況檢查。
Callgrind:收集程序運行時的一些數據,函數調用關系等信息。
Cachegrind:模擬CPU中的一級緩存I1,D1和L2二級緩存,能夠精確地指出程序中cache的丟失和命中。
Helgrind:用來檢查多線程程序中出現的競爭問題。
Massif:堆棧分析器,它能測量程序在堆棧中使用了多少內存,告訴我們堆塊,堆管理塊和棧 的大小。
2.7.2 配置
tina根目錄下, 運行make menuconfig,選擇 Development --> <*> valgrind .........................debugging and profiling tools for linux
2.7.3 使用
valgrind --tool=memcheck --leak-check=full {program}
2.8 輕量級日志永久轉存.
全志輕量級日志永久轉存方案依賴于內核原生的pstore文件系統,設計了pstore/blk模塊,配 合全志的Flash驅動,實現在內核奔潰時,自動把日志轉存到Flash中,并在開機后以文件形式 呈現到用戶空間。
此方案在全志釋放的Linux-4.9及之后的內核版本中支持,暫時不兼容Linux-3.4/3.10/4.4等 舊內核版本。
pstore/blk 模塊及其衍生的 pstore/zone , mtdpstore 模塊已合并進Linux社區。詳細的 使用文檔可參考社區內核文檔。
Documentation/admin-guide/pstore-blk.rst
全志的實現支持社區的所有Frontend功能,包括:
kmsg -內核Panic/Oops/emerg/restart/halt/poweroff時的日志信息。
pmsg -用戶空間的信息轉存(Android用于存儲系統日志)。
ftrace - ftrace信息。
console -串口終端信息。
在pstore中,kmsg前端基于kmsg_dump的機制,在最新的版本中支持所有的kmsg_dump_reason。kmsg_dump機制可以在特定時機出發回調,把內核的日志緩存log_buf導出。
在pstore中,pmsg是pstore提供的用戶空間轉存信息的方法。用戶空間程序把需要記錄的信息寫入到/dev/pmsg0的設備節點,在重啟時,即可在pstore的掛載目錄中獲取寫入的信息。在Android平臺把pmsg用于存儲系統日志。
當前不同存儲介質對Frontend的支持情況如下表。
表2-1: pstore支持的Frontend
介質 | panic | oops | pmsg | ftrace | console |
---|---|---|---|---|---|
nor | N | Y | N | N | N |
(ubi) | spinand | N | Y | N | N |
(nftl) | spinand | Y | Y | Y | Y |
mmc | Y | Y | Y | Y | Y |
rawnand | Y | Y | Y | Y | Y |
! 警告:并不是所有的 rawnand/(nftl) spinand 都支持所有的 Fronend 功能,以實際驅動為準。
2.8.1 使能日志轉存.
日志永久轉存的方案,除了內核使能pstore/blk之外,還需要為其提供一個專用分區。因此使能日志轉存有兩個步驟。
使能內核功能模塊
指定分區
2.8.1.1 使能內核功能模塊
進入內核的 menuconfig ,在Tina平臺可以在任意目錄執行: m kernel_menuconfig
[kernel menuconfig] |-> File systems |-> Miscellaneous filesystems |-> [*] Persistent store support |-> Log panic/oops to a block device |-> block device identifier |-> Size in Kbytes of kmsg dump log to store |-> Maximum kmsg dump reason to store |-> Size in Kbytes of pmsg to store |-> Size in Kbytes of console to store
上述的屬性配置,例如 block device identifier 可以通過 h 按鍵獲取詳細的說明。這些屬性 配置同時支持Kconfig和Module Parameters的兩種配置方式,且 Module Parameters 具 有更高的優先級。
block device identifier 指定使用的塊設備
Size in Kbytes of kmsg dump log to store 為kmsg前端分配的空間大小
Maximum kmsg dump reason to store kmsg dumper支持的reason最大值(見enum kmsg_dump_reason)
Size in Kbytes of pmsg to store 為pmsg前端分配的空間大小
Size in Kbytes of console to store 為console前端分配的空間大小
技巧:block device identifier 見指定分區章節,其他屬性使用默認配置即可。
2.8.1.2 指定分區
為內核pstore/blk模塊指定使用的塊設備分區,首先我們創建一個小容量分區,容量大小建議 [256K-1M] ,參考下表。
表2-2: pstore分區大小建議
Flash容量 | 建議大小 |
---|---|
容量<= 128M | 256K |
128M <容量<= 1G | 512K |
容量> 1G | 1M |
在sys_partition.fex中添加pstore分區,例如:
[partition] name = pstore size = 512 user_type = 0x
在創建了分區后,需要“告知”內核模塊使用哪個分區。如上文所述,目前為止pstore/blk支 持Kconfig和Module Parameters兩種配置方式。Kconfig比較簡單,因此下文主要是講解 Module Parameters的配置方式。
Module Parameter要不在手動加載模塊時指定:
# insmod pstore_blk.ko blkdev=XXXX
如果是編譯進內核,需要在內核 cmdline 中添加內核模塊參數。
在全志平臺,需要修改 env-XXX.cfg 。在對應存儲介質的 setargs_XXX 中添加如下內容。
pstore_blk.blkdev=<分區路徑>
例如:
setargs_mmc=... pstore_blk.blkdev=/dev/mmcblk0p ...
除了路徑之外,還可以使用如下的形式。
pstore_blk.blkdev=<主設備號:次設備號>
其中 主設備號 表示的存儲介質, 次設備號 代指哪個分區。
我們可以在進入到命令行后,通過ll命令獲取主次設備號,例如:
$ ll /dev/mmcblk0* brw------- 1 root root 179, 0 Jan 2 04:20 /dev/mmcblk brw------- 1 root root 179, 16 Jan 2 04:20 /dev/mmcblk0boot brw------- 1 root root 179, 32 Jan 2 04:20 /dev/mmcblk0boot brw------- 1 root root 179, 1 Jan 2 04:20 /dev/mmcblk0p brw------- 1 root root 179, 2 Jan 2 04:20 /dev/mmcblk0p brw------- 1 root root 179, 3 Jan 2 04:20 /dev/mmcblk0p brw------- 1 root root 179, 5 Jan 2 04:20 /dev/mmcblk0p
以 /dev/mmcblk0p5 為例, 主設備號是 179 ,從設備號是 5 ,因此cmdline可以寫為blkoops.blkdev=179:
下面進一步說明 pstore分區 的對應關系:
在Tina個別平臺做了進一步封裝,只需要在 env-XXXX.cfg 中添加blkoops_partition=<分區名>和blkoops_blkdev=<分區路徑|設備號>,例如:
blkoops_partition=pstore #分區名對應sys_partition.fex blkoops_blkdev=93:7 #可先任意寫一個 setargs_nand=... pstore_blk.blkdev=${blkoops_blkdev} ...
uboot則會根據blkoops_partition的分區名,自動匹配和修改blkoops_blkdev。
對于不支持進一步封裝的方案,可在啟動后查詢cmdline的partitions參數,例如:
$ cat /proc/cmdline .... partitions=boot-res@mmcblk0p2:env@mmcblk0p5:boot@mmcblk0p6....
OK,到此日志永久轉存的功能已經使能。
2.8.2 獲取奔潰日志.
2.8.2.1 掛載文件系統.
全志輕量級日志轉存的方案基于的是pstore文件系統,因此需要掛載文件系統后才能使用。
在Tina平臺中,pstore文件系統已經實現默認開機自動掛載,可以通過 mount 命令確認,例如:
# mount ··· pstore on /sys/fs/pstore type pstore (rw,relatime) ···
Android平臺,需要自行實現掛載,掛載命令可參考:
mount -t pstore pstore /sys/fs/pstore
掛載后,在觸發日志轉存重啟后,可以在掛載點 /sys/fs/pstore 中可獲取奔潰日志文件,例如:
root@TinaLinux:/sys/fs/pstore# ll drwxr-x--- 2 root root 0 Jan 1 1970. drwxr-xr-x 5 root root 0 Jan 1 1970 .. -r--r--r-- 1 root root 15504 Mar 19 19:39 dmesg-pstore-blk- -r--r--r-- 1 root root 15881 Mar 19 19:39 dmesg-pstore-blk- -r--r--r-- 1 root root 2 Jan 1 1970 pmsg-pstore-blk- root@TinaLinux:/sys/fs/pstore#
可以通過命令 echo c > /proc/sysrq-trigger 主動觸發內核奔潰以驗證功能。
2.8.2.2 讀取文件
奔潰日志會以文件形式呈現到掛載點,一次奔潰一份日志,文件名格式如下。
<日志類型>-pstore-blk-<編號>
我們可通過標準的IO接口訪問導出的日志文件。
我們可以通過名字區分dmesg日志記錄和psmg日志記錄,但dmseg日志記錄如何細分pan-ic/oops/oom呢?
在dmesg日志記錄的第一行可以進一步細分日志類型和觸發次數累計,例如:
root@TinaLinux:/sys/fs/pstore# head -n 3 dmesg-pstore-blk- OOM: Total 8 times OOM#8 Part <4>[ 95.111229] [] (do_page_fault) from [] (do_PrefetchAbort+0x38/ x9c)
除此之外, 文件時間表示的是奔潰觸發時間
2.8.2.3 刪除文件
可以直接刪除生成的日志文件
rm /sys/fs/pstore/*
對使用mtdpstore模塊的spinor/(ubi) spinand存儲方案,考慮到存儲物料的擦除特性,當同 時存在多個連續文件,且剛好這些文件數據存儲在同一個物理塊內時,要把同一個塊內的文件全 部刪除后才會真正刪除文件。
2.8.3 高級功能配置.
2.8.3.1 分區的空間分布
默認情況下,pstore/blk的每一份記錄為64K。意味著如果分區大小為256K,則一共能同時存 在 4 份記錄。假設只使能kmsg和pmsg的記錄,此時分區的劃分情況大致如下表:
表2-3: pstore分區分布
0 - 64K | 64k - 128K | 128K - 192K | 192K - 256 K |
---|---|---|---|
pmsg | dmesg.0 | dmesg.1 | dmesg. |
顯而易見,在劃分了pmsg的空間后,剩余的空間全部分配給dmesg。
2.8.3.2 高級功能
內核模塊通過cmdline中傳遞模塊參數,可設置高級功能。日志永久轉存模塊支持以下模塊參 數。推薦使用默認配置
表2-4: pstore支持參數
模塊名 | 功能 | 示例 | 默認值 |
---|---|---|---|
pstore_blk.blkdev | 供blkoops使用的分區 | pstore_blk.blkdev=179:10 | NULL |
pstore_blk.oops_size | dmesg記錄大小 | pstore_blk.oops_size=64 | 64KB |
pstore_blk.pmsg_size | pmsg記錄大小 | pstore_blk.pmsg_size=64 | 64KB |
pstore_blk.console_size | console記錄大小 | pstore_blk.console_size=64 | 64KB |
pstore_blk.ftrace_size | ftrace記錄大小 | pstore_blk.ftrace_size=64 | 64KB |
pstore_blk.dump_oops | 是否記錄Oops日志 | pstore_blk.dump_oops=1 | True |
pstore.update_ms | 定時刷新日志信息 | pstore.update_ms=1000 | -1 |
技巧:默認情況下,只有重啟后才會刷新 pstore 的記錄,除非使能了 pstore.update_ms 。
審核編輯黃宇
-
Linux
+關注
關注
87文章
11230瀏覽量
208934 -
內存
+關注
關注
8文章
3002瀏覽量
73887 -
Tina
+關注
關注
2文章
45瀏覽量
16957 -
系統
+關注
關注
1文章
1008瀏覽量
21316
發布評論請先 登錄
相關推薦
評論