嵌入式系统移植

一、系统分层

 移植的目的

        不同架构的处理器指令集不兼容,即便是相同的处理器架构,板卡不同驱动代码也不兼容

        Linux是一个通用的内核并不是为某一个特定的处理器架构或板卡设计的,所以从官方获取Linux源码后我们要先经过相应的配置使其与我们当前的硬件平台相匹配后才能进行编译和安装

系统移植过程

二、开发板启动过程

        开发板上电后首先运行SOC内部iROM中固化的代码(BL0),这段代码先对基本的软硬件环境(时钟等...)进行初始化,然后再检测拨码开关位置获取启动方式,然后再将对应存储器中的uboot搬移到内存,然后跳转到uboot运行;

        uboot开始运行后首先对开发板上的软硬件环境做进一步初始化,然后将linux内核、设备树(dtb)、根文件系统(rootfs)从外部存储器(或网络)搬移到内存,然后跳转到linux运行;

        linux开始运行后先对系统环境做初始化,当系统启动完成后,Linux再从内存中(或网络)挂载根文件系统。

        系统移植步骤:uboot移植、linux内核移植(包含设备树)和根文件系统移植。

三、交叉开发环节搭建

1.ubuntu网络环境配置

 2.tftp服务器环境搭建

        ntftp(Trivial File Transfer Protocol)即简单文件传输协议是TCP/IP协议族中的一个用来在客户机与服务器之间进行简单文件传输的协议,提供不复杂、开销不大的文件传输服务。端口号为69。

3.nfs服务器环境搭建

        nnfs(Network File System)即网络文件系统,其基于UDP/IP使用nfs能够在不同计算机之间通过网络进行文件共享,能使使用者访问网络上其它计算机中的文件就像在访问自己的计算机一样。

        nfs是网络文件系统,不是用来传东西的,是把嵌入式的根文件系统通过nfs放在网络上的某个介质中,nfs是通过以太网中的udp传送命令的。tftp是通过TCP/IP协议用来在客户机与服务器之间进行简单文件传输的协议。

四、uboot

uboot详细介绍:http://t.csdn.cn/mYHye

1.开发板启动过程

Bootloader

        在操作系统运行之前运行的一小段代码,用于将软硬件环境初始化到一个合适的状态,为操作系统的加载和运行做准备(其本身不是操作系统)

Bootloader基本功能

    -> 初始化软硬件环境

    -> 引导加载linux内核

    -> 给linux内核传参

    -> 执行用户命令

注:bootloader是启动引导程序的统称,嵌入式linux常用的bootloader是uboot 

常见的Bootloader

 2.SD卡启动盘制作

五、uboot的使用

1.uboot模式

自启动模式:uboot启动后若没有用户介入,倒计时结束后会自动执行自启动

                    环境变量(bootcmd)中设置的命令(一般作加载和启动内核)

交互模式:倒计时结束之前按下任意按键uboot会进入交互模式,交互模式下

                用户可输入uboot命令 

2.uboot帮助命令

        help:查看uboot支持的所有命令

        help 命令:查看当前命令的使用方法 

3.uboot环境变量命令

printenv:打印uboot中所有的环境变量

setenv:设置指定的环境变量(保存在RAM中)

                setenv 环境变量 环境变量的值 

saveenv:保存所有环境变量到EMMC中(保存到外存里,diao电不丢失)

4.uboot常用环境变量

ipaddr:uboot的IP地址

serverip:服务器的IP地址(即ubuntu的IP) 

bootdelay:进入自启动模式之前倒计时的秒数

5.uboot网络传输命令

loadb:通过Kermit协议下载文件到指定的内存地址

        loadb  地址

tftp:通过tftp协议下载文件到指定的内存地址

        tftp  地址  文件名 

注:使用tftp之前要配置好网络及tftp服务器

6.uboot存储器访问命令

mmc read:将EMMC中指定扇区中的内容读取到内存中指定的地址

                mmc read  <addr> <blk#> <cnt>

                addr:  内存地址

                blk#:  EMMC中的扇区编号

                cnt:  读取的扇区的个数

mmc write

    将内存中指定地址中的内容写入到EMMC中指定的扇区

        mmc write <addr> <blk#> <cnt> 

7.uboot自启动环境变量

