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 信息包含了所有的选项说明,但我相信读到这里的小伙伴只有少部分真正去阅读了工具选项和说明。主要有几点:

  1. 说明是英文的,一看英文就反感。没说你,我自己就是这样。
  2. 选项很枯燥,看了也不知道怎么用
  3. 喜欢手把手的那种详细说明文档

但我还是十分建议你花 5 分钟去仔细阅读一下工具所有选项以及相应的说明,主要理由有以下几点:

  1. 不喜欢看英文的文档,那是因为你看得太少了,需要多看
  2. 选项很枯燥,看了也不知道怎么用,还是因为看得太少了
  3. 不要寄希望与别人的手把手文档,有当然好,没有就上帮助文档,这才是必由之路。

说到底,自带的帮助文档是第一手的资料,阅读第一手的资料,有助于你提高自己的学习能力。

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. 几个思考题

到这里差不多应该结束了,给大家留三个思考题:

问题1system.imgsystem_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.img
  • system_b 的 image 为: out/target/product/panther/system_other.img

按照我的理解是 system_asystem_b 分区,制作镜像时可以提供一样的文件,或者像其他分区一样,system_b 不提供任何文件,仅保留一个空分区记录。

但为什么这里会传递 system_other.imgsystem_b 分区呢?

镜像文件 system_other.imgsystem.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”获取个人微信。

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

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

相关文章

(第六天)初识Spring框架-SSM框架的学习与应用(Spring + Spring MVC + MyBatis)-Java EE企业级应用开发学习记录

SSM框架的学习与应用(Spring Spring MVC MyBatis)-Java EE企业级应用开发学习记录&#xff08;第六天&#xff09;初识Spring框架 ​ 昨天我们已经把Mybatis框架的基本知识全部学完&#xff0c;内容有Mybatis是一个半自动化的持久层ORM框架&#xff0c;深入学习编写动态SQL&a…

Vector<T> 动态数组(模板语法)

C数据结构与算法 目录 本文前驱课程 1 C自学精简教程 目录(必读) 2 动态数组 Vector&#xff08;难度1&#xff09; 其中&#xff0c;2 是 1 中的一个作业。2 中详细讲解了动态数组实现的基本原理。 本文目标 1 学会写基本的C类模板语法&#xff1b; 2 为以后熟练使用 S…

基于Java的代驾管理系统 springboot+vue,mysql数据库,前台用户、商户+后台管理员,有一万五千字报告,完美运行

基于Java的代驾管理系统 springbootvue&#xff0c;mysql数据库&#xff0c;前台用户、商户后台管理员&#xff0c;有一万五千字报告&#xff0c;完美运行。 系统完美实现用户下单叫车、商户接单、管理员管理系统&#xff0c;页面良好&#xff0c;系统流畅。 各角色功能&#x…

【CicadaPlayer】getPlayerBufferDuration分析

https://github.com/alibaba/CicadaPlayer/blob/release/0.4.4/mediaPlayer/SuperMediaPlayer.cpp核心关键函数int64_t SuperMediaPlayer::getPlayerBufferDuration(bool gotMax, bool internal)17个地方出现: getPlayerBufferDuration的durations 数组 分别 对音频、视频、字…

利用R作圆环条形图

从理念上看&#xff0c;本质就是增加了圆环弧度的条形图。如上图2。 需要以下步骤&#xff1a; 数据处理&#xff0c;将EXCEL中的数据做成3*N的表格导入系统&#xff0c;代码如下&#xff1a;library(tidyverse) library(stringr)library(ggplot2)library(viridis) stuper &…

UDP 多播(组播)

前言&#xff08;了解分类的IP地址&#xff09; 1.组播&#xff08;多播&#xff09; 单播地址标识单个IP接口&#xff0c;广播地址标识某个子网的所有IP接口&#xff0c;多播地址标识一组IP接口。单播和广播是寻址方案的两个极端&#xff08;要么单个要么全部&#xff09;&am…

AI聊天机器人平台Poe发布更新;自然语言理解课程概要

&#x1f989; AI新闻 &#x1f680; AI聊天机器人平台Poe发布更新 突破功能限制 增加企业级服务 摘要&#xff1a;知名问答网站Quora旗下的AI聊天机器人平台Poe发布了一系列更新&#xff0c;包括推出Mac应用、支持同时进行多个对话、接入Meta的Llama 2模型等功能。用户只需支…

自动化运维:Ansible之playbook基于ROLES部署LNMP平台

目录 一、理论 1.playbook剧本 2.ROLES角色 3.关系 4.Roles模块搭建LNMP架构 二、实验 1.Roles模块搭建LNMP架构 三、问题 1.剧本启动php报错语法问题 2.剧本启动mysql报错语法问题 3.剧本启动nginx开启失败 4.剧本安装php失败 5.使用yum时报错 6.rpm -Uvh https…

