AUTOSAR通信篇 - CAN网络通信(二:CanIf)

news2024/11/25 21:49:45

在上一篇,我们介绍了CAN模块,接下来我们介绍在CAN模块之上的模块Can Interface(CanIf)模块。在AUTOSAR软件架构中,CanIf也在BSW层,它处于CAN模块之上紧挨着CAN模块。CanIf是一个硬件独立层,具有到 CAN 驱动程序和 CAN 收发器驱动程序层以及 PDU 路由器、通信管理器和网络管理等上层的标准化接口。 所有需要 CAN 通信的上层都必须与负责 CAN 通信处理的 CanIf通信。 这包括消息的传输和接收以及 CAN 控制器的状态处理。下图显示了 CAN 接口在 AUTOSAR 架构中的位置。

 CanIf 提供的服务可分为以下几大类:

  • 初始化
  • 数据发送
  • 数据接收
  • Can控制器模式控制
  • PDU 模式控制

在介绍CanIf提供的服务之前,我们首先理解几个概念:Hardware Object Handles(HOH)、Hardware Transmit Handle(HTH) 和 Hardware Receive Handle(HRH)。

HOH是CAN Mailbox数据结构的抽象,它包括CanId、DLC和数据等CAN相关的参数。基于CAN硬件buffer抽象出来的在CanIf中被引用的硬件对象是独立于CAN硬件buffer。HOH被用做调用CanDrv的接口服务的传参,它有CanDrv的配置提供,被CanDrv用来识别CAN邮箱的通信buffer。

CanIf作为HOH的使用者,不会根据硬件特定信息对其进行解释。 因此,CanIf 保持独立于硬件

HOH分为两类:HTH和HRH

  • HRH是对一个CAN控制器信箱的逻辑Hardware Receive Object的引用的handle;
  • HTH是对一个CAN控制器信箱的逻辑Hardware Transmit Object的引用的handle;

一个HRH可以被配置用于接收:

  • 一个CanId(FullCan)
  • 一组CanIds(BasicCan)
  • 一个范围/区域 CanIds(BasicCan)
  • 所有CanIds

一个HTH可以被配置用于发送:

  • 一个CanId
  • 固定的一组CanIds

下图是一帧Can报文到硬件对象之间的映射关系

 HTH需要在配置阶段静态分配到一个CanIfBufferCfg,CanIf Tx L-PDU不直接引用HTHs而是引用CanIfBufferCfg。

CanIf 存储有关为传输目的配置的可用硬件对象的信息。 函数CanIf_Transmit()将CanTxPduId映射到对应的HTH,调用函数Can_Write()。

如果全局启用总线镜像并且已通过调用 CAN 控制器的 CanIf_EnableBusMirroring() 激活,则 CanIf 应在使用 Can_Write() 在该控制器上传输之前存储每个帧的内容。帧内容只应在实际发送时提供给总线镜像模块。 因此,必须存储帧内容,以便它可以从 CanIf_TxConfirmation() 中提供给总线镜像模块。

初始化

EcuM调用CanIf的函数CanIf_Init()对整个CanIf进行初始化。 所有全局变量和数据结构都在初始化过程中被初始化,包括标志和缓冲区。 EcuM通过调用相应的初始化服务分别对CanDrvs和CanTrcvs进行初始化。 CanIf 期望 CAN 控制器在初始化过程完成后保持在 STOPPED 模式,就像在上电复位之后一样。 在这种模式下,CanIf 和 CanDrv 既不能发送也不能接收 CAN L-PDU。 如果需要在运行时重新初始化整个 CAN 模块,EcuM 应调用 CanSm 以通过调用 CAN 接口模块的 API 服务 CanIf_SetControllerMode () 来发起所需的CAN 控制器状态转换。 CanIf 将来自 CanSm 的调用映射到相应 CanDrvs 的调用。

数据发送

请求发送

CanIf 的发送请求函数 CanIf_Transmit() 是上层在 CAN 网络上发送 L-PDU 的通用接口。 上层通信层模块仅通过 CanIf 的服务发起传输,而无需直接访问 CanDrv。 如果 CanDrv 可以将 L-PDU 数据写入 CAN 硬件传输对象,则发起的传输请求成功完成。

