树莓派第一次开机

这篇具有很好参考价值的文章主要介绍了树莓派第一次开机。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

基于树莓派的OpenEuler基础实验一

一、树莓派介绍

树莓派由英国的树莓派基金会发行,旨在通过发行这个廉价开源的可随意破解的微型计算机,推动中小学编程教育,发行之后很快在全世界的开源创客圈中流行。截止到2018年10月,最新版本的树莓派主板是3B+,国内某宝上卖230元左右,还有更微型的树莓派主板Zero,国内某宝卖100元左右。树莓派是一种麻雀虽小五脏俱全的掌上电脑,它可以完成普通电脑的所有功能,有USB接口、HDMI显示屏接口、网线接口、耳机接口、蓝牙、Wifi、可编程引脚,可外接摄像头和显示屏。其CPU计算速度大概相当于iphone 4S,足以满足创客开发日常需求。而且,树莓派是最适合学习Linux和Python的工具,而且能通过它登堂入室,走进计算机科学的大千世界,搭上目前火热的人工智能、物联网、嵌入式开发、智能硬件的车。中国很多高校的毕业设计和课程设计要用到树莓派,特别是自动化专业。

树莓派较普通电脑的优势

1、廉价便携可折腾

在国内您花费千元左右就能够购买全套顶配的开发配件。在使用树莓派的时候,你可以大胆地尝试电路改线、CPU超频、破解、删库、病毒攻击、渗透测试、内存挤占等一系列实践,大不了就是重新安装操作系统(5分钟不到),闹翻天也不过买块新树莓派(五百元左右)。这样就不必冒着风险折腾自家宝贵的笔记本电脑和台式电脑。

史上最全的树莓派购买指南

2、树莓派运行开源的Linux操作系统

普通电脑上普遍运行Windows操作系统,但树莓派上运行的是Linux操作系统。你可以接触到真正的程序员和黑客每天面对的酷炫的Linux命令行和图形界面。Linux是开源的操作系统,由世界各地的开发者历经三十年的时间逐渐积累优化,衍生出许多发行版(比如智能手机上的安卓操作系统),Linux的诞生和发展催生了开源软件文化和开源软件社群,很多软件和代码库对Linux极其友好,但如果你用Windows安装配置就会发现十分困难。

十个使用Linux操作系统的理由

3、编程好平台

作为旨在为编程教学而生的计算机,树莓派内置了各种编程语言的开发环境,包括Python2、Python3、Java、Wolfram、科学计算内核,还有艺术图形可视化编程工具Processing、音乐可视化编程工具Sonic Pi、创客可视化编程工具Scratch、NodeJS、我的世界Mine Craft等。无需复杂的安装配置,直接上手敲代码运行即可。

4、开源大社区

树莓派的所有硬件、操作系统、软件、杂志、论坛全部是开源免费的,并且在全世界有规模庞大的玩家社群,他们贡献出自己的奇思妙想和源代码,你可以直接用别人写好的库和代码。一些知名开源项目,比如谷歌的人工智能框架TensorFlow、人脸识别项目face_recognition、开源机器视觉库SimpleCV、OpenCV、安卓操作系统等,都会专门开发树莓派可用的版本并撰写技术手册。

树莓派官方杂志MagPi的中文翻译版

开源人脸识别项目face_recognition

在树莓派上安装开源机器视觉库OpenCV

5、引脚可编程

树莓派主板上有GPIO引脚(通用输入输出接口),在3B+主板上是40个引脚,通过对这些引脚编程,可以控制各种各样的传感器、电子元器件、电路,进而进行机器人控制、数字电路实验,开发物联网应用。

6、便携随身带

树莓派非常便携,只有信用卡大小,可以随身携带,可以用普通安卓手机充电器或者移动电源供电,可以随身携带,非常方便。各种上天入地,翻山下海的任务都可以交给树莓派。树莓派除了传统的3B+之外还有微型的树莓派Zero,专门为便携嵌入式设计,可以放在手心里。

基于树莓派摄像头的冷水珊瑚礁科考

基于树莓派的FRILLER多地形机器人

7、灵活可扩展