bootcmd

        自启动的环境变量

        该环境变量可以设置成一到多个uboot命令的集合(若有多个使用\;分割)

        自启动模式下uboot就会按照bootcmd中命令的顺序逐条执行

        eg:

                setenv bootcmd tftp 40008000 interface.bin\;go 40008000

                saveenv

bootm        uboot内核启动命令

启动指定内存地址上的Linux内核并为内核传递参数bootm kernel-addr ramdisk-addr dtb-addr

注:

      kernel-addr:  内核的下载地址 

      ramdisk-addr:  根文件系统的下载地址   

      dtb-addr:  设备树的下载地址

      若不使用相应的地址,对应的位置写“-”

  eg:

      bootm 0x41000000 - 0x42000000 

bootargs        自启动参数环境变量

    eg:

    setenv bootargs root=/dev/nfs nfsroot=xxx.xxx.xxx.xxx:/opt/4412/rootfs     

    rw console=ttySAC2,115200 init=/linuxrc ip=***.***.***.***

    注:

        root  根文件系统类型(nfs)

        nfsroot  网络文件系统路径(xxx.xxx.xxx.xxx:/opt/4412/rootfs)

        rw        操作网络文件系统的权限(rw)

        console  控制台(使用串口2,波特率115200)

        init          init进程的位置(/linuxrc)

        ip            linux启动后自身的IP(***.***.***.***)

8.Linux 内核的安装与加载

通过 tftp 加载内核和根文件系统
set serverip 192.168.1.100
set ipaddr 192.168.1.200
set gatewayip 192.168.1.1
setenv bootcmd tftp 0x41000000 uImage\;tftp 0x42000000 exynos4412-fs4412.dtb\;tftp 0x43000000 ramdisk.img\;bootm 0x41000000 0x43000000 0x42000000
setenv bootargs=root=/dev/nfs nfsroot=192.168.100.200:/opt/4412/rootfs rw console=ttySAC2,115200 init=/linuxrc ip=192.168.100.230

 

通过 EMMC 加载内核和根文件系统
set serverip 192.168.1.100
set ipaddr 192.168.1.200
set gatewayip 192.168.1.1
setenv bootcmd 'mmc read 0 0x41000000 0x800 0x2000;mmc read 0 0x42000000 0x2800 0x800;mmc read 0 0x43000000 0x3000 0x2000;bootm 0x41000000 0x43000000 0x42000000'
setenv bootargs=root=/dev/nfs nfsroot=192.168.100.200:/opt/4412/rootfs rw console=ttySAC2,115200 init=/linuxrc ip=192.168.100.230

通过 tftp 加载内核通过 nfs 挂载根文件系统
set serverip 192.168.1.100
set ipaddr 192.168.1.200
set gatewayip 192.168.1.1
setenv bootcmd tftp 0x41000000 uImage\;tftp 0x42000000 exynos4412-fs4412.dtb\;bootm 0x41000000 - 0x42000000
setenv bootargs=root=/dev/nfs nfsroot=192.168.100.200:/opt/4412/rootfs rw console=ttySAC2,115200 init=/linuxrc ip=192.168.100.230

六、交叉编译工具链

1.交叉编译

        机器码(二进制)是处理器能直接识别的语言,不同的机器码代表不同的运算指令,处理器能够识别哪些机器码是由处理器的硬件设计所决定的,不同的处理器机器码不同,所以机器码不可移植

        汇编语言是机器码的符号化,即汇编就是用一个符号来代替一条机器码,所以不同的处理器汇编也不一样,即汇编语言也不可移植

        C语言在编译时我们可以使用不同的编译器将C源码编译成不同架构处理器的汇编,所以C语言可以移植

        机器码(二进制)是处理器能直接识别的语言,不同的机器码代表不同的运算指令,处理器能够识别哪些机器码是由处理器的硬件设计所决定的,不同的处理器机器码不同,所以机器码不可移植

        汇编语言是机器码的符号化,即汇编就是用一个符号来代替一条机器码,所以不同的处理器汇编也不一样,即汇编语言也不可移植

        C语言在编译时我们可以使用不同的编译器将C源码编译成不同架构处理器的汇编,所以C语言可以移植

交叉编译工具链

交叉编译工具链的获取:

1) 官网获取(不推荐,需要自己进行复杂配置与编译)

        http://ftp.gnu.org/gnu/gcc/

