Android 几种系统升级方式详解

目录

◆ 概述
● 几种启动模式
● MISC分区
● CACHE分区
● 几种系统升级方式
◆ Recovery升级
● 升级包构成,签名,制作
● 升级脚本
● 升级过程
◆ OTA升级
● 升级包构成,制作
● 升级脚本
● 升级过程
◆ fastboot升级
◆ ADB升级

几种启动模式

◆ 正常模式
进入方式:不按键,正常启动时进入.
文件:loader + Uboot + Boot.img + system.img
◆ recovery模式
进入方式:特殊组合按键,reboot recovery命令, MISC分区
指令,系统崩溃.
文件:loader + Uboot + recovery.img
recovery.img = Boot.img + recovery(/sbin/recorey)
操作界面在recovery程序中提供
◆ fastboot模式
进入方式:特殊组合按键
文件:loader + Uboot
操作界面在Uboot中提供

在这里插入图片描述

MISC分区

◆存放Bootloader Control Block (BCB),是bootloader与Recovery的通信接口.启动时bootloader中读取BCB, 根据指令决定启动方式.

struct bootloader_message {char command[32];char status[32];char recovery[1024];
};

command:“boot-recovery”:指示bootloader应该进入recovery modestatus:完成相应的更新后,bootloader将执行结果写入到这个字段recovery:该文件的内容格式如下:

“recovery\n
<recovery command>\n
<recovery command>

是一个字符串,以“recovery\n”开头,后面一行对应一个recovery命令,与/cache/recovery/command文件相对应

CACHE分区

recovery通过/cache/recovery/目录下的三个文件与主系统通信,增量升级过程中也需要借助于/cache分区存放临时文件.进入recovery 程序后,会先读取BCB的内容,失败再读取/cache/recovery/command的内容,以决定是否有特殊命令要执行

◆ /cache/recovery/command:recovery命令,由主系统写入,每一行就是一条命令,是以下命令的组合:● --wipe_data:擦除用户数据,会清除/data分区和/cache分区● --wipe_cache :擦除/cache分区● --update_package=path: 表示要进行OTA升级,recovery使用路径为path的OTA升级包● --send_intent=anystring: 传递的intent

◆ /cache/recovery/log:recovery模式在工作中的log输出,再次进入recovery的时候会清除

◆ /cache/recovery/intent:recovery传递给主系统的intent,在recovery结束时将定义的intent字符串写入到/cache/recovery/intent中

几种系统升级方式

◆ recovery升级也称为卡刷,全量升级,按键进入recovery后执行存储卡上下载好的升级包依赖于能正常进入recovery, 升级包大

◆ OTA升级OTA(over the air),也称为在线升级,增量升级,一般为按键进入recovery后执行下载好的升级包,也可下载全量升级包依赖于系统运行正常, 需要网络,升级包小,操作便捷

◆ fastboot升级也称线刷,进入fastboot模式后,机器连接USB线,使用PC上的烧录工具将镜像文件烧录到机器,类似于USB烧录依赖于Uboot正常即可,升级数据量大,操作相对复杂,稳定性高

◆ ADB升级也称一键刷机,通过ADB,使用flash_image程序,借助于PC将镜像文件更新到机器依赖于ADB开放和能正常root, 升级数据量大,操作简单,稳定性低

recovery升级

在这里插入图片描述

recovery升级-升级包构成

在这里插入图片描述
◆system/, data/, recovery/:这些目录对应需要升级的分区,分别对应system,data,recovery分区的内容

◆boot.img这些文件对应需要升级的文件,升级过程中会直接覆盖镜像

◆MANIFEST.MF签名相关文件.遍历包中的所有文件,对非文件夹非签名文件的文件,逐个生成SHA1的数字签名信息,再用Base64进行编码

◆CERT.SF签名相关文件.对Manifest文件,使用SHA1-RSA算法,用私钥进行签名

◆CERT.RSA签名相关文件.文件中保存了公钥、所采用的加密算法等信息

◆metadata文件是描述设备信息及环境变量的元数据。主要包括一些编译选项,时间戳以及设备型号等

◆otacert签名公钥,对应xxx.x509.pem文件

◆update-binary是一个二进制文件,相当于一个脚本解释器,能够识别updater-script中描述的操作.对应源码位于:bootable/recovery/updater/

◆updater-script此文件是一个脚本文件,具体描述了更新过程。我们可以根据具体情况编写该脚本来适应我们的具体需求.