你可以用树莓派进行各领域的开发,搭上当前火热的人工智能、大数据、物联网的车。搭配一个摄像头模块(40元),你可以做网络摄像头以及各种机器视觉和人工智能应用。搭配一个英特尔神经棒(500元),可以大大加快神经网络计算速度,可以达到毫秒级的物体检测。

二、openEuler embedded介绍

为从生态上解决国内嵌入式和实时操作系统遭受国外技术垄断的风险,华为公司推出了旨在具备实时性、安全可靠、互联互通、混合部署等特性的开源嵌入式操作系统OpenEuler Embedded。它基于openEuler社区的嵌入式系统软件平台,可同时部署Linux内核、自研微内核以及实时OS。OpenEuler Embedded针对嵌入式场景的需求,在内核特性、系统配置、软件包组合、镜像裁剪、安全加固、轻量化等方面进行创新,其OS镜像最小可达5M,并具有<5S的快速启动能力。OpenEuler Embedded总体架构如下图所示:

树莓派第一次开机,树莓派,树莓派

在硬件方面,OpenEuler Embedded目前重点支持ARM架构的处理器,如ARM32、ARM64,并通过QEMU和树莓派4B两个平台承载。未来OpenEuler Embedded还计划实现对RISC-V、X86、龙芯等架构的支持,全面面向多核异构嵌入式系统。在系统软件方面,OpenEuler Embedded采用了混合部署架构,加入linux内核以继承Linux的管理能力、丰富的生态,同时可加入RTOS内核以使系统能够支撑具有高实时、高可靠、高安全等需求的应用场景。在此基础上,OpenEuler Embedded摒弃了低效的资源静态部署方案,采用嵌入式虚拟化的办法,解决了混合关键性系统各子系统之间的兼容性、安全性等问题,实现了对各子系统内核的良好兼容,灵活开发和部署。OpenEuler Embedded还引入分布式软总线技术,打通了鸿蒙和欧拉两大生态。

在操作系统的开发方面,介于嵌入式系统资源有限,OpenEuler Embedded发布了专用的SDK (Software Development Kit)并集成了与OpenEuler Embedded配套的嵌入式系统仿真方案,未来计划集成图形化IDE (Integrated Development Environment), 组成一套完整的开发工具体系,实现对操作系统的开发、调试与优化。

综上所述,OpenEuler Embedded具有强大的开发平台,广阔的应用场景,着眼于生态建设,并且其结构的设计符合嵌入式和实时操作系统的未来发展趋势。因此,本课程的实践部分将基于OpenEuler开发,为中国嵌入式实时系统打破技术壁垒,走向世界,提供人才基础。

考虑到openeuler embedded更适用于产品化,在教学中对学生的门槛比较高,因此,为了方便教学,实验过程中,学生可自行构建openeuler embedded,或者选用已经构建好的openeuler树莓派镜像。

三、树莓派开机指南

1. 硬件准备

  • SD卡、读卡器、树莓派实验套件、一台电脑

2. 软件准备

  • 下载压缩包【树莓派开机工具】,解压,共有两个文件夹
  • 基本工具包括:SD卡格式化工具SD Formatter、镜像烧录工具、局域网IP扫描器、远程ssh工具
  • 开机常用文件:包括ssh空文件和wifi配置文件

3. openEuler embedded的构建

环境:Ubuntu20.04

1)运行环境准备

  • 安装python3和pip

    • apt-get install python3 python3-pip
  • 安装oebuild

    • sudo su
    • pip install oebuild
    • sudo apt install docker docker.io -y
    • sudo groupadd docker
    • sudo usermod -a -G docker $(whoami)
    • sudo systemctl-reload && systemctl restart docker
    • sudo chmod o+rw /var/run/docker.sock

