【acrn】What is ACRN

ACRN hypervisor(虚拟机监控程序)直接运行在裸机硬件上,适合于各种物联网和嵌入式设备解决方案。 ACRN hypervisor
解决了 datacenter hypervisors 和 hard partitioning hypervisors 之间当前存在的差距。
ACRN hypervisor 体系结构通过为物联网和嵌入式设备提供 guest OS 共享优化,将系统划分为不同的功能域。

Introduction to Project ACRN

  1. ACRN 是一个轻量级的 hypervisor。
  2. 考虑到了实时性和安全性的需要,简化了嵌入式开发。
  3. ACRN 定义了一个借用了堆栈和体系结构实现的设备管理管理程序,用于使用 VMM 在统一的系统上安全地管理运行多个软件子系统。
  4. ACRN Hypervisor 借用了 VMM 堆栈,直接在裸机硬件上运行,适用于各种 IoT 和嵌入式设备解决方案。
  5. ACRN Hypervisor 解决了 datacenter gypervisorshard partitioning hypervisors 之间存在的空白。
  6. ACRN Hypervisor 管理程序架构将系统划分为不同的功能域,并对于物联网和嵌入式设备的用户 VM 共享优化。

ACRN Open Source Roadmap

ACRN High-Level Architecture

自2018年7月发布最初的 v0.1 版本以来,ACRN 架构一直在发展。从v1.1版本开始,ACRN架构具有灵活性,可以支持逻辑分区,共享和混合模式。 如图1所示,硬件资源可以分为两部分:

在这里插入图片描述

  1. 如图 1 所示(左侧),资源由预启动的用户虚拟机(pre-User VM)进行分区和使用,它独立于其他虚拟机运行,拥有专用的硬件资源(CPU内核、内存和 I/O 设备)
  2. 其他虚拟机不知道 pre-User VM 存在。
  3. pre-User VM 可以用作安全 OS 虚拟机。在发生系统严重故障时采取紧急措施。
  4. 如图 1 所示(右侧),其余硬件资源在 service VM 和 User VMs 之间共享。服务虚拟机类似于 Xen 的 Dom0,用户虚拟机类似于 Xen 的 DomU。
  5. 如果没有 pre-User VM,那么 service VM 是 ACRN 启动的第一个 VM。service VM 可以通过运行本机驱动程序直接访问硬件资源,并且它通过设备模型为 User VMs 提供设备共享服务。service VM 以及 User VMs 可以是其它操作系统(Ubuntu *,Android *,Windows *或VxWorks *)。
  6. 有一个特殊的 User VMs——Posted-launched RTVM,旨在运行硬实时 OS(Zephyr *,VxWorks *或Xenomai *),RTVM 可用于软件可编程逻辑控制器(PLC),进程间通信(IPC)或机器人技术应用程序。

Usage Scenarios

  1. ACRN可用于资源受限的嵌入式平台中的异构工作负载整合,以实现功能安全性或硬实时支持为目标。
  2. 它可以采用多个单独的系统,并允许在单个计算平台上运行的工作负载合并解决方案既可以运行安全关键型应用程序,也可以运行非安全性应用程序,以及可以保护系统的安全功能。
  3. ACRN的源代码中包含许多预定义的方案。 它们都建立在上面已经说明的三种基本操作模式的基础上,即逻辑分区,共享和混合模式。 它们还指定了可以运行的VM数量,它们的属性以及可以访问的VM,这些VM可以与其他VM共享或专有地共享。

The predefined scenarios are in the misc/vm_configs/scenarios folder in the source code.
XML examples for some platforms can also be found under misc/vm_configs/xmls/config-xmls.

Industrial Workload Consolidation

在这里插入图片描述
支持工业应用程序的工作负载整合甚至更具挑战性。ACRN hypervisor需要在不受干扰的情况下运行不同的工作负载,增加保护系统的安全功能,将硬实时敏感的工作负载与一般计算工作负载一起运行,并进行数据分析以进行及时的操作和预测性维护。

虚拟化在工业环境中尤其重要,因为设备和应用程序的寿命很长。虚拟化使工厂能够通过使用vm来运行远远超出预期退役日期的旧控制系统和操作系统,从而使其控制系统硬件现代化。

