什么叫动态分区,它是如何实现的?

在这里插入图片描述

动态分区(Dynamic Partitions)是 Android 10 引入的分区管理机制,旨在解决传统固定分区(如 systemvendor)在系统更新时面临的 空间浪费灵活性不足 的问题。它的核心思想是:将多个物理分区合并为一个“超级分区”(super partition),并在其中动态分配逻辑分区的空间


动态分区的核心概念

1. 传统分区的局限性

在 Android 9 及更早版本中,每个分区(如 systemvendorproduct)是独立的,大小固定。这会导致:

  • 空间浪费:例如 system 分区必须按最大可能需求分配,即使实际使用量很小。
  • 更新困难:如果 OTA 更新需要调整分区大小,必须重新分区(可能导致数据丢失)。

2. 动态分区的解决方案

动态分区通过以下方式改进:

  • 超级分区(Super Partition):将所有动态分区(如 systemvendor)合并到一个大的 super 分区中。
  • 逻辑分区动态分配:在 super 分区内,各逻辑分区(如 systemvendor)的大小可以 按需调整
  • 支持无缝更新(A/B):通过元数据槽(metadata slots)实现回滚。

动态分区的实现原理

1. 分区布局

  • super 分区:一个物理分区(如 /dev/block/by-name/super),存储所有动态分区。
  • 逻辑分区:在 super 分区内划分的逻辑单元(如 systemvendorproduct)。
  • 元数据(Metadata):记录分区布局、大小和属性(存储在 super 分区的头部)。

2. 关键组件

组件作用
lpmake打包多个镜像(system.imgvendor.img)成 super.img
lpdump查看 super 分区的布局信息。
dm-linear(内核驱动)super 分区的逻辑块映射到动态分区。
initfs_mgr在启动时加载动态分区。

3. 工作流程

(1)构建阶段
  1. 使用 mkuserimg_mke2fs 生成各分区镜像(如 system.img)。
  2. lpmake 将所有镜像打包成 super.img
    lpmake --device-size=5G \
           --group=main:4G \
           --partition=system:2G:main:readonly \
           --partition=vendor:1G:main:readonly \
           --image=system=system.img \
           --image=vendor=vendor.img \
           --output=super.img
    
    • main 是分区组,剩余空间(4G - 2G - 1G = 1G)可用于未来扩展。
(2)刷机阶段
  • 通过 fastboot 刷入 super.img
    fastboot flash super super.img
    
(3)启动阶段
  1. 内核 读取 super 分区的元数据。
  2. dm-linear 驱动 将逻辑分区映射到虚拟块设备(如 /dev/block/mapper/system)。
  3. init 挂载 这些设备到 /system/vendor 等目录。

动态分区的优势

特性传统分区动态分区
分区大小固定动态调整
空间利用率可能浪费按需分配
OTA 更新需严格匹配分区大小可动态扩展
A/B 更新需要双倍分区通过元数据槽支持

实际应用场景

  1. OTA 更新
    • 如果新版本 system 需要更多空间,可以直接从 super 分区未分配区域扩展,无需重新分区。
  2. 厂商自定义
    • 设备厂商可以灵活调整 odmsystem_ext 等分区大小。
  3. GKI(通用内核镜像)
    • 动态分区是 GKI 的配套功能,确保内核与分区解耦。

动态分区的限制

  1. 只读分区
    • systemvendor 必须为只读(readonly),否则无法通过 Android 验证(AVB)。
  2. 兼容性
    • 仅支持 Android 10+ 设备,旧设备需保留传统分区。
  3. 调试复杂性
    • 需使用 lpdumpadb shell ls /dev/block/mapper 查看动态分区状态。

如何检查动态分区

1. 查看 super 分区布局

adb shell lpdump

输出示例:

Partition table:
  Name: system
  Group: main
  Size: 2 GiB
  Attributes: readonly
  ...

2. 查看映射的设备节点

adb shell ls /dev/block/mapper

输出示例:

system
vendor
product

总结

