Diagnostic Log and Trace——开发人员如何使用 DLT
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_VERBOSEDLT_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_testcmake_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_testRUNTIME 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) 用于打印指针的架构独立宏
Diagnostic Log and Trace——开发人员如何使用 DLT相关推荐
- Diagnostic Log and Trace——dlt的编译和安装
概述 GENIVI DLT 提供日志和跟踪接口,基于 AUTOSAR 标准 4.0 DLT 中指定的标准化协议.它被其他 GENIVI 组件使用,但可以作为其他应用程序的日志框架,与 GENIVI 无 ...
- 【DLT学习笔记2】-- 什么是DLT?(Diagnostic Log and Trace)
DLTGENIVI项目下的log软件工程 DLT包括:DLT daemon DTL viewer两个子工程. DLT daemon运行在ECU上,DTLviewer运行在调试PC上. github地址 ...
- DLT(Diagnostic Log and Trace)嵌入式系统程序运行记录
http://blog.csdn.net/yanlinembed/article/details/49837975 DLT的使用有属于Application范畴与Context范畴.在使用DLT时,需 ...
- Diagnostic Log and Trace——DLT 离线日志存储
doc/dlt_offline_logstorage.md · RTplay/dlt-daemon - Gitee.com DLT离线日志存储介绍 Logstorage 是一种将 DLT 日志存储在目 ...
- 面向JavaScript开发人员的Adobe AIR与Dreamweaver
入门教程,非常详细,CS4里面应该可以省略前面几步直接开发了. Adobe AIR对于HTML/JavaScript应用程序与桌面的集成有着出色的支持,但除了所有附加功能之外,还需要一些其他工具和技术 ...
- 面向.NET开发人员的Dapr——可观察性
目录: 面向.NET开发人员的Dapr--前言 面向.NET开发人员的Dapr--分布式世界 面向.NET开发人员的Dapr--俯瞰Dapr 面向.NET开发人员的Dapr--入门 面向.NET开发人 ...
- 为什么JavaScript仅在IE中打开开发人员工具一次后才能工作?
IE9错误-JavaScript仅在打开开发人员工具一次后才能工作. 我们的网站为用户提供免费的pdf下载,并且具有简单的"输入密码下载"功能. 但是,它根本无法在Internet ...
- 终端软件升级功能开发_5个很棒的终端技巧可帮助您升级为开发人员
终端软件升级功能开发 There are plenty of beginner tutorials around that help you learn command line basics, su ...
- 初级开发人员的缺点_作为一名初级开发人员,我如何努力克服自己的挣扎
初级开发人员的缺点 by Syeda Aimen Batool 通过Syeda Aimen Batool 作为一名初级开发人员,我如何努力克服自己的挣扎 (How I'm working to ove ...
最新文章
- ADPRL - 近似动态规划和强化学习 - Note 8 - 近似策略迭代 (Approximate Policy Iteration)
- C++建立动态二维数组
- C语言常用字符串操作函数大全详解(strstr,strtok,strrchr,strcat,strcmp,strcpy,strerror,strspn,strchr等)
- ViT(Vision Transformer)学习
- C++ 什么是伪函数,以及伪函数的使用
- Decorator模式设计模式
- 数学基础知识总结 —— 12. 求极限的重要工具「洛必达法则」
- 各邮箱的邮件接收服务器和发送服务器
- php中fastcgi和php-fpm是什么
- 选择变色镜片——爱眼护眼
- flutter引入高德地图_Flutter接入高德地图后运行报错
- 微信小程序----Grid(九宫格)(flex实现九宫格布局)
- 如何清除注册表中的Java安装信息
- 软考证书可以落户上海吗?很多人不知道
- Android studio百度地图SDK开发 2020最新超详细的Android 百度地图开发讲解(6) POI检索, 根据地址输入提示检索 Sug
- MATLAB2018
- esp8266 mesh 组网
- 设置.exe程序图标(ico文件)
- RPM包安装或者安装源码包
- ORA-00604: error occurred at recursive SQL level 1 ...——oracle服务空间不足