Android OTA 相关工具(六) 使用 lpmake 打包生成 super.img
我在 《Android 动态分区详解(二) 核心模块和相关工具介绍》 介绍过 lpmake 工具,这款工具用于将多个分区镜像打包生成一个 Android 专用的动态分区镜像,一般称为 super.img。Android 编译时,系统会自动调用 lpmake 并传入相关参数来生成 super.img,不需要我们手动操作。但难免还是有朋友想深入研究下 super.img,希望自己手动生成 super.img。所以这里专门开一篇详解介绍下 lpmake 工具。
本文基于 android-13.0.0_r41 编译生成的 lpmake 介绍该工具的使用,但也适用于 Android 10(Q) 开始的其它 Android 版本。
《Android OTA 相关工具》系列,目前已有文章列表:
- 《Android OTA 相关工具(一) 虚拟 A/B 之 snapshotctl》
- 《Android OTA 相关工具(二) 动态分区之 dmctl》
- 《Android OTA 相关工具(三) A/B 系统之 bootctl 工具》
- 《Android OTA 相关工具(四) 查看 payload 文件信息》
- 《Android OTA 相关工具(五) 使用 lpdump 查看动态分区》
- 《Android OTA 相关工具(六) 使用 lpmake 打包生成 super.img》
本文为洛奇看世界(guyongqiangx)原创,转载请注明出处。
文章链接:https://blog.csdn.net/guyongqiangx/article/details/132581720
1. lpmake 的编译
lpmake 工具从 Android Q 版代码开始引入,源码位于 system/extras/partition_tools 目录下,默认编译 Android 后输出到 out/host/linux-x86/bin/lpmake ,第一次编译以后,通过 source 和 lunch 操作设置 Android 编译环境后就可以引用。
例如:
$ source build/envsetup.sh
$ lunch aosp_panther-userdebug
$ which lpmake
/local/public/users/rocky/android-13.0.0_r41/out/host/linux-x86/bin/lpmake
$ lpmake -h
lpmake: option requires an argument -- 'h'
Must specify --device OR --device-size.
当然,也可以将 out/host/linux-x86/bin 添加到当前目录下使用:
$ echo $PATH
/home/rocky/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
$ export PATH=${PWD}/out/host/linux-x86/bin:$PATH
$ echo $PATH
/public/rocky/android-13.0.0_r41/out/host/linux-x86/bin:/home/rocky/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
$ which lpmake
/public/rocky/android-13.0.0_r41/out/host/linux-x86/bin/lpmake
$ lpmake -h
lpmake: option requires an argument -- 'h'
Must specify --device OR --device-size.
两种方式都差不多,不过个人推荐前者。
2. lpmake 的帮助信息
关于一个工具,最好的文档就是自己的帮助手册,我这里顺手将 lpmake 的 help 命令输出贴在这里。
android-13.0.0_r41$ lpmake help
lpmake - command-line tool for creating Android Logical Partition images.Usage:lpmake [options]Required options:-d,--device-size=[SIZE|auto] Size of the block device for logical partitions.Can be set to auto to automatically calculate theminimum size, the sum of partition sizes plusmetadata-size times the number of partitions.-m,--metadata-size=SIZE Maximum size to reserve for partition metadata.-s,--metadata-slots=COUNT Number of slots to store metadata copies.-p,--partition=DATA Add a partition given the data, see below.-o,--output=FILE Output file.Optional:-b,--block-size=SIZE Physical block size, defaults to 4096.-a,--alignment=N Optimal partition alignment in bytes.-O,--alignment-offset=N Alignment offset in bytes to device parent.-S,--sparse Output a sparse image for fastboot.-i,--image=PARTITION=FILE If building a sparse image for fastboot, includethe given file (or sparse file) as initial data forthe named partition.-g,--group=GROUP:SIZE Define a named partition group with the givenmaximum size.-D,--device=DATA Add a block device that the super partitionspans over. If specified, then -d/--device-sizeand alignments must not be specified. The formatfor DATA is listed below.-n,--super-name=NAME Specify the name of the block device that willhouse the super partition.-x,--auto-slot-suffixing Mark the block device and partition names needingslot suffixes before being used.-F,--force-full-image Force a full image to be written even if nopartition images were specified. Normally, thiswould produce a minimal super_empty.img whichcannot be flashed; force-full-image will producea flashable image.--virtual-ab Add the VIRTUAL_AB_DEVICE flag to the metadataheader. Note that the resulting super.img willrequire a liblp capable of parsing a v1.2 header.Partition data format:<name>:<attributes>:<size>[:group]Attrs must be 'none' or 'readonly'.Device data format:<partition_name>:<size>[:<alignment>:<alignment_offset>]The partition name is the basename of the /dev/block/by-name/ path of theblock device. The size is the device size in bytes. The alignment andalignment offset parameters are the same as -a/--alignment and -O/--alignment-offset.
虽然上面的 help 信息包含了所有的选项说明,但我相信读到这里的小伙伴只有少部分真正去阅读了工具选项和说明。主要有几点:
- 说明是英文的,一看英文就反感。没说你,我自己就是这样。
- 选项很枯燥,看了也不知道怎么用
- 喜欢手把手的那种详细说明文档
但我还是十分建议你花 5 分钟去仔细阅读一下工具所有选项以及相应的说明,主要理由有以下几点:
- 不喜欢看英文的文档,那是因为你看得太少了,需要多看
- 选项很枯燥,看了也不知道怎么用,还是因为看得太少了
- 不要寄希望与别人的手把手文档,有当然好,没有就上帮助文档,这才是必由之路。
说到底,自带的帮助文档是第一手的资料,阅读第一手的资料,有助于你提高自己的学习能力。
3. lpmake 的用法
除了帮助文档,看看 Android 里具体如何使用 lpmake 工具,对学习理解也有很大帮助。实在理解不了帮助文档,那照着别人的用法依葫芦画瓢总比较容易一点。
3.1 示例 1
这里说说 Android 编译中对 lpmake 的调用。
Android 编译时,build_super_image.py 脚本会准备命令并调用 lpmake 生成 super.img,直接在 Android 编译的 log 中搜索 lpmake 就可以看到详细的命令。
这里以 Android 13 中编译参考设备 panther 为例,看看 build_super_image.py 是如何调用 lpmake 的:
$ source build/envsetup.sh
$ lunch aosp_panther-userdebug
$ make dist -j80 2>&1 | tee make-dist.log
$ grep -ni lpmake make-dist.log
56:2023-08-30 02:26:10 - common.py - INFO : Running: "/public/rocky/android-13.0.0_r41/out/host/linux-x86/bin/lpmake --metadata-size 65536 --super-name super --metadata-slots 3 --virtual-ab --device super:8531214336 --group google_dynamic_partitions_a:8527020032 --group google_dynamic_partitions_b:8527020032 --partition system_a:readonly:886816768:google_dynamic_partitions_a --image system_a=out/target/product/panther/obj/PACKAGING/target_files_intermediates/aosp_panther-target_files-eng.rocky/IMAGES/system.img --partition system_b:readonly:27312128:google_dynamic_partitions_b --image system_b=out/target/product/panther/obj/PACKAGING/target_files_intermediates/aosp_panther-target_files-eng.rocky/IMAGES/system_other.img --partition system_dlkm_a:readonly:348160:google_dynamic_partitions_a --image system_dlkm_a=out/target/product/panther/obj/PACKAGING/target_files_intermediates/aosp_panther-target_files-eng.rocky/IMAGES/system_dlkm.img --partition system_dlkm_b:readonly:0:google_dynamic_partitions_b --partition system_ext_a:readonly:301395968:google_dynamic_partitions_a --image system_ext_a=out/target/product/panther/obj/PACKAGING/target_files_intermediates/aosp_panther-target_files-eng.rocky/IMAGES/system_ext.img --partition system_ext_b:readonly:0:google_dynamic_partitions_b --partition product_a:readonly:368046080:google_dynamic_partitions_a --image product_a=out/target/product/panther/obj/PACKAGING/target_files_intermediates/aosp_panther-target_files-eng.rocky/IMAGES/product.img --partition product_b:readonly:0:google_dynamic_partitions_b --partition vendor_a:readonly:621752320:google_dynamic_partitions_a --image vendor_a=out/target/product/panther/obj/PACKAGING/target_files_intermediates/aosp_panther-target_files-eng.rocky/IMAGES/vendor.img --partition vendor_b:readonly:0:google_dynamic_partitions_b --partition vendor_dlkm_a:readonly:43040768:google_dynamic_partitions_a --image vendor_dlkm_a=out/target/product/panther/obj/PACKAGING/target_files_intermediates/aosp_panther-target_files-eng.rocky/IMAGES/vendor_dlkm.img --partition vendor_dlkm_b:readonly:0:google_dynamic_partitions_b --sparse --output out/target/product/panther/obj/PACKAGING/super.img_intermediates/super.img"
这里因为分区很多,所以 lpmake 的命令参数非常长,手动对这个 lpmake 命令整理一下会清楚很多:
/public/rocky/android-13.0.0_r41/out/host/linux-x86/bin/lpmake \--metadata-size 65536 \--super-name super \--metadata-slots 3 \--virtual-ab \--device super:8531214336 \--group google_dynamic_partitions_a:8527020032 \--group google_dynamic_partitions_b:8527020032 \--partition system_a:readonly:886816768:google_dynamic_partitions_a \--image system_a=out/target/product/panther/system.img \--partition system_b:readonly:27312128:google_dynamic_partitions_b \--image system_b=out/target/product/panther/system_other.img \--partition system_dlkm_a:readonly:348160:google_dynamic_partitions_a \--image system_dlkm_a=out/target/product/panther/system_dlkm.img \--partition system_dlkm_b:readonly:0:google_dynamic_partitions_b \--partition system_ext_a:readonly:301395968:google_dynamic_partitions_a \--image system_ext_a=out/target/product/panther/system_ext.img \--partition system_ext_b:readonly:0:google_dynamic_partitions_b \--partition product_a:readonly:368046080:google_dynamic_partitions_a \--image product_a=out/target/product/panther/product.img \--partition product_b:readonly:0:google_dynamic_partitions_b \--partition vendor_a:readonly:621752320:google_dynamic_partitions_a \--image vendor_a=out/target/product/panther/vendor.img \--partition vendor_b:readonly:0:google_dynamic_partitions_b \--partition vendor_dlkm_a:readonly:43040768:google_dynamic_partitions_a \--image vendor_dlkm_a=out/target/product/panther/vendor_dlkm.img \--partition vendor_dlkm_b:readonly:0:google_dynamic_partitions_b \--sparse \--output out/target/product/panther/super.img
这里我把
--image的路径进行了简化,将类似下面这样的完整路径:
out/target/product/panther/obj/PACKAGING/target_files_intermediates/aosp_panther-target_files-eng.rocky/IMAGES/system.img使用另外一个比较简短的路径替代:
out/target/product/panther/system.img
上面这个 lpmake 命令的参数重点:
-
--metadata-size 65536指定单个 metadata 数据的大小,通常为 64K,即 65536。
-
--super-name super指定了 super 设备的设备名称。
-
--metadata-slots 3每一个 metadata 的 slot 数量,关于这个数值为什么是 3,而不是 2 在 《Android 动态分区详解(一) 5 张图让你搞懂动态分区原理》有过疑惑,后面看情况是不是要单独写一点东西来说明分析这个。
-
--virtual-ab用于设置 metadata 头部的
VIRTUAL_AB_DEVICE标识,解析这个标识需要 liblp 能够解析 v1.2 版本的 metadata header 数据。 -
--device super:8531214336指定 super 设备的大小,可以指定具体的大小数值,也可以通过
--device super:auto自动计算所需的最小 size。 -
--group google_dynamic_partitions_a:8527020032设备 super 内的分组信息,使用
GROUP:SIZE格式指定具体的 group 名称,以及最大大小。 -
--partition system_a:readonly:886816768:google_dynamic_partitions_a设备 super 内的分区信息,使用
<name>:<attributes>:<size>[:group]格式指定分区名称,属性,大小,以及所属分组名称。 -
--image system_a=out/target/product/panther/system.img指定分区需要写入的 image 路径。
-
--sparse指定生成的 super.img 是否是 sparse 格式,如果指定则输出 sparse 格式的 super 镜像。
-
--output out/target/product/panther/super.img指定输出的 super 镜像文件路径和文件名。
根据前面的提示,以下参数是必须的:
--device-size=[SIZE|auto]
--metadata-size=SIZE
--metadata-slots=COUNT
--partition=DATA
--output=FILE
主要就是用于生成 super 头部的 metadata,缺少任何一个都会影响 metadata 数据的生成,所以是必须的。
上面的命令中,Android 参考设备 panther 上面的分区比较多,分区信息通过 --partition 指定,具体包含的镜像通过 --image 指定。
至于 --group 以及 --image 参数都不是必须的。理论上你可以不用再 super 上创建分组,在制作 super 时也可以不用传入具体分区的镜像数据,这样生成的 super 就是一个只有 metadata 描述数据,而没有任何分区镜像数据的空的 super.img,相当于 Android 编译生成的 super_empty.img
3.2 示例 2
另外,文章《Android 动态分区详解(二) 核心模块和相关工具介绍》 中也介绍过 lpmake 工具的另外一个例子,可以参考上面的参数执行分析这个命令:
lpmake --metadata-size 65536 --super-name super --metadata-slots 3 \--device super:3028287488 \--group bcm_ref_a:1509949440 --group bcm_ref_b:1509949440 \--partition system_a:readonly:1077702656:bcm_ref_a \--image system_a=out/target/product/inuvik/system.img \--partition system_b:readonly:0:bcm_ref_b \--partition vendor_a:readonly:104992768:bcm_ref_a \--image vendor_a=out/target/product/inuvik/vendor.img \--partition vendor_b:readonly:0:bcm_ref_b \--sparse --output out/target/product/inuvik/super.img
3.3 示例 3
这里再提供一个 Android 文档中介绍 lpmake 时使用的例子:
lpmake --device-size 10240000000 \--metadata-size 65536 \--metadata-slots 2 \-o /tmp/super.img \-p "cache:2da85788-f0e1-4fda-9ee7-e5177eab184b:none:67108864" \-i "cache=out/target/hikey960/cache.img"
这个例子中,创建了一个 10GB 的 super 动态分区,里面只包含了一个 64M 大小的 “cache” 分区。
现在,你可以手动自己使用 lpmake 来生成 super.img 了吗?
4. 几个思考题
到这里差不多应该结束了,给大家留三个思考题:
问题1:system.img 和 system_other.img
仔细观察上面第 3 节生成参考设备 panther 的 super.img 的命令中,system_a 分区和 system_b 分区传入的镜像文件竟然不一样:
/public/rocky/android-13.0.0_r41/out/host/linux-x86/bin/lpmake \--metadata-size 65536 \--super-name super \--metadata-slots 3 \--virtual-ab \--device super:8531214336 \--group google_dynamic_partitions_a:8527020032 \--group google_dynamic_partitions_b:8527020032 \--partition system_a:readonly:886816768:google_dynamic_partitions_a \--image system_a=out/target/product/panther/system.img \--partition system_b:readonly:27312128:google_dynamic_partitions_b \--image system_b=out/target/product/panther/system_other.img \...--sparse \--output out/target/product/panther/super.img
其中:
system_a的 image 为:out/target/product/panther/system.imgsystem_b的 image 为:out/target/product/panther/system_other.img
按照我的理解是 system_a 和 system_b 分区,制作镜像时可以提供一样的文件,或者像其他分区一样,system_b 不提供任何文件,仅保留一个空分区记录。
但为什么这里会传递 system_other.img 给 system_b 分区呢?
镜像文件 system_other.img 和 system.img 有什么区别?
问题 2:按照我上面的方法,研究下 super_empty.img 是如何生成的?
问题 3:为什么我 OTA 讨论群里的这位群友反馈他生成的 super.img 只有几十 K?


