在嵌入式系統(tǒng)(如基于瑞芯微RK3399的Android設(shè)備)開發(fā)或維護中,系統(tǒng)常因內(nèi)核崩潰(Panic)、用戶空間異常等突發(fā)情況重啟,導(dǎo)致關(guān)鍵日志丟失。此時,Last Log(依托Linux內(nèi)核的ramoops機制實現(xiàn))可在系統(tǒng)異常時保存核心日志,為事后故障分析提供關(guān)鍵依據(jù)。本文將詳細(xì)介紹其配置方法與問題排查實踐,并通過具體案例演示實戰(zhàn)流程。

一、Last Log的核心:Ramoops機制
ramoops是Linux內(nèi)核的一項功能——它會預(yù)留一段固定內(nèi)存區(qū)域,當(dāng)系統(tǒng)發(fā)生異常(如內(nèi)核Panic、意外重啟)時,自動將關(guān)鍵日志(內(nèi)核日志、用戶空間日志、函數(shù)追蹤等)寫入該區(qū)域。由于這段內(nèi)存的特殊性,系統(tǒng)重啟后數(shù)據(jù)不會丟失,可通過/sys/fs/pstore目錄訪問這些“遺留日志”,進而分析故障根因。
二、配置Ramoops,啟用Last Log
要啟用Last Log,需在**設(shè)備樹(DTS)**中添加ramoops相關(guān)節(jié)點,為其分配內(nèi)存并定義日志參數(shù)。
2.1設(shè)備樹節(jié)點添加
在設(shè)備樹源文件(.dts)中,添加以下兩個節(jié)點(需根據(jù)硬件內(nèi)存布局調(diào)整參數(shù)):
ramoops_mem: ramoops_mem {reg = <0x00x1100000x00xf0000>; /* 預(yù)留內(nèi)存的起始地址與大小 */reg-names ="ramoops_mem"; /* 內(nèi)存區(qū)域命名,供后續(xù)引用 */};ramoops {compatible ="ramoops"; /* 與內(nèi)核ramoops驅(qū)動兼容 */record-size = <0x00x20000>; /* 單個日志記錄的大小 */console-size = <0x00x80000>; /* 內(nèi)核控制臺日志(last_log)的空間 */ftrace-size = <0x00x00000>; /* 函數(shù)追蹤(ftrace)日志的空間 */pmsg-size = <0x00x50000>; /* 用戶空間日志(如Android logcat)的空間 */memory-region = <&ramoops_mem>; /* 引用上面定義的內(nèi)存區(qū)域 */};
2.2節(jié)點參數(shù)詳解
?ramoops_mem節(jié)點:負(fù)責(zé)定義預(yù)留內(nèi)存區(qū)域。
?reg = <起始地址 地址長度...>:指定內(nèi)存的起始地址與大小(需確保該區(qū)域不與其他模塊內(nèi)存沖突)。
?reg-names = "ramoops_mem":為內(nèi)存區(qū)域命名,方便ramoops節(jié)點引用。
?ramoops節(jié)點:負(fù)責(zé)配置ramoops的行為。
?compatible = "ramoops":聲明與內(nèi)核ramoops驅(qū)動兼容,確保驅(qū)動能識別并使用該節(jié)點。
?record-size/console-size/ftrace-size/pmsg-size:分別指定“單條日志”“內(nèi)核控制臺日志”“函數(shù)追蹤日志”“用戶空間日志”的預(yù)留空間大小。
?memory-region = <&ramoops_mem>:指定日志存儲的目標(biāo)內(nèi)存區(qū)域(即前面定義的ramoops_mem)。
三、查看與解析Last Log
系統(tǒng)重啟后,可通過/sys/fs/pstore目錄訪問Last Log文件。不同文件對應(yīng)不同類型的日志,需結(jié)合場景選擇查看。
3.1訪問日志文件
通過命令行進入/sys/fs/pstore目錄,列出所有日志文件:
cd/sys/fs/pstorels
以RK3399設(shè)備為例,通常會看到以下文件(不同場景下文件存在性不同):
?dmesg-ramoops-0:內(nèi)核Panic后保存的日志,記錄內(nèi)核崩潰前的關(guān)鍵調(diào)用棧、錯誤信息。
?pmsg-ramoops-0:用戶空間日志(如Android系統(tǒng)的logcat日志),記錄應(yīng)用、系統(tǒng)服務(wù)的運行信息。
?ftrace-ramoops-0:函數(shù)追蹤(ftrace)日志,記錄指定時間段內(nèi)的函數(shù)調(diào)用流程,用于性能分析。
?console-ramoops-0:上次啟動的內(nèi)核日志(last_log),但僅保存優(yōu)先級高于默認(rèn)日志級別的日志。
3.2日志查看命令
根據(jù)日志類型,使用不同命令查看內(nèi)容:
?查看內(nèi)核Panic日志:
catdmesg-ramoops-0
?查看上次內(nèi)核高優(yōu)先級日志(last_log):
catconsole-ramoops-0
?解析用戶空間日志(如Android logcat):
logcat-L pmsg-ramoops-0
(通過logcat工具解析后,日志格式更符合Android開發(fā)習(xí)慣)
?查看函數(shù)追蹤日志:
catftrace-ramoops-0
四、實戰(zhàn):用Last Log排查典型問題(含具體案例)
以下通過內(nèi)核空指針、Android應(yīng)用ANR、驅(qū)動初始化失敗三個典型場景,演示Last Log的排查流程。
案例1:內(nèi)核空指針解引用導(dǎo)致系統(tǒng)Panic重啟
現(xiàn)象:設(shè)備運行過程中突然黑屏重啟,無明顯操作觸發(fā)。
排查步驟:
1.系統(tǒng)重啟后,進入/sys/fs/pstore目錄,查看內(nèi)核Panic日志:
catdmesg-ramoops-0
1.日志關(guān)鍵內(nèi)容(示例):
Kernel panic - not syncing: Null pointer dereferenceCPU: 0 PID: 1234 Comm: problem_process Tainted: G W ...Call trace:[<ffffffc0002a3450>] dump_backtrace+0x0/0x180[<ffffffc0002a3830>] show_stack+0x10/0x20[<ffffffc000a55080>] dump_stack+0xd8/0x134[<ffffffc0002f4f2c>] panic+0x18c/0x334[<ffffffc0000a2b50>] __do_page_fault+0x3a0/0x480...[<ffffffc0008b1234>] problematic_driver_function+0x20/0x80 [problematic_driver]
1.分析:日志中Null pointer dereference明確存在空指針解引用問題;Call trace的堆棧追蹤顯示,故障源于problematic_driver模塊的problematic_driver_function函數(shù)。由此可定位到該驅(qū)動存在“未正確初始化指針就解引用”的代碼邏輯問題,需修改驅(qū)動代碼(如增加指針有效性檢查)并重新測試。
案例2:Android應(yīng)用頻繁ANR(應(yīng)用無響應(yīng))
現(xiàn)象:某社交應(yīng)用打開后幾秒內(nèi)提示“應(yīng)用無響應(yīng)”,強制關(guān)閉后再次打開仍異常。
排查步驟:
1.應(yīng)用觸發(fā)ANR后,進入/sys/fs/pstore目錄,解析用戶空間日志:
logcat-L pmsg-ramoops-0
1.日志關(guān)鍵內(nèi)容(示例):
09-2214:30:00.12312345678E AndroidRuntime: FATAL EXCEPTION: main09-2214:30:00.12312345678E AndroidRuntime: Process: com.example.social, PID:123409-2214:30:00.12312345678E AndroidRuntime: java.lang.RuntimeException: ANR in com.example.social...09-2214:30:00.12312345678E AndroidRuntime: Caused by: android.os.DeadlineExceededException: Main thread idle timeout of5seconds expired...09-2214:30:00.12312345678E AndroidRuntime: at com.example.social.MainActivity.loadLargeImageSync(MainActivity.java:123)
1.分析:日志中ANR與DeadlineExceededException表明“主線程因耗時操作被阻塞”;調(diào)用棧顯示,MainActivity的loadLargeImageSync方法(同步加載大圖片)導(dǎo)致主線程卡頓超過5秒。需將該方法改為異步加載(如使用AsyncTask或線程池),避免主線程被長時間占用。
案例3:設(shè)備啟動卡在logo界面,驅(qū)動初始化失敗
現(xiàn)象:設(shè)備上電后,屏幕一直停留在廠商logo界面,無法進入系統(tǒng)。
排查步驟:
1.強制重啟設(shè)備(或等待自動重啟)后,進入/sys/fs/pstore目錄,查看高優(yōu)先級內(nèi)核日志:
catconsole-ramoops-0
1.日志關(guān)鍵內(nèi)容(示例):
[ 2.345678] problematic_driver: probe of1-001a failed witherror-110[ 2.345789] platform12340000.device: Driver problematic_driver failed to probe[ 2.345890] Kernelpanic- not syncing: Essential driver failed to initialize
1.分析:日志中probe of 1-001a failed with error -110表明problematic_driver在探測硬件設(shè)備(I2C地址1-001a)時失?。ㄥe誤碼-110對應(yīng)“操作超時”);且該驅(qū)動屬于“核心驅(qū)動”,直接導(dǎo)致內(nèi)核Panic。需檢查兩方面:
?硬件層面:確認(rèn)I2C設(shè)備是否存在、供電是否正常、硬件連線是否松動;
?驅(qū)動層面:修改驅(qū)動的“探測超時時間”,或增加硬件存在性檢測邏輯。
五、總結(jié)
通過配置ramoops啟用Last Log,能在系統(tǒng)異常時“留存”關(guān)鍵日志,為嵌入式系統(tǒng)(尤其是無持久化日志存儲的場景)的問題排查提供有力支持。結(jié)合/sys/fs/pstore下的不同日志文件,可覆蓋內(nèi)核Panic、用戶空間異常、性能追蹤、啟動故障等多個維度的分析;再通過“現(xiàn)象-操作-日志分析-根因定位”的實戰(zhàn)流程,能高效解決各類系統(tǒng)問題,是提升系統(tǒng)穩(wěn)定性的核心調(diào)試工具。
-
嵌入式系統(tǒng)
+關(guān)注
關(guān)注
41文章
3747瀏覽量
133639 -
內(nèi)核
+關(guān)注
關(guān)注
4文章
1468瀏覽量
42880 -
瑞芯微
+關(guān)注
關(guān)注
27文章
794瀏覽量
54325
發(fā)布評論請先 登錄
恩智浦解讀Zephyr log系統(tǒng)的使用 Zephyr的shell和log功能介紹
全棧開發(fā)進階指南:LuatOS-log庫從入門到實戰(zhàn)!
Flink on YARN(下):常見問題與排查思路
Flink on YARN(下):常見問題與排查思路
談一談Firefly Android系統(tǒng)的功能
分享幾種RK3399開啟ramoops查看kernel log的方法
嵌入式系統(tǒng)log模塊設(shè)計
Linux主機排查腳本介紹
嵌入式Linux上使用Ramoops的代碼應(yīng)用
利用Last Log(Ramoops)排查系統(tǒng)問題:配置與實踐指南
評論