[AUTOSAR][诊断管理][ECU][$19] 读取ECU的DTC故障信息

news/2023/12/9 12:18:00

一、简介

  1. 在车载诊断中常用的诊断协议有ISO 14229等,在协议中主要定义了诊断请求、诊断响应的报文格式及ECU该如何处理诊断请求的应用。
  2. 其中ISO 14229系列标准协议定义了用于行业内诊断通信的需求规范,也就是UDS。UDS主要应用于OSI七层模型的第七层——应用层,它支持的汽车总线包括:CAN、LIN、FlexRay、Ethernet及K-LINE。
  3. UDS中的服务根据其功能分为6大类,共26种。其中包含的0x19服务(ReadDTCInformation)则是UDS中的重中之重。那么我们今天就一起进入到19服务中,感受其中的奥秘。

二、 服务介绍

19服务(ReadDTCInformation)用于读取ECU的DTC故障信息,此服务允许客户端从服务器读取诊断故障代码(DTC)的相关信息。此服务包含28个子服务(Subfunction),常用的5种子服务如下:

  • 0x01 reportNumberOfDTCByStatusMask(读取客户端定义状态掩码匹配的DTC数量)
  • 0x02 reportDTCByStatusMask(读取客户端定义状态掩码匹配的DTC)
  • 0x04 reportDTCSnapshotRecordByDTCNumber(检索客户端定义DTC掩码的快照数据)
  • 0x06 reportDTCExtDataRecordByDTCNumber(读取某个DTC及其相关的扩展数据,扩展数据包括DTC状态,优先级,发生次数,时间戳,里程等。)
  • 0x0A reportSupportedDTC(读取ECU支持的所有DTC的状态,包含支持的各个DTC编号以及相关状态)

今天主要解析19服务中的04子服务,也就是检索客户端定义DTC的快照号对应的快照记录数据,在AUTOSAR中也叫冻结帧。

(1)子服务介绍

  1. 快照数据概念介绍
    前面讲19服务常用子服务的时候,提到了Subfunction为04的子服务,使用04子服务对服务端进行请求,可以获取DTC发生时记录的快照数据。那04子服务是如何获取快照数据的呢?首先我们需要理解什么是快照数据。从ISO 14229-1协议可知,快照数据为发生某一故障时记录的DTC的电压、发动机转速、时间戳等,从而使工程师在ECU出现故障时能及时了解车辆的历史和实时故障信息。

  2. 报文格式介绍
    接下来通过介绍19 04子服务请求和响应的报文格式,分析报文中各个字节的相关定义。

请求格式

在这里插入图片描述
从图1中可知,19 04的请求报文包括四个部分,其中服务ID和Subfunction就不用过多解释了。DTCMaskRecord表示某个故障的DTC,当系统检测到一个故障发生时,则会存储其对应的故障数值,这个故障数值就是DTC。通过读取DTC可知一个故障发生时的具体位置以及原因和类型。通常UDS中DTC占3个字节,OBD Ⅱ占2个字节,在ISO 15031-6中定义的DTC由两个字节根基和一个字节的故障类型组成。我们通常用到的DTC格式都是由ISO 15031-6中定义的。图2是ISO 15031-6中定义的DTC的两个字节根基,图中很详细地解释了每一个Bit的含义。

在这里插入图片描述
SnapshotRecordNumber需要提前定义,可以有多个。如SnapshotRecordNumber设置为FF,则表示读取所有的快照数据组。

响应格式

图3
图3为响应报文格式,当使用19 04对ECU进行请求时,ECU给出的肯定响应的报文格式由七部分组成。此时的DTCAndStatusRecord由三个字节的DTC和一个字节的StatusOfDTC组成,StatusOfDTC表示DTC的状态。假设现在的DTC状态为0x09,则Bit0和Bit3置1。如某个DTC一直存在并且确认,则在ECU响应的报文中的StatusOfDTC为0x09。如图4
图4
SnapshotRecordNumber这个字节表示DTC快照记录的组号;DTCSnapshotRecordNumberOfldentifiers表示快照DID的个数,占一个字节;Dataldentifier这部分由两个字节组成,表示快照数据对应的DID,DTCSnapshotRecord表示快照DID对应的具体数据。