CanIf在调用CanIf_Transmit()时执行以下行为:

  • 检查CanIf的初始化状态;
  • 识别CanDrv(仅当使用多个CanDrv时)
  • 决定用于访问CAN硬件传输对象的HTH
  • 调用CanDrv的Can_Write()函数

如果发送成功,CanIf_Transmit()返回E_OK。

发送请求时序图

发送数据流

传输请求服务 CanIf_Transmit() 是基于 L-PDU。 对 L-SDU 特定数据的访问由以下参数组织:

  • Transmit L-PDU => L-SDU ID
  • 引用一个数据结构,其中包含L-SDU相关数据:指向L-SDU的指针,指向MetaData的指针和L-SDU长度。

对 L-SDU 数据结构的引用在多个 CanIf 的 API 服务中用作参数,例如 CanIf_Transmit() 或回调服务 <User_RxIndication>()。在 L-PDU 被配置为触发传输的情况下,L-SDU 指针是空指针。

发送数据流示意图

发送缓存

 在 CanIf 范围内,传输过程从调用 CanIf_Transmit() 开始,到调用上层模块的回调服务 <User_TxConfirmation>() 结束。在传输过程中,CanIf、CanDrv 和 CAN Mailbox 一起将要传输的 L-PDU 存储在一个位置。 根据传输方式,它们是:

  • CAN硬件传输对象,或
  • CanIf内部的发送L-PDU buffer(如果使能发送缓存)

如果使能发送缓存,如果Tx L-PDU在请求发送时被CanDrv拒绝,CanIf将会把Tx L-PDU储存在CanIf Transmit L-PDU buffer(即CanIfBufferCfg),但每个Tx L-PDU实体只会存一次。如果没有使能发送缓存,如果发送请求被拒绝,CanIf_Transmit()函数返回发送失败;若使能了发送缓存,发送请求因CanDrv CAN_BUSY被拒绝,L-PDU被缓存在CanIf的CanIfTxBuffer,此时尽管发送行为并未执行,但CanIf_Transmit()函数返回E_OK,在这种情况下,CanIf 通过 CanIf_TxConfirmation() 回调处理 L-PDU 的未完成传输,上层不必重试传输请求。

每个Tx L-PDU通过CanIfBufferCfg配置容器引用HTHs,即使不使用发送缓存也是这样配置,只不过这种情况中CanIfBufferCfg的参数CanIfBufferSize设置为0,此时CanIfBufferCfg配置容器仅仅是一个引用HTH的媒介。

当CanIfBufferSize配置大于0时,即可缓存CanIf Tx L-PDU或发送请求。如果L-PDU的发送需要保持特殊的次序,那么上层发送报文的请求必须依赖于前一帧报文发送成功的确认。

如果Tx L-PDU已经被缓存过,那么下次该L-PDU的缓存会直接覆盖上一次缓存的内容,因此发送出去的总是最新的数据。如果所有buffer都被占用,此时CanIf_Transmit()被调用发送一帧新的L-PDU(未被缓存过),那么该新的L-PDU或发送请求不会被缓存,CanIf_Transmit()返回E_NOT_OK。

CanIf在传输确认过程会判断CanIfTxBuffer中是否有缓存的L-PDU或发送请求,如果有则将其放入空闲的硬件传输对象。此过程是遵循优先级仲裁的,即优先级最高的先发送,CanIf对L-PDU和发送请求不做区分。当Can_Write()返回E_OK,CanIf立即将该L-PDU或发送请求从缓存清除(在发送确认返回之前)。

发送确认

如果前一个发送请求成功完成,CanDrv通过调用CanIf_TxConfirmation()通知CanIf。如果总线镜像全局使能且已调用CanIf_EnableBusMirroringSupport()对CAN控制器激活,那么在该CAN控制器上每帧经过CanIf_TxConfirmation()确认发送的报文,CanIf都应调用Mirror_ReportCanFrame()以存储报文内容和实际的CAN ID。

当CanIf_TxConformation()被调用时,CanIf需要识别被成功传输的L-PDU所连接的上层,并通过调用<User_TxConfirmation>(E_OK)通知上层传输完成,<User_TxConfirmation>()由上层实现。