2)构建

  • 初始化oebuild

    • cd ~
    • oebuild init //该操作会初始化 oebuild 的目录,表示要初始化目录的名称
  • oebuild更新

    • cd

    • oebuild update

      更新工作主要有两点:

      • pull相关的运行容器镜像
      • 从gitee上下载yocto-meta-openeuler仓代码,如果本地没有openeuler相关容器,则在这一步执行会比较漫长,请耐心等待。
  • 编译环境建立

    //进入oebuild工作目录,创建对应的编译配置文件

    • cd
    • oebuild generate -p raspberrypi4-64 //生成raspberrypi4-64配置文件
    • oebuild bitbake //进入构建交互终端
    • bitbake openeuler-image //构建镜像
    • bitbake openeuler-image -c do_populate_sdk //构建sdk
  • 二进制介绍

    • Image: 树莓派内核镜像

    • openeuler-glibc-x86-64-openeuler-image-cortexa72-raspberrypi4-64-toolchain-*.sh: SDK工具链

    • openeuler-image-raspberrypi4-64-*.rootfs.rpi-sdimg: openEuler Embedded树莓派支持SD卡镜像

      树莓派第一次开机,树莓派,树莓派

    • 将得到的openeuler-image-raspberrypi4-64-20230809013758.rootfs.rpi-sdimg镜像通过共享文件夹传输给windows,windows后续再将其烧录到树莓派的SD卡中。

4. 第一次开机

(1)格式化SD卡
  • 如果SD卡是旧卡,需要用SDFormatter格式化工具先格式化。如果用新的SD卡可以跳过此步。

格式化之后,可以看到SD卡对应的盘变成了空盘。

(2)烧录镜像

将第3步中获得的镜像文件openeuler-image-raspberrypi4-64-20230809013758.rootfs.rpi-sdimg烧录到SD卡中

  • 打开烧录工具Win32DiskImager(或者另一个镜像烧录工具balena-etcher),选好镜像文件和要烧录的SD卡对应的盘。

    选SD卡对应盘符号的时候一定要小心,不要选到其它盘或者硬件,不然镜像可能会覆盖写到其它盘里

  • 然后点击write,开始烧录

    树莓派第一次开机,树莓派,树莓派

  • 烧录成功后,将空白的ssh文件放入SD卡的boot盘【旨在一开始就让树莓派允许SSH进行连接】

    • 手动创建一个空白记事本.txt文件,命名为ssh,重命名,删除.txt扩展名,将这个文件放入SD卡的boot盘中。
    • 在003文件夹中也有已创建好的ssh文件,可以直接复制到SD卡的boot盘中
(3)Wi-Fi网络配置

需要显示屏

配置wifi文件

  • 新建一个空白文件wpa_supplicant.txt

  • 编辑wpa_supplicant.txt文件,输入以下配置,其中可以使用多个network{}来配置多个wifi,【不建议使用校园网,需要认证】

    country=GB
    ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev
    update_config=1
    network={
    	ssid="第一个WiFi的名字,不删除引号,不能有中文"
    	psk="WiFi密码,不删除引号"
    	priority=数字,数字越大代表优先级越高
    }
    network={
    	ssid="第二个WiFi的名字,不删除引号,不能有中文"
    	psk="WiFi密码,不删除引号"
    	priority=数字,数字越大代表优先级越高
    }
    

    priority表示几个wifi同时都搜得到的时候优先连接哪个。

  • 将txt后缀改成conf

  • 将wpa_supplicant.conf文件放入SD卡的boot盘中

开机

  • 拔出SD卡,插到树莓派的SD卡槽里,插好HDMI线连接显示器、电源线、鼠标线以及键盘线(鼠键支持2.4G无线接收器类型),通电

    • 树莓派上的红灯常亮,表示通电。绿灯间歇性亮,表示读写SD卡
  • 开机后可以看到显示器上输出很多树莓派启动日志,待树莓派启动成功后,输入用户名(root),然后修改密码(比如说openeuler@123)**登录。

    • 开机后通过命令ifconfig或者ip a查看wlan0下是否有ip地址,或者通过手机热点查看是否连接上了设备,如果有则说明wifi连接成功,否则连接失败。
使能无线驱动
  • 修改/etc/network/interfaces文件中无线网卡wlan0的配置

    iface wlan0 inet dhcp
           wireless_mode managed
           wireless_essid any
           wpa-driver wext
           wpa-conf /etc/wpa_supplicant.conf
    当前树莓派所使用的无线网卡驱动是 nl80211系列
    因此将wpa-driver wext 改为 wpa-driver nl80211
    才能正确启动wpa_supplicant
    iface wlan0 inet dhcp
           wireless_mode managed
           wireless_essid any
           wpa-driver nl80211
           wpa-conf /etc/wpa_supplicant.conf
    
  • 修改完成后重启networking service使配置生效

    • service networking restart
