回顾一下上期第一个示例打印DLT日志的流程。
这次来分析第二个示例。
目录dlt-daemon/examples/example2/下有以下文件
?CMakeLists.txt? dlt_id.h? example2.c? example2.xml
其中example2.xml编译用不到,里面描述了一些程序的信息,我们先不管它。
// CMakeLists.txt
#######
# SPDX license identifier: MPL-2.0
#
# Copyright (C) 2011-2015, BMW AG
#
# This file is part of GENIVI Project DLT - Diagnostic Log and Trace.
#
# This Source Code Form is subject to the terms of the
# Mozilla Public License (MPL), v. 2.0.
# If a copy of the MPL was not distributed with this file,
# You can obtain one at http://mozilla.org/MPL/2.0/.
#
# For further information see http://www.genivi.org/.
#######
#
# DLT example implementation
#
cmake_minimum_required( VERSION 2.6 )
project( automotive-dlt-example2 )
#
# find dependency packages
#
find_package(PkgConfig)
pkg_check_modules(DLT REQUIRED automotive-dlt)
#
# include directories
#
include_directories(
${DLT_INCLUDE_DIRS}
)
#
# build project
#
set(dlt_example2_SRCS example2.c)
add_executable(dlt-example2 ${dlt_example2_SRCS})
target_link_libraries(dlt-example2 ${DLT_LIBRARIES})
set_target_properties(dlt-example2 PROPERTIES LINKER_LANGUAGE C)
install(TARGETS dlt-example2
RUNTIME DESTINATION bin
COMPONENT base)
//dlt_id.h
/*
* SPDX license identifier: MPL-2.0
*
* Copyright (C) 2011-2015, BMW AG
*
* This file is part of GENIVI Project DLT - Diagnostic Log and Trace.
*
* This Source Code Form is subject to the terms of the
* Mozilla Public License (MPL), v. 2.0.
* If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/.
*
* For further information see http://www.genivi.org/.
*/
/* generated file, do not edit */
#ifndef DLT_ID_H
#define DLT_ID_H
#define DLT_EXA2_CON_EXA2_ID1 1000
#define DLT_EXA2_CON_EXA2_ID2 1001
#define DLT_EXA2_CON_EXA2_ID3 1002
#endif /* DLT_ID_H */
文件中用宏定义了3个ID,打印log时使用,没有什么特殊意义。
//example2.c
/*
* SPDX license identifier: MPL-2.0
*
* Copyright (C) 2011-2015, BMW AG
*
* This file is part of GENIVI Project DLT - Diagnostic Log and Trace.
*
* This Source Code Form is subject to the terms of the
* Mozilla Public License (MPL), v. 2.0.
* If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/.
*
* For further information see http://www.genivi.org/.
*/
/*!
* \author Alexander Wenzel <alexander.aw.wenzel@bmw.de>
*
* \copyright Copyright ? 2011-2015 BMW AG. \n
* License MPL-2.0: Mozilla Public License version 2.0 http://mozilla.org/MPL/2.0/.
*
* \file example2.c
*/
/*******************************************************************************
** **
** SRC-MODULE: example2.c **
** **
** TARGET : linux **
** **
** PROJECT : DLT **
** **
** AUTHOR : Alexander Wenzel Alexander.AW.Wenzel@bmw.de **
** **
** PURPOSE : **
** **
** REMARKS : **
** **
** PLATFORM DEPENDANT [yes/no]: yes **
** **
** TO BE CHANGED BY USER [yes/no]: no **
** **
*******************************************************************************/
#include <stdio.h> /* for printf() and fprintf() */
#include <stdlib.h> /* for atoi() and exit() */
#include <dlt.h>
#include "dlt_id.h"
DLT_DECLARE_CONTEXT(con_exa2);
int main()
{
int num;
struct timespec ts;
DLT_REGISTER_APP("EXA2", "Third Example");
DLT_REGISTER_CONTEXT(con_exa2, "CON", "First context");
DLT_NONVERBOSE_MODE();
for (num = 0; num < 10; num++) {
DLT_LOG_ID(con_exa2, DLT_LOG_INFO, DLT_EXA2_CON_EXA2_ID1, DLT_INT32(12345678), DLT_STRING("Hello world 1!"));
DLT_LOG_ID(con_exa2, DLT_LOG_ERROR, DLT_EXA2_CON_EXA2_ID2, DLT_INT32(87654321), DLT_STRING("Hello world 2!"));
DLT_LOG_ID(con_exa2, DLT_LOG_WARN, DLT_EXA2_CON_EXA2_ID3, DLT_INT32(11223344), DLT_STRING("Hello world 3!"));
ts.tv_sec = 0;
ts.tv_nsec = 1000000;
nanosleep(&ts, NULL);
}
DLT_UNREGISTER_CONTEXT(con_exa2);
DLT_UNREGISTER_APP();
}
Application ID是“EXA2”, Context ID是“CON”。
这里的流程与示例1相比有变化:
1. 增加了DLT_NONVERBOSE_MODE设置。
2. 打印log的位置换成了 DLT_LOG_ID.
3. 打印的内容变成多条,更贴近实际。
4. 每条消息中的等级不同,包括INFO,ERROR,WARN等。消息中增加了ID,消息包括int和String多种类型。
三条消息每条打印10次。
DLT_NONVERBOSE_MODE
/**
* Switch to non-verbose mode
*
*/
#define DLT_NONVERBOSE_MODE() do { \
(void)dlt_nonverbose_mode(); } while(false)
这个宏调用了dlt_nonverbose_mode()函数,含义为切换到非冗余模式。默认是冗余模式。
简单说明下非冗余模式和冗余模式:
NonVerbose Mode
To be able to transmit parameter values only - without the need of any meta information about them -, additional properties like parameter names or types -, the Non-Verbose Mode can be used.
To allow the correct disassembly of the contained parameter values within a received Dlt message, a dedicated Message ID is added to the payload.
A separate, external file contains the description of the payload layout according to the corresponding Message ID.
概况的说就是传递消息比较简洁。
数据格式如下,消息头后面就是消息ID和数据
Verbose Mode
Dlt messages which are sent in Verbose Mode contain a complete description of the parameters next to the parameter values itself.
This means that on the one hand no external file is needed for disassembly; On the other hand, a higher amount of data is sent on the bus.
The Verbose Mode can be used on ECUs where enough memory and high network bandwidth are available. Because of the self-description, the stored data on the external client is interpretable at any time and without any further external information.
通俗的含义就是什么详细信息都发,发的数据多所以用在内存充足而且网络带宽高的地方。
数据格式比上面详细很多。
DLT_LOG_ID
/**
* Send log message with variable list of messages (intended for non-verbose mode)
* @param CONTEXT object containing information about one special logging context
* @param LOGLEVEL the log level of the log message
* @param MSGID the message id of log message
* @param ... variable list of arguments
* calls to DLT_STRING(), DLT_BOOL(), DLT_FLOAT32(), DLT_FLOAT64(),
* DLT_INT(), DLT_UINT(), DLT_RAW()
* @note To avoid the MISRA warning "The comma operator has been used outside a for statement"
* use a semicolon instead of a comma to separate the __VA_ARGS__.
* Example: DLT_LOG_ID(hContext, DLT_LOG_INFO, 0x1234, DLT_STRING("Hello world"); DLT_INT(123));
*/
#ifdef _MSC_VER
/* DLT_LOG_ID is not supported by MS Visual C++ */
/* use function interface instead */
#else
# define DLT_LOG_ID(CONTEXT, LOGLEVEL, MSGID, ...) \
do { \
DltContextData log_local; \
int dlt_local; \
dlt_local = dlt_user_log_write_start_id(&CONTEXT, &log_local, LOGLEVEL, MSGID); \
if (dlt_local == DLT_RETURN_TRUE) \
{ \
__VA_ARGS__; \
(void)dlt_user_log_write_finish(&log_local); \
} \
} while(false)
#endif
发送带有消息变量列表的日志消息(用于NonVerbose Mode)。日志带ID。
带有ID的日志更有实用性,可以区分不同来源的日志。运行的结果在dlt-viewer中显示如下:
只关注log日志(而且是打印消息的),其他消息由DLT处理不关注。解析第1条打印log日志:
[1000]? Na----Hello world 1!-|4e 61 bc 00 0f 00 48 65 6c 6c 6f 20 77 6f 72 6c 64 20 31 21 00
1000:表示MSGID,就是程序里面的DLT_EXA2_CON_EXA2_ID1
Na----Hello world 1!-:表示LOG数据DLT_INT32(12345678)和DLT_STRING("Hello world 1!")
其中12345678写成16进制为0x00bc614e,在小端模式存储时,写成4e 61 bc 00。其余字符按照ASCII码显示。
4e 61 bc 00 0f 00 48 65 6c 6c 6f 20 77 6f 72 6c 64 20 31 21 00这串数字表示DLT_INT32(12345678)和DLT_STRING("Hello world 1!")的ASCII码值。
其他条目的日志类似。