上层通信层模块可以设计或配置为,用针对不同L-PDU或L-PDU组的单个或多个回调服务来处理发送确认。所有这些服务均在相应L-PDU发送请求的发送确认中由CanIf调用。Transmit L-PDU 能够发送与目标上层模块相关的不同的确认服务,此分配是在配置期间静态分配的。一个transmit L-PDU只能分配一个发送确认回调服务。

 

发送确认时序图(轮询模式)

数据接收

依照AUTOSAR基础软件架构,接收到的数据由上层通信栈(如:COM,CanNM,CanTp,DCM)解析,这意味着上层模块既不直接访问CanDrv的Rx缓存也不直接访问CanIf的Tx缓存。当CanIfPublicReadRxPduDataApi设为TRUE时,CanIf提供内部缓存Rx消息。当接收到一帧新L-PDU,CanDrv调用CanIf的CanIf_RxIndication()函数通知CanIf。对L-PDU数据的访问由以下参数组成:

  • Hardware Receive Handle(HRH)
  • Received CAN Identifier(CanId)
  • Received Data Length
  • Reference to Received L-PDU

Received L-PDU是独立于硬件的,位于通信系统的最底层CanDrv。HRH相当于CanDrv和使用L-PDU的上层之间的连接器。

在CanDrv调用CanIf_RxIndication()提示接收到L-PDU后,CanIf进行接收到收到报文提醒的后续处理。CanIf 无法识别 CanDrv 是使用临时缓冲还是直接硬件访问。 它期望在调用 CanIf_RxIndication() 时使用标准化的 L-PDU 数据。CAN硬件对象会被锁定直到数据拷贝到临时或上层模块buffer结束才结束。在CanIf的CanIf_RxIndication()函数返回后CAN硬件对象立即释放以避免(接收)数据丢失。属于所接收L-PDU的CanDrv、CanIf以及上层模块访问同一个临时的中间buffer,该临时中间buffer位于CAN控制器的CAN硬件对象或者位于CanDrv中的临时buffer。

报文接收数据流

数据接收提醒

 函数CanIf_RxIndictaion()的参数引用了最新接收的CAN L-PDU。若函数CanIf_RxIndication()被调用,CanIf将评估接收到的CAN L-PDU并准备L-SDU用以后续上层通信模块访问。CAN L-PDU检测通过,若配置有<User_RxIndication>(), CanIf通过<User_RxIndication>()异步通知上层模块。详细过程如下:

如果全局使能总线镜像功能,并且通过调用CanIf_EnableBusMirroringSupport()针对CAN控制器激活,那么针对该CAN控制器接收的每一帧由CanIf_RxIndication()提醒的报文,CanIf应该调用Mirror_ReportCanFrame()。当CanIf_RxIndication()被调用,CanIf对接收的L-PDU进行软件过滤,若L-PDU没通过软件过滤,CanIf结束接收;若接收的L-PDU通过CanIf的软件过滤,CanIf进行数据长度校验;若通过数据长度校验,CanIf根据配置的数据长度拷贝数据到静态接收buffer。如果接收的L-PDU配置使用了MetaData还需要将CAN ID拷贝到CAN_ID-32类型的MetaDataItem。CanIf识别所接收的L-PDU是否配置了目标上层模块(CanIfRxPduUserRxIndicationUL),若配置目标上层模块,对对该L-PDU调用上层模块提供的提醒回调(CanIfRxPduUserRxIndicationName)。

一个L-PDU只可分配一个接收提醒回调服务函数

总结起来,在调用CanIf_RxIndication()阶段,CanIf做以下工作:

  • 软件滤波(仅针对BasicCAN)
  • 数据长度校验
  • 缓存接收到的L-PDU
  • 调用上层接收提醒回调服务

以上CanIf所作的工作都依赖于配置属性,若静态配置时没有配置,则跳过相应步骤

读取接收数据

上层模块用于读取从CAN网络接收到的L-PDU数据的API CanIf_ReadRxPduData()是共用的。上层模块只通过CanIf发起接受请求,并不直接访问CanDrv,当CanIf将接收到的L-PDU写入上层模块的buffer后,接受请求成功完成。函数CanIf_ReadRxPduData()可以在不依赖接收事件(RxIndication)的情况下读出数据。如果在配置时启用(参见CanIfPublicReadRxPduDataApi),则不一定要为L-SDU配置接收指示服务(参见CanIfRxPduUserRxIndicationUL)。如果需要,也可以启用接收指示。