三、示例代码

(1)19_read_dtc_info.c

/********************************************************************************
* @file    19_read_dtc_info.c
* @author  jianqiang.xue
* @version V1.0.0
* @date    2023-05-30
* @brief   读取DTC信息
********************************************************************************/
/* Includes ------------------------------------------------------------------*/
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#include <stdlib.h>
#include "modules.h"
#include "os_api.h"
#include "edebug.h"
#include "kv_sys.h"
#include "ecu_ble_uart.h"
/* Private includes ----------------------------------------------------------*/
#include "std_math.h"
#include "app_can.h"
#include "can_nm.h"
#include "app_nm.h"
#include "diag_main.h"
#if AUTOSAR_DIAG_DTC_SWITCH
#include "dtc_main.h"
#endif
/* Private define ------------------------------------------------------------*/
#define UDS_ID         0x19
#define MAX_BUFF_SIZE  150
/* Private typedef -----------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/***************软定时器创建***************/
/* Private func --------------------------------------------------------------*//*** @brief  通过状态掩码报告DTC数目* @param  *data: 数据指针* @param  len: 数据长度* @retval 0--成功  >0--错误*/
static int8_t uds19_01(uint8_t *data, uint16_t len, uint8_t *out) {if (len != 3) {LOGE("len err != 3, sub%02x", data[1]);send_nrc_data(UDS_ID, NRC_INCORRECT_MESSAGE_LENTH);return 1;}if (data[1] & 0x80) { // 无需应答LOGI("No answer required, sub%02x", data[1]);} else {// 回复正响应码  单帧格式: len, 服务ID|0x40, 子功能ID,out[0] = 6;  // 数据总长度= 服务号 + sub_id + mask + data + num(2byte)out[1] = UDS_ID | 0x40;   // 服务号,回复上位机需要 |0x40out[2] = data[1];out[3] = AUTOSAR_DIAG_DTC_STATE_BIT; // 获取DTC掩码out[4] = 0; // SAE_J2012-DA_DTCFormat_00uint16_t dtc_count = get_dtc_num_by_mask(data[2]);out[5] = (uint8_t)(dtc_count >> 8);out[6] = (uint8_t)(dtc_count & 0xFF);out[7] = 0xAA;app_can_enqueue_msg(CAN_MSG_EVENT_SEND, NWL_RES_ADDR, out, 8);}return 0;
}/*** @brief  通过状态掩码报告DTC* @param  *data: 数据指针* @param  len: 数据长度* @retval 0--成功  >0--错误*/
static int8_t uds19_02(uint8_t *data, uint16_t len, uint8_t *out) {if (len != 3) {LOGE("len err != 3, sub%02x", data[1]);send_nrc_data(UDS_ID, NRC_INCORRECT_MESSAGE_LENTH);return 1;}if (data[1] & 0x80) { // 无需应答LOGI("No answer required, sub%02x", data[1]);} else {// 回复正响应码  单帧格式: len, 服务ID|0x40, 子功能ID,out[1] = UDS_ID | 0x40;   // 服务号,回复上位机需要 |0x40out[2] = data[1];out[3] = AUTOSAR_DIAG_DTC_STATE_BIT; // 获取DTC掩码uint8_t d_len = 0;d_len = get_dtc_status_by_mask(data[2], &out[4], MAX_BUFF_SIZE - 4 - 1); // 4--数据头 1--连续帧头预留out[0] = 3 + d_len; // 数据总长度 = 服务号 + sub_id + mask + ndata// 判断数据长度,单帧还是连续帧发送if (out[0] > 7) {memmove(out + 1, out, out[0] + 1); // 单帧改连续帧格式,数据总长度 + 长度位,数据总长度 + 长度位out[0] = NWL_FIRST_FRAME << 4; // 数据帧格式(nwl_frame_st_t)if (g_tx_msg.data != 0) {free(g_tx_msg.data);g_tx_msg.data = NULL;}// 发送首帧(只含6byte data)后,剩余长度:去除 (服务号|sub_id|mask + D0D1D2)d_len = out[1] - 3 - 3;g_tx_msg.data = malloc(d_len);if (g_tx_msg.data == NULL) {send_nrc_data(UDS_ID, NRC_ACCESS_DENIED);return 2;}app_can_enqueue_msg(CAN_MSG_EVENT_SEND, NWL_RES_ADDR, out, 8);memcpy(g_tx_msg.data, out + 8, d_len);g_tx_msg.len = d_len;} else {memset(&out[out[0] + 1], 0xAA, 8 - out[0] - 1);  // 空白区填充指定值app_can_enqueue_msg(CAN_MSG_EVENT_SEND, NWL_RES_ADDR, out, 8);}}return 0;
}/*** @brief  通过DTC码报告DTC 快照记录* @param  *data: 数据指针* @param  len: 数据长度* @retval 0--成功  >0--错误*/
static int8_t uds19_04(uint8_t *data, uint16_t len, uint8_t *out) {uint32_t dtc_id;if (len != 6) {LOGE("len err != 6, sub%02x", data[1]);send_nrc_data(UDS_ID, NRC_INCORRECT_MESSAGE_LENTH);return 1;} else { // == 6uint8_t record_numb = data[5]; // 记录号if ((record_numb > SS_NB_MAX) && record_numb != 0xFF && record_numb != 0x00) {LOGE("record numb nonsupport:%02x, sub%02x", record_numb, data[1]);send_nrc_data(UDS_ID, NRC_REQUEST_OUT_OF_RANGE);return 2;}dtc_id = data[2];dtc_id <<= 8;dtc_id += data[3];dtc_id <<= 8;dtc_id += data[4];uint8_t SN = is_dtc_id(dtc_id); // 得到dtc id,对应的数组索引if (SN == 0xFF) {LOGE("dtc id id err:%02x, sub%02x", dtc_id, data[1]);send_nrc_data(UDS_ID, NRC_SUBFUNCTION_NOT_SUPPORTED);return 2;}if (data[1] & 0x80) { // 无需应答LOGI("No answer required, sub%02x", data[1]);} else {// 回复正响应码  单帧格式: len, 服务ID|0x40, 子功能ID,out[1] = UDS_ID | 0x40;   // 服务号,回复上位机需要 |0x40out[2] = data[1]; // SUB_ID 子功能IDout[3] = data[2]; // DTC_ID 低16bitout[4] = data[3]; // DTC_ID 高8bitout[5] = data[4]; // DTC_ID 低8bitout[6] = get_dtc_snap_shot_status(SN, record_numb); // DTC Status 最近一次错误状态out[7] = record_numb;out[8] = SS_TYPE_MAX_NUMBER;uint16_t d_len = 0;d_len = get_dtc_snap_shot_by_id(SN, record_numb, &out[9], MAX_BUFF_SIZE - 8 - 1); // 7--数据头 1--连续帧头预留// 数据总长度 = 服务号 + 子功能ID + DTC_ID(3byte) + DTC Status + record_numb + MAX_NUMBER + DATA_LENout[0] = 8 + d_len;memmove(out + 1, out, out[0] + 1); // 单帧改连续帧格式,数据总长度 + 长度位out[0] = NWL_FIRST_FRAME << 4; // 数据帧格式(nwl_frame_st_t)if (g_tx_msg.data != 0) {free(g_tx_msg.data);g_tx_msg.data = NULL;}// 发送首帧(只含6byte data)后,剩余长度:去除 (服务号 + 子功能ID + DTC_ID(3byte) + DTC Status)d_len = out[1] - 2 - 3 - 1;g_tx_msg.data = malloc(d_len);if (g_tx_msg.data == NULL) {send_nrc_data(UDS_ID, NRC_ACCESS_DENIED);return 3;}app_can_enqueue_msg(CAN_MSG_EVENT_SEND, NWL_RES_ADDR, out, 8);memcpy(g_tx_msg.data, out + 8, d_len);g_tx_msg.len = d_len;}}return 0;
}/*** @brief  通过DTC码报告DTC扩展数据记录* @param  *data: 数据指针* @param  len: 数据长度* @retval 0--成功  >0--错误*/
static int8_t uds19_06(uint8_t *data, uint16_t len, uint8_t *out) {uint32_t dtc_id;if (len != 6) {LOGE("len err != 6, sub%02x", data[1]);send_nrc_data(UDS_ID, NRC_INCORRECT_MESSAGE_LENTH);return 1;}uint8_t record_numb = data[5];  // 记录号if ((record_numb > SS_NB_MAX) && record_numb != 0xFF && record_numb != 0x00) {LOGE("record numb nonsupport:%02x, sub%02x", record_numb, data[1]);send_nrc_data(UDS_ID, NRC_REQUEST_OUT_OF_RANGE);return 2;}dtc_id = data[2];dtc_id <<= 8;dtc_id += data[3];dtc_id <<= 8;dtc_id += data[4];uint8_t SN = is_dtc_id(dtc_id); // 得到dtc id,对应的数组索引if (SN == 0xFF) {LOGE("dtc id id err:%02x, sub%02x", dtc_id, data[1]);send_nrc_data(UDS_ID, NRC_SUBFUNCTION_NOT_SUPPORTED);return 2;}if (data[1] & 0x80) { // 无需应答LOGI("No answer required, sub%02x", data[1]);} else {// 回复正响应码  单帧格式: len, 服务ID|0x40, 子功能ID,out[1] = UDS_ID | 0x40;   // 服务号,回复上位机需要 |0x40out[2] = data[1]; // SUB_ID 子功能IDout[3] = data[2]; // DTC_ID 低16bitout[4] = data[3]; // DTC_ID 高8bitout[5] = data[4]; // DTC_ID 低8bitout[6] = get_dtc_snap_shot_status(SN, record_numb); // DTC Status 最近一次错误状态out[7] = record_numb;//os_delay(1);uint16_t d_len = 0;d_len = get_dtc_snap_shot_ex_data(SN, record_numb, &out[8], MAX_BUFF_SIZE - 8 - 1); // 7--数据头 1--连续帧头预留// 数据总长度 = 服务号 + 子功能ID + DTC_ID(3byte) + DTC Status + record_numb  + DATA_LENout[0] = 7 + d_len;if (out[0] > 7) {memmove(out + 1, out, out[0] + 1); // 单帧改连续帧格式,数据总长度 + 长度位out[0] = NWL_FIRST_FRAME << 4; // 数据帧格式(nwl_frame_st_t)if (g_tx_msg.data != 0) {free(g_tx_msg.data);g_tx_msg.data = NULL;}// 发送首帧(只含6byte data)后, 去除 (服务号 + 子功能ID + DTC_ID(3byte) + DTC Status)d_len = out[1] - 2 - 3 - 1;g_tx_msg.data = malloc(d_len);if (g_tx_msg.data == NULL) {send_nrc_data(UDS_ID, NRC_ACCESS_DENIED);return 3;}memcpy(g_tx_msg.data, out + 8, d_len);g_tx_msg.len = d_len;app_can_enqueue_msg(CAN_MSG_EVENT_SEND, NWL_RES_ADDR, out, 8);} else {memset(&out[out[0] + 1], 0xAA, 8 - out[0] - 1);  // 空白区填充指定值app_can_enqueue_msg(CAN_MSG_EVENT_SEND, NWL_RES_ADDR, out, 8);}}return 0;
}/*** @brief  报告支持的全部DTC* @param  *data: 数据指针* @param  len: 数据长度* @retval 0--成功  >0--错误*/
static uint8_t uds19_0A(uint8_t *data, uint16_t len, uint8_t *out) {if (len != 2) {LOGE("len err != 2, sub%02x", data[1]);send_nrc_data(UDS_ID, NRC_INCORRECT_MESSAGE_LENTH);return 1;}if (data[1] & 0x80) { // 无需应答LOGI("No answer required, sub%02x", data[1]);} else {// 回复正响应码  单帧格式: len, 服务ID|0x40, 子功能ID, maskout[1] = UDS_ID | 0x40;   // 服务号,回复上位机需要 |0x40out[2] = data[1]; // SUB_ID 子功能IDout[3] = AUTOSAR_DIAG_DTC_STATE_BIT; // 掩码uint16_t d_len = 0;d_len = get_all_dtc_status(&out[4], MAX_BUFF_SIZE - 4 - 1); // 4--数据头 1--连续帧头预留// 数据总长度 = 服务号 + 子功能ID + 掩码  + DATA_LENout[0] = 3 + d_len;// LOGD("%u,%u\r\n", out[0], d_len);if (out[0] > 7) {memmove(out + 1, out, out[0] + 1); // 单帧改连续帧格式,数据总长度 + 长度位out[0] = NWL_FIRST_FRAME << 4; // 数据帧格式(nwl_frame_st_t)if (g_tx_msg.data != 0) {free(g_tx_msg.data);g_tx_msg.data = NULL;}// 发送首帧(只含6byte data)后, 去除 (服务号 + 子功能ID + DTC_ID(3byte) + DTC Status)d_len = out[1] - 2 - 3 - 1;g_tx_msg.data = malloc(d_len);if (g_tx_msg.data == NULL) {send_nrc_data(UDS_ID, NRC_ACCESS_DENIED);return 3;}memcpy(g_tx_msg.data, out + 8, d_len);LOGD("%x,%u,%x,%u\r\n", g_tx_msg.data[d_len-1], d_len, out[out[1]+1], out[1]+1);g_tx_msg.len = d_len;app_can_enqueue_msg(CAN_MSG_EVENT_SEND, NWL_RES_ADDR, out, 8);} else {memset(&out[out[0] + 1], 0xAA, 8 - out[0] - 1);  // 空白区填充指定值app_can_enqueue_msg(CAN_MSG_EVENT_SEND, NWL_RES_ADDR, out, 8);}}return 0;
}void uds19_main(nwl_msg_t* p) {uint8_t data[MAX_BUFF_SIZE];uint8_t d_len = 0;if (p->len < 2) {LOGE("len err < 2");send_nrc_data(UDS_ID, NRC_INCORRECT_MESSAGE_LENTH);goto end;}switch (p->data[1] & 0x7F) { // 子功能,bit7为应答位。  =1则不允许应答// 通过状态掩码报告DTC数目case 0x01: {if (uds19_01(p->data, p->len, data) != 0) {}break;}// 通过状态掩码报告DTCcase 0x02:if (uds19_02(p->data, p->len, data) != 0) {}break;// 通过DTC码报告DTC 快照记录case 0x04: {if (uds19_04(p->data, p->len, data) != 0) {}break;}// 通过DTC码报告DTC扩展数据记录case 0x06: {if (uds19_06(p->data, p->len, data) != 0) {}break;}// 报告支持的全部DTCcase 0x0A: {if (uds19_0A(p->data, p->len, data) != 0) {}break;}default:send_nrc_data(UDS_ID, NRC_SUBFUNCTION_NOT_SUPPORTED);break;}
end:return;
}#if AUTOSAR_DIAG_SWITCH && USE_UDS_19 && AUTOSAR_DIAG_DTC_SWITCH
DIAG_SERVICE_REG(UDS_ID, DIAG_NO_SECURITY_LEVEL, (DEFAULT_SESSION|EXTENDED_SESSION),(DIAG_PHYS_REQ|DIAG_FUNC_REQ), NULL, NULL, uds19_main);
#endif

http://www.ppmy.cn/news/1173030.html

相关文章

常用Web安全扫描工具汇整

漏洞扫描是一种安全检测行为&#xff0c;更是一类重要的网络安全技术&#xff0c;它能够有效提高网络的安全性&#xff0c;而且漏洞扫描属于主动的防范措施&#xff0c;可以很好地避免黑客攻击行为&#xff0c;做到防患于未然。 1、AWVS Acunetix Web Vulnerability Scanner&a…

leetcode(力扣) 128. 最长连续序列(哈希)

文章目录 题目描述思路分析完整代码 题目描述 给定一个未排序的整数数组 nums &#xff0c;找出数字连续的最长序列&#xff08;不要求序列元素在原数组中连续&#xff09;的长度。 请你设计并实现时间复杂度为 O(n) 的算法解决此问题。 示例 1&#xff1a; 输入&#xff1a;nu…

浙江大学利用 SVM 优化触觉传感器,盲文识别率达 96.12%

生物传感是人类与机器、人类与环境、机器与环境交互的重要媒介。其中&#xff0c;触觉能够实现精准的环境感知&#xff0c;帮助使用者与复杂环境交互。 为模仿人类的触觉&#xff0c;科研人员开发了各种传感器&#xff0c;以模拟皮肤对环境的感知。然而&#xff0c;触觉传感的要…

构建实时视频聊天应用:使用WebRTC和Netty的完整指南

构建实时视频聊天应用&#xff1a;使用WebRTC和Netty的完整指南 使用WebRTC和Netty构建实时视频聊天应用准备工作步骤1&#xff1a;创建Netty服务器步骤2&#xff1a;创建WebRTC前端应用步骤3&#xff1a;处理WebRTC连接步骤4&#xff1a;处理Netty服务器端步骤5&#xff1a;运…

Flutter和SwiftUI比较

0.语言 SwiftUI 毫无疑问是Swift语言编写&#xff0c; 在2019年正式推出&#xff0c;目前最新是Swift 5.9 (2023年9月)&#xff0c;由Apple公司维护和发行&#xff1b; 该编程语言发明人已离职Apple。 语言官网&#xff1a;https://developer.apple.com/swift/ 最好用Xcode编…

Ubuntu22.04安装,SSH无法连接

Ubuntu初始化安装后&#xff0c;系统默认不允许root通过ssh连接&#xff0c;因此需要完成三个设置 1.修改ssh配置文件 vim /etc/ssh/sshd_config 将PermitRootLogin注释打开&#xff0c;并将值改为yes 保存修改并退出 :wq 2.重启ssh服务 sudo service ssh restart 3.重新打…

Linux常用命令——clear命令

在线Linux命令查询工具 clear 清除当前屏幕终端上的任何信息 补充说明 clear命令用于清除当前屏幕终端上的任何信息。 语法 clear实例 直接输入clear命令当前终端上的任何信息就可被清除。 在线Linux命令查询工具

字符设备驱动框架(字符设备基础一)

编写字符设备驱动框架&#xff1a;首先驱动向 Linux 内核进行设备号申请&#xff0c;之后的字符设备注册时&#xff0c;会对申请的设备号进行使用。而 Linux 内核会将字符设备抽象成一个具体的struct cdev结构体&#xff0c;该结构体记录了字符设备的字符设备号、内核对象等信息…

【FPGA】IIC协议通用主机接口的设计与实现详解

一、认识IIC IIC&#xff08;I2C&#xff09;协议是一种串行通信协议&#xff0c;用于连接微控制器和外围设备。IIC协议只需要两根信号线&#xff08;时钟线SCL和数据线SDA&#xff09;就能完成设备之间的通信&#xff1b;支持多主机和多从机通信&#xff0c;通过设备地址区分不…

可管理链接仪表板Bender

什么是 Bender &#xff1f; Bender 是一款无需任何代码即可管理的链接仪表板。非常适合管理服务列表。其深受 Homer 仪表板 的启发&#xff0c;旨在通过一项重大更改提供相同的功能&#xff0c;无需编辑 yaml 文件&#xff01; Homer 软件我们之前已经介绍过了&#xff0c;两者…

数据库 MySQL总结以及常见命令总结

一、数据库类型 关系型数据库&#xff1a;MYSQL 非关系型数据库&#xff1a;NoSQL、MongoDB、Cassandra、Dynamo 主流关系数据库&#xff1a; 商用数据库&#xff0c;例如&#xff1a;Oracle&#xff0c;SQL Server&#xff0c;DB2等&#xff1b; 开源数据库&#xff0c;例如…

程序员节1024

这里写自定义目录标题 欢迎使用Markdown编辑器新的改变功能快捷键合理的创建标题&#xff0c;有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右SmartyPants 创建一个自定义列表如何创建一个…

Kotlin中的List集合

在Kotlin中&#xff0c;List集合用于存储一组有序的元素。List集合分为可变集合&#xff08;MutableList&#xff09;和不可变集合&#xff08;List&#xff09;。本篇博客将分别介绍可变集合和不可变集合&#xff0c;并提供相关的API示例代码。 不可变集合&#xff08;List&a…

跨境电商:经济合作新引擎,技术赋能新亮点

随着数字化浪潮席卷全球&#xff0c;跨境电商正蓬勃发展&#xff0c;成为中国外贸高质量发展的新引擎。中国的跨境电商行业在"买全球、卖全球"方面正经历着显著的增长&#xff0c;延展出新的商业生态&#xff0c;以技术创新和国际合作为支撑&#xff0c;促进了中国制…

谈谈你对spring boot 3.0的理解

谈谈你对spring boot 3.0的理解 一&#xff0c;Spring Boot 3.0 的兼容性 Spring Boot 3.0 在兼容性方面做出了很大的努力&#xff0c;以支持存量项目和老项目。尽管如此&#xff0c;仍需注意以下几点&#xff1a; Java 版本要求&#xff1a;Spring Boot 3.0 要求使用 Java 1…

MFC Windows 程序设计[331]之帮助静态框实例(附源码)

MFC Windows 程序设计[331]之帮助静态框实例 程序之美前言主体运行效果核心代码逻辑分析结束语程序之美 前言 MFC是微软公司提供的一个类库(class libraries),以C++类的形式封装了Windows API,并且包含一个应用程序框架,以减少应用程序开发人员的工作量。其中包含大量Wi…

Unity中Shader的Fallback

文章目录 前言一、解决 Pass 复用的方案方案一&#xff1a;使用之前的UsePass方案&#xff0c;把ShadowCaster的Pass提出来到一个单独的Shader中&#xff0c;在使用的时候直接使用 UsePass方案二&#xff1a;使用Fallback功能 前言 Unity中Shader的Fallback&#xff0c;我们在…

计算机网络(谢希仁)第八版课后题答案(第一章)

1.计算机网络可以向用户提供哪些服务 连通性:计算机网络使上网用户之间可以交换信息&#xff0c;好像这些用户的计算机都可以彼此直接连通一样。 共享:指资源共享。可以是信息、软件&#xff0c;也可以是硬件共享。 2.试简述分组交换的要点 采用了存储转发技术。把报文(要发…

C语言_文件_进程常用函数/命令 + 实例

文件相关命令&#xff1a; ps -aux|grep init? //搜索包含init名称的进程 top //linux下的资源管理器&#xff08;动态&#xff09;//open 返回的int 是给后面的读/写/光标移动 用的fd&#xff0c;没有open就不能进行后面的操作&#xff1b; int op…

【Java小知识点】类加载器的区别

&#x1f384;欢迎来到边境矢梦的csdn博文&#x1f384; &#x1f384;本文主要梳理Java类加载器的区别&#x1f384; &#x1f308;我是边境矢梦&#xff0c;一个正在为秋招和算法竞赛做准备的学生&#x1f308; &#x1f386;喜欢的朋友可以关注一下&#x1faf0;&#x1faf…
最新文章