鴻蒙OH南向開發 輕量系統內核(LiteOS-M)【異常調測】

基本概念

OpenHarmony LiteOS-M提供異常接管調測手段,幫助開發者定位分析問題。異常接管是操作系統對運行期間發生的異常情況進行處理的一系列動作,例如打印異常發生時異常類型、發生異常時的系統狀態、當前函數的調用棧信息、CPU現場信息、任務調用堆棧等信息。

運行機制

棧幀用于保存函數調用過程中的函數參數、變量、返回值等信息。調用函數時,會創建子函數的棧幀,同時將函數入參、局部變量、寄存器入棧。棧幀從高地址向低地址生長。以ARM32 CPU架構為例,每個棧幀中都會保存PC、LR、SP和FP寄存器的歷史值。LR鏈接寄存器(Link Register)指向函數的返回地址,FP幀指針寄存器(Frame Point)指向當前函數的父函數的棧幀起始地址。利用FP寄存器可以得到父函數的棧幀,從棧幀中獲取父函數的FP,就可以得到祖父函數的棧幀,以此類推,可以追溯程序調用棧,得到函數間的調用關系。

當系統發生異常時,系統打印異常函數的棧幀中保存的寄存器內容,以及父函數、祖父函數的棧幀中的LR鏈接寄存器、FP幀指針寄存器內容,用戶就可以據此追溯函數間的調用關系,定位異常原因。

堆棧分析原理如下圖所示,實際堆棧信息根據不同CPU架構有所差異,此處僅做示意。

圖1 堆棧分析原理示意圖

圖中不同顏色的寄存器表示不同的函數。可以看到函數調用過程中,寄存器的保存。通過FP寄存器,棧回溯到異常函數的父函數,繼續按照規律對棧進行解析,推出函數調用關系,方便用戶定位問題。

接口說明

OpenHarmony LiteOS-M內核的回溯棧模塊提供以下接口,接口詳細信息可以查看API參考。

表1 回溯棧模塊接口

接口名功能
LOS_BackTrace打印調用處的函數調用棧關系。
LOS_RecordLR在無法打印的場景,用該接口獲取調用處的函數調用棧關系。

使用指導

開發流程
開啟異常調測的典型流程如下:

  1. 配置異常接管相關宏。

需要在target_config.h頭文件中修改配置:

配置項含義設置值
LOSCFG_BACKTRACE_DEPTH函數調用棧深度,默認15層15
LOSCFG_BACKTRACE_TYPE回溯棧類型:
0:表示關閉該功能;
1:表示支持Cortex-m系列硬件的函數調用棧解析;
2:表示用于Risc-v系列硬件的函數調用棧解析;
根據工具鏈類型設置1或2


2. 使用示例中有問題的代碼,編譯、運行工程,在串口終端中查看異常信息輸出。示例代碼模擬異常代碼,實際產品開發時使用異常調測機制定位異常問題。
本示例演示異常輸出,包含1個任務,該任務入口函數模擬若干函數調用,最終調用一個模擬異常的函數。代碼實現如下:

本演示代碼在./kernel/liteos_m/testsuites/src/osTest.c中編譯驗證,在TestTaskEntry中調用驗證入口函數ExampleExcEntry。

    #include <stdio.h>#include "los_config.h"#include "los_interrupt.h"#include "los_task.h"UINT32 g_taskExcId;#define TSK_PRIOR 4/* 模擬異常函數 */UINT32 GetResultException0(UINT16 dividend){UINT32 result = *(UINT32 *)(0xffffffff);printf("Enter GetResultException0\. %u\r\n", result);return result;}UINT32 GetResultException1(UINT16 dividend){printf("Enter GetResultException1.\r\n");return GetResultException0(dividend);}UINT32 GetResultException2(UINT16 dividend){printf("Enter GetResultException2.\r\n");return GetResultException1(dividend);}UINT32 ExampleExc(VOID){UINT32 ret;printf("Enter Example_Exc Handler.\r\n");/* 模擬函數調用 */ret = GetResultException2(TSK_PRIOR);printf("Divided result =%u.\r\n", ret);printf("Exit Example_Exc Handler.\r\n");return ret;}/* 任務測試入口函數,創建一個會發生異常的任務 */UINT32 ExampleExcEntry(VOID){UINT32 ret;TSK_INIT_PARAM_S initParam = { 0 };/* 鎖任務調度,防止新創建的任務比本任務高而發生調度 */LOS_TaskLock();printf("LOS_TaskLock() Success!\r\n");initParam.pfnTaskEntry = (TSK_ENTRY_FUNC)ExampleExc;initParam.usTaskPrio = TSK_PRIOR;initParam.pcName = "Example_Exc";initParam.uwStackSize = LOSCFG_BASE_CORE_TSK_DEFAULT_STACK_SIZE;/* 創建高優先級任務,由于鎖任務調度,任務創建成功后不會馬上執行 */ret = LOS_TaskCreate(&g_taskExcId, &initParam);if (ret != LOS_OK) {LOS_TaskUnlock();printf("Example_Exc create Failed!\r\n");return LOS_NOK;}printf("Example_Exc create Success!\r\n");/* 解鎖任務調度,此時會發生任務調度,執行就緒隊列中最高優先級任務 */LOS_TaskUnlock();return LOS_OK;}


述代碼串口終端輸出異常信息如下:

    LOS_TaskLock() Success!Example_Exc create Success!Enter Example_Exc Handler.Enter GetResultException2.Enter GetResultException1.*************Exception Information**************Type      = 4ThrdPid   = 5Phase     = exc in taskFaultAddr = 0xfffffffcCurrent task info:Task name = Example_ExcTask ID   = 5Task SP   = 0x210549bcTask ST   = 0x21053a00Task SS   = 0x1000Exception reg dump:PC        = 0x2101c61aLR        = 0x2101c64dSP        = 0x210549a8R0        = 0x4R1        = 0xaR2        = 0x0R3        = 0xffffffffR4        = 0x2103fb20R5        = 0x5050505R6        = 0x6060606R7        = 0x210549a8R8        = 0x8080808R9        = 0x9090909R10       = 0x10101010R11       = 0x11111111R12       = 0x0PriMask   = 0x0xPSR      = 0x41000000----- backtrace start -----backtrace 0 -- lr = 0x2101c64cbacktrace 1 -- lr = 0x2101c674backtrace 2 -- lr = 0x2101c696backtrace 3 -- lr = 0x2101b1ec----- backtrace end -----TID  Priority   Status StackSize WaterLine StackPoint TopOfStack EventMask  SemID  CPUUSE CPUUSE10s CPUUSE1s   TaskEntry name---  -------- -------- --------- --------- ---------- ---------- --------- ------ ------- --------- --------  ---------- ----0        0      Pend    0x1000      0xdc 0x2104730c 0x210463e8         0 0xffff     0.0       0.0      0.0  0x2101a199 Swt_Task1       31     Ready     0x500      0x44 0x210478e4 0x21047428         0 0xffff     0.0       0.0      0.0  0x2101a9c9 IdleCore0002        5  PendTime    0x6000      0xd4 0x2104e8f4 0x210489c8         0 0xffff     5.7       5.7      0.0  0x21016149 tcpip_thread3        3      Pend    0x1000     0x488 0x2104f90c 0x2104e9e8       0x1 0xffff     8.6       8.6      0.0  0x21016db5 ShellTaskEntry4       25     Ready    0x4000     0x460 0x21053964 0x2104f9f0         0 0xffff     9.0       8.9      0.0  0x2101c765 IT_TST_INI5        4   Running    0x1000     0x458 0x210549bc 0x21053a00         0 0xffff    76.5      76.6      0.0  0x2101c685 Example_ExcOS exception NVIC dump:interrupt enable register, base address: 0xe000e100, size: 0x200x2001 0x0 0x0 0x0 0x0 0x0 0x0 0x0interrupt pending register, base address: 0xe000e200, size: 0x200x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0interrupt active register, base address: 0xe000e300, size: 0x200x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0interrupt priority register, base address: 0xe000e400, size: 0xf00x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x00x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x00x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x00x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0interrupt exception register, base address: 0xe000ed18, size: 0xc0x0 0x0 0xf0f00000interrupt shcsr register, base address: 0xe000ed24, size: 0x40x70002interrupt control register, base address: 0xe000ed04, size: 0x40x1000e805memory pools check:system heap memcheck over, all passed!memory pool check end!根據實際運行環境,上文中的數據會有差異,非固定結果