5. 其它
- 到目前为止,我写过 Android OTA 升级相关的话题包括:
- 基础入门:《Android A/B 系统》系列
- 核心模块:《Android Update Engine 分析》 系列
- 动态分区:《Android 动态分区》 系列
- 虚拟 A/B:《Android 虚拟 A/B 分区》系列
- 升级工具:《Android OTA 相关工具》系列
更多这些关于 Android OTA 升级相关文章的内容,请参考《Android OTA 升级系列专栏文章导读》。
如果您已经订阅了动态分区和虚拟分区付费专栏,请务必加我微信,备注订阅账号,拉您进“动态分区 & 虚拟分区专栏 VIP 答疑群”。我会在方便的时候,回答大家关于 A/B 系统、动态分区、虚拟分区、各种 OTA 升级和签名的问题,此群仅限专栏订阅者参与~
除此之外,我有一个 Android OTA 升级讨论群,里面现在有 400+ 朋友,主要讨论手机,车机,电视,机顶盒,平板等各种设备的 OTA 升级话题,如果您从事 OTA 升级工作,欢迎加群一起交流,请在加我微信时注明“Android OTA 讨论组”。此群仅限 Android OTA 开发者参与~
公众号“洛奇看世界”后台回复“wx”获取个人微信。
相关文章:
Android OTA 相关工具(六) 使用 lpmake 打包生成 super.img
我在 《Android 动态分区详解(二) 核心模块和相关工具介绍》 介绍过 lpmake 工具,这款工具用于将多个分区镜像打包生成一个 Android 专用的动态分区镜像,一般称为 super.img。Android 编译时,系统会自动调用 lpmake 并传入相关参数来生成 sup…...
信创环境 Phytium S2500 虚拟机最大内存规格测试
在 ARM 架构中,"IPA" 通常指的是 "Instruction Set Architecture"(指令集架构),arm环境的虚拟机支持的最大内存规格与母机上内存多少无关,由arm本身的ipa size决定,ipa size 可以理解为虚拟机的物理地址空间,kernel5.4.32中ipa默认是44bits(16T si…...
新建工程——第一个S32DS工程
之前的"测试开发板"章节 测试开发板——第一个AutoSAR程序,使用了一个 demo 工程,不管是裸机程序还是 AutoSAR 程序,那都是别人已经创建好的工程。本节来介绍如何来创建自己的工程,本节介绍如何创建一个 S32DS 的工程,点亮开发板上的 LED 我们从官方提供的例程…...
基于Open3D的点云处理16-特征点匹配
点云配准 将点云数据统一到一个世界坐标系的过程称之为点云配准或者点云拼接。(registration/align) 点云配准的过程其实就是找到同名点对;即找到在点云中处在真实世界同一位置的点。 常见的点云配准算法: ICP、Color ICP、Trimed-ICP 算法…...
设计模式—简单工厂
目录 一、前言 二、简单工厂模式 1、计算器例子 2、优化后版本 3、结合面向对象进行优化(封装) 3.1、Operation运算类 3.2、客户端 4、利用面向对象三大特性(继承和多态) 4.1、Operation类 4.2、加法类 4.3、减法类 4…...
真机安装Linux Centos7
准备工具: 8G左右U盘最新版UltraISOCentOS7光盘镜像 操作步骤 下载镜像 地址:http://isoredirect.centos.org/centos/7/isos/x86_64/ 安装刻录工具UltraISO,刻录镜像到U盘 ① 选择ISO镜像文件 ② 写入磁盘镜像,在这里选择你的U盘…...
ceph peering机制-状态机
本章介绍ceph中比较复杂的模块: Peering机制。该过程保障PG内各个副本之间数据的一致性,并实现PG的各种状态的维护和转换。本章首先介绍boost库的statechart状态机基本知识,Ceph使用它来管理PG的状态转换。其次介绍PG的创建过程以及相应的状…...
Java | File类
目录: File类File类中常用的方法:boolean exists( ) :判断此 文件/目录 是否存在boolean createNewFile( ) :创建一个文件boolean mkdir( ) :创建 “单层” 目录/文件夹boolean mkdirs( ) :创建 “多层” 目…...
数学建模之灰色预测
灰色预测(Grey Forecasting)是一种用于时间序列数据分析和预测的方法,通常用于处理具有较少历史数据的情况或者数据不够充分的情况。它是一种非常简单但有效的方法,基于灰色系统理论,用来估计未来的趋势。 以下是灰色…...
03_nodejd_npm install报错
npm install报错 npm ERR! code ERESOLVE npm ERR! ERESOLVE unable to resolve dependency tree npm ERR! npm ERR! While resolving: 5kcrm11.0.0 npm ERR! Found: vue2.5.17 npm ERR! node_modules/vue npm ERR! vue"2.5.17" from the root project npm ERR! np…...
three.js(二):webpack + three.js + ts
用webpackts 开发 three.js 项目 webpack 依旧是主流的模块打包工具;ts和three.js 是绝配,three.js本身就是用ts写的,ts可以为three 项目提前做好规则约束,使项目的开发更加顺畅。 1.创建一个目录,初始化 npm mkdir demo cd de…...
最小二乘法处理线性回归
最小二乘法是一种数学优化技术,用于查找最适合一组数据点的函数。 该方法主要用于线性回归分析,当然,也可用于非线性问题。 开始之前,我们先理解一下什么是回归。 回归:回归是一种监督学习算法,用于建模和…...
ModbusCRC16校验 示例代码
作者: Herman Ye Galbot Auromix 测试环境: Ubuntu20.04 更新日期: 2023/08/30 注1: Auromix 是一个机器人爱好者开源组织。 注2: 本文在更新日期经过测试,确认有效。 笔者出于学习交流目的, 给…...
一不留神就掉坑
乘除顺序问题 在据卡特兰数[1]公式,解决leetcode-96 不同的二叉搜索树[2]时,遇到一个非常诡异的问题, package mainimport "fmt"func main() { for i : 0; i < 40; i { fmt.Printf("第%d个卡特兰数为:%d\n", i, numTrees(i)) }}func numTrees(n int) i…...
Redis数据类型(list\set\zset)
"maybe its why" List类型 列表类型是⽤来存储多个有序的字符串,列表中的每个字符串称为元素(element),⼀个列表最多可以存储个2^32 - 1个元素。在Redis中,可以对列表两端插⼊(push)…...
TongWeb安装以及集成
TongWeb 安装步骤 静默安装 获取linux可执行安装包 如: Install_TWx.x.x.x_Enterprise_Linux.bin 创建安装所需配置文件 install.properties 内容如下 [root@node5 tongweb]# cat install.properties INSTALL_UI=silent USER_INSTALL_DIR=/home/tongweb SILENT_JDK_HOME=/jd…...
ScreenToGif-动图制作软件实用操作
ScreenToGif官网:ScreenToGif ⭕第一步:启动页面 ⭕第二步:选项 🥝录像机-捕获频率选择手动-播放延迟1000ms(可以任意) ⭕第三步:录像机开始录屏 🥝我们调整录屏的大小后,打开画图,…...
sqlibs安装及复现
sqlibs安装 安装phpstudy后,到github上获取sqlibs源码 sqli-labs项目地址—Github获取:GitHub - Audi-1/sqli-labs: SQLI labs to test error based, Blind boolean based, Time based. 在phpstudy本地文件中的Apache目录中解压上方下载的源码。 将sq…...
OpenAI 创始人 Sam Altman 博客有一篇 10 年前的文章
OpenAI 创始人 Sam Altman 博客有一篇 10 年前的文章《Advice for ambitious 19 year olds》,给 19 岁年轻人的建议,从 #参考答案 看到,非常适合我们🤣年轻人,顺便用 GPT4 重新翻译了下全文。 太长不读纯摘要版本如下&…...
写的一款简易的热点词汇记录工具
项目需要对用户提交的附件、文章、搜索框内容等做热词分析。如下图: 公司有大数据团队。本着不麻烦别人就不麻烦别人的原则,写了一款简易的记录工具,原理也简单,手工在业务插入锚点,用分词器分好词,排掉字…...
浅谈 React Hooks
React Hooks 是 React 16.8 引入的一组 API,用于在函数组件中使用 state 和其他 React 特性(例如生命周期方法、context 等)。Hooks 通过简洁的函数接口,解决了状态与 UI 的高度解耦,通过函数式编程范式实现更灵活 Rea…...
多场景 OkHttpClient 管理器 - Android 网络通信解决方案
下面是一个完整的 Android 实现,展示如何创建和管理多个 OkHttpClient 实例,分别用于长连接、普通 HTTP 请求和文件下载场景。 <?xml version"1.0" encoding"utf-8"?> <LinearLayout xmlns:android"http://schemas…...
可靠性+灵活性:电力载波技术在楼宇自控中的核心价值
可靠性灵活性:电力载波技术在楼宇自控中的核心价值 在智能楼宇的自动化控制中,电力载波技术(PLC)凭借其独特的优势,正成为构建高效、稳定、灵活系统的核心解决方案。它利用现有电力线路传输数据,无需额外布…...
Leetcode 3577. Count the Number of Computer Unlocking Permutations
Leetcode 3577. Count the Number of Computer Unlocking Permutations 1. 解题思路2. 代码实现 题目链接:3577. Count the Number of Computer Unlocking Permutations 1. 解题思路 这一题其实就是一个脑筋急转弯,要想要能够将所有的电脑解锁&#x…...
Matlab | matlab常用命令总结
常用命令 一、 基础操作与环境二、 矩阵与数组操作(核心)三、 绘图与可视化四、 编程与控制流五、 符号计算 (Symbolic Math Toolbox)六、 文件与数据 I/O七、 常用函数类别重要提示这是一份 MATLAB 常用命令和功能的总结,涵盖了基础操作、矩阵运算、绘图、编程和文件处理等…...
HashMap中的put方法执行流程(流程图)
1 put操作整体流程 HashMap 的 put 操作是其最核心的功能之一。在 JDK 1.8 及以后版本中,其主要逻辑封装在 putVal 这个内部方法中。整个过程大致如下: 初始判断与哈希计算: 首先,putVal 方法会检查当前的 table(也就…...
水泥厂自动化升级利器:Devicenet转Modbus rtu协议转换网关
在水泥厂的生产流程中,工业自动化网关起着至关重要的作用,尤其是JH-DVN-RTU疆鸿智能Devicenet转Modbus rtu协议转换网关,为水泥厂实现高效生产与精准控制提供了有力支持。 水泥厂设备众多,其中不少设备采用Devicenet协议。Devicen…...
【Kafka】Kafka从入门到实战:构建高吞吐量分布式消息系统
Kafka从入门到实战:构建高吞吐量分布式消息系统 一、Kafka概述 Apache Kafka是一个分布式流处理平台,最初由LinkedIn开发,后成为Apache顶级项目。它被设计用于高吞吐量、低延迟的消息处理,能够处理来自多个生产者的海量数据,并将这些数据实时传递给消费者。 Kafka核心特…...
OCR MLLM Evaluation
为什么需要评测体系?——背景与矛盾 能干的事: 看清楚发票、身份证上的字(准确率>90%),速度飞快(眨眼间完成)。干不了的事: 碰到复杂表格(合并单元…...
C++--string的模拟实现
一,引言 string的模拟实现是只对string对象中给的主要功能经行模拟实现,其目的是加强对string的底层了解,以便于在以后的学习或者工作中更加熟练的使用string。本文中的代码仅供参考并不唯一。 二,默认成员函数 string主要有三个成员变量,…...