自动泊车的自动驾驶控制算法

1. 自动泊车系统 自动泊车系统(AutomatedParkingASSiSt,APA)利用车辆搭载的传感器感知车辆周边环境,扫描满足当前车辆停放的障碍物空间车位或线车位,并通过人机交互(HumanMachine Interface,HMI)获取驾驶员对目标车位的选择或自动确定目标车位,自动规划泊车路径,通过控制器向车…

windows环境搭建ELK

目录 资源下载&#xff08;8.9.1&#xff09; ES安装、注册、使用 Kibana安装、注册、使用 Logstash安装、注册、使用 Filebeat安装、使用&#xff08;如果只有一个数据流&#xff0c;则不需要使用filebeat&#xff0c;直接上logstash即可&#xff09; 资源下载&#xff0…

WebSocket--技术文档--架构体系--《WebSocket实现原理以及关键组件》

WebSocket产生背景 简单的说&#xff0c;WebSocket协议之前&#xff0c;双工通信是通过多个http链接来实现&#xff0c;这导致了效率低下。WebSocket解决了这个问题。下面是标准RFC6455中的产生背景概述。 长久以来, 创建实现客户端和用户端之间双工通讯的web app都会造成HTT…

配置开启Hive远程连接

配置开启Hive远程连接 Hive远程连接默认方式远程连接Hive自定义身份验证类远程连接Hive权限问题额外说明 Hive远程连接 要配置Hive远程连接&#xff0c;首先确保HiveServer2已启动并监听指定的端口 hive/bin/hiveserver2检查 HiveServer2是否正在运行 # lsof -i:10000 COMMA…

详解 ElasticSearch Kibana 配置部署

默认安装部署所在机器允许外网 SSH工具 Putty 链接&#xff1a;https://pan.baidu.com/s/1b6gumtsjL_L64rEsOdhd4A 提取码&#xff1a;lxs9 Winscp 链接&#xff1a;https://pan.baidu.com/s/1tD8_2knvv0EJ5OYvXP6VTg 提取码&#xff1a;lxs9 WinSCP安装直接下一步到完成…

elementUi中的el-table表格的内容根据后端返回的数据用不同的颜色展示

效果图如下&#xff1a; 首先 首先&#xff1a;需要在表格行加入 <template slot-scope"{ row }"> </template>标签 <el-table-column prop"usable" align"center" label"状态" width"180" ><templ…

ELK安装、部署、调试 (二) ES的安装部署

ElasticSearch是一个基于Lucene的搜索服务器。它提供了一个分布式多用户能力的全文搜索引擎&#xff0c;基于RESTful web接口操作ES&#xff0c;也可以利用Java API。Elasticsearch是用Java开发的&#xff0c;并作为Apache许可条款下的开放源码发布&#xff0c;是当前流行的企业…

Linux 桌面上的 Firefox 面临着大问题

导读毫无疑问&#xff0c;无论是在桌面、笔记本电脑还是移动设备上&#xff0c;浏览器都是任何操作系统中最重要的应用之一。 如果没有一个功能强大、快速且稳定的浏览器&#xff0c;操作系统的实用性将大幅度降低&#xff0c;以至于我相当确定&#xff0c;如果一个操作系统没有…

Mysql的page,索引,Explain Type等基本常识

Mysql的基本问题 Mysql 为什么建议使用自增id&#xff1f; 因为id&#xff08;主键&#xff09;是自增的话&#xff0c;那么在有序的保存用户数据到页中的时候&#xff0c;可以天然的保存&#xff0c;并且是在聚集索引&#xff08;id&#xff09;中的叶子节点可以很好的减少插…

WebGL非矩阵变换

目录 平移 示例代码&#xff1a; 齐次坐标矢量的最后一个分量w 旋转 p的坐标&#xff0c;可得等式 R1&#xff1a; 使用r、α、β来表示点p的坐标&#xff0c;可得等式 R2&#xff1a; 利用三角函数两角和公式&#xff0c;可得等式 R3&#xff1a; 最后&#xff0c;将…

下岗吧,Excel

ChatGPT的诞生使Excel公式变得过时。通过使用 ChatGPT 的代码解释器你可以做到&#xff1a; 分析数据创建图表 这就像用自然语言与电子表格交谈一样。我将向大家展示如何使用 ChatGPT 执行此操作并将结果导出为Excel格式&#xff1a; 作为示例&#xff0c;我将分析并创建美国…

阿里云效和阿里在线idea使用

阿里云效 https://flow.aliyun.com/all?page1 阿里在线idea&#xff1a;https://ide.aliyun.com/ 在云效中创建的项目可以在在线idea 打开 运行中的项目 设置ssh 设置以后可以使用云效率的代码构建来构建代码 设置 添加自有云或者体验5h