启用Wi-Fi网卡
  • 使用ifup启动Wi-Fi连接并自动获取IP地址

    • ifup wlan0

      当修改/etc/wpa_supplicant.conf配置文件后, 例如新增Wi-Fi网络配置或修改Wi-Fi网络配置, 需要使用ifdown wlan0来关闭网卡, ifup wlan0开启网卡使wpa_supplicant配置重新加载生效

  • 使用ifconfig命令查看wlan0网卡, 已经具有IP地址, 并可以正常通信

    树莓派第一次开机,树莓派,树莓派

  • 注意:如果不成功的话可以查看是否是wpa_supplicant.conf没有修改成功

    • cat wpa_supplicant.conf
(4)远程登陆树莓派

知道树莓派的ip地址后,就可以用我们的笔记本电脑远程登录树莓派

  • 以MobaXterm为例进行展示,课后可以自行尝试使用Putty

    【注意:电脑需要与树莓派连接至同一个热点,确保二者在同一个网段,否则远程登陆不成功】

    • 电脑端进入cmd终端窗口,输入ipconfig,查看二者是否在同一网段

    树莓派第一次开机,树莓派,树莓派

    与前面树莓派的ip地址192.168.1.110在同一网段(前三个数字相同)

    • 输入前面获得的树莓派的ip地址和用户名,OK

      树莓派第一次开机,树莓派,树莓派

    • 输入密码

      树莓派第一次开机,树莓派,树莓派

    • 选No即可

    树莓派第一次开机,树莓派,树莓派

    • 输入密码,即可登录成功

      树莓派第一次开机,树莓派,树莓派

    • 输入uname -a 可以查看版本名

      树莓派第一次开机,树莓派,树莓派

    • 查看openeuler embedded系统信息

      • cat /etc/os-release

        树莓派第一次开机,树莓派,树莓派

  • 注意:服务器版本的openeuler树莓派镜像的网络配置过程可以参考 openeuler官方安装指导

★树莓派的关机

  • 不能直接拔掉电源,会造成树莓派数据无法及时保存而丢失
  • 可以按需选择相关的终端命令操作
    • sudo poweroff 关闭电源
    • sudo shutdown -h now 立刻关机
    • sudo shutdown -r now 立刻重启
    • sudo reboot 重启
    • sudo shutdown -h +2 2分钟之后关机

四、基于SDK的应用开发

1. 交叉编译

交叉编译是什么
  • 编译可以分为两类:
    • 本地编译:编译器和目标程序都是相同架构的编译过程,如编译器运行在x86_64/ARM架构平台上,编译生成x86_64/ARM架构的可执行程序。
    • 交叉编译:编译器和目标程序运行在不同架构的编译过程,如编译器运行在x86架构平台上,编译生成ARM架构的可执行程序。
  • 通俗的来说,交叉编译就是在pc(x86架构)上的代码,通过相应的交叉编译工具链编译后,能在树莓派上运行(arm架构)。
为什么需要交叉编译?

这是因为通常编译工具链对编译环境有较高的要求,编译复杂的程序时,可能需要巨大的存储空间以及强大的 CPU 运算能力加快编译速度。嵌入式往往面临资源受限的问题,包括处理器性能、内存容量、存储空间等。因此,需要使用交叉编译器在构建主机上编译目标代码,以在嵌入式系统上运行。通常做法是在 PC 上使用交叉编译工具链生成能够在嵌入式设备运行的可执行程序,然后再将程序放到设备中去执行。

2. SDK环境配置

openEuler Embedded提供了SDK自解压安装包,包含了应用程序开发所依赖的交叉编译器、库、头文件,下面将介绍如何构建ARM64的SDK,以及如何使用SDK进行用户态程序、内核模块的开发。

安装SDK