如图2所示,服务VM可以启动许多启动后的用户VM,并为它们提供设备共享功能。总共,最多可启动7个用户vm:

  • 5 regular User VMs
  • One Kata Containers User VM (see Run Kata Containers on a Service VM for more details)
  • RTVM(Real-time VM)

在本例中,一个启动后的用户VM提供人机界面(HMI)功能,另一个提供人工智能(AI)功能,一些计算功能运行Kata容器,RTVM运行需要硬实时特性的软可编程逻辑控制器(PLC)

图2显示了ACRN的工业使用场景框图:

  • ACRN从SoC平台引导,并支持固件,如UEFI BIOS。
  • ACRN管理程序可以创建运行不同操作系统的vm:
    • 服务VM,如 Ubuntu
    • 一种人机界面(HMI)应用程序操作系统,如Windows
    • Linux上的人工智能(AI)应用程序
    • 一个Kata容器应用程序
    • 一个实时控制系统,如Zephyr*, VxWorks *或RT-Linux*。
  • 服务VM为其他虚拟机提供设备共享功能,如磁盘和网络中介。它还可以运行一个编配代理,允许使用Kubernetes等工具进行用户VM编配。
  • 人机界面应用操作系统可以是Windows*或Linux *。Windows在工业人机界面环境中占据主导地位。
  • ACRN可以支持软实时操作系统,如用于软plc控制的preempt-rt Linux,或提供较少抖动的硬实时操作系统。

Automotive Application Scenarios

如图3所示,ACRN管理程序可用于构建汽车软件定义座舱(SDC)和车内体验(IVE)解决方案。

在这里插入图片描述
作为参考实现,ACRN为嵌入式系统管理程序供应商提供了使用参考I/O中介解决方案构建解决方案的基础。在这个场景中,汽车SDC系统由运行在服务VM中的仪器集群(IC)系统和运行启动后的用户VM的车载信息娱乐(IVI)系统组成。此外,还可以修改SDC场景,以添加更多启动后的用户vm,它们可以托管后座娱乐(RSE)系统(图中没有显示)。

仪表集群(IC)系统用于显示驾驶员关于车辆的操作信息,如:

  • 汽车的速度、油位、行驶里程和其他驾驶信息;
  • 在挡风玻璃上投射向上的图像,并在燃油不足或胎压不足时发出警报;
  • 显示后视镜和环绕摄像头,以协助泊车。

车载信息娱乐(IVI)系统的功能包括:

  • 导航系统、收音机和其他娱乐系统;
  • 通过语音识别连接到移动设备进行电话、音乐和应用程序;
  • 通过手势识别或触摸控制交互。

后座娱乐(RSE)系统可以运行:

  • 娱乐系统;
  • 虚拟办公室;
  • 连接前排IVI系统和移动设备(云连接);
  • 通过语音识别连接到移动设备进行电话、音乐和应用程序;
  • 通过手势识别或触摸控制交互。

ACRN管理程序可以支持Linux VM和Android VM,作为ACRN管理程序管理的用户VMs。开发人员和原始设备制造商可以使用这个参考堆栈来运行他们自己的vm,以及IC、IVI和RSE vm。服务VM在后台运行,用户VM作为启动后的VM运行。

上面的图3显示了ACRN的SDC使用场景的框图。

  • ACRN hypervisor位于引导加载程序的最上方,具有快速引导功能。
  • 对资源进行分区,以确保安全关键域和非安全关键域能够在一个平台上共存。
  • 丰富的I/O中介器允许跨vm共享各种I/O设备,提供全面的用户体验。
  • 通过有效的虚拟化,一个SoC支持多个操作系统。

Best Known Configurations

ACRN GitHub代码库定义了5个最著名的配置(BKC),针对SDC和行业使用场景。开发人员可以从这些预定义配置之一开始,并根据自己的应用程序场景需求对其进行定制。

在这里插入图片描述

SDC

在这个SDC场景中,仪器集群(IC)系统与服务VM一起运行,车载信息娱乐(IVI)系统在用户VM中运行。
在这里插入图片描述

Industry

在这个行业场景中,服务VM为基于windows的HMI用户VM提供设备共享功能。一个启动后的用户VM可以运行一个Kata容器应用程序。另一个用户VM支持硬实时或软实时操作系统应用程序。多达5个额外的用户VMs启动后支持功能,如人机界面(HMI),人工智能(AI),计算机视觉等。
在这里插入图片描述