定位流程
異常接管一般的定位步驟如下:

  1. 確認編譯時關掉優化選項,否則下述的描述內容可能被優化掉。
  2. 打開編譯后生成的鏡像反匯編(asm)文件。如果默認沒有生成,可以使用objdump工具生成,命令為:
    arm-none-eabi-objdump -S -l XXX.elf


3. 搜索PC指針(指向當前正在執行的指令)在asm中的位置,找到發生異常的函數。
PC地址指向發生異常時程序正在執行的指令。在當前執行的二進制文件對應的asm文件中,查找PC值0x2101c61a,找到當前CPU正在執行的指令行,反匯編如下所示:

    2101c60c <GetResultException0>:2101c60c:	b580      	push	{r7, lr}2101c60e:	b084      	sub	sp, #162101c610:	af00      	add	r7, sp, #02101c612:	4603      	mov	r3, r02101c614:	80fb      	strh	r3, [r7, #6]2101c616:	f04f 33ff 	mov.w	r3, #4294967295	; 0xffffffff2101c61a:	681b      	ldr	r3, [r3, #0]2101c61c:	60fb      	str	r3, [r7, #12]2101c61e:	68f9      	ldr	r1, [r7, #12]2101c620:	4803      	ldr	r0, [pc, #12]	; (2101c630 <GetResultException0+0x24>)2101c622:	f001 f92b 	bl	2101d87c <printf>2101c626:	68fb      	ldr	r3, [r7, #12]2101c628:	4618      	mov	r0, r32101c62a:	3710      	adds	r7, #162101c62c:	46bd      	mov	sp, r72101c62e:	bd80      	pop	{r7, pc}2101c630:	21025f90 	.word	0x21025f90