2) BSP板级开发支持包(推荐)

        samsung、全志...

交叉编译工具链的内容

1) 交叉编译工具

        gcc/readelf/size/nm/strip/objcopy/objdump/addr2line

2) 库

         ARM架构的库

 2.ELF文件格式

        ELF格式是Linux平台上应用最广泛的二进制工业标准之一

        ELF格式的文件内包含了很多个段不同的段存储了不同的信息;因为ELF格式的文件要通过Linux系统的加载和管理才能运行,所以除了最基本的代码段和数据段之外,其中还存储了很多其它的信息,如符号表、调试信息等

ELF文件相关命令

file

        file + 文件名  查看文件的详细信息

readelf

    readelf -h + 文件名   列出elf文件的头部信息

    readelf -a + 文件名   列出elf文件的所有信息

BIN文件格式

BIN

        BIN文件一般是直接运行在CPU之上的可执行文件,文件内只包含了CPU能够直接识别和运行的指令和数据,不包含其它系统相关的信息

3.交叉编译工具链常用工具

size  列出目标文件每一段的大小以及总体的大小

    size + 文件名 

nm  列出目标文件中的符号表(标示符)

    nm + 文件名 

strip  丢弃目标文件中的符号

    strip + 文件名 

    注:对于嵌入式开发,这个命令很重要

objdump  从目标文件中显示信息 

    eg: 

        objdump -d + 文件名  将目标文件反汇编(机器码->汇编)

objcopy  对目标文件进行复制和转换

    eg:

      objcopy --gap-fill=0xff -O binary a.out a.bin 

       将目标文件转换为bin格式

七、uboot源码配置编译

1.uboot源码结构

(1)uboot源码获取

        uboot源码下载:http://www.denx.de/wiki/U-Boot/

        uboot版本命名:前期:uboot-1.2.3        现在:uboot-2008.01

        uboot版本选择:支持对应的硬件平台;相对成熟的版本(资料多)

(2)uboot特点

        代码结构清晰

        支持丰富的处理器与开发板,易于移植

        支持丰富的用户命令

        支持丰富的网络协议

        支持丰富的文件系统

        支持丰富的设备驱动

        更新活跃、用户较多、资料丰富

        开放源代码

        较高的稳定性

        不具有通用性(不同的处理器、开发板uboot不可通用)

(3)uboot源码结构

        平台相关代码

                即与CPU架构或开发板硬件相关的源码,硬件的改动对应的代码也需要进行修改

                arch:与CPU架构相关的源代码

                board:与开发板相关的源代码,包含各种官方评估板对应的源码

        平台无关代码

                api:  应用接口

                common:  uboot命令源码

                disk:  对磁盘设备的支持

                drivers:  设备驱动源码

                fs:  对文件系统的支持 

                include:  头文件

                lib:  库

                net:  对网络协议的支持

                post:  上电自检程序

                ... ...

        配置文件、帮助文档、示例程序、工具等:

                README:  说明文档

                doc:  帮助文档

                Makefile:  编译管理

                CREDITS:  开发者

                COPYING:  版权

                examples:  示例程序

                tools:  工具

                ... ...

2.uboot的配置与编译

(1)uboot配置

        指定当前使用的硬件平台

                make <board_name>_config

                注1:<board_name>为当前使用的开发板的名字

                注2:执行该命令的前提是uboot源码支持该开发板

                注3:该命令必须在uboot源码的顶层目录下执行

        指定编译uboot源码使用的编译器

                在uboot源码顶层目录下的Makefile中指定(CROSS_COMPILE变量)

(2)uboot编译

        编译uboot

                make

                注1:该命令必须在uboot源码的顶层目录下执行

                注2:该命令执行后在uboot源码顶层目录下生成u-boot.bin

        清除编译过程中生成的中间文件

                make clean

                make distclean

                注1:该命令必须在uboot源码的顶层目录下执行

八、Linux内核移植

1.Linux内核概述

(1)内核与操作系统

        内核是一个操作系统的核心,提供了操作系统最基本的功能,是操作系统工作的基础,决定着整个系统的性能和稳定性

        操作系统是在内核的基础上添加了各种工具集、桌面管理器、库、shell、应用程序等

