博客專欄

        EEPW首頁 > 博客 > Diagnostic Log and Trace——開發人員如何使用 DLT

        Diagnostic Log and Trace——開發人員如何使用 DLT

        發布人:電子禪石 時間:2023-11-17 來源:工程師 發布文章

        DLT 示例應用

        要在應用程序中使用 DLT,它必須鏈接到 DLT 庫。在系統上安裝 DLT 守護程序后,將有一個名為 libdlt.so 的共享庫,它為應用程序提供接口以獲取與 DLT 守護程序的連接。在使用共享 dlt 庫構建程序之前,必須在構建環境中設置庫路徑和包含路徑。默認情況下,頭文件“dlt.h”位于標準包含目錄中名為“dlt/”的目錄中。


        此示例通過使用最少的代碼示例概述了應用程序內部的 DLT 使用情況。

        #include <dlt/dlt.h>
         
        DLT_DECLARE_CONTEXT(ctx); /* declare context */
         
        int main()
        {
        	DLT_REGISTER_APP("TAPP", "Test Application for Logging");
         
        	DLT_REGISTER_CONTEXT(ctx, "TES1", "Test Context for Logging");
         
        	/* … */
         
        	DLT_LOG(ctx, DLT_LOG_ERROR, DLT_CSTRING("This is an error"));
         
        	/* … */
         
        	DLT_UNREGISTER_CONTEXT(ctx);
        	DLT_UNREGISTER_APP();
        	return 0;

        DLT 非常易于使用。開發人員必須做的第一件事是包含 dlt 頭文件。可以使用下一行中顯示的宏靜態聲明 DLT 上下文。首先,必須在主函數內注冊一個 DLT 應用程序。為此,必須指定應用程序標識符 APID 和應用程序描述。之后,可以指定一個或多個 DLT 上下文。要以詳細模式記錄消息,可以使用 DLT_LOG 宏。作為參數,必須指定日志上下文、日志級別和參數變量列表。 DLT 要求使用 DLT 類型宏對每個參數進行強類型化。在本例中,DLT_CSTRING 用于指定一個常量字符串。在應用程序清理時,所有 DLT 上下文以及 DLT 應用程序都必須注銷。

        ————————————————

        cmake 中如何加入 DLT

        要將 DLT 加入 CMake,推薦的方法是使用作為安裝一部分生成的 CMake 配置文件。

        你可以這樣:

        find_package(automotive-dlt REQUIRED)
        ...
        target_link_libraries(myapp PRIVATE Genivi::DLT)

        這讓您的項目自動獲得 libdlt 所需的所有必要編譯和鏈接標志,包括包含目錄。


        生成的 CMake 配置文件遵循“Modern CMake”約定,并且只導出一個 IMPORTED CMake 目標;它不設置任何變量,除了可用于將 DLT 視為可選依賴項的automotive-dlt_FOUND 變量。


        生成的 CMake 配置文件(在調用 find_package(automotive-dlt) 時隱式使用)默認僅將頂級目錄添加到編譯器的頭文件搜索路徑中;這要求用戶的 #include 指令以常規形式編寫,例如<dlt/dlt.h>。如果您還希望能夠使用舊形式 <dlt.h>(出于向后兼容性原因,pkg-config 模塊始終允許使用),您可以使用 CMake 選項 -DWITH_LEGACY_INCLUDE_PATH=On 配置 DLT,以便達到目的。

        ————————————————

        DLT使用 pkg-config

        除了上面詳述的 CMake 集成之外,還可以通過 pkg-config 使用 DLT。這也可以通過 CMake 的 PkgConfig 模塊來完成。


        PkgConfig 與“Modern CMake”的使用


        在這里,您也讓 PkgConfig 模塊創建目標;然而,目標的名稱由 PkgConfig 模塊確定:

        ————————————————

        find_package(PkgConfig)
        pkg_check_modules(DLT REQUIRED IMPORTED_TARGET automotive-dlt)

        根據“Modern CMake”,不需要再添加的變量,而只有要添加到鏈接庫的 CMake 目標:

        target_link_libraries(myapp PRIVATE PkgConfig::DLT)

        PkgConfig 與“Legacy CMake”(<3.0)的使用

        在這里,您讓 PkgConfig 模塊只創建變量,而不創建目標:

        find_package(PkgConfig)
        pkg_check_modules(DLT REQUIRED automotive-dlt)

        到 INCLUDE_DIRECTORIES(或者,從 CMake 2.8.11 開始,TARGET_INCLUDE_DIRECTORIES),添加

        ${DLT_INCLUDE_DIRS}

        TARGET_LINK_LIBRARIES:


        ${DLT_LINK_LIBRARIES}  (preferred, for CMake >= 3.12)

        ${DLT_LIBRARIES}       (otherwise)

        ${DLT_LIBRARIES} 的內容不包括庫的路徑(例如 -L/path/to/lib),因此如果庫駐留在不在鏈接器默認搜索路徑上的位置,您要么必須添加LINK_DIRECTORIES 的路徑:


        link_directories(${DLT_LIBRARY_DIRS})

        或者,不使用 ${DLT_LIBRARIES},而是使用 ${DLT_LDFLAGS},它結合了 ${DLT_LIBRARIES} 和 ${DLT_LIBRARY_DIRS}:


        target_link_libraries(myapp ${DLT_LDFLAGS})

        局限性

        在 Android 上,應避免在 DLT 應用程序中定義 SIGUSR1,因為 DLT 庫會阻止 SIGUSR1 在退出時終止管家線程。

        ————————————————

        測試工程源碼

        下面是我的工程:


        dlt_test/

        ├── CMakeLists.txt

        ├── dlt_test.c

        └── LICENSE

        dlt_test.c


        #include <dlt/dlt.h>

         

        DLT_DECLARE_CONTEXT(ctx); /* declare context */

         

        int main()

        {

            DLT_REGISTER_APP("TAPP", "Test Application for Logging");

         

            // DLT_REGISTER_CONTEXT(ctx, "TES1", "Test Context for Logging");

            // 向守護進程注冊新的上下文,初始日志級別為DLT_LOG_VERBOSE

            DLT_REGISTER_CONTEXT_LL_TS(ctx, "TES1", " First context ", DLT_LOG_VERBOSE, DLT_TRACE_STATUS_OFF);

            // dlt_register_context_ll_ts(&ctx, "TES1", " First context ", DLT_LOG_VERBOSE, DLT_TRACE_STATUS_OFF);

         

         

            /* … */

            sleep(3);

            DLT_LOG(ctx, DLT_LOG_VERBOSE , DLT_CSTRING("This is an error"));

         

            /* … */

            sleep(3);

            DLT_UNREGISTER_CONTEXT(ctx);

            DLT_UNREGISTER_APP();

            return 0;

        }

        CMakeLists.txt


        # for dlt_test

         

        cmake_minimum_required (VERSION 3.0)

        # The version number.

        set (rtser_VERSION_MAJOR 0)

        set (rtser_VERSION_MINOR 1)

        set (rtser_VERSION_PATCH 0)

        ######################### Project settings #####################################

        project(dlt_test)

        #打印make詳細信息

        set(CMAKE_VERBOSE_MAKEFILE on)

        #設置編譯級別

        add_definitions (-Wall -g)

        SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O0")

        #SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O0 -pthread")

        #include( FindPkgConfig )

         

        ######## config inc&src&linklib settings and build #############################

        find_package(PkgConfig)

        pkg_check_modules(DLT REQUIRED IMPORTED_TARGET automotive-dlt)

        include_directories(

        )

         

        link_directories(

        )

         

        file(GLOB SOURCES

            "*.c"

        )

         

        add_executable(dlt_test

            ${SOURCES}

        )

         

         

        target_link_libraries(dlt_test PRIVATE PkgConfig::DLT)

         

        #安裝位置

        set(CMAKE_INSTALL_PREFIX ${PROJECT_BINARY_DIR})

        # build a CPack driven installer package

        include (InstallRequiredSystemLibraries)

        set (CPACK_RESOURCE_FILE_LICENSE  

             "${CMAKE_CURRENT_SOURCE_DIR}/LICENSE")

        set (CPACK_PACKAGE_VERSION_MAJOR "${rtser_VERSION_MAJOR}")

        set (CPACK_PACKAGE_VERSION_MINOR "${rtser_VERSION_MINOR}")

        set (CPACK_PACKAGE_VERSION_PATCH "${rtser_VERSION_PATCH}")

        include (CPack)

         

        ######## Install targets ########

        install(TARGETS dlt_test

        RUNTIME DESTINATION  /usr/bin/

        )

        記錄的一般規則

        需要在關鍵位置打印log,例如錯誤處理,不要亂用log,因為打印log需要消耗資源;


        避免高頻輸出;


        合并多條消息,請始終考慮每條日志消息都會產生一定的開銷。所有必要的信息總是被組合在一起。此類log通常使用正則表達式 - 讓工作更輕松!


        不要使用 ASCII art;


        不要使用 ASCII 創建圖表;


        避免在循環中跟蹤;


        日志級別的使用

        DLT 中提供以下日志級別:


        DLT_LOG_FATAL 致命的系統錯誤,應該很少見


        DLT_LOG_ERROR 影響正確功能的錯誤


        DLT_LOG_WARN 無法確保正確行為時發出警告


        DLT_LOG_INFO 信息,提供高層次的理解


        DLT_LOG_DEBUG 程序員詳細調試信息


        DLT_LOG_VERBOSE 程序員的詳細調試信息


        請注意默認日志級別設置為 INFO;這意味著記錄在 INFO、WARN、ERROR 和 FATAL 中的消息將被記錄。提示:可以通過設置環境變量來更改默認日志級別(請參閱 DLT 庫 - 運行時配置)。


        DLT API 使用

        注冊申請

        重要的提示:因為 DLT是非異步線程安全函數,所以在子線程中不能使用。


        DLT_REGISTER_APP 是異步的。建立 IPC 通道可能需要幾毫秒的時間。因此,如果您在注冊后立即登錄,可能會丟失消息。在應用程序初始化期間,必須通過調用 DLT_REGISTER_APP() 盡早注冊 DLT 應用程序。每個應用程序只允許調用一次 DLT_REGISTER_APP()。必須指定應用程序 ID(最多四個字符)并且在 ECU 中必須是唯一的。在這個例子中使用了“MAPP”。并且還可以指定應用程序的描述,這里是“用于日志記錄的測試應用程序”。


        int main(int argc, const char* argv[])

        {

            DLT_REGISTER_APP("MAPP","Test Application for Logging");

        }

        獲取應用程序 ID

        要獲取應用程序 ID 值,請求分配一個至少 4 字節長度的字符數組并輸入到函數調用中。


        應用程序 ID 將存儲在此輸入字符數組中。


        MACRO


        DLT_GET_APPID(appid);

        Function


        dlt_get_appid(appid);

        定義和注冊所有日志上下文

        可以根據需要定義盡可能多的上下文。這些上下文可以在不同的 C 或 CPP 文件中聲明為上下文。但是每個上下文只允許聲明一次。因此,必須為每個上下文使用唯一的變量名稱。


        DLT_DECLARE_CONTEXT(myContext1);

        DLT_DECLARE_CONTEXT(myContext2);

        DLT_DECLARE_CONTEXT(myContext3);

        如果應使用來自另一個 C 或 CPP 文件的上下文,則可以通過調用來導入這些上下文:


        DLT_IMPORT_CONTEXT(myContext1);

        DLT_IMPORT_CONTEXT(myContext2);

        DLT_IMPORT_CONTEXT(myContext3);

        在注冊應用程序并聲明上下文后,需要在應用程序初始化期間盡早注冊上下文。 DLT_REGISTER_CONTEXT() 不應在 DLT_REGISTER_APP() 之前調用。


        在注冊每個上下文期間,必須提供一個上下文 ID(最多四個字符)。在這個例子中使用了“TESX”。還可以提供上下文的描述;這里是“用于日志記錄的測試上下文 X”。還可以使用宏 DLT_REGISTER_CONTEXT_LL_TS 使用預定義的日志級別和跟蹤狀態注冊上下文。使用此方法注冊第三個上下文。


        int main(int argc, const char* argv[])

        {

          DLT_REGISTER_APP("MAPP","Test Application for Logging");

         

          DLT_REGISTER_CONTEXT(myContext1,"TES1","Test Context 1 for Logging");

          DLT_REGISTER_CONTEXT(myContext2,"TES2","Test Context 2 for Logging");

          DLT_REGISTER_CONTEXT_LL_TS(myContext3, "TES3","Test Context 3 for Logging",

                                     DLT_LOG_DEBUG, DLT_TRACE_STATUS_OFF);

        }

        注意:請注意,在 DLT 守護程序和應用程序之間的日志級別同步完成之前,可能需要一秒鐘的時間。


        注銷上下文和應用程序

        在終止應用程序注冊的上下文之前,最后需要取消注冊應用程序。


        int main(int argc, const char* argv[])

        {

        /* business logic */

         

          DLT_UNREGISTER_CONTEXT(myContext1);

          DLT_UNREGISTER_CONTEXT(myContext2);

          DLT_UNREGISTER_CONTEXT(myContext3);

         

          DLT_UNREGISTER_APP();

         

          return 0;

        }

        log命令

        DLT 提供的函數允許使用任意數量的參數靈活構建消息。支持 Verbose 和 Non-Verbose 消息,具有不同的 API。使用這些函數發送消息需要多個函數調用,以啟動消息構造、添加參數和發送消息。


        下表顯示了使用常量字符串和整數進行日志記錄的所有 4 種類型的示例。


        Verbose與非Verbose API


        以下部分顯示了所有 4 種日志類型的示例,例如一個字符串和一個整數。


        MACRO


        Verbose


        DLT_LOG(ctx, DLT_LOG_INFO, DLT_STRING("ID: "), DLT_UINT32(123));

        Non-Verbose


        DLT_LOG_ID(ctx, DLT_LOG_INFO, 42 /* unique message ID */, DLT_STRING("ID: "),

                   DLT_UINT32(123));

        Function


        Verbose


        if (dlt_user_log_write_start(&ctx, &ctxdata, DLT_LOG_INFO) > 0) {

            dlt_user_log_write_string(&myctxdata, "ID: ");

            dlt_user_log_write_uint32(&myctxdata, 123);

            dlt_user_log_write_finish(&myctxdata);

        }

        Non-Verbose


        if (dlt_user_log_write_start_id(&ctx, &ctxdata, DLT_LOG_INFO, 42) > 0) {

            dlt_user_log_write_string(&myctxdata, "ID: ");

            dlt_user_log_write_uint32(&myctxdata, 123);

            dlt_user_log_write_finish(&myctxdata);

        }

        記錄參數

        可以使用以下參數類型。可以將多個參數添加到單個日志消息中。所有日志參數的大小加在一起不應超過 1390 字節,包括 DLT 消息頭。


        類型 說明

        DLT_STRING(TEXT) 字符串


        DLT_STRING_ATTR(TEXT,NAME) 字符串(帶屬性)


        DLT_SIZED_STRING(TEXT,LENGTH) 已知長度的字符串


        DLT_SIZED_STRING_ATTR(TEXT,LENGTH,NAME) 已知長度的字符串(帶屬性)


        DLT_CSTRING(TEXT) 常量字符串(不以非詳細模式發送)


        DLT_CSTRING_ATTR(TEXT,NAME) 常量字符串(帶屬性;不以非詳細模式發送)


        DLT_SIZED_CSTRING(TEXT,LENGTH) 已知長度的常量字符串(不以非詳細模式發送)


        DLT_SIZED_CSTRING_ATTR(TEXT,LENGTH,NAME) 已知長度的常量字符串(帶屬性;不以非詳細模式發送)


        DLT_UTF8(TEXT) utf8 編碼的字符串


        DLT_UTF8_ATTR(TEXT,NAME) Utf8 編碼字符串(帶屬性)


        DLT_SIZED_UTF8(TEXT,LENGTH) 已知長度的 Utf8 編碼字符串


        DLT_SIZED_UTF8_ATTR(TEXT,LENGTH,NAME) 已知長度的 utf8 編碼字符串(帶屬性)


        DLT_RAW(BUF,LENGTH) 原始緩沖區


        DLT_RAW_ATTR(BUF,LENGTH,NAME) 原始緩沖區(帶屬性)


        DLT_INT(VAR) 整數變量,取決于平臺


        DLT_INT_ATTR(VAR,NAME,UNIT) 整數變量,取決于平臺(帶屬性)


        DLT_INT8(VAR) 整數 8 位變量


        DLT_INT8_ATTR(VAR,NAME,UNIT) 整數 8 位變量(帶屬性)


        DLT_INT16(VAR) 整數 16 位變量


        DLT_INT16_ATTR(VAR,NAME,UNIT) 整數 16 位變量(帶屬性)


        DLT_INT32(VAR) 整數 32 位變量


        DLT_INT32_ATTR(VAR,NAME,UNIT) 整數 32 位變量(帶屬性)


        DLT_INT64(VAR) 整數 64 位變量


        DLT_INT64_ATTR(VAR,NAME,UNIT) 整數 64 位變量(帶屬性)


        DLT_UINT(VAR) 無符號整數變量


        DLT_UINT_ATTR(VAR,NAME,UNIT) 無符號整數變量(帶屬性)


        DLT_UINT8(VAR) 無符號 8 位整數變量


        DLT_UINT8_ATTR(VAR,NAME,UNIT) 無符號 8 位整數變量(帶屬性)


        DLT_UINT16(VAR) 無符號 16 位整數變量


        DLT_UINT16_ATTR(VAR,NAME,UNIT) 無符號 16 位整數變量(帶屬性)


        DLT_UINT32(VAR) 無符號 32 位整數變量


        DLT_UINT32_ATTR(VAR,NAME,UNIT) 無符號 32 位整數變量(帶屬性)


        DLT_UINT64(VAR) 無符號 64 位整數變量


        DLT_UINT64_ATTR(VAR,NAME,UNIT) 無符號 64 位整數變量(帶屬性)


        DLT_BOOL(VAR) 布爾變量


        DLT_BOOL_ATTR(VAR,NAME) 布爾變量(帶屬性)


        DLT_FLOAT32(VAR) 浮點型 32 位變量


        DLT_FLOAT32_ATTR(VAR,NAME,UNIT) 浮點型 32 位變量(帶屬性)


        DLT_FLOAT64(VAR) Float 64 位變量


        DLT_FLOAT64_ATTR(VAR,NAME,UNIT) Float 64 位變量(帶屬性)


        DLT_HEX8(UINT_VAR) 8 位十六進制值


        DLT_HEX16(UINT_VAR) 16 位十六進制值


        DLT_HEX32(UINT_VAR) 32 位十六進制值


        DLT_HEX64(UINT_VAR) 64 位十六進制值


        DLT_BIN8(UINT_VAR) 8 位二進制值


        DLT_BIN16(UINT_VAR 16 位二進制值


        DLT_PTR(PTR_VAR) 用于打印指針的架構獨立宏

        ————————————————

        版權聲明:本文為CSDN博主「andylauren」的原創文章,遵循CC 4.0 BY-SA版權協議,轉載請附上原文出處鏈接及本聲明。

        原文鏈接:https://blog.csdn.net/andylauren/article/details/121118770




        *博客內容為網友個人發布,僅代表博主個人觀點,如有侵權請聯系工作人員刪除。



        關鍵詞: DLT

        技術專區

        關閉
        主站蜘蛛池模板: 泽库县| 桂林市| 金溪县| 静海县| 留坝县| 崇阳县| 孝义市| 宁明县| 右玉县| 新龙县| 顺义区| 鄂托克旗| 五华县| 乐都县| 忻州市| 扬中市| 兰考县| 桂阳县| 芜湖市| 神池县| 桃园县| 万荣县| 离岛区| 靖西县| 通化县| 苗栗县| 东安县| 扎兰屯市| 武平县| 文安县| 玉林市| 闻喜县| 潢川县| 健康| 衡阳县| 伊通| 平陆县| 沈丘县| 伊川县| 麻栗坡县| 柏乡县|