recovery升级-升级包签名

◆update.zip的签名

$ java –jar out/host/linux/framework/signapk.jar –w /build/target/product/security/xxx.x509.pem /build/target/product/security/xxx.pk8 update_signed.zipupdate.zip

recovery升级包在进行签名时使用signapk.jar工具,与APK签名使用的工具相同,但与APK签名不同的是,使用了-w选项,指对整个文件进行签名,使用-w签名的包在结尾是6个特征字节

制作包使用私钥对update.zip进行签名,recovery中使用对应的公钥进行验证,recovery 代码里面使用的公钥(/res/keys)是按照RSAPublicKey数据结构存储。这个数据是通过RSAPublicKey工具(dumpkey.jar)从制作出来的x509证书文件中获得

◆破解签名验证
在update.zip签名时使用的公钥/私钥对不是公开的key(比如testkey)的情况下,因为用户无法得到正确的私钥,而且recovery使用的公钥随recovery.img发布,所以很难伪造签名来通过recovery验证

变通的做法是给系统刷入一个使用testkey公钥进行验证recovery.img,而包对应使用testkey进行签名.或者刷入一个不进行签名验证的recovery.img

recovery升级-制作升级包

◆制作方式有手动制作和自动制作两种
● 手动制作
准备好升级文件和目录,手动写脚本updater-script,copy脚本解
释程序update-binary(system/bin/updater),打包成zip文件,然后
使用signapk.jar对zip文件进行签名

● 自动制作
源码根目录执行 make otapackage,out目录下生成全量升级包,
名称为: out/target/product/h600s/h600s-ota-eng.lsg.zip
第一步:编译Makefile,生成原始包
第二步:在原始包的基础上使用python脚本生成全量升级包,
python脚本路径:build/tools/releasetools/ota_from_target_files,
入口函数是:WriteFullOTAPackage(input_zip,output_zip)

☆注意:
make otapackage 会对整个系统进行编译,要注意这里的编译方式
与正常编译的一致性
在这里插入图片描述

recovery升级-脚本

◆assert(condition)
如果condition参数的计算结果为False,则停止脚本执行,否则继续
执行脚本。

◆show_progress(frac,sec)
frac表示进度完成的数值,sec表示整个过程的总秒数。主要用与显示
UI上的进度条。
示例: show_progress(0.1, 10);
下面的操作可能进行10s,完成后进度条前进0.1(也就是10%)

◆format(fs_type, partition_type, location, fs_size,mount_point)
fs_type,文件系统类型,取值一般为“vfat”或“ext4”。
Partition_type,分区类型,一般取值为“MTD”或则“EMMC”。
location,设备路径
fs_size,等于0表示格式化整个分区,大于0表示按指定大小格式化,
小于0表示在分区最后保留一定大小

◆mount(fs_type,partition_type,location,mount_point)
前两个参数同上,location要挂载的设备,mount_point挂载点。作用:挂载一个文件系统到指定的挂载点。

◆ui_print(const char *fmt, …)
作用:将字符串显示到屏幕上
示例:ui_print(“update system.img…”);

◆symlink(target,src1,src2,……,srcN)
target,字符串类型,是符号连接的目标。SrcX代表要创建的符号连接的目标点。
示例:symlink(“mksh”, “/system/bin/sh”);

◆set_perm(uid,gid,mode,file1,file2,……,fileN)
作用是设置单个文件或则一系列文件的权限,最少要指定一个文件
示例:set_perm(0, 1000, 0750, “/system/bin/tc”);

◆package_extract_file(srcfile_path,desfile_paht)
srcfile_path,要提取的文件,desfile_path,提取文件的目标位置。
示例:package_extract_file(“boot.img”,”/tmp/boot.img”)将升级包中的boot.img文件拷贝到内存文件系统的/tmp下

◆package_extract_dir(src_path,destination_path)src_path,
要提取的目录,destination_path目标目录。作用:从升级包内,提取目录到指定的位置。
示例:package_extract_dir(“system”,”/system”)

◆write_raw_image(src-image,partition):
src-image源镜像文件,partition,目标分区。作用:将镜像写入目标分区。
示例:write_raw_image(“/sdcard/system.img”,“system”);将system.img镜像写入到系统的system分区。

◆/etc/recovery.fstab
提供各分区对应的设备, 及分区文件系统类型. 非编译生成, 在board目录是挂载和烧录的关键.