(2)Linux层次结构

 (3)Linux内核特点

                代码结构清晰、模块化设计

                支持丰富的硬件平台

                较高的稳定性

                轻量化及较强的裁剪性

                开放源代码

                更新活跃、用户较多、资料丰富

                支持丰富的网络协议

                ... ...

2.Linux内核源码结构

(1)Linux内核源码获取

        Linux内核源码下载:https://www.kernel.org/

        Linux内核版本命名:主版本号.次版本号.修订版本

        Linux内核版本选择:支持对应的硬件平台;相对成熟的版本(资料多);稳定版本(次版本号为偶数的版本一般都是稳定版)

(2)Linux内核源码结构

        平台相关代码

                arch:  与CPU架构相关的源代码

        平台无关代码

                block:磁盘设备的支持  crypto:加密相关

                drivers:设备驱动  firmware:固件

                fs:文件系统  include:头文件

                init:内核初始化  ipc:进程间通信

                kernel:内核核心调度机制等  lib:库

                mm:内存管理  net:网络协议

                scripts:工具、脚本等  security:安全

                usr:打包与压缩      virt:虚拟

        帮助文档、示例程序、工具等

                COPYING:  版权

                CREDITS:  内核贡献者

                README:  说明文档

                Documentation:  帮助文档

                Makefile:  编译管理

                samples:  示例

                tools:  工具

                ... ...

3.Linux内核的配置与编译

(1)Linux内核源码配置

        指定处理器架构及编译工具

                在Linux内核源码顶层目录下的Makefile中指定(ARCH、CROSS_COMPILE)

        导入当前处理器的默认配置

                make <soc_name>_defconfig

                注1:soc_name为当前使用的处理器的名字

                注2:内核源码的arch/arm/configs下对各个厂商的soc都有一个默认配置文件,执行该命令后就会将对应的配置文件中的信息导入到源码顶层目录下的.config文件中,CONFIG_xxx=y表示内核选中了该功能,内核编译时就会将该功能对应的代码编译,内核的体积也会增大。#CONFIG_xxx is not set表示内核没有选中该功能,内核编译时该功能对应的代码不会被编译,内核的体积也会减小。

        修改配置

        默认配置只能保证内核拥有最基本的功能,我们需要根据自己的实际需求对内核做进一步的配置

        方法1:直接修改.config文件(不推荐)

        方法2:make menuconfig

        make menuconfig

                修改配置

        [ ] 有两种状态

                输入Y,显示“*”,内核中该功能被选中,相关代码会被编译进内核

                输入N,显示“ ”,内核中该功能不被选中,相关代码不会被编译进内核

        < > 有三种状态

                输入Y,显示“*”,内核中该功能被选中,相关代码会被编译进内核

                输入N,显示“ ”,内核中该功能不被选中,相关代码不会被编译进内核

                输入M,显示“M”,内核中该功能被选为模块(被编译为独立的模块)

        注:使用make menuconfig配置的本质还是修改.config文件

(2)Linux内核源码编译

        内核编译(以下命令均在内核源码的顶层目录下执行)

                make uImage          编译内核(编译选为“*”的选项到内核)

                make modules        编译内核模块(编译选为“M”的选项为独立模块)

                make dtbs               编译设备树(将设备树源文件dts编译为二进制文件dtb)

                make clean             删除编译过程中产生的中间文件

九、设备树

1.设备树

        设备树是一种描述硬件信息的数据结构,Linux内核运行时可以通过设备树将硬件信息直接传递给Linux内核,而不再需要在Linux内核中包含大量的冗余编码

2.设备树语法概述

(1)设备树文件

        dts  设备树源文件

        dtsi 类似于头文件,包含一些公共的信息,可被其它设备树文件引用

        dtb  编译后的设备树文件

(2)设备树语法

        设备树的语法为树状结构,由一系列的节点和属性组成,根节点下包含子节点

        子节点下还可以包含子节点,节点内部包含了对应设备的属性

3.Linux内核驱动移植

        在make menuconfig界面中选中要安装的驱动

        在设备树中添加/修改相应的设备信息

        重新编译内核/设备树

十、Linux内核调试及rootfs移植

1.根文件系统

        根文件系统是内核启动后挂载的第一个文件系统系统引导程序会在根文件系统挂载后从中把一些基本的初始化脚本和服务等加载到内存中去运行