通过这种方式CanIf的上层模块接收L-PDU的机制可以在配置时用参数CanIfRxPduUserRxIndicationUL和CanIfRxPduReadData根据上层模块的需求选择。

如果配置参数CanIfPublicReadRxPduDataApi设置为TRUE,CanIf应将每个接收到的L-SDU(CanIfRxPduReadData启用)存储到接收L-SDU缓冲器中。这意味着如果配置参数CanIfRxPduReadData设置为TRUE,CanIf必须为该接收L-SDU分配一个接收L-SDU buffer。调用CanIfRxIndication()后,通过软件滤波和数据长度校验CanIf应将接收到的L-SDU存放到这个接收L-SDU buffer,在调用CanIfRxReadData()时,分配的L_SDU buffer已有最近接收的L-SDU。

数据读取时序图

CAN控制器模式

CanIf提供服务,用以控制底层CAN控制器的通信模式。这意味着所有CAN控制器都由相应提供的API服务控制,以请求和读取当前控制器模式。当上层模块调用CanIf_SetControllerMode()请求时,CAN控制器状态可能会被更改,上层模块的请求,由CanIf通过CanDrv的API传递到相应CAN控制器。

对连接在一个CAN网络上的所有CAN控制器进行一致的管理是CanSm的任务。通过这种方式,CanSm负责将一个CAN网络的所有CAN控制器按照一定顺序设置为睡眠模式或唤醒它们。CanIf通过调用函数CanIf_SetControllerMode()或CanIf_ControllerBusOff()来接受每个状态转换请求。CanIf不决定CAN控制器请求的模式转换是否有效。CanIf仅通过获取当前模式和执行所请求的模式转换来与CanDrv交互。即网络相关状态机在CanSm中实现,CanIf仅存储请求的模式并执行请求的转换,根据CanSm请求的运行模式,CanIf转发请求CanDrvs。

控制器模式转换

基于切换请求,实际的切换的动作以异步的方式发生,如请求进入CAN_CS_SLEEP模式。状态成功切换到CAN_CS_SLEEP模式后,CanDrv调用函数CanIf_ControllerModeIndication()通知CanIf,CanIf调用<User_ControllerModeIndication>()将状态切换结果通过回调函数异步通知上层。上层模块可以通过CanIf_GetControllerMode()轮询控制器当前的模式。

并非所有CAN控制器都支持Sleep和Wake-Up模式。CanDrv通过其接口提供独立于硬件的操作模式来封装这些模式,这些模式必须由CanIf管理。

唤醒

CanIf识别内部发起的CAN控制器唤醒(内部唤醒)和CAN网络唤醒请求(外部唤醒)。内部唤醒调用CanIf的函数CanIf_SetControllerMode(ControllerId,CAN_CS_STARTED)发起;外部唤醒是CanDrv或CanTrcv发给ECU集成代码的CAN控制器事件。

无论使用何种唤醒方法(直接关于CAN控制器或CAN收发器),只要CAN控制器和CAN收发器设置为某种“监听唤醒”模式,ECU都支持通过CAN网络唤醒。这通常是一种睡眠模式,在这种模式下,通常的通信被禁用。只有这种模式才能确保CAN控制器停止运行。因此,可以使能唤醒中断。CAN网络唤醒包括两个步骤:

  • 唤醒检测
  • 唤醒验证

唤醒检测:如果使能CAN网络支持唤醒,通过服务CanIf_CheckWakeup(WakeupSource)检测到唤醒,就通知CanIf。在CAN总线“唤醒”事件的情况下,可能会在执行EcuM_CheckWakeup(WakeupSource)期间调用函数CanIf_CheckWakeup(WakeupSource)。当CanIf_CheckWakeup(EcuM_WakeupSourceType WakeupSource)被调用,CanIf通过函数 Can_CheckWakeup()或CanTrcv_CheckWakeup() "询问" CanDrvs / CanTrcvs具体那个CAN硬件设备引起的总线唤醒。如果Can_CheckWakeup()或CanTrcv_CheckWakeup()至少一个返回E_OK,那么CanIf_CheckWakeup()返回E_OK,若Can_CheckWakeup()或CanTrcv_CheckWakeup()均返回E_NOT_OK,那么CanIf_CheckWakeup()返回E_NOT_OK。被调用的通信服务属于配置期间定义的服务(见CanIfDispatchCfg)。通过这种方式,ECU和CanSm能够改变CAN控制器状态,并控制与总线关闭恢复或唤醒程序相关步骤的系统行为。