Hybrid

在这个混合场景中,一个预启动的Safety/RTVM由管理程序启动。服务VM运行一个启动后运行的用户VM,该VM运行非安全或非实时任务。
在这里插入图片描述

Hybrid real-time (RT)

在这个混合场景中,一个预启动的Safety/RTVM由管理程序启动。服务VM运行一个启动后运行的用户VM,该VM运行非安全或非实时任务。
在这里插入图片描述

Logical Partition

这个场景是用于VM逻辑分区的简化VM配置:一个是安全VM,另一个是基于linux的用户VM。
在这里插入图片描述

Licensing

ACRN管理程序和ACRN设备模型软件都是在许可的bsd -3条款许可下提供的,该许可允许“以源代码和二进制形式重新发布和使用,无论是否进行修改”,以及许可中注明的完整的版权通知和免责声明。

ACRN Device Model, Service VM, and User VM

为了保持hypervisor代码库尽可能小和高效,设备模型实现的大部分驻留在服务VM中,以提供共享和其他功能。下面的传递部分描述了共享哪些设备以及用于共享这些设备的机制的细节。

服务VM以系统最高的虚拟机优先级运行,以确保所需的设备时间敏感需求和系统服务质量(QoS)。服务VM任务以混合优先级运行。在回调服务于特定用户VM请求时,服务VM中的相应软件(或中介)将继承用户VM优先级。在服务OS中还可能有其他低优先级后台任务。

在我们上面描述的汽车示例中,用户VM是车辆控制和车内娱乐的中心枢纽。它提供了对电台和娱乐选项的支持,对车辆气候控制和车辆导航显示的控制。它还提供了连接选项,可以使用USB、蓝牙和Wi-Fi进行第三方设备与车辆的互动,如Android Auto或Apple CarPlay,以及许多其他功能。

Boot Sequence

ACRN系统管理程序可以直接从第三方引导加载程序引导。一个流行的引导加载程序是grub,它也被Linux发行版广泛使用。

使用GRUB引导ACRN介绍了如何使用GRUB引导ACRN hypervisor。

在这里插入图片描述
引导过程如下:

  1. UEFI boots GRUB.
  2. GRUB boots the ACRN hypervisor and loads the VM kernels as Multi-boot modules.
  3. The ACRN hypervisor verifies and boots kernels of the Pre-launched VM and Service VM.
  4. In the Service VM launch path, the Service VM kernel verifies and loads the ACRN Device Model and Virtual bootloader through dm-verity.
  5. The virtual bootloader starts the User-side verified boot process.

在 boot mode 中,预启动的 VM 和 service VM 的 boot 设置被定义在misc/vm_configs/$(SCENARIO)/vm_configurations.c 代码的 vm_configs[vm id].os_config数据结构中的 bootargs 变量中。

GRUB菜单可以覆盖它们的启动选项。有关详细信息,请参阅使用GRUB来引导ACRN。虚拟机管理程序源代码或GRUB菜单不包含启动后的引导选项;它们在guest映像文件中定义,或由启动脚本指定。

Slim Bootloader是一种可用于引导ACRN的替代引导固件。引导ACRN管理程序教程提供了关于如何将SBL与ACRN一起使用的更多信息。

ACRN Hypervisor Architecture

ACRN管理程序是类型1的管理程序,直接运行在裸机硬件上。它实现了一种混合VMM体系结构,使用一个特权服务VM,运行管理I/O设备并提供I/O中介的服务VM。支持多个用户虚拟机,每个虚拟机运行不同的操作系统。

在独立的vm中运行系统可以隔离其他vm及其应用程序,减少潜在的攻击面并最大限度地减少安全干扰。但是,在不同的vm中运行系统可能会给应用程序带来额外的延迟。

图1显示了ACRN系统管理程序体系结构,其中表示了所有类型的虚拟机(vm):

  • Pre-launched User VM (Safety/RTVM)
  • Pre-launched Service VM
  • Post-launched User VM
  • Kata Container VM (post-launched)
  • real-time VM (RTVM)

服务VM拥有包括平台设备在内的大多数设备,并提供I/O中介。值得注意的例外是分配给预先启动的用户VM的设备。一些PCIe设备可以通过VM配置传递到启动后的用户操作系统。服务VM一起运行特定于管理程序的应用程序,例如ACRN设备模型和ACRN VM管理器。