2.根文件系统内容

        bin  shell命令(elf格式)(通过busybox编译生成)

        dev  设备文件(内核启动后会将设备信息写入该目录)

        etc  内核配置文件

        lib  共享库(elf格式)(从交叉编译工具链中获取)

        linuxrc  内核运行的第一个应用程序(通过busybox编译生成)

        mnt  挂载目录(非必要)

        proc  进程相关文件(内核启动后会将进程信息写入该目录)

        root  超级用户家目录(非必要)

        sbin     系统管理shell命令(elf格式)(通过busybox编译生成)

        sys  驱动相关文件(内核启动后会将驱动信息写入该目录)

        usr  shell命令(elf格式)(通过busybox编译生成)

3. BusyBox将很多常用的工具集成到一个很小的可执行文件中,为普通用户提供大多数常用的命令,BusyBox实现的命令都是精简版的,很多扩展都不支持。BusyBox被称为Linux工具里的瑞士军刀

        BusyBox的获取:https://busybox.net/downloads/

使用BusyBox制作的Linux工具有哪些特点,为什么嵌入式领域一般都使用BusyBox?

BusyBox是一个开源项目,它提供了一个精简的Unix工具集合,适用于嵌入式系统和嵌入式Linux环境。以下是BusyBox的一些特点

  1. 精简和轻量:BusyBox将多个常用的Unix工具(如ls、cp、grep等)合并为一个可执行文件,通过共享代码和函数来减少二进制文件的大小。这使得BusyBox成为嵌入式系统中的理想选择,因为它可以大大减小系统的存储空间和内存占用。

  2. 可配置性:BusyBox提供了许多可配置选项,可以根据嵌入式系统的需求选择性地编译所需的工具。这使得系统开发人员能够根据具体的应用场景和硬件要求,灵活地构建和定制自己的嵌入式Linux环境。

  3. 兼容性:BusyBox是以兼容POSIX标准为目标开发的,它提供了与传统Unix工具相似的接口和功能。这使得已经熟悉标准Unix工具的开发人员能够快速上手并在嵌入式系统中使用BusyBox提供的工具。

  4. 开源和活跃的社区支持:BusyBox是一个开源项目,拥有庞大的社区支持和活跃的开发团队。这意味着用户可以从社区中获得帮助、修复错误和安全漏洞,并及时获得新的功能和改进。

为什么嵌入式领域一般都使用BusyBox呢?

主要原因有以下几点:

  1. 资源限制:嵌入式系统通常具有有限的资源,包括存储空间和内存。BusyBox的精简和轻量特性使得它成为在资源受限的环境下高效利用资源的选择。

  2. 定制性:BusyBox提供了可配置选项,使得开发人员可以根据具体的需求和硬件平台选择所需的工具,从而定制自己的嵌入式Linux环境。这种定制性使得BusyBox适应性强,可以满足各种嵌入式系统的需求。

  3. 兼容性:BusyBox提供了与传统Unix工具相似的接口和功能,这使得已经熟悉标准Unix工具的开发人员能够无缝迁移到BusyBox提供的工具。这简化了开发人员的学习曲线,并提高了开发效率。

  4. 开源社区支持:BusyBox作为一个开源项目,拥有庞大的社区支持和活跃的开发团队。这意味着用户可以从社区中获得支持、修复错误和漏洞,并及时获得新的功能和改进。这为嵌入式系统开发者提供了一个可靠的资源和知识库。

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

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

相关文章

vi/vim 如何在PowerShell里粘贴内容

vi/vim 如何在PowerShell里粘贴内容 Shift 鼠标右键 Vi/Vim 有两种主要的模式&#xff1a;命令模式和插入模式。 要进入命令模式&#xff0c;只需按下英文输入状态下的冒号&#xff08;:&#xff09;键。一旦进入命令模式&#xff0c;您可以在底部的命令行中输入各种命令。例…

服务器垃圾怎样清理?C盘垃圾如何清理?

好多人都在问电脑垃圾如何清理&#xff1f;服务器的垃圾清理是系统维护中必不可少的一项任务&#xff0c;而C盘垃圾的清理同样也是必须要做的任务之一。那么&#xff0c;如何一键清理服务器垃圾&#xff0c;C盘垃圾如何清理呢&#xff1f;今天&#xff0c;我会以服务器助手为例…