在前面openEuler embedded的构建中,我们已经构建了SDK,得到了openeuler-glibc-x86-64-openeuler-image-cortexa72-raspberrypi4-64-toolchain-*.sh文件,是SDK安装包。接下来进行安装

  • 安装依赖软件包

    • sudo apt-get install make gcc g++ flex bison libgmp3-dev libmpc-dev libssl-dev
  • 执行SDK自解压安装脚本

    • sh openeuler-glibc-x86_64-openeuler-image-cortexa72-raspberrypi4-64-toolchain-23.03.sh
    • 根据提示输入工具链的安装路径,默认路径是 /opt/openeuler/<openeuler version>
  • 设置SDK环境变量

    前一步执行结束最后已打印source命令,运行即可

    • . /opt/openeuler/oecore-x86_64/environment-setup-cortexa72-openeuler-linux
  • 查看是否安装成功

    • 运行如下命令,查看是否安装成功、环境设置成功

      aarch64-openeuler-linux-gcc -v

      树莓派第一次开机,树莓派,树莓派

3. 使用SDK交叉编译hello world样例

1)准备代码

以构建一个hello world程序为例,运行在openEuler Embedded根文件系统镜像中。

  • 在Ubuntu上创建一个hello.c文件

    #include <stdio.h>
    
    int main(void)
    {
        printf("hello openEuler\r\n");
    }
    
  • 在hello.c程序所在目录执行如下命令

    • 交叉编译生成二进制aarch64-linux-gnu-gcc hello.c -o hello

    • 使用交叉编译器编译后,生成的 hello 已经变成了 ARM 平台的可执行文件

    • 可以通过 readelf 工具来查看具体的程序信息,readelf -a hello

      树莓派第一次开机,树莓派,树莓派

  • 将上一步生成的可执行文件拷贝到树莓派的openeuler embedded中,并执行

    • chmod +x hello

    • ./hello

      树莓派第一次开机,树莓派,树莓派

      运行成功

五、基于树莓派的OpenEuler内核模块基础实验

1. Linux内核模块

内核模块就是实现了某个功能的一段内核代码,在内核运行过程中,可以加载这部分代码到内核中,从而动态地增加了内核的功能。Linux引入内核模块这一机制,当需要修改、增加内核某个功能时,不再需要重新编译一遍整个内核,只需要编译相关某一段功能代码即内核模块,再加载到内核中即可,避免内核变得臃肿,实现灵活增减。

一些常用模块指令
  • 加载内核模块

    lsmod xx.ko

  • 卸载内核模块

    rmmod xx.ko

  • 列出当前内核中已经加载的内核模块

    lsmod查看全部内核模块

    lsmod | grep xx 查看指定内核模块

  • 查看内核模块的相关信息

    modinfo xx.ko

  • 显示模块打印信息

    dmesg或者dmesg | tail -n 5查看最后5行信息

2. 第一个内核模块helloworld

(1)编写代码和生成hello内核模块
  • 创建文件hello.c

    • vi hello.c
    • i进入编辑模式,输入或者复制以下内容
    #include <linux/init.h>
    #include <linux/module.h>
    
    static int hello_init(void)
    {
        printk("Hello, openEuler Embedded!\r\n");
        return 0;
    }
    
    static void hello_exit(void)
    {
        printk("Byebye!");
    }
    
    module_init(hello_init);
    module_exit(hello_exit);
    
    MODULE_LICENSE("GPL");
    
    • Esc进入命令行模式,按:wq保存退出
  • 编写Makefile,和hello.c文件放在同一个目录,方法同上

    Makefile是用来执行一组操作的特殊文件,其中最重要的操作是程序的编译。

    • vi Makefile
    KERNELDIR := ${KERNEL_SRC}
    CURRENT_PATH := $(shell pwd)
    
    target := hello
    obj-m := $(target).o
    
    build := kernel_modules
    
    kernel_modules:
            $(MAKE) -C $(KERNELDIR) M=$(CURRENT_PATH) modules
    clean:
            $(MAKE) -C $(KERNELDIR) M=$(CURRENT_PATH) clean
    

KERNEL_SRC 为SDK中内核源码树的目录,该变量在安装SDK后会被自动设置。

  • make指令用于执行Makefile,构建模块

    make

    树莓派第一次开机,树莓派,树莓派