ACRN hypervisor还运行ACRN VM管理器来收集用户操作系统的运行信息,并控制用户VM,比如启动、停止和暂停VM、暂停或恢复虚拟CPU。

在这里插入图片描述
ACRN虚拟机监控程序利用英特尔虚拟化技术(Intel VT), ACRN虚拟机监控程序以虚拟机扩展(VMX)根操作、主机模式或VMM模式运行。所有来宾操作,包括用户VM和服务VM,都在VMX非根操作或来宾模式下运行。(为了简单起见,下文将使用术语VMM模式和来宾模式)。

VMM模式有4个保护环,但是只在环0特权中运行ACRN管理程序,使环1-3未使用。客人(包括服务VM和用户虚拟机),以客人模式运行,也有自己的四个保护环(环0到3)。用户内核运行在环0客人模式,土地和用户应用程序运行在用户模式的第3环(环1 & 2通常不使用的商业操作系统)。

在这里插入图片描述
如图11所示,VMM模式和来宾模式通过VM退出和VM进入进行切换。当引导加载程序将控制权交给ACRN管理程序时,处理器还没有启用VMX操作。ACRN管理程序需要首先通过VMXON指令启用VMX操作。最初,当启用VMX操作时,处理器保持在VMM模式。它通过VM恢复指令(或首次VM启动)进入来宾模式,并通过VM退出事件返回VMM模式。VM退出是对某些指令和事件的响应。

在来宾模式下处理器执行的行为是由虚拟机控制结构(vmcs)控制的。vmcs包含客户状态(在VM入口加载并在VM退出时保存)、主机状态(在VM退出时加载)和客户执行控制。ACRN hypervisor为每个虚拟CPU创建一个VMCS数据结构,并使用VMCS配置在来宾模式下运行的处理器的行为。

当来宾操作系统执行某个敏感指令时,可能会发生VMCS配置中定义的VM退出事件。当发生VM退出时,控制权回到ACRN管理程序。ACRN hypervisor模拟来宾操作系统指令(如果退出是因为特权问题),并恢复来宾操作系统到它的下一条指令,或者修复VM退出原因(例如,如果来宾操作系统内存页尚未映射)并恢复来宾操作系统以重新执行该指令。

注意,VMM模式中使用的地址空间与来宾模式中使用的地址空间不同。来宾模式和VMM模式使用不同的内存映射表,因此ACRN hypervisor不受来宾访问的保护。ACRN管理程序使用EPT来映射来宾地址,使用来宾页表将来宾线性地址映射到来宾物理地址,并使用EPT表将来宾物理地址映射到机器物理地址或主机物理地址(HPA)。

ACRN Device Model Architecture

因为设备可能需要在VM之间共享,所以使用设备模拟来让VM应用程序(和操作系统)访问这些共享设备。传统上,设备模拟有三种架构方法:

  • 第一种架构是虚拟机监控程序中的设备模拟,这是在VMware*工作站产品(基于操作系统的虚拟机监控程序)中实现的一种常见方法。在这种方法中,hypervisor包括各种来宾操作系统可以共享的公共设备的模拟,包括虚拟磁盘、虚拟网络适配器和其他必要的平台元素。
  • 第二个架构称为用户空间设备模拟。顾名思义,设备模拟不是嵌入到系统管理程序中,而是在一个单独的用户空间应用程序中实现。例如,QEMU提供了这种设备模拟,许多独立的管理程序也使用这种设备模拟。这个模型非常有利,因为设备模拟独立于管理程序,因此可以为其他管理程序共享。它还允许任意设备模拟,而不必让hypervisor(在特权状态下操作)负担此功能。
  • 基于管理程序的设备模拟的第三个变体是半虚拟化(PV)驱动程序。在XEN项目引入的这个模型中,虚拟机监控程序包括物理驱动程序,每个客户操作系统包括一个虚拟机监控程序感知驱动程序,该驱动程序与虚拟机监控程序驱动程序协同工作。

在上面讨论的设备仿真模型中,共享设备是有代价的。无论设备模拟是在管理程序中执行,还是在独立VM中的用户空间中执行,都会存在开销。只要设备需要由多个客户操作系统共享,这种开销就是值得的。如果没有必要共享,那么还有更有效的方法来访问设备,例如“透传”。