Linux基础+html和script一些基本语法

文章目录 linux 基础名字含义指令 html 语法style 样式属性样式标签属性颜色margin 边距ransform 旋转角度重复样式opacity 透明度div 方块元素box-shadow 阴影属性浮动 script获取节点onclick 点击触发setTimeout 定时器利用定时器实现 动画效果 javascript强弱语言区分parseI…

NoSQL之Redis配置与优化(初级)理论较多

目录 一、关系数据库与非关系型数据库 1、 关系型数据库 2、 非关系型数据库 二、关系型数据库和非关系型数据库区别 1、 数据存储方式不同 2、 扩展方式不同 3、 对事务性的支持不同 三、非关系型数据库产生背景 1、可用于应对Web2.0纯动态网站类型的三高问题&#xf…

Dell-Precision5520 电脑 Hackintosh 黑苹果efi引导文件

原文来源于黑果魏叔官网&#xff0c;转载需注明出处。&#xff08;下载请直接百度黑果魏叔&#xff09; 硬件配置 硬件型号驱动情况 主板Dell-Precision5520 处理器Intel Core i7-7820HQ已驱动 内存Micron 2400MHz DDR4 16GB x2已驱动 硬盘Samsung 970EVO 512GB已驱动 显…

ES6新特性总结

最近&#xff0c;在面试中也是经常被问道ES6关于新特性的面试题&#xff0c;那我也来个总结&#xff0c;记录下。 ES6新特性总结 let、const命令&#xff08;1&#xff09;let&#xff08;2&#xff09;const 模板字符串增强的函数&#xff08;1&#xff09;函数的参数可以设置…

网络安全技术入门(1):简介

文章目录 1.前言2.什么是网络安全技术&#xff1f;3.列举一些常见的网络安全技术3.1 防火墙3.2 加密技术3.3 身份认证和访问控制3.4 恶意软件防护3.5 网络监控和日志管理3.6 威胁情报和漏洞管理3.7 安全培训和意识教育 4.网络安全研究的关键技术5.网络安全防护技术有哪些&#…

IP路由协议(RIP、IGRP、OSPF、IS-IS、BGP)

文章目录 1、路由分类2、RIP协议1&#xff09;RIP的工作原理2&#xff09;RIP路由表的更新过程3&#xff09;RIP路由表的更新原则4&#xff09;RIP的特性5&#xff09;RIP协议的版本 4、IGRP协议1&#xff09;IGRP路由表的更新2&#xff09;IGRP的度量标准 5、OSPF协议1&#x…

基于matlab使用二维规范化互相关进行模式匹配和目标跟踪(附源码)

一、前言 此示例演示如何使用二维规范化互相关进行模式匹配和目标跟踪。该示例使用预定义或用户指定的目标以及要跟踪的类似目标的数量。归一化互相关图显示&#xff0c;当值超过设置的阈值时&#xff0c;将标识目标。 在此示例中&#xff0c;您使用规范化互相关来跟踪视频中…

FOF常用的七种投资策略全解析

从当前市场上的投资策略种类来看&#xff0c;大致有七种&#xff0c;包括核心*卫星投资策略、「杠铃」投资策略、反向投资策略、成本平均策略和时间分散化策略、买入并持有策略、美林投资时钟策略、Alpha/Beta投资策略。 投资策略一:美林投资时钟策略 美林投资时钟投资策略相信…

【后台管理框架】JAVA后台管理框架推荐

目录 若依 Guns 2.vue-element-admin 3.JEECG-BOOT 4.GIN-VUE-ADMIN 5.vue-admin-beautiful 6.Dcat-admin 7.RuoYi 8.renren-fast-vue 9.ant-design-pro 10.iview-admin 11.material-dashboard 参考资料 若依 若依管理系统 Guns Guns Tech. 后台管理系统是内容…

微信小程序如何读取本地云存储txt数据,避免乱码

第一步 找到你的txt文件&#xff0c;重命名为json文件 第二步 上传到云存储中&#xff0c;获取File ID 第三步 编写js代码 相关技术文档&#xff1a; https://developers.weixin.qq.com/miniprogram/dev/api/file/FileSystemManager.readFile.html onShow(){wx.cloud.d…