4. 可以看到:

  1. 異常時CPU正在執行的指令是ldr r3, [r3, #0],其中r3取值為0xffffffff,導致發生非法地址異常。
  2. 異常發生在函數GetResultException0中。

5. 根據LR值查找異常函數的父函數。

包含LR值0x2101c64d的反匯編如下所示:

    2101c634 <GetResultException1>:2101c634:	b580      	push	{r7, lr}2101c636:	b082      	sub	sp, #82101c638:	af00      	add	r7, sp, #02101c63a:	4603      	mov	r3, r02101c63c:	80fb      	strh	r3, [r7, #6]2101c63e:	4806      	ldr	r0, [pc, #24]	; (2101c658 <GetResultException1+0x24>)2101c640:	f001 f91c 	bl	2101d87c <printf>2101c644:	88fb      	ldrh	r3, [r7, #6]2101c646:	4618      	mov	r0, r32101c648:	f7ff ffe0 	bl	2101c60c <GetResultException0>2101c64c:	4603      	mov	r3, r02101c64e:	4618      	mov	r0, r32101c650:	3708      	adds	r7, #82101c652:	46bd      	mov	sp, r72101c654:	bd80      	pop	{r7, pc}2101c656:	bf00      	nop2101c658:	21025fb0 	.word	0x21025fb0

6. LR值2101c648上一行是bl 2101c60c ,此處調用了異常函數,調用異常函數的父函數為GetResultException1。

7. 重復步驟3,解析異常信息中backtrace start至backtrace end之間的LR值,得到調用產生異常的函數調用棧關系,找到異常原因。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/86444.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/86444.shtml
英文地址,請注明出處:http://en.pswp.cn/web/86444.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

算法-堆排序

文章目錄 整體架構流程技術細節小結 整體架構流程 大頂推&#xff1a;是構建一個完整的二叉樹 大頂推&#xff1a;即父節點的值大于左右子樹的值。 循環構建大頂推 在給定的數組&#xff0c;既可以明確樹的高度。 在循環的時候&#xff0c;構建樹的高度從lgn至0。即從堆低往堆…

【鴻蒙HarmonyOS Next App實戰開發】二維碼生成技術實現與解析

隨著移動應用開發中對便捷交互體驗的需求日益增長&#xff0c;二維碼作為信息傳遞的重要載體&#xff0c;其生成與使用變得越來越普遍。本文將基于鴻蒙HarmonyOS應用開發框架&#xff0c;詳細介紹如何實現一個功能完備的二維碼生成器&#xff0c;并附上完整代碼解析。 注意該實…

1 Studying《Is Parallel Programming Hard》6-9

目錄 Chapter 6 Partitioning and Synchronization Design 6.1 分區練習 6.2 設計準則 6.3 同步粒度 6.4 并行快速路徑 6.5 超越黨派分歧 6.6 分區、并行和優化 Chapter 7 Locking 7.1 活命 7.2 鎖的類型 7.3 鎖定實施問題 7.4 基于鎖的存在性保證 7.5 鎖定&a…

Java練習題精選16-20

Java練習題精選16-20 一、第十六題二、第十七題三、第十八題四、第十九題五、第二十題一、第十六題 現有一個存放學生成績的數組{66, 77, 88, 99},要求將該數組正序輸出每個下標所對應的元素。 public class Test {public static void main(String[] args) {int<

新能源知識庫(68)汽車電鍍與蒸汽

汽車電鍍是提升零部件耐磨性、抗腐蝕性和美觀性的關鍵工藝&#xff0c;其流程根據基材&#xff08;金屬或塑料&#xff09;和部件功能需求有所差異。 汽車電鍍是以 基材特性和 功能需求為導向的精密工藝&#xff1a; ?金屬件?&#xff1a;核心流程為 ?除油→酸洗→電鍍→鈍…

Veo 3 視頻生成大模型完整操作教程(2025)

隨著 AI 多模態能力的飛躍&#xff0c;Google DeepMind 發布的 Veo 3 成為了生成視頻領域的一顆重磅炸彈。它不僅能夠根據文本生成高質量的視頻畫面&#xff0c;還能同步生成對白、背景音和環境音&#xff0c;是目前最接近真正“AI 導演”的大模型。 本文將帶你詳細了解 Veo 3…

10【認識文件系統】

1 認識硬件——磁盤 1.1 物理構成 磁盤是計算機中唯一的機械設備&#xff0c;同時也是一種外部存儲設備&#xff08;外設&#xff09;。早期的計算機通常配備的是機械硬盤&#xff08;HDD&#xff09;&#xff0c;依靠磁頭和盤片的機械運動來進行數據的讀寫。但隨著用戶對計算…

Windows命令連接符的安全風險分析與防御策略

1. 命令連接符簡介 在 Windows 的命令行環境&#xff08;CMD/PowerShell&#xff09;中&#xff0c;命令連接符用于在同一行執行多個命令&#xff0c;提高效率。然而&#xff0c;攻擊者常利用這些符號構造惡意命令&#xff0c;繞過安全檢測或執行多階段攻擊。 常見命令連接符…

大屏可視化制作指南

一、大屏可視化概述 &#xff08;一&#xff09;概念 大屏可視化是指通過大屏幕展示復雜數據的視覺呈現形式&#xff0c;它借助圖形、圖表、地圖等元素&#xff0c;將海量數據以直觀易懂的方式呈現出來&#xff0c;幫助用戶快速理解數據背后的含義和價值。 &#xff08;二&a…

Halcon ——— OCR字符提取與多類型識別技術詳解

工業視覺實戰&#xff1a;OCR字符提取與多類型識別技術詳解 在工業自動化領域&#xff0c;OCR字符提取是產品追溯、質量控制和信息讀取的核心技術。本文將深入解析Halcon中OCR字符提取的全流程&#xff0c;重點解釋核心算子參數&#xff0c;并提供完整的工業級代碼實現。 一、O…

嵌入式項目:基于QT與Hi3861的物聯網智能大棚集成控制系統

關鍵詞&#xff1a;MQTT、物聯網、QT、網絡連接、遠程控制 一、系統概述 本系統是一套完整的智能大棚監控解決方案&#xff0c;由兩部分構成&#xff1a; 基于Hi3861的嵌入式硬件系統&#xff08;負責環境數據采集和設備控制&#xff09;基于Qt開發的跨平臺控制軟件&#xf…

揭開 Git 裸倉庫的神秘面紗:`git clone --mirror` 詳解與使用指南

大家好&#xff01;在使用 Git 進行版本控制時&#xff0c;我們最熟悉的莫過于那些帶有工作目錄的本地倉庫了——我們在里面編輯文件、提交代碼&#xff0c;然后推送到遠程倉庫。但有時候&#xff0c;我們可能會遇到一種特殊的倉庫&#xff1a;裸倉庫&#xff08;Bare Reposito…

opensuse安裝rabbitmq

您好&#xff01;安裝 RabbitMQ 消息隊列是一個非常棒的選擇&#xff0c;它是許多現代應用架構中的核心組件。 在 openSUSE Tumbleweed 上安裝 RabbitMQ 主要有兩種流行的方式&#xff1a;一種是使用系統的包管理器 zypper&#xff0c;另一種是使用 Docker 容器。我將為您詳細…

超詳細YOLOv8/11圖像菜品分類全程概述:環境、數據準備、訓練、驗證/預測、onnx部署(c++/python)詳解

文章目錄 一、環境準備二、數據準備三、訓練四、驗證與預測五、模型部署 一、環境準備 我的都是在Linux系統下&#xff0c;訓練部署的&#xff1b;模型訓練之前&#xff0c;需要配置好環境&#xff0c;Anaconda、顯卡驅動、cuda、cudnn、pytorch等&#xff1b; 參考&#xff1…

JUC:4.線程常見操作與兩階段終止模式

在線程中&#xff0c;wait()、join()、sleep()三個方法都是進行阻塞的方法。對應可以使用interrupt()方法進行打斷&#xff0c;被打斷后線程會拋出打斷異常&#xff0c;但是不會修改IsInterrupt&#xff0c;也就是此時去調用IsInterrupted()方法后獲得的實際上是false。 而當線…

分布式session解決方案

在實際項目中&#xff0c;前臺代碼部署在nginx中&#xff0c;后臺服務內嵌了tomcat運行在不同的節點中&#xff0c;常見的架構如下&#xff1a; 在上述架構中&#xff0c;nginx轉發前臺請求&#xff0c;第一次登錄后&#xff0c;將用戶登錄信息寫入到一臺服務session中&#xf…

UDP 緩沖區

UDP 有接收緩沖區&#xff0c;沒有發送緩沖區 引申問題 1、為什么沒有發送緩沖區&#xff1f; 直接引用原文 “因為 UDP 是不可靠的&#xff0c;它不必保存應用進程的數據拷貝&#xff0c;因此無需一個真正的發送緩沖區” 2、沒有發送緩沖區的情況下&#xff0c;sendto 的數…

解密 C++ 中的左值(lvalue)與右值(rvalue)的核心內容

在 C 中&#xff0c;表達式&#xff08;expression&#xff09; 可以被歸類為左值或右值。最簡單的理解方式是&#xff1a; 左值&#xff08;lvalue&#xff09;&#xff1a; 能放在賦值號 左邊的表達式&#xff0c;通常表示一個有名字、有內存地址、可以持續存在的對象。你可…

MATLAB(2)選擇結構

選擇結構又可以叫做分支結構&#xff0c;它根據給定的條件是否成立&#xff0c;決定程序運行的方向。在不同的條件下執行不同的操作。 MATLAB可以用來實現選擇結構的語句有三種&#xff1a;if語句、switch語句、try語句。 一.if語句 1.if語句 1.1條件為矩陣的情況 if語句的…

Ehcache、Caffeine、Spring Cache、Redis、J2Cache、Memcached 和 Guava Cache 的主要區別

主流緩存技術 Ehcache、Caffeine、Spring Cache、Redis、J2Cache、Memcached 和 Guava Cache 的主要區別&#xff0c;涵蓋其架構、功能、適用場景和優缺點等方面&#xff1a; Ehcache 類型: 本地緩存&#xff08;JVM 內存緩存&#xff09; 特點: 輕量級&#xff0c;運行在 JV…