例如(H8):
/xboot emmc /dev/block/platform/jzmmc.0/by-name/xboot/boot emmc /dev/block/platform/jzmmc.0/by-name/boot/recovery emmc /dev/block/platform/jzmmc.0/by-name/recovery/system ext4 /dev/block/platform/jzmmc.0/by-name/system/data ext4 /dev/block/platform/jzmmc.0/by-name/data/cache ext4 /dev/block/platform/jzmmc.0/by-name/cache/misc emmc /dev/block/platform/jzmmc.0/by-name/misc/mnt/sdcard2 vfat /dev/block/platform/jzmmc.0/by-name/storage1/mnt/sdcard0 vfat /dev/block/platform/jzmmc.0/by-name/storage2/mnt/sdcard1 vfat /dev/block/mmcblk2p1 /dev/block/mmcblk2/sdcard auto /dev/block/mmcblk2p1 /dev/block/mmcblk2

recovery升级-过程

源码路径: bootable/recovery/
升级update.zip的核心函数在 install_package()
■1.ensure_path_mount()
先判断所传的update.zip包路径所在的分区是否已经挂载。如果没有则先挂载。

■2.load_keys()
加载公钥源文件,路径位于/res/keys。这个文件在Recovery镜像的根文件系统中。

■3.verify_file()
对升级包update.zip包进行签名验证。

■4.mzOpenZipArchive()
打开升级包,并将相关的信息拷贝到一个临时的ZipArchinve变量中。这一步并未对我们的update.zip包解压。

■5.try_update_binary()
在这个函数中才是对我们的update.zip升级的地方。这个函数一开始先根据我们上一步获得的zip包信息

以及升级包的绝对路径将update_binary文件拷贝到内存文件系统的/tmp/update_binary中。以便后面使用。