动态分区是 Android 10 引入的现代化分区管理方案,通过 超级分区 + 逻辑动态分配 解决了传统分区的空间浪费和更新难题。它的实现依赖于:

  1. super 分区 作为物理容器。
  2. lpmake 工具 打包镜像。
  3. 内核驱动 dm-linear 提供动态映射。
    对于 Android ROM 开发者和设备厂商,动态分区提供了更大的灵活性,但同时也需要适配新的工具链和调试方法。

结束语
Flutter是一个由Google开发的开源UI工具包,它可以让您在不同平台上创建高质量、美观的应用程序,而无需编写大量平台特定的代码。我将学习和深入研究Flutter的方方面面。从基础知识到高级技巧,从UI设计到性能优化,欢饮关注一起讨论学习,共同进入Flutter的精彩世界!

### C语言中的内存分区及相关概念 #### 内存分区概述 C语言程序在运行时会将其使用的内存划分为多个区域,这些区域各自承担不同的功能。通常情况下,C语言的内存可以被划分为五个主要部分:栈区、堆区、全局/静态区、常量区以及代码区[^1]。 #### 各类内存分区的功能描述 - **栈区 (Stack)** 栈区用于存储局部变量和函数调用的信息。当进入一个函数时,该函数所需的局部变量会被压入栈中;而当函数返回时,这些局部变量则从栈中弹出并释放空间。这种操作方式使得栈具有高效的空间管理能力[^2]。 - **堆区 (Heap)** 堆区是一个动态分配的内存池,程序员可以通过标准库函数 `malloc` 和 `free` 来手动申请和释放内存。相比栈而言,堆提供了更大的灵活性,但也增加了管理和维护的成本。 - **全局/静态区 (Global / Static Area)** 这一部分主要用于存放全局变量和静态变量。如果初始化了某个全局或静态变量,则它会被放置于数据段(Data Segment);如果没有显式赋初值,则位于未初始化的数据段(BSS Segment)。 - **常量区 (Constant Area)** 字符串字面量和其他只读数据一般保存在此区域内。由于它们的内容不可更改,在某些实现里可能还会受到额外保护以防意外修改。 - **代码区 (Text Section)** 可执行机器指令构成的部分即为代码区或者叫正文段。这部分通常是只读属性以防止自我破坏行为发生。 #### 示例代码展示不同类型的变量及其所在位置 下面给出一段简单的例子来演示上述理论知识的应用场景: ```c #include <stdio.h> #include <stdlib.h> // 定义了一个全局变量b int b = 20; void exampleFunction() { int c = 30; // 局部自动变量 static int d = 40; // 静态局部变量 printf("Address of local variable 'c': %p\n", &c); } int main(){ char* strConst = "Hello"; // 指向字符串常量的指针 int a = 10; // 自动局部变量 int *heapVarPtr; heapVarPtr = (int*) malloc(sizeof(int)); if(heapVarPtr != NULL){ *heapVarPtr = 50; } printf("Value of global var 'b' is:%d \n",&b); // 访问全局变量 printf("Address of automatic local var 'a':%p\n",&a);// 打印地址查看是否处于栈上 printf("String constant '%s' address :%p\n",strConst,strConst); free(heapVarPtr); // 解除堆上的资源占用 exampleFunction(); // 调用含有静态局部变量的方法 return 0; } ``` 此代码片段展示了不同类型变量的位置分布情况,并通过打印各变量的地址进一步验证其所属的具体内存区间。 #### 关联到磁盘分区的概念扩展 虽然两者名称相似,但需要注意的是,“C语言内存分区”与“硬盘物理分区”的含义完全不同。后者涉及操作系统层面对于外部储存设备的实际划分过程,例如利用工具完成新卷建立之后还需要借助特定命令如mkfs对其进行格式化以便能够正常挂载使用[^3]。 然而,在实际开发过程中有时也需要考虑二者之间的间接联系。例如嵌入式系统设计阶段可能会涉及到针对目标硬件平台定制专属文件系统的工作流程,这就要求开发者既熟悉高级编程语言内部工作机制又要掌握底层驱动原理等方面的知识点。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值