ACRN设备模型是用户VM的占位符。它为用户OS分配内存,配置和初始化用户VM使用的设备,加载虚拟固件,初始化虚拟CPU状态,并调用ACRN hypervisor服务来执行来宾操作系统指令。ACRN设备模型是一个运行在服务VM中的应用程序,它基于命令行配置仿真设备,如下面的架构图12所示:

在这里插入图片描述
ACRN设备模型包含以下三个方面:

设备模拟:

ACRN设备模型提供设备模拟例程,这些例程将它们的I/O处理程序注册到I/O dispatcher。当用户VM设备发出I/O请求时,I/O dispatcher将此请求发送到相应的设备模拟例程。

VHM:
Virtio和Hypervisor服务模块是服务VM中的一个内核模块,充当支持设备模型的中间层。VHM客户端处理流程描述如下:

  1. ACRN hypervisor IOREQ通过发送到服务VM的向上调用通知被转发到VHM。
  2. VHM将IOREQ标记为“在处理中”,这样相同的IOREQ就不会再次出现。IOREQ将发送给客户进行处理。同时,VHM已经准备好迎接另一个IOREQ。
  3. IOREQ客户端可以是服务VM用户域应用程序,也可以是服务VM内核空间模块。一旦IOREQ被处理并完成,客户端将向VHM发出IOCTL调用,以通知IOREQ状态更改。然后VHM检查并对ACRN管理程序进行超调用,通知它IOREQ已经完成。

设备透传

在最高级别上,设备透传就是为给定的来宾操作系统提供设备隔离,以便该设备可以仅由该来宾操作系统使用。

在这里插入图片描述
通过使用设备透传可以实现接近本机的性能。对于那些由于通过管理程序(在管理程序中使用驱动程序或通过管理程序到用户空间模拟)竞争和性能下降而没有采用虚拟化的网络应用程序(或具有高磁盘I/O需求的应用程序),这是理想的。当设备本身不被共享时,将设备分配给特定的客户机也很有用。例如,如果一个系统包含多个视频适配器,那么可以将这些适配器传递到唯一的客户域。

最后,可能存在只有一个客户域使用的专用PCI设备,因此应该将它们传递给客户。单独的USB端口也可以隔离到一个给定的域,或者一个串口(它本身不能共享)可以隔离到一个特定的客户机。在ACRN管理程序中,我们只支持USB控制器透传,不支持传统串行端口(例如0x3f8)的透传。

设备透传的硬件支持

英特尔目前的处理器架构提供了对VT-d设备透传的支持。VT-d将客户物理地址映射到机器物理地址,因此设备可以直接使用客户物理地址。当发生这种映射时,硬件负责访问(和保护),客户操作系统可以像使用非虚拟化系统一样使用设备。除了将来宾操作系统映射到物理内存之外,隔离还可以防止该设备访问属于其他来宾操作系统或管理程序的内存。

帮助中断扩展到大量vm的另一个创新是消息有信号中断(Message signts interrupts, MSI)。MSI将中断转换为更容易虚拟化的消息(扩展为数千个独立中断),而不是依赖于与客户机相关联的物理中断引脚。MSI从PCI version 2.2开始就可用了,但PCI Express (PCIe)也可用,它允许织物伸缩到许多设备。MSI是I/O虚拟化的理想选择,因为它允许隔离中断源(与必须多路复用或通过软件路由的物理引脚相反)。

对设备透传的管理程序支持

通过使用最新的增强虚拟化的处理器架构,管理程序和虚拟化解决方案可以支持设备透传(使用VT-d),包括Xen、KVM和ACRN管理程序。在大多数情况下,必须使用内核构建时选项将来宾操作系统(用户操作系统)编译为支持透传。可能还需要对主机VM隐藏设备(就像使用pciback对Xen所做的那样)。有些限制适用于PCI,例如,PCI -to-PCI桥接器后面的PCI设备必须分配给相同的客户OS。PCIe没有这个限制。

Virtio框架体系结构

Virtio是任何类型的管理程序中一组公共仿真设备的抽象。在ACRN参考栈中,我们的实现与Virtio规范0.9和1.0兼容。通过遵循这个规范,虚拟环境和客户应该有一个直观、高效、标准和可扩展的虚拟设备机制,而不是针对每个环境或针对每个操作系统的机制。