■6.fork()
创建子进程。其中的子进程主要负责执行binary(execv(binary,args),即执行我们的安装命令脚本.

父进程负责接受子进程发送的命令去更新ui显示(显示当前的进度)。子父进程间通信依靠管道。

脚本里描述的过程大概有以下几步:
■1.比较时间戳,匹配机型设备信息,条件不符则停止脚本运行
■2.显示进度条起始位置
■3.格式化system分区并挂载
■4.提取包中的recovery以及system目录下的内容到系统的/system下
■5.为/system下的文件建立符号连接, 设置属性
■6.更新包中的boot.img
■7.如果要更新/data分区,则挂载/data,并更新/data分区的内容
■8.如果有其他的镜像文件比如uboot等需要更新,则更新这些镜像文件
■9.卸载已挂载的分区,脚本结束

recovery升级-定制

◆1. 修改releasetool.py
recovery在 build/tools/releasetools/common.py 中提供了一个类
(DeviceSpecificParams)用于自定义一些功能

具体的功能实现放在名为releasetool.py的文件中,这个文件放在具体
的board文件夹下,比如build/target/board/h600s/releasetools.py

可以自定义的功能有: FullOTA_InstallBegin, FullOTA_InstallEnd,
IncrementalOTA_InstallBegin, IncrementalOTA_InstallEnd

◆2. 直接修改build/tools/releasetools/ 下的文件

OTA升级

OTA升级-升级包构成

在这里插入图片描述

OTA升级-制作升级包

◆OTA不一定是升级增量包,但一般指增量升级.增量升级只能在指定两个版本间进行升级.

◆制作增量包以原始包(target包)为基础,将第一次生成的target包暂时称为target-A.zip,将第二次生成的target包暂时称为target-B.zip
◆利用这两个target包,生成增量包
./build/tools/releasetools/ota_from_target_files -v -i target-A.zip target-B.zip ota-A-B-incremental.zip

☆注意
1. 发布版本时要注意备份原始包,且保证原始包的数据与下单版本完全一致;
2. 目标版本(target-B.zip)比基础版本(target-A.zip)少的文件会在基础版本中删除,目标版本(target-B.zip)比基础版本(target-A.zip)多的文件会在基础版本中增加,要保持一致性不要轻易删除文件;
3. 同一模块的名字在两个版本中不要随意改变;

OTA升级-原始包

◆make otapackage过程中生成,路径如下:out/target/product/h600s/obj/PACKAGING/target_files_intermediates/h600starget_files-eng.lsg.zip

◆单个原始包(target包)可以生成全量包(full包),两个原始包(target包)可以生成增量包(increment包),都使用到脚本:
build/tools/releasetools/ota_from_target_files

包含的基本目录:
◆BOOT/, RECOVERY/
包括RAMDISK/和kernel

◆SYSTEM/
system目录的原始拷贝

◆OTA/
applypatch等升级中用到的程序

◆META/
文件清单及文件对应权限,分区类型和大小等信息
在这里插入图片描述
在这里插入图片描述

OTA升级-脚本

在增量升级中特有的:
◆apply_patch_check(file, [sha1_1, …])
检查文件file的SHA1值是不是多个中的一个,前面的为目标SHA1值
示例:
apply_patch_check(“/system/app/BBKSettings.apk”,
“8bca5488310c0625bc4498285c37e5fecd873b3a”,
“48f4d405351a334feea17a52ad118c346f64a253”)

◆apply_patch(srcfile, tgtfile, tgtsha1, tgtsize, sha1_1, patch_1, …)
srcfile:源文件,tgtfile:目标文件,“-“表示与源文件相同
tgtsha1:目标文件SHA1值,tgtsize:目标文件长度
作用:利用patch文件将源文件升级到目标文件
示例:apply_patch(”/system/app/BBKSettings.apk”, “-”,
8bca5488310c0625bc4498285c37e5fecd873b3a, 911757,
48f4d405351a334feea17a52ad118c346f64a253,
package_extract_file(“patch/system/app/BBKSettings.apk.p”));

OTA升级-过程

◆总体上分为两步:
第一步:OTA升级程序根据机器版本从服务器上找出最适合的升级包,然后下载到本地,调用RecoverySystem类的方法,使机器重启进入recovery,并将升级包路径写入cache分区

第二步:进入recovery界面后,获取升级包路径,自动开始执行升级过程,升级完毕后自动重启进入正常启动模式

脚本里描述的过程大概有以下几步:
■1.检查系统版本,机型信息,系统版本必须是两个版本中的一个

■2.检查文件是否一致(“Verifying current system…”),当前系统中的文件必须与起始版本文件的sha1 值一致,调用apply_patch_check进行检查

■3.删除不需要的文件(“Removing unneeded files…”),调用delete,只存在于起始版本或目标版本中的文件在这里先删除

■4.应用差量文件(“Patching system files…”),调用apply_patch,使用.p文件升级起始版本的文件为目标版本的文件

■5.增加新文件(“Unpacking new files…”),将增加的新文件拷贝到机器上,注意对于目标版本中新增的文件,通常会删除旧文件在增加新文件

■6.修改文件权限,结束

增量升级一个文件的过程如下(applypatch):
■1.获取目标文件的 sha1 值(target_sha1),此值会与当前文件的sha1值进行比较,如果一致就证明文件已于目标文件一致,无需升级直接返回

■2.载入源文件(source_file)(注意是一次性载入),如果载入失败,则试图入/cache/saved.file文件

■3.判断源文件所在分区是否有足够剩余空间,如果没有足够空间则将源文件复制到cache分区,保存为/cache/saved.file,并删除源文件

■4.在源文件目录建立".patch"的文件,使用patch工具进行增量

■5.增量完毕后,计算文件(.patch)的 sha1 值并与target_sha1比较。如果一致就证明增量成功,成功则将".patch"去掉.patch; 失败则重试,达到设定的重试次数后,认为失败,返回结果

fastboot

在这里插入图片描述
fastboot界面示例

◆操作步骤:
1.准备好fastboot数据包和fastboot PC工具
2.机器关机,按组合键进入fastboot模式
3.机器连接USB线,安装好USB驱动,在PC工具上能看到识别设备成功
4.从PC工具上选择fastboot数据包,开始升级

当机器进入fastboot模式,PC上fastboot驱动安装完毕后,就能通过fastboot命令操作机器
◆fastboot devices
作用:输出所有连接的设备

◆fastboot erase
作用:擦除分区
示例:fastboot erase system; fastboot erase userdata

◆flashboot flash [ ]
作用:刷入镜像
示例: fastboot flash system system.img

◆fastboot reboot
作用:重启

ADB升级

◆大多数的一键刷机工具都是采用此种方式,机器要开放ADB且能获得root权限

◆需要借助flash_image程序,flash_image程序由bootable/recovery/下编译生成

◆示例:
adb root
adb shell mount /sdcard
adb shell push c:\system.img /mnt/sdcard/
adb shell flash_image system /mnt/sdcard/system.img
adb shell reboot

☆注意
此种方式不稳定,变砖可能性较大

Root

◆为什么要Root?
拥有root权限后,可以访问,修改,删除系统的任何文件.删除预置应用,修改系统等

◆怎么样Root?
最终目标是将su放入/system/bin/下,安装授权管理程序Superuser.apk

◆Root的方式?
实现方式有多种,包括利用Android漏洞,利用recovery刷入此两文件.
利用Android漏洞的方式不一定对所有机型都适用

◆怎样刷第三方ROM?
刷入一个不做签名验证或利用testkey做签名验证的recovery. 刷入recovery的
方式可以利用fastboot, 也可以使用adb方式

觉得本文对您有用,麻烦点赞、关注、收藏,您的肯定是我创作的无限动力,谢谢!!!

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

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

相关文章

【研发日记】Matlab/Simulink技能解锁(七)——两种复数移相算法

复数移相&#xff0c;也称为复数相位旋转&#xff0c;就是在原有复数的基础上&#xff0c;不改变模数&#xff0c;只把相位角做一定的偏移。 文章目录 前言 三角函数移相 复数乘法移相 分析和应用 总结 前言 见《【研发日记】Matlab/Simulink技能解锁(二)——在Function编…

(三)Spring教程——依赖注入与控制反转

Spring框架是为了简化企业级应用开发而创建的&#xff0c;其强大之处在于对Java SE和Java EE开发进行全方位的简化&#xff0c;Spring还对常用的功能进行封装&#xff0c;可以极大地提高Java EE的开发效率。 依赖注入是Spring的核心技术之一&#xff0c;也被称为“控制反转”&a…

【Linux】自动化编译工具——make/makefile(超细图例详解!!)

目录 一、前言 二、make / Makefile背景介绍 &#x1f95d;Makefile是干什么的&#xff1f; &#x1f347;make又是什么&#xff1f; 三、demo实现【见见猪跑&#x1f416;】 四、依赖关系与依赖方法 1、概念理清 2、感性理解【父与子&#x1f468;】 3、深层理解【程序…

【JavaEE】HTTP 协议

文章目录 一、HTTP 协议1、HTTP 是什么2、理解 "应用层协议"3、理解 HTTP 协议的工作过程4、HTTP 协议格式5、HTTP 请求 (Request)5.1 认识 URL 6、 二、HTTPS1、HTTPS是什么2、"加密" 是什么3、HTTPS 的工作过程3.1 对称加密3.2 非对称加密3.3 证书3.4 完…

零样本身份保持:ID-Animator引领个性化视频生成技术新前沿

在最新的研究进展中&#xff0c;由Xuanhua He及其团队提出的ID-Animator技术&#xff0c;为个性化视频生成领域带来了突破性的创新。这项技术的核心在于其零样本&#xff08;zero-shot&#xff09;人物视频生成方法&#xff0c;它允许研究者和开发者根据单一的参考面部图像生成…

深度解刨性能测试工具Locust

&#x1f345; 视频学习&#xff1a;文末有免费的配套视频可观看 &#x1f345; 关注公众号【互联网杂货铺】&#xff0c;回复 1 &#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;涨薪更快 Locust安装 …

gin框架学习笔记(三) ——路由请求与相关参数

参数种类与参数处理 查询参数 在讲解查询参数的定义之前&#xff0c;我们先来看一个例子&#xff0c;当我打开了CSDN&#xff0c;我现在想查看我的博客浏览量&#xff0c;那么我就需要点击我的头像来打开我的个人主页,像下面这样: 我们现在把浏览器的网址取下来&#xff0c;…

【35分钟掌握金融风控策略27】贷中风控策略与客户运营体系

目录 贷中风控策略与客户运营体系 贷中风控日标 贷中风控数据源 贷中风控策略与客户运营体系 贷中是风控的第二道防线&#xff0c;贷中阶段风控的重点工作就是存量客户风控及运营。在当下&#xff0c;新客市场趋于饱和且获客成本越来越高&#xff0c;所以&#xff0c;在做好…

基于Java的俄罗斯方块游戏的设计与实现

关于俄罗斯方块项目源码.zip资源-CSDN文库https://download.csdn.net/download/JW_559/89300281 基于Java的俄罗斯方块游戏的设计与实现 摘 要 俄罗斯方块是一款风靡全球&#xff0c;从一开始到现在都一直经久不衰的电脑、手机、掌上游戏机产品&#xff0c;是一款游戏规则简单…

在React中利用Postman测试代码获取数据

文章目录 概要名词解释1、Postman2、axios 使用Postman测试API在React中获取并展示数据小结 概要 在Web开发中&#xff0c;通过API获取数据是一项常见任务。Postman是一个功能强大的工具&#xff0c;可以帮助开发者测试API&#xff0c;并查看API的响应数据。在本篇博客中&…

【C语言】—— 动态内存管理

【C语言】——动态内存管理 一、动态内存管理概述1.1、动态内存的概念1.2、动态内存的必要性 二、 m a l l o c malloc malloc 函数2.1、函数介绍2.2、应用举例 三、 c a l l o c calloc calloc 函数四、 f r e e free free 函数4.1、函数介绍4.2、应用举例 五、 r e a l l o …

无列名注入

在进行sql注入时&#xff0c;一般都是使用 information_schema 库来获取表名与列名&#xff0c;因此有一种场景是传入参数时会将 information_schema 过滤 在这种情况下&#xff0c;由于 information_schema 无法使用&#xff0c;我们无法获取表名与列名。 表名获取方式 Inn…

FullCalendar日历组件集成实战(3)

背景 有一些应用系统或应用功能&#xff0c;如日程管理、任务管理需要使用到日历组件。虽然Element Plus也提供了日历组件&#xff0c;但功能比较简单&#xff0c;用来做数据展现勉强可用。但如果需要进行复杂的数据展示&#xff0c;以及互动操作如通过点击添加事件&#xff0…

SwiftUI中的常用图形(Shapes)

概述 在SwiftUI中&#xff0c;常用的图形&#xff08;Shape&#xff09;主要有&#xff1a; Circle&#xff1a;圆形 Ellipse&#xff1a;椭圆形 Capsule&#xff1a;胶囊形 Rectangle&#xff1a;矩形 RoundedRectangle&#xff1a;圆角矩形 上面的这些图形都继承了Shape协议…

Hive读写文件机制

Hive读写文件机制 1.SerDe是什么&#xff1f; SerDe是Hive中的一个概念&#xff0c;代表着“序列化/反序列化” &#xff08;Serializer/Deserializer&#xff09;。 SerDe在Hive中是用来处理数据如何在Hive与底层存储系统&#xff08;例如HDFS&#xff09;之间进行转换的机制…

2024国考行测、申论资料大全,做好备考真的很重要!

1. 国考是什么? 国考,全称国家公务员考试,是选拔国家公务员的重要途径。通过国考,你将有机会进入政府部门,为国家建设贡献力量。 2. 国考难在哪里? 国考之所以难,主要体现在以下几个方面: (1) 竞争激烈 每年国考报名人数都在百万以上,而录取率却不足2%。千军万马过独木桥…

node和npm版本太高导致项目无法正常安装依赖以及正常运行的解决办法:如何使用nvm对node和npm版本进行切换和管理

1&#xff0c;点击下载 nvm 并且安装 进入nvm的github&#xff1a; GitHub - coreybutler/nvm-windows: A node.js version management utility for Windows. Ironically written in Go. 这里下载发行版&#xff0c;Releases coreybutler/nvm-windows GitHub 找到 这个 nv…

洗地机哪款好用?希亦、追觅、顺造、米家等高品质洗地机推荐

家用洗地机已经成为家庭清洁的重要利器&#xff0c;其多功能性能帮助您轻松应对各种清洁任务&#xff0c;从而保持家居环境的清洁整洁。然而&#xff0c;市场上品牌繁多、功能各异的洗地机让人眼花缭乱。为了帮助大家做出明智的选择&#xff0c;我们将在本文中提供全面的选购指…

选择法(数值排序)(C语言)

一、运行结果&#xff1b; 二、源代码&#xff1b; # define _CRT_SECURE_NO_WARNINGS # include <stdio.h>//声明排序函数sort; void sort(int a[], int n);int main() {//初始化变量值&#xff1b;int i, a[10];//填充数组&#xff1b;printf("请输入10个整数\n&…

蓝桥杯备战22.k倍区间——前缀和

目录 题目 分析 暴力求解 优化思路 AC代码 题目链接&#xff1a; P8649 [蓝桥杯 2017 省 B] k 倍区间 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 题目 分析 很明显这题是一道前缀和的题 暴力求解 只得了28分 #include<iostream> using namespace std; co…