唤醒验证:当检测到总线唤醒事件,该唤醒事件会被直接通知到ECU状态管理器,若该唤醒事件需要验证,EcuM(或者一个CDD)将打开对应CAN控制器(CanIf_SetControllerMode())和CAN收发器(CanIf_SetTrcvMode())

PDU通道模式控制

PDU通道组

每个L-PDU被分配给一个专用的物理CAN通道,该通道连接到一个CAN控制器和一个CAN网络。通过这种方式,可以从处理逻辑上单个L-PDU信道组的角度来控制属于一个物理信道的所有L-PDU。这些逻辑组代表一个ECU连接到一个底层CAN网络的所有L-PDU。下图所示为通道L-PDU组以及和它相关上层和网络的示意图:

通道PDU组

一个L-PDU只能分配给一个通道组,典型的如PduR和网络管理模块负责控制PDU工作模式。

PDU通道模式

PDU通道模式切换只有在CAN控制器模式为CAN_CS_STARTED模式下才可以进行。PDU通道有四种模式:

  • CANIF_OFFLINE
  • CANIF_TX_OFFLINE
  • CANIF_TX_OFFLINE_ACTIVE
  • CANIF_ONLINE

下图所示为PDU通道模式转换图

CanIf提供接口函数CanIf_GetPduMode()可用于获取当前PDU通道模式;接口函数CanIf_SetPduMode()用于设置PDU通道模式。

CANIF_OFFLINE

当PDU通道模式为CANIF_OFFLINE时,此时通道进行通信。CanIf初始化完成时,CanIf此时就将所有通道切换到CANIF_OFFLINE状态,此外当调用CanIf_SetControllerMode(ControllerId, CAN_-
CS_SLEEP)时,CanIf将相应通道的PDU通道设为CANIF_OFFLINE模式。在CANIF_OFFLINE模式下,CanIf:

  • 停止相关L-PDU的发送请求到CanDrv(CanIf_Transmit()调用返回E_NOT_OK给上层模块);
  • 清除相关的CanIf发送buffer;
  • 停止调用上层模块的接收提醒;
  • 停止调用上层模块的发送确认;

即在此模式下,报文收发均被禁止。

CANIF_TX_OFFLINE

当调用CanIf_SetControllerMode(ControllerId, CAN_CS_STOPPED)或CanIf_ControllerBusOff(ControllerId)时,CanIf将相应通道的PDU模式设置为CANIF_TX_OFFLINE。在CANIF_TX_OFFLINE模式下CanIf:

  • 停止相关L-PDU的发送请求到CanDrv(CanIf_Transmit()调用返回E_NOT_OK给上层模块);
  • 清除相关的CanIf发送buffer;
  • 停止调用上层模块的发送确认;
  • 使能调用上层模块的接收提醒;

即在此模式下,可以进行报文接收,不可以进行报文发送。已经在CAN发送硬件对象中等待发送的发送L-PDU将在模式更改为CANIF_TX_OFFLINE或CANIF_OFFLINE模式后立即发送。

CANIF_OFFLINE_ACTIVE

如果CanIfTxOfflineActiveSupport = TRUE,则CanIf通过CANIF_TX_OFFLINE_ACTIVE模式提供成功传输的模拟。该模式通过调用CanIf_SetPduMode(控制器Id,CANIF_TX_OFFLINE_ACTIVE)使能,仅影响传输路径。对于分配给处于CANIF_TX_OFFLINE_ACTIVE模式的通道的每个L-PDU,CANIF应立即调用上层模块的发送确认回调服务,而不是在调用CanIf_Transmit()期间缓存或转发L-PDU至CanDrv。

该功能对于实现特殊操作模式(诊断被动模式)以避免总线阻塞而不影响通知机制是有用的。这种模式通常用于诊断用途。

CANIF_ONLINE