Virtio提供了一个通用的前端驱动框架,它不仅标准化了设备接口,还增加了跨不同虚拟化平台的代码重用。

在这里插入图片描述
为了更好地理解Virtio,特别是它在ACRN项目中的应用,这里重点介绍Virtio的几个关键概念:

前端Virtio驱动程序(又称前端驱动程序,或本文档中的FE驱动程序)

Virtio采用了前端-后端架构,为前端和后端Virtio驱动提供了一个简单而灵活的框架。FE驱动提供api来配置接口、传递消息、产生请求和通知后端Virtio驱动。该方法不仅易于实现,而且消除了仿真设备的性能开销。

后端Virtio驱动程序(也称为后端驱动程序,或本文档中的BE驱动程序)

与FE驱动程序类似,BE驱动程序运行在主机OS的用户区或内核区。BE驱动消耗来自FE驱动的请求,并将它们发送给主机的本机设备驱动。一旦请求被主机本机设备驱动程序完成,BE驱动程序就会通知FE驱动程序请求的完整性。

简单明了:作为现有总线上的标准设备的Virtio设备

与从头创建新的设备总线不同,Virtio设备构建在现有总线上。这为FE和BE驱动程序之间的交互提供了一种简单的方式。例如,FE驱动程序可以读/写设备寄存器,虚拟设备可以中断FE驱动程序,代表BE驱动程序,以防一些事情发生。目前Virtio支持PCI/PCIe总线和MMIO总线。在ACRN项目中,只支持PCI/PCIe总线,所有Virtio设备共享相同的供应商ID 0x1AF4。

效率高:鼓励配料操作

批处理操作和延迟通知对于实现高性能I/O非常重要,因为FE和BE驱动程序之间的通知通常涉及昂贵的客户退出。因此,尽可能地鼓励批量操作和抑制通知。这将为性能关键设备提供一个有效的实现。

标准:virtqueue

所有Virtio设备共享一个标准的环形缓冲区和描述符机制,称为virtqueue,如图6所示。virtqueue是一个分散收集缓冲区的队列。在虚拟队列上有三种重要的方法:

  • add_buf is for adding a request/response buffer in a virtqueue
  • get_buf is for getting a response/request in a virtqueue, and
  • kick is for notifying the other side for a virtqueue to consume buffers.

FE驱动程序在客户物理内存中创建虚拟队列。BE驱动程序只需要解析virtqueue结构就可以获得请求并完成请求。Virtqueue组织是特定于用户操作系统的。在Linux中的Virtio实现中,virtqueue被实现为一个称为vring的环形缓冲区结构。

在ACRN中,可以直接利用virtqueue api,这样用户就不需要担心virtqueue的细节。有关virtqueue实现的更多细节,请参考用户VM。

可扩展:功能位

每个虚拟设备及其驱动程序都有一个简单的可扩展特性协商机制。每个虚拟设备可以要求它的设备特定的功能,而相应的驱动程序可以用驱动程序理解的功能子集来响应设备。该特性机制使虚拟设备和驱动程序能够向前和向后兼容。

在ACRN参考堆栈中,我们实现了如图16所示的用户空间和内核空间:

在这里插入图片描述
在Virtio用户域框架中,实现与Virtio规范0.9/1.0兼容。VBS-U与设备模型静态连接,并通过PCIe接口与设备模型通信:PIO/MMIO或MSI/MSI- x。VBS-U通过用户空间vring服务API助手访问Virtio API。用户空间vring服务API助手通过远程内存映射(mmap)访问共享环。VHM通过ACRN管理程序映射用户VM内存。

在这里插入图片描述
VBS-U将数据平面处理工作下放给VBS-K。例如,VBS-U在正确的时间初始化VBS-K。FE驱动程序设置VIRTIO_CONFIG_S_DRIVER_OK以避免运行时不必要的设备配置更改。VBS-K可以通过VBS-K virtqueue api访问共享环。VBS-K virtqueue api与VBS-U virtqueue api类似。VBS-K寄存器作为VHM客户端来处理连续范围的寄存器。

每个VBS-K可能有一个或多个vhm客户机,所有VBS-Ks也可能有一个vhm客户机。VBS-K通过VHM中断api通知FE。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Jia ming

感谢欣赏!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值