(2)将编译好的hello.ko拷贝到openEuler Embedded系统中
  • 加载模块

    insmod hello.ko

  • 查看加载的内容

    dmesg | tail -n 2

    树莓派第一次开机,树莓派,树莓派

  • 模块的卸载及查看

    rmmod hello

    dmesg | tail -n 1

(3)原理

重新回顾hello.c,通过insmod加载helloworld.ko内核模块时,自动执行module_init()函数,该函数输出Hello, openEuler Embedded!

执行rmmod卸载内核模块helloworld.ko时,会自动执行hello_exit()函数,该函数输出Byebye!文章来源地址https://www.toymoban.com/news/detail-637340.html

到了这里,关于树莓派第一次开机的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 新学期第一次课

    在信息化飞速发展的今天,大数据技术的应用日益广泛,其重要性也日益凸显。对于大数据学院的同学来说,掌握行业前沿技术是至关重要的。本篇文章将详细指导同学们如何加入QQ群、云班课,并学会使用思维导图和CSDN博客。 我们有两个QQ群,分别是2021计应1班行业前沿技

    2024年02月10日
    浏览(25)
  • python 第一次作业

    因为笔者有一些 c/c++ 语言的基础,所以应该学 python 会稍微简单一些 输入的时候所有的输入都是字符串类型,我们需要进行类型转换 参见资源里面的第三题和第四题,为了方便起见,直接把代码贴在下面

    2024年03月25日
    浏览(36)
  • docker第一次作业

    docker第一次作业 1.安装docker服务,配置镜像加速器  yum install -y yum-utils device-mapper-persistent-data lvm2 y um-config-manager --add-repo https: //mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo sed -i \\\'s+download.docker.com+mirrors.aliyun.com/docker-ce+\\\'  /etc/yum.repos.d/docker-ce.repo yum makecache fast yum -y install docke

    2024年02月12日
    浏览(30)
  • jQuery第一次接触

    jQuery是一个轻量级js库 1.下载jquery库,网址Download jQuery | jQuery npm i jquery 2.还可以从cdn中载入jquery script src=\\\"https://cdn.staticfile.org/jquery/1.10.2/jquery.min.js\\\" 3.j代表js,query代表查询,jQuery可以进行查询的js语言,主要用来查询html元素 4.基础语法$(selector).action(),其中selector代表要进行操

    2024年02月12日
    浏览(30)
  • 第一次PR经历

         

    2024年02月13日
    浏览(28)
  • 第一次作业

    作业内容:1,atd和crond的区别                   2,指定在2023/08/26 09:00将时间写入testmail.txt文件中                   3,指定在每天凌晨4:00将该时间点之前的系统日志信息备份到个目录下(/var/log/messages ),备份后日志文件名显示格式logfileYY-MM-DD HH-MM 1、运行方式不同

    2023年04月20日
    浏览(33)
  • 第一次面试复盘

    这个秋招到目前为止第一次拿到了面试机会,虽然是小公司,但是人家是有官网的!!!很爱!先赶紧复盘一下,因为还有很多笔试没有复盘。 你们的数学建模解决了什么问题?你觉得你们为什么能拿到这个成绩 说下对java这门语言的了解 它是一种面向对象的编程语言,所以

    2024年01月22日
    浏览(31)
  • 网络安全第一次作业

    1、什么是防火墙 防火墙是一种网络安全系统,它根据预先确定的安全规则监视和控制传入和传出的网络流量。其主要目的是阻止对计算机或网络的未经授权的访问,同时允许合法通信通过。 防火墙可以在硬件、软件或两者的组合中实现,并且可以配置为根据各种条件(如

    2024年02月07日
    浏览(35)
  • Python第一次作业练习

     输入:101 -成绩不及格/输入错误(超过100)​ 输入:87 -成绩良好      

    2024年02月09日
    浏览(28)
  • java第一次作业(一)

    知识点: 考查java的输入格式以及for循环 java格式 注意Main与main 代码: 知识点: for循环 数组 /输入数组 /数组比大小 代码: 知识点: println与print区别:println是输完之后转行 重点: 多重for循环 代码: 知识点: 调用函数 booean函数 重点: Scanner输入 代码: 知识点: 最后又有

    2024年03月25日
    浏览(42)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包