在CANIF_TX_OFFLINE模式下CanIf:

  • 使能转发相关L-PDU的CanIf_Transmit()发送请求到CanDrv;
  • 使能调用上层模块的接收提醒;
  • 使能调用上层模块的发送确认;

即在此模式下,报文收发功能正常运行。

总结

CanIf的主要功能就是隔离底层硬件(驱动)区别,为上层提供统一的调用接口。其角色定位于"上传下达"的中转站。另外CanIf根据需求可配置的报文缓存。熟悉CanIf提供的常用API及其功能,即可满足日常工作中遇到问题分析的需求。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/584651.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【MySQL】如何实现单表查询?

在我们对数据进行操作时&#xff0c;查询无疑是至关重要的&#xff0c;查询操作灵活多变&#xff0c;我们可以根据开发的需求&#xff0c;设计高效的查询操作&#xff0c;把数据库中存储的数据展示给用户。 文章目录 前言1. 基础查询1.1 基础查询语法1.2 基础查询练习 2. 条件查…

算法与数据结构-复杂度分析(上)

文章目录 什么是大 O 复杂度表示法为什么要用大 O 复杂度表示法如何分析一段代码的时间复杂度1、只关注循环执行次数最多的一段代码2、加法法则&#xff1a;总复杂度等于量级最大的那段代码的复杂度3、乘法法则&#xff1a;嵌套代码的复杂度等于嵌套内外代码复杂度的乘积 几种常…

Unity老动画系统Animation

1、创建老动画系统 给要制作动画的GameObeject添加Animation组件 2、Animation参数 Animation&#xff1a;默认播放的动画 Animations&#xff1a;该动画组件可以控制的所有动画 Play AutoMatically&#xff1a;是否一开始就自动播放默认动画 Animate Physics&#xff1a;动画…

【JavaSE】Java基础语法(三十二):Stream流

文章目录 1. 体验Stream流2. Stream流的常见生成方式3. Stream流中间操作方法【应用】4. Stream流终结操作方法【应用】5. Stream流的收集操作 1. 体验Stream流 案例需求 按照下面的要求完成集合的创建和遍历 创建一个集合&#xff0c;存储多个字符串元素把集合中所有以"…

Python文件打包成exe文件

文章目录 背景安装pyinstaller开始打包总结 背景 今天因为在线将pdf转为word被收费了&#xff0c;有点不爽&#xff0c;所以自己动手撸一个pdf转word的小工具&#xff0c;想着打包成exe给朋友使用&#xff0c;万一哪天会用到呢&#xff1f; 安装pyinstaller 打开cmd命令窗口…

【AGC】云监控日志服务查询不到Logger日志相关问题

【关键字】 AGC、云监控、日志服务 【问题描述】 开发者反馈在使用AGC云监控&#xff0c;填写了Logger日志&#xff0c;但是在云监控的日志服务查不到的问题。具体如下所述&#xff1a; 云函数按要求写了Logger日志&#xff0c;但是在云监控的日志服务页面查询不到&#xff…

R语言混合效应(多水平/层次/嵌套)模型及 贝叶斯实现技术

回归分析是科学研究中十分重要的数据分析工具。随着现代统计技术发展&#xff0c;回归分析方法得到了极大改进。混合效应模型&#xff08;Mixed effect model&#xff09;&#xff0c;即多水平模型&#xff08;Multilevel model&#xff09;/分层模型(Hierarchical Model)/嵌套…

【计算思维题】少儿编程 蓝桥杯青少组计算思维 数学逻辑思维真题详细解析第7套

少儿编程 蓝桥杯青少组计算思维 数学逻辑思维真题详细解析第7套 1、下图中,乐乐家的位置用数对(4,3)表示,学校在乐乐家西南方向。下列选项中,学校的位置不可能是 A、(5,4) B、(2,2) C、(2,1) D、(1,2) 答案:A 考点分析:主要考查小朋友们的观察能力和方…

springboot聚合项目程打包,提示包不存在

报错提示如下&#xff0c;这是子模块large_screen调用login_security模块时&#xff0c;找不到login_security的包&#xff0c;但是login_security能单独打包成功 项目结构&#xff0c;两个子模块可以启动 解决办法&#xff1a; 父pom,要用 <packaging>pom</packag…

基础sql代码讲解含运行截图(详细版)

