目录
1、 Persistency概念
2、 体系架构概述
2.1 设计方法及原则
2.1.1 键值存储
2.1.1 文件存储
2.2 类概述
3、需求规范及约束
3.1 功能概述
3.2 功能需求
3.3 非功能性需求
3.4 对其他功能集群的依赖
3.5 直接访问存储硬件
4、功能规格
4.1 持久性框架
4.1.1 Manifest中的持久化
4.1.2 Manifest中的键值存储
4.1.3 Manifest中的文件存储
4.2 功能集群的生命周期
4.3 并行访问持久数据
4.4 安全概念
4.5 冗余概念
4.6 初始化、更新持久数据
4.6.1 初始化持久数据
4.6.2 更新持久数据
4.6.3 更新成功后持久化数据的终结
4.6.4 更新失败后持久性数据的回滚
4.6.5 删除持久数据
4.7 访问文件的附加信息
持久性模块是自适应平台体系结构中的一个功能集群。persistency功能集群提供了对底层文件系统的自适应应用程序的访问,存在两个原因:(1)persistency功能集群使平台对存储实施访问控制和管理。(2)autosar支持的PSE51不允许直接访问文件系统;但是自适应应用程可以使用persistency功能集群跨多个行驶循环存储状态。
作为一个功能集群,持久性将C++ API应用于实现持久存储数据的应用程序。这些数据可以是文件,也可以是关键值数据库。C++ API在AutoSar标准命名空间ara::per中实现。持久性API通常与AUTOSAR标准一致。
persistency为自适应平台的应用程序和其他功能集群提供了将信息存储于Adaptive Machine的非易失性存储器中的机制。该数据在启动和点火周期内可用。Persistency提供了访问非易失性存储器的标准interface。
应用程序将存储位置标识作为参数传给persistency API来决定不同的存储位置。存储位置可以分为两类:(1) 键值存储;(2) 文件存储;应用可以任意组合使用这两类存储类型。
持久性数据是进程私有的。不能通过persistency在不同进程之间进行数据共享,这是为了防止通信管理之外的其他通信途径。
* Persistency做好了处理同一进程下多线程并发访问的准备。若要共享键值存储或文件存储,可以通过OpenKeyValueStorage和OpenFileStorage返回的SharedHandle传递到另一个线程;或者通过使用OpenKeyValueStorage和OpenFileStorage可以分别在同一个Key Value存储或文件存储的独立线程中调用。
* Persistency可以保证存储数据的完整性。通过冗余数据检查数据是否完整,
* Persistency提供能安全存储。
* Persistency为应用程序统计信息提供了已使用的资源的数量GetCurrentKeyValueStorageSize, GetCurrentFileStorageSize or GetCurrentFileSize.
* Persistency可以为数据提供加密存储,确保敏感数据存储到物理设备之前进行加密。
集群持久化提供了两种机制来访问自适应机器上的非易失性内存:文件存储和键值存储
持久化是作为一个库实现的,能够在应用程序上下文中运行。这消除了显式管理为应用程序配置的权限。同时,由于资源是由一个进程独占的,所以多个进程不能同时访问资源。最后,这种方法使应用程序开发人员能够实现一个中心持久化平台模块或者一个专用的持久化包装应用程序,其他应用程序可以与之通信,例如使用ara::com
为了启动和关闭所有直接实现ara接口的功能集群,应用程序应该使用ara::core::Initialize和ara::core::Deinitialize。为了确保一个正确的初始化和释放过程,Persistency应该实现它自己的一对ara::per::ifc::Initialize和ara::per::ifc::Deinitialize,它们将由ara::core::Initialize和ara::core::Deinitialize触发。
持久化功能集群能够保证存储数据的完整性。持久化集群可以使用冗余信息来检测数据损坏。在这方面,持久化集群支持两种类型的度量:crc和“M out of N”模式。这些可在部署期间配置,可以单独使用,也可以一起使用
持久化功能集群能够通过调用GetCurrentKeyValueStorageSize, GetCurrentFileStorageSize或GetCurrentFileSize来生成关于已使用资源数量的统计数据
P持久化集群可以处理同一进程下多线程并发访问。若要共享键值存储或文件存储,可以通过OpenKeyValueStorage和OpenFileStorage返回的SharedHandle传递到另一个线程;或者通过使用OpenKeyValueStorage和OpenFileStorage可以分别在同一个Key Value存储或文件存储的独立线程中调用。
相关函数介绍见5.1
键值存储是通过提供一个KeyValueStorage类来实现的。这个类的每一个实例都代表一个key-value数据库,因此应用程序可以通过使用数据库的数量来使用该类的多个实例。通过使用OpenKeyValueStorage创建这个类的实例将把数据库的所有key-value加载到RAM中,然后使用GetValue和SetValue函数进行访问这些元素,调用SyncToStorage.方法同步到物理存储介质中,以及通过调用DiscardPendingChanges方法,进行删除上次调用SyncToStorage或使用OpenKeyValueStorage打开KeyValueStorage以来的所有挂起的更改
如何访问这些元素,如下所示:
auto db = ara::per::OpenKeyValueStorage(kvsInstanceSpecifier).ValueOrThrow();
auto value = db->GetValue
db->SetValue(keyName, newValue).ValueOrThrow()
相关函数介绍见5.2
文件存储是通过提供ReadAccessor和ReadWriteAccessor类实现的。文件存储是通过OpenFileStorage函数访问的。文件存储中的单个文件可以使用FileStorage类提供的OpenFileReadOnly、OpenFileWriteOnly和OpenFileReadWrite方法来访问。
KeyValueStorage: 提供了访问Key-Value存储及其元素的所有方法,它是使用OpenKeyValueStorage创建的,并在SharedHandle中传递给应用程序
FileStorage: 提供了访问文件存储及其文件的方法,它是使用OpenFileStorage创建的,并在SharedHandle中传递给应用程序,使用ReadAccessor和ReadWriteAccessor两个类来提供对其文件的访问
ReadAccessor: 供了读取文件内容的方法,使用OpenFileReadOnly或OpenFileReadWrite创建并在UniqueHandle中传递给应用程序。
ReadWriteAccessor: 继承ReadAccessor类,提供了读写文件内容的方法,使用OpenFileReadWrite或OpenFileWriteOnly创建,并通过UniqueHandle中传递给应用程序
SharedHandle: 用于提供对键值存储或文件存储的共享访问
UniqueHandle: 用于提供对文件的非共享访问
AUTOSAR自适应平台持久性为自适应应用程序和AUTOSAR自适应平台的其他集群提供服务,因此必须处理以下几点:
* 持续存储启动和点火周期的数据
* 访问持久存储的数据
* 使用唯一标识符访问数据
* 从文件中读写数据
* 对持久数据进行加密
* 存储数据的错误检测和纠正
* 监控存储空间
【详情见:
https://www.autosar.org/fileadmin/user_upload/standards/adaptive/20-11/AUTOSAR_RS_Persistency.pdf (4.2 Functional Requirements)】
持久性的功能集群应该满足以下功能需求:
* 持久性的数据配置
* 持久性的数据存储
* 持久性的数据安全存储
* 安装、更新、回滚和删除持久性数据
* 持久性数据的资源处理
持久性功能集群暂时无任何非功能性需求
(1) 持久化(至少部分)是作为自适应应用程序的可执行文件的一部分进行编译的,因此也作为流程的一部分执行,这就创建了对执行管理的隐式依赖。
(2) 为了实现冗余和安全的目的,自适应加密接口的持久化服务。
(3) 对于持久性数据的安装、更新和删除,持久性与更新和配置管理(update and Configuration Management, UCM)进行交互
现代的嵌入式控制器使用闪存和类似的硬件来存储数据。这些设备有一个内在的问题,即可以从每个存储单元读取的信号会随着时间的推移而减少,主要受写访问次数的影响。最后,单元格将在每次读访问时产生任意值
不幸的是,在典型的系统中,写访问的分布非常不均匀。有些参数可能每秒更新几次,而有些代码可能在ECU的整个生命周期中都保持不变。为了避免早期的读取错误,应该部署磨损均衡,这样单个数据元素的频繁更新就分布在整个内存区域
另一方面,大多数操作系统都包括一个文件系统或至少一个闪存驱动程序来处理磨损水平,这样Persistency的典型实现就不必关心磨损水平。
功能集群持久化提供了两种不同的机制来访问持久内存:Key-Value storage提供了对一组具有相关值的键的访问(类似于数据库),而File storage提供了对一组文件的访问(类似于文件系统的目录)。自适应应用程序中持久性的典型用法如图下图所示。如图所示,自适应应用程序可以使用多个键值存储和多个文件存储的组合
自适应应用程序的持久化使用在执行清单中建模(进一步简单地称为清单),作为可执行程序的AdaptiveApplicationSwComponentTypes的一部分。该模型有两个主要部分:由PersistencyKeyValueStorageInterface和PersistencyFileStorageInterface聚合的应用程序设计信息,以及由PersistencyKeyValueStorage和PersistencyFileStorage聚合的部署信息。
API规范持有类ara::per::KeyValueStorage和ara::per::FileStorage,分别用于访问键值存储或文件存储。这些类的全局函数接收由PersistencyInterface类型的PortPrototype的标识符(完全限定的shortName路径),作为ara::core::InstanceSpecifier输入参数(参见5.1.1和5.2.1)。根据PortPrototype的性质,键值存储或文件存储将被访问为:当PortPrototype实例化为RPortPrototype时,只读;当PortPrototype实例化为PRPortPrototype时,读写;当PortPrototype实例化为PPortPrototype时,只写。
清单包含引用可执行文件的每个流程的单独部署数据。Process通过PersistencyPortPrototypeToDeploymentMapping类的专门化绑定到部署数据,该类引用了由PersistencyInterface、PersistencyDeploy和Process类型化的PortPrototype
每个Key-Value Storage都由一个PortPrototype来表示,该PortPrototype由应用程序设计中的PersistencyKeyValueStorageInterface和一个包含部署信息的PersistencyKeyValustorage来表示。每个键值存储可以保存多个键值对。自适应应用程序可以在运行时使用持久化API添加和删除键值对
在自适应应用程序的安装或更新期间,可以使用默认数据部署带有预定义键值对的键值存储。在安装或更新过程中,使用Adaptive Application软件包提供的部署信息和数据,由UCM模块(间接)触发此操作。
Key-Value Storage的应用设计和部署信息之间的链接由PersistencyPortPrototypeToKeyValueStorageMapping表示,它指的是一个由PersistencyKeyValueStorageInterface、对应的PersistencyKeyValueStorage和一个Process类型的PortPrototype
每个文件存储都由一个PortPrototype来表示,该PortPrototype由PersistencyFileStorageInterface在应用程序设计中针对各自的AdaptiveApplicationSwComponentType类型,以及一个包含部署信息的PersistencyFileStorage。如[3]所述,每个文件存储可以保存多个文件。与上面提到的键值对类似,Adaptive Application可以使用持久化API在运行时创建和删除文件
在安装或更新期间,可以部署带有初始内容的预定义文件的文件存储。该操作也是由UCM模块(间接)触发的。Adaptive Application的软件包中提供了所有所需的部署信息和文件。
文件存储的应用程序设计和部署信息之间的链接由PersistencyPortPrototypeToFileStorageMapping表示,它指的是一个由PersistencyFileStorageInterface、相应的PersistencyFileStorage和一个Process类型的PortPrototype。
使用ara::core::Initialize和ara::core::Deinitialize,应用程序可以使用直接的ara接口(即自适应平台基础)启动和关闭所有功能集群。
当调用ara::core::Initialize时,Persistency将读取manifest信息,并准备对manifest中定义的所有Key-Value storage和File storage的访问结构。
当ara::core::Deinitialize被调用时,Persistency将隐式确保所有文件存储的所有打开文件都被持久化,就像ara::per::ReadWriteAccessor::SyncToFile被调用并关闭,就像ara::per::UniqueHandles被析构一样。并且所有Key-Value storage中的未持久化值将被删除,就像ara::per::KeyValueStorage::DiscardPendingChanges被调用一样。然后,所有的访问结构都将被释放
应用程序不会在ara::core::Initialize之前或ara::core::Deinitialize之后调用任何持久化API,但是persistence需要保护自己不受这种可能性的影响。Persistency的所有函数及其类的所有方法在静态初始化之后,在ara::core::Initialize调用之前或在ara::core::Deinitialize调用之后调用时,都将返回错误kNotInitialized.
持久数据始终是一个进程的本地数据。因此,持久性永远不会在两个(或更多)进程之间共享持久数据,即使是同一个可执行文件。做出这一决定的背景是,除了功能性集群通信管理(communication Management)提供的机制外,persistence不应该为应用程序提供额外的通信路径。
如果持久性数据需要由多个进程(相同或不同应用程序的进程)访问,则应用程序设计人员有责任提供用于通信的服务接口;另一方面,持久化准备处理来自同一应用程序的多个线程的并发访问,这些线程运行在同一进程的上下文中。要创建对键值存储或文件存储的共享访问,由ara::per::OpenKeyValueStorage和ara::per::OpenFileStorage返回的ara::per::SharedHandle可以传递(即复制)给另一个线程,ara::per::OpenKeyValueStorage和ara::per::OpenFileStorage可以分别在独立的线程中调用,用于相同的键值存储或文件存储。所有操作键值存储和文件存储的支持从多个线程并发访问,当对应的键值存储或文件存储不打开时,ara::per::RecoverKeyValueStorage和ara::per::ResetKeyValueStorage或ara::per::RecoverAllFiles和ara::per::
ResetAllFiles才会成功
可以同时从多个线程访问Key-Value Storage中的单个键,因为ara::per::KeyValueStorage::GetValue和ara::per::KeyValueStorage::SetValue的操作是任意的,好比 ara::per::KeyValueStorage::RemoveKey, ara::per::KeyValueStorage::RemoveAllKeys,ara::per::KeyValueStorage::SyncToStorage, and ara::per::KeyValueStorage::DiscardPendingChanges
对文件存储中的单个文件的访问不能在多个线程之间共享,因为不可能同步读和写访问以及在文件中查找位置的相应变化。因此,由OpenFile * api返回的ara::per::UniqueHandle只能移动到另一个线程,并且试图打开一个已经打开的文件将会失败。同样,ara::per::FileStorage::DeleteFile、ara::per::FileStorage::RecoverFile、ara::per::FileStorage::ResetFile等操作也不可能在打开的文件上执行
当ara::per::UniqueHandle超出作用域时,或者当它们所属的文件存储被关闭时,文件会隐式关闭。访问一个关闭的文件存储的文件的ara::per::UniqueHandle将导致未定义的行为
持久化支持对存储在Key-Value Storage或File Storage中的数据进行加密和认证。是否应用加密和身份验证,在部署时决定。应用程序不知道这个事实。
一般情况下,键值存储、键值存储的key值、文件存储或者文件存储的文件在创建存储后和存储保存时进行加密,在文件打开时进行解密。存储身份验证的签名同样在打开存储时进行验证,并且初始化期间或者保存键值存储或文件存储时进行计算
对于只读键值存储和文件存储,在初始化期间只进行一次加密。用于对只读键值存储或文件存储进行身份验证的已签名哈希值是在清单中作为 PersistencyDeploymentToCryptoKeySlotMapping.verificationHash 或者 PersistencyDeploymentElementToCryptoKeySlotMapping.verificationHash 提供,或者在初始化期间所计算。
持久化功能集群应使用Crypto API的服务进行加密和解密以及创建和签名验证。它将从PersistencyDeploymentToCryptoKeySlotMapping或PersistencyDeploymentElementToCryptoKeySlotMapping引用的CryptoKeySlot中派生出要使用的算法和密钥,并将它们用于访问Crypto API。
持久化功能集群应负责存储数据的完整性。可以通过计算存储数据的crc或散列值,以及创建冗余副本来实现。所有这些措施都有效地为存储的数据创建了一些冗余。需要采取的具体措施是可配置的:应用程序设计人员可以使用PersistencyInterface.redundancy请求冗余,或者使用PersistencyInterface.redundancyHandling预先选择要采取的实际措施。在部署期间,集成器可以使用PersistencyDeployment.redundancyHandling定义确保数据完整性的实际措施。如果PersistencyInterface.redundancyHandling处理配置后,将其作为指导,但也可以选择其他更合适的措施,基于对最终系统的更好的知识。
若数据损坏,无法使用冗余信息恢复,则使用kValidationFailed持久化将失败。然后,应用程序可以选择使用ara::per::RecoverKeyValueStorage, ara::per::KeyValueStorage::RecoverKey, ara::per::RecoverAllFiles,或者ara::per::FileStorage::RecoverFile来尽可能多地恢复,并将相应的Key-Value Storage或FileStorage重新设置为一致状态。当然,在这种情况下,应用程序必须验证恢复的数据。或者它可以使用ara::per::ResetKeyValueStorage, ara::per::KeyValueStorage::ResetKey, ara::per::ResetAllFiles,或者ara::per::FileStorage::ResetFile根据当前清单将损坏的项重置为初始状态。
当应用程序使用ara::per::OpenKeyValueStorage或ara::per::OpenFileStorage打开键值存储或文件存储时,或者调用ara::per::UpdatePersistency时,Persistency将检查存储的数据是否存在。如果没有找到持久数据,则持久化将初始化持久数据
当应用程序使用ara::per::OpenKeyValueStorage或ara::per::OpenFileStorage打开键值存储或文件存储时,或者当ara::per::UpdatePersistency被调用时,Persistency将比较外围软件集群的版本信息和manifest中的版本信息 。如果清单中的版本高于存储的版本,则persistence应首先创建持久数据的备份,然后更新数据。
任何时候只需要保留一组备份数据。当执行新的更新操作时,可能会覆盖旧的备份数据。持久数据的更新将在7.6.2.1和7.6.2.2节中描述
当应用程序使用ara::per::OpenKeyValueStorage或ara::per::OpenFileStorage打开键值存储或文件存储时,或者当ara::per::UpdatePersistency被调用时,Persistency将比较可执行文件。清单中的版本与存储的版本相对应。如果清单中的版本高于存储版本,则持久化将使用ara::per::RegisterApplicationDataUpdateCallback为每个根据[上述]更新的键值存储和文件存储调用应用程序注册的函数。
应用程序使用ara::per::RegisterApplicationDataUpdateCallback注册的函数可以被应用程序用于手动更新Key-Value存储的键值对或文件存储的文件。键值存储或文件存储由提供给该函数的ara::core::InstanceSpecifier标识。然后应用程序可能会基于可执行文件版本,作为函数的第二个参数提供的存储数据,以旧格式或旧类型读入存储数据,转换数据,并以当前版本所期望的新格式或新类型再次存储数据
在初始化和更新之后,通常在应用程序的验证阶段使用ara::per:: updatepersistence调用持久性。当此操作成功时,UCM将最终确定应用程序,然后以正常的执行模式再次启动。
在这种情况下,persistence应该删除在之前的更新期间创建的任何备份
当一个键值存储或文件存储被应用程序使用ara::per::OpenKeyValueStorage或ara::per::OpenFileStorage打开,并且ara::per::UpdatePersistency自从Persistency被初始化后还没有被调用,持久化将比较清单中SoftwareCluster.version版本与存储的版本相对应。如果两个版本完全相同,则持久化应删除所有备份数据
当应用程序使用 ara::per::OpenKeyValueStorage or ara::per::OpenFileStorage打开键值存储或文件存储,或者ara::per::UpdatePersistency方法被调用时,持久化集群应比较清单中的SoftwareCluster.version版本与存储的版本,若清单中的版本低于存储中的版本,持久性应将清单中的版本与备份数据中存储的版本进行比较。如果版本匹配,持久化将恢复备份。否则移除所有的键值存储和文件存储,重新初始化清单中的持久数据
当调用ara::per::ResetPersistency时,该Persistency将删除所有键值存储和文件存储
持久化集群可以通过ara::per::FileStorage::GetFileInfo【见5.2.11.7】方法来过去存储文件的信息,该方法返回文件创建时间(creationTime)、最后一次修改时间(modificationTime)、最后一次访问时间(accessTime)以及创建方式和由谁创建(fileCreationState)和最后一次修改(fileModificationState)的信息。方法ara::per::FileStorage::GetFileInfo将需要的信息收集到一个ara::per::FileInfo结构体中【见5.2.10】,并将其返回给应用程序。如果持久化集群使用底层操作系统的文件系统,那么部分信息(如创建或访问时间)可以从文件系统获取。只有当文件当前未打开时,此信息才会是准确的