用student表为例&#xff0c;表的结构如下&#xff1a; 查询student表中的全部数据 SELECT * FROM student 插入数据&#xff1a; INSERT INTO student (id,name,phone,age) VALUES (2,张,1123,19) 还可以不写字段名字进行插入&#xff0c;但是此种方式必须和数据库字段一一…

3:String类

文章目录 String类1&#xff1a;介绍&#xff1a;2&#xff1a;String类实现了很多的接口&#xff1a;3&#xff1b;String类常用构造器4&#xff1a;不同方式创建String类对象的区别&#xff08;1&#xff09;直接赋值的方式&#xff08;2&#xff09;常规new的方式&#xff0…

租赁行业提供固定资产管理的解决方案

在租赁行业&#xff0c;固定资产管理和盘点是非常重要的环节。然而&#xff0c;由于资产数量庞大、资产分散、资产更新频繁等因素&#xff0c;使得固定资产管理和盘点变得十分复杂和繁琐。为了解决这些问题&#xff0c;易点易动固定资产管理系统应运而生。 易点易动固定资产管…

vulnhub 靶机渗透:Stapler

Stapler nmap扫描21 端口22 53端口80端口目录爆破 139端口666 端口3306端口12380端口获取数据库root权限获取系统立足点提权 其他思路系统立足点1系统立足点2提权1提权2 https://www.vulnhub.com/entry/stapler-1,150/ 靶机ip:192.168.54.27 kali ip:192.168.54.128 nmap扫描 …

【剑指offer】数据结构——树

目录 数据结构——树直接解【剑指offer】07. 重建二叉树【剑指offer】08. 二叉树的下一个结点【剑指offer】26. 树的子结构【剑指offer】27. 二叉树的镜像【剑指offer】28. 对称的二叉树【剑指offer】32.1 从上到下打印二叉树【剑指offer】32.2 从上到下打印二叉树2【剑指offer…

考研C语言第六章

6.2指针 类似寻宝图&#xff0c;先把地址存储到指针变量里面&#xff0c;然后去找这个地址 指针大小 当64bit——8bit 当32bit——4bit 定义指针一定要和里面的数定义一样类型的 6.3指针的传递使用场景 指针的使用场景&#xff1a;传递和偏移 &#xff08;不需要的话就别用指…

opencv_c++学习(二十八)

一、单目相机位姿估计 如上图所示&#xff0c;根据图像的情况反推相机的运动情况。 如实现上述功能则需要拍摄当前物体的图像&#xff0c;然后拍摄一段时间之后物体的图像&#xff0c;然后联合两张图像则可以获取两个时刻的相机位姿关系。 位姿估计函数&#xff1a; bool cv:s…

Musl libc 库成功适配到 openEuler Embedded,推动欧拉嵌入式生态发展

近期&#xff0c;RISC-V SIG 在欧拉嵌入式操作系统上成功实现了 musl libc 的适配&#xff0c;完成了使用 musl libc 库替换 glibc 库构建镜像的工作。目前&#xff0c;以 musl libc 为基础库编译的镜像已在 Raspberry Pi4 开发板上可用&#xff0c;这一成果推动了 openEuler E…

C Primer Plus第十一章编程练习答案

学完C语言之后&#xff0c;我就去阅读《C Primer Plus》这本经典的C语言书籍&#xff0c;对每一章的编程练习题都做了相关的解答&#xff0c;仅仅代表着我个人的解答思路&#xff0c;如有错误&#xff0c;请各位大佬帮忙点出&#xff01; 1.设计并测试一个函数&#xff0c;从输…

《Opencv3编程入门》学习笔记—第二章

《Opencv3编程入门》学习笔记 记录一下在学习《Opencv3编程入门》这本书时遇到的问题或重要的知识点。 第二章 OpenCV 官方例程引导与赏析 openv官方提供的示例程序&#xff1a;具体位于..\opencv\sources\samples\cpp ..\opencv\sources\samples\cpp\tutorial_code路径下存…

sql优化常用的方法

文章目录 1、explain 输出执行计划2、in 和 not in 要慎用3、少用select *4、善用limit 15、 order by字段建索引6、count(*)推荐使用7、where 子句中避免is null /is not null8、应尽量避免在 where!或<>9、应尽量避免在 where 子句中使用 or10、尽量用union all代替uni…