网站维护有多长时间/搭建网站的软件

网站维护有多长时间,搭建网站的软件,pvc建筑模板生产厂家,红色企业网站源码基于I.MX6ULL-MINI开发板 LED学习GPIO应用编程输入设备 开发板中所有的设备(对象)都会在/sys/devices 体现出来,是 sysfs 文件系统中最重要的目录结构 /sys下的子目录说明/sys/devices这是系统中所有设备存放的目录,也就是系统中…

基于I.MX6ULL-MINI开发板

  • LED学习
  • GPIO应用编程
  • 输入设备

开发板中所有的设备(对象)都会在/sys/devices 体现出来,是 sysfs 文件系统中最重要的目录结构

/sys下的子目录说明
/sys/devices这是系统中所有设备存放的目录,也就是系统中的所有设备在 sysfs 中的呈现、表达,也是 sysfs 管理设备的最重要的目录结构。
/sys/block块设备的存放目录,这是一个过时的接口,按照 sysfs 的设计理念,系统所有的设备都存放在/sys/devices 目录下,所以/sys/block 目录下的文件通常是链接到/sys/devices 目录下的文件。
/sys/bus这是系统中的所有设备按照总线类型分类放置的目录结构,/sys/devices 目录下每一种设备都是挂在某种总线下的,譬如 i2c 设备挂在 I2C 总线下。同样,/sys/bus 目录下的文件通常也是链接到了/sys/devices 目录。
/sys/class这是系统中的所有设备按照其功能分类放置的目录结构,同样该目录下的文件也是链接到了/sys/devices 目录。按照设备的功能划分组织在/sys/class 目录下,譬如/sys/class/leds目录中存放了所有的 LED 设备,/sys/class/input 目录中存放了所有的输入类设备。
/sys/dev这是按照设备号的方式放置的目录结构,同样该目录下的文件也是链接到了/sys/devices 目录。该目录下有很多以主设备号:次设备号(major:minor)命名的文件,这些文件都是链接文件,链接到/sys/devices 目录下对应的设备。
/sys/firmware描述了内核中的固件。
/sys/fs用于描述系统中所有文件系统,包括文件系统本身和按文件系统分类存放的已挂载点。
/sys/kernel这里是内核中所有可调参数的位置。
/sys/module这里有系统中所有模块的信息。
/sys/power这里是系统中电源选项,有一些属性可以用于控制整个系统的电源状态。

应用层想要对底层硬件进行操控,通常可以通过两种方式

  1. /dev/目录下的设备文件(设备节点);
  2. /sys/目录下设备的属性文件。

LED学习

led设备路径

/sys/class/leds/sys-led

在这里插入图片描述

brightness:LED亮度,可读可写,0亮,非0灭
max_brightness:LED最大亮度,只读
trigger:触发模式,可读可写,模式如下:
none(无触发)、mmc0(当对 mmc0 设备发起读写操作的时候 LED 会闪烁)、timer(LED 会有规律的一亮一灭,被定时器控制住)、heartbeat(心跳呼吸模式,LED 模仿人的心跳呼吸那样亮灭变化)。

代码

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>#define LED_TRIGGER "/sys/class/leds/sys-led/trigger"
#define LED_BRIGHTNESS "/sys/class/leds/sys-led/brightness"
/*
在 C 语言中,反斜杠 \ 的作用是 行连接符(line continuation character)。
它允许你在多个行中编写一条连续的语句,而不需要写成一行。
具体来说,反斜杠告诉编译器:下一行是当前行的延续,继续合并在一起,而不加上额外的换行符。
*/
#define USAGE()     fprintf(stderr,"usage:\n" \"    %s<on|off>\n"   \"    %s<trigger><type>\n",argv[0],argv[0])  //argv[0]存放程序的名称或路径int main(int argc, char *argv[])//argc参数个数,argv[]参数
{int fd1, fd2;//校验传参if(2>argc){USAGE();return 1;}// 打开sysfs中的trigger和brightness文件fd1 = open(LED_TRIGGER, O_RDWR);if (0 > fd1) {perror("open LED_TRIGGER error");return 1;}fd2 = open(LED_BRIGHTNESS, O_RDWR);if (0 > fd2) {perror("open LED_BRIGHTNESS error");close(fd1);return 1;}//根据传参控制LEDif(!strcmp(argv[1],"on")){//判断传入的第一个参数是否是onwrite(fd1,"none",4);//往trigger写入none,共4个字节,trigger设置为无触发write(fd2,"1",1);//点亮LED}else if(!strcmp(argv[1],"off")){//判断传入的第一个参数是否是offwrite(fd1,"none",4);write(fd2,"0",1);//熄灭LED}else if(!strcmp(argv[1],"trigger")){//如果传入的第一个参数是trigger但是参数个数不是三个,提示用法if(3!=argc){USAGE();return 1;}if(0 > write(fd1,argv[2],strlen(argv[2]))){//判断写入是否正确,将第三个参数即触发模式传给fd1 (none、mmc0、timer、heartbeat)perror("write error");return 1;}}elseUSAGE();return 0;
}

在这里插入图片描述

GPIO应用编程

GPIO目录

/sys/class/gpio

一共包含了 5 个 GPIO控制器,分别为 GPIO1、GPIO2、GPIO3、GPIO4、GPIO5,在这里分别对应 gpiochip0、gpiochip32、gpiochip64、gpiochip96、gpiochip128 这 5 个文件夹,每一个 gpiochipX 文件夹用来管理一组 GPIO

在这里插入图片描述
每一个gpiochipX文件夹里面有以下内容

在这里插入图片描述

base:与 gpiochipX 中的 X 相同,表示该控制器所管理的这组 GPIO 引脚中最小的编号,如gpiochip32的base就是32
label:该组 GPIO 对应的标签,也就是名字
ngpio:该控制器所管理的 GPIO 引脚的数量,引脚编号范围是:base ~ base+ngpio-1

GPIO5_IO10在sysfs中对应的编号:128+10=138

export

export:用于将指定编号的 GPIO 引脚导出。在使用 GPIO 引脚之前,需要将其导出,导出成功之后才能使用它。注意 export 文件是只写文件,不能读取,将一个指定的编号写入到 export 文件中即可将对应的 GPIO 引脚导出

如下图,这个文件夹就是导出来的 GPIO 引脚对应的文件夹,用于管理、控制该 GPIO 引脚

在这里插入图片描述

unexport

unexport:将导出的 GPIO 引脚删除。当使用完 GPIO 引脚之后,我们需要将导出的引脚删除,同样该文件也是只写文件、不可读

在这里插入图片描述

gpioX文件夹里的文件
在这里插入图片描述

direction:配置 GPIO 引脚为输入或输出模式。该文件可读、可写,读表示查看 GPIO 当前是输入还是输出模式,写表示将 GPIO 配置为输入或输出模式;读取或写入操作可取的值为"out"(输出模式)和"in"(输入模式)
在这里插入图片描述
value:在 GPIO 配置为输出模式下,向 value 文件写入"0"控制 GPIO 引脚输出低电平,写入"1"则控制 GPIO 引脚输出高电平。在输入模式下,读取 value 文件获取 GPIO 引脚当前的输入电平状态。
active_low:这个属性文件用于控制极性,可读可写,默认情况下为 0,如果设置为1,则逻辑1为低电平,逻辑0为高电平
edge:控制中断的触发模式,该文件可读可写。在配置 GPIO 引脚的中断触发模式之前,需将其设置为输入模式
非中断引脚echo "none" > edge
上升沿触发echo "rising" > edge
下降沿触发echo "falling" > edge
边沿触发 echo "both" > edge

输出代码

#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>static char gpio_path[100];//存放gpio设备文件路径//修改GPIO的状态
static int gpio_config(const char *attr, const char *value)//attr:修改的选项(direction、active_value、value)value:传入的值
{char file_path[100];int fd;int len;sprintf(file_path, "%s/%s", gpio_path, attr);//将/sys/class/gpio/gpiox/(direction或active_value或value)传给file_pathif(0 > (fd = open(file_path,O_WRONLY))){perror("open error");return fd;}len = strlen(value);if(len!= write(fd,value,len))//向file_path写入value,即修改gpio的状态{perror("write error");close(fd);return 1;}close(fd);return 0;
}int main(int argc, char *argv[])
{//判断传参是否正确if(3!=argc){fprintf(stderr,"usage: %s<gpio><value>\n", argv[0]);return 1;}//判断gpiox文件是否导出sprintf(gpio_path,"/sys/class/gpio/gpio%s",argv[1]);if(access(gpio_path,F_OK))//判断路径是否存在,不存在则创建,F_OK参数用于判断文件是否存在{int fd;int len;if(0 > (fd = open("/sys/class/gpio/export",O_WRONLY)))//打开export文件并将路径存放在fd,准备写入{perror("open error");return 1;}len = strlen(argv[1]);if(len != write(fd,argv[1],len))//向export写入gpio号,即导出gpio文件{perror("write error");close(fd);return 1;}close(fd);//关闭文件}//修改gpio的状态if(gpio_config("direction","out"))//配置为输出模式{return 1;}if(gpio_config("active_low","0"))//默认极性{return 1;}if(gpio_config("value",argv[2]))//控制GPIO高低电平{return 1;}//退出程序return 0;}

中断输入代码

#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
#include <poll.h>static char gpio_path[100];//存放gpio设备文件路径//修改GPIO的状态
static int gpio_config(const char *attr, const char *value)//attr:修改的选项(direction、active_low、value)value:传入的值
{char file_path[100];int fd;int len;sprintf(file_path, "%s/%s", gpio_path, attr);//将/sys/class/gpio/gpiox/(direction或active_low或value)传给file_pathif(0 > (fd = open(file_path,O_WRONLY))){perror("open error");return fd;}len = strlen(value);if(len!= write(fd,value,len))//向file_path写入value,即修改gpio的状态{perror("write error");close(fd);return 1;}close(fd);return 0;
}int main(int argc, char *argv[])
{struct pollfd pfd;//用于poll调用来监视文件描述符的事件,记得包含头文件poll.hchar file_path[100];//存储/sys/class/gpio/gpiox/value的路径int ret;            //poll函数的返回值char value;         //从GPIO引脚读取的值//判断传参是否正确if(2!=argc){fprintf(stderr,"usage: %s<gpio> <value>\n", argv[0]);return 1;}//判断gpiox文件是否导出sprintf(gpio_path,"/sys/class/gpio/gpio%s",argv[1]);if(access(gpio_path,F_OK))//判断路径是否存在,不存在则创建,F_OK参数用于判断文件是否存在{int fd;int len;if(0 > (fd = open("/sys/class/gpio/export",O_WRONLY)))//打开export文件并将路径存放在fd,准备写入{perror("open error");return 1;}len = strlen(argv[1]);if(len != write(fd,argv[1],len))//向export写入gpio号,即导出gpio文件{perror("write error");return 1;}close(fd);//关闭文件}//修改gpio的状态if(gpio_config("direction","in"))//配置为输入模式{return 1;}if(gpio_config("active_low","0"))//默认极性{return 1;}if(gpio_config("edge","both"))//设置中断触发方式,both是边沿触发{return 1;}//打开value属性文件sprintf(file_path,"%s/%s",gpio_path,"value");if(0 > (pfd.fd = open(file_path,O_RDONLY)))//用pfd.fd存储vlaue的文件路径{perror("open error");return 1;}/*调用pollstruct pollfd{int fd;         //文件描述符short events;   //等待的事件short revents;  //返回的事件}*/pfd.events = POLLPRI;//只关心高优先级数据可读(中断)read(pfd.fd,&value, 1);//在进入循环之前,先读取一次GPIO状态,以清除先前的状态for( ; ; ){ret = poll(&pfd,1,-1);//调用poll,阻塞直到事件发生if(0 > ret){perror("poll error");return 1;}else if(0 == ret){fprintf(stderr,"poll timeout.\n");continue;}//校验高优先级数据是否可读if(pfd.revents & POLLPRI){if(0 > lseek(pfd.fd,0,SEEK_SET))//使用lseek重置文件指针,确保每次读取最新的GPIO状态{perror("lseek error");return 1;}if(0 > read(pfd.fd,&value,1)){perror("read error");return 1;}printf("gpio中断触发<value=%c\n",value);}}//退出程序return 0;
}

poll函数复习

int poll(struct pollfd *fds, nfds_t nfds, int timeout);
/*
fds:指向一个 struct pollfd 类型的数组,储存关心的文件描述符
nfds:fds数组中元素的个数
timeout:决定poll函数的阻塞行为-1:一直阻塞,直到有信号来0:不阻塞>0:阻塞时间上限
*///struct pollfd 结构体
struct pollfd {int fd;        /* 文件描述符 */short events;  /* 等待的事件 */short revents; /* 返回的事件 */
};

在这里插入图片描述

输入设备

读取输入设备时,应用程序打开输入设备对应的设备文件,向其发起读操作,每一次 read 操作获取的都是一个 structinput_event 结构体类型数据,该结构体定义在<linux/input.h>头文件中

struct input_event {struct timeval time;__u16 type;		//描述发生了哪一种类型的时间__u16 code;		//该类事件具体是哪个事件,如键盘上不同的按键1、2、3...__s32 value;		
/*
内核每次上报事件都会向应用层发送一个数据 value,对 value 值的解释随着 code 的变化而变化。譬如对于按键事件(type=1)来说,如果 code=2(键盘上的数字键 1,也就是 KEY_1),那么如果 value 等于 1,则表示 KEY_1 键按下;value 等于 0 表示 KEY_1 键松开,如果 value 等于 2则表示 KEY_1 键长按。再比如,在绝对位移事件中(type=3),如果 code=0(触摸点 X 坐标 ABS_X),那么 value 值就等于触摸点的 X 轴坐标值;同理,如果 code=1(触摸点 Y 坐标 ABS_Y),此时value 值便等于触摸点的 Y 轴坐标值;所以对 value 值的解释需要根据不同的 code 值而定
*/
};

type
在这里插入图片描述

code
Key

在这里插入图片描述

相对位移

在这里插入图片描述

绝对位移

在这里插入图片描述

通过数据同步使得应用程序得知本轮已经读取到完整的数据同步类事件有如下,所有的输入设备都需要上报同步事件,上报的同步事件通常是SYN_REPORT,而 value 值通常为 0
在这里插入图片描述

查看输入设备是哪个设备节点

cat /proc/bus/input/devices

在这里插入图片描述

输入设备代码

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <linux/input.h>int main(int argc, char *argv[])
{struct input_event in_ev = {0};int fd = -1;int value = -1;//校验传参if(2 != argc){fprintf(stderr, "Usage: %s <input_dev>\n", argv[0]);return 1;}// 打开输入事件文件if(0 > (fd = open(argv[1], O_RDONLY))){perror("open error");return 1;}for( ; ; ){// 读取输入事件if(sizeof(struct input_event) != (read(fd, &in_ev, sizeof(struct input_event)))){perror("read error");break;}// 按键输入的类型if(EV_KEY == in_ev.type){switch (in_ev.value){case 0:printf("code<%d>:松开\n", in_ev.code);break;case 1:printf("code<%d>:按下\n", in_ev.code);break;  case 2:printf("code<%d>:长按\n", in_ev.code);break;                       }}}
}

开发板KEY0按键测试

在这里插入图片描述
键盘测试

接入键盘,我使用的是2.4G连接方式
在这里插入图片描述

查看设备时发现有两个

在这里插入图片描述

event3是键盘上的按键

在这里插入图片描述

event4是键盘上的旋钮
由此可知这两个东西不是同一个设备

在这里插入图片描述

鼠标测试

在这里插入图片描述
在这里插入图片描述

只能读取鼠标的左、右和滚轮的按下和松开

在这里插入图片描述

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

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

相关文章

递归、搜索与回溯第四讲:floodfill算法

递归、搜索与回溯第四讲&#xff1a;floodfill算法 1.Floodfill算法介绍2.图像渲染3.岛屿数量4.岛屿的最大面积5.被围绕的区域6.太平洋大西洋水流问题7.扫雷游戏8.衣橱整理 1.Floodfill算法介绍 2.图像渲染 3.岛屿数量 4.岛屿的最大面积 5.被围绕的区域 6.太平洋大西洋水流问题…

【深度学习与实战】2.3、线性回归模型与梯度下降法先导案例--最小二乘法(向量形式求解)

为了求解损失函数 对 的导数&#xff0c;并利用最小二乘法向量形式求解 的值‌ 这是‌线性回归‌的平方误差损失函数&#xff0c;目标是最小化预测值 与真实值 之间的差距。 ‌损失函数‌&#xff1a; 考虑多个样本的情况&#xff0c;损失函数为所有样本的平方误差之和&a…

气象可视化卫星云图的方式:方法与架构详解

气象卫星云图是气象预报和气候研究的重要数据来源。通过可视化技术,我们可以将卫星云图数据转化为直观的图像或动画,帮助用户更好地理解气象变化。本文将详细介绍卫星云图可视化的方法、架构和代码实现。 一、卫星云图可视化方法 1. 数据获取与预处理 卫星云图数据通常来源…

实现极限网关(INFINI Gateway)配置动态加载

还在停机更新 Gateway 配置&#xff0c;OUT 了。 今天和大家分享一个 Gateway 的功能&#xff1a;动态加载配置&#xff08;也称热更新或热加载&#xff09;。 这个功能可以在 Gateway 不停机的情况下更新配置并使之生效。 配置样例如下&#xff1a; path.data: data path.…

Day15 -实例 端口扫描工具 WAF识别工具的使用

一、端口扫描工具 1、zenmap 我这里user是汉字名&#xff0c;没有解析成功。等后续换一个英文账户试一试。 魔改kali的nmap nmap -p8000-9000 8.140.159.19 2、masscan cmd启动&#xff0c;拖入exe文件。然后先写ip&#xff0c;会报错给提示 寻路犬系统 我们去找一下他的…

如何解决高并发场景下的性能瓶颈?实践分享

解决高并发性能瓶颈的核心方法包括优化系统架构、合理使用缓存技术、数据库优化及扩展策略、负载均衡设计。 其中&#xff0c;优化系统架构是根本解决性能问题的关键所在。良好的系统架构能够有效支撑业务高效稳定运行&#xff0c;避免性能瓶颈带来的损失。企业可通过微服务架构…

性能测试、负载测试、压力测试的全面解析

在软件测试领域&#xff0c;性能测试、负载测试和压力测试是评估系统稳定性和可靠性的关键手段。​它们各自关注不同的测试目标和应用场景&#xff0c;理解这些差异对于制定有效的测试策略至关重要。 本文对性能测试、负载测试和压力测试进行深入分析&#xff0c;探讨其定义、…

学习本地部署DeepSeek的过程(基于LM Studio)

除了使用Ollama部署DeepSeek&#xff0c;还可以使用LM Studio部署DeepSeek&#xff0c;后者是一款允许用户在本地计算机上运行大型语言模型&#xff08;LLMs&#xff09;的桌面应用程序&#xff0c;旨在简化本地模型的使用&#xff0c;无需云端连接或复杂配置即可体验 AI 功能。…

等差数列公式推导

前言&#xff1a; 通过实践而发现真理&#xff0c;又通过实践而证实真理和发展真理。从感性认识而能动地发展到理性认识&#xff0c;又从理性认识而能动地指导革命实践&#xff0c;改造主观世界和客观世界。实践、认识、再实践、再认识&#xff0c;这种形式&#xff0c;循环往…

【MySQL】用户账户、角色、口令、PAM

目录 查看用户账户设置 连接 1.本地连接 2.远程连接 账户 角色 操作用户账户和角色 配置口令和账户有效期限 手工使口令过期 配置口令有效期限 PAM身份验证插件 客户端连接&#xff1a;使用 PAM 账户登录 在连接到MySQL服务器并执行查询时&#xff0c;会验证你的身…

5种生成模型(VAE、GAN、AR、Flow 和 Diffusion)的对比梳理 + 易懂讲解 + 代码实现

目录 1 变分自编码器&#xff08;VAE&#xff09;​ 1.1 概念 1.2 训练损失 1.3 VAE 的实现 2 生成对抗网络&#xff08;GAN&#xff09;​ 2.1 概念 2.2 训练损失 a. 判别器的损失函数 b. 生成器的损失函数 c. 对抗训练的动态过程 2.3 GAN 的实现 3 自回归模型&am…

印刷电路板 (PCB) 的影响何时重要?在模拟环境中导航

我和我的同事们经常被问到关于 PCB 效应的相同问题&#xff0c;例如&#xff1a; 仿真何时需要 PCB 效果&#xff1f; 为什么时域仿真需要 PCB 效应&#xff1f; 当 PCB 效应必须包含在仿真中时&#xff0c;频率是否重要&#xff1f; 设计人员应该在多大程度上关注 VRM 模型中包…

2024跨境电商挑战:AI反检测技术在避免封号中的作用

2024跨境电商挑战&#xff1a;AI反检测技术在避免封号中的作用 跨境电商的浪潮席卷全球&#xff0c;为商家打开了通往世界各地的大门。然而&#xff0c;随着平台监管的加强&#xff0c;合规性问题成为商家不得不面对的挑战。在电商平台的严格监控下&#xff0c;任何违规行为都…

网络运维学习笔记(DeepSeek优化版) 024 HCIP-Datacom OSPF域内路由计算

文章目录 OSPF域内路由计算&#xff1a;单区域的路由计算一、OSPF单区域路由计算原理二、1类LSA详解2.1 1类LSA的作用与结构2.2 1类LSA的四种链路类型 三、OSPF路由表生成验证3.1 查看LSDB3.2 查看OSPF路由表3.3 查看全局路由表 四、2类LSA详解4.1 2类LSA的作用与生成条件4.2 2…

多智能体融合(Multi-Agent Fusion)

多智能体融合&#xff08;Multi-Agent Fusion&#xff09;是指在多智能体系统&#xff08;MAS, Multi-Agent System&#xff09;中&#xff0c;多个智能体&#xff08;Agent&#xff09;通过协作、竞争或共享信息&#xff0c;实现全局最优的智能决策和任务执行。该方法广泛应用…

[学习笔记]NC工具安装及使用

工具简介 Netcat&#xff08;简称 nc&#xff09;是一款强大的命令行网络工具&#xff0c;被称作瑞士军刀&#xff0c;用来在两台机器之间建立 TCP/UDP 连接&#xff0c;并通过标准的输入输出进行数据的读写&#xff0c;大家也可以使用Nmap&#xff08;增强版nc工具&#xff0…

SvelteKit 最新中文文档教程(11)—— 部署 Netlify 和 Vercel

前言 Svelte&#xff0c;一个语法简洁、入门容易&#xff0c;面向未来的前端框架。 从 Svelte 诞生之初&#xff0c;就备受开发者的喜爱&#xff0c;根据统计&#xff0c;从 2019 年到 2024 年&#xff0c;连续 6 年一直是开发者最感兴趣的前端框架 No.1&#xff1a; Svelte …

【Unity】 HTFramework框架(六十三)SerializableDictionary可序列化字典

更新日期&#xff1a;2025年3月26日。 Github 仓库&#xff1a;https://github.com/SaiTingHu/HTFramework Gitee 仓库&#xff1a;https://gitee.com/SaiTingHu/HTFramework 索引 一、SerializableDictionary可序列化字典1.使用SerializableDictionary2.实现思路 二、Serializ…

斜对角线的应用

引入 题目描述 经典应用&#xff1a;八皇后问题 dg和udg数组的解释 对角线 d g [ u i ] d g [ u i ] dg[ui]dg[ui] dg[ui]dg[ui]&#xff0c;反对角线 u d g [ n − u i ] u d g [ n − u i ] udg[n−ui]udg[n−ui] udg[n−ui]udg[n−ui]中的下标 u i ui ui和 n − …

STM32学习笔记之存储器映射(原理篇)

&#x1f4e2;&#xff1a;如果你也对机器人、人工智能感兴趣&#xff0c;看来我们志同道合✨ &#x1f4e2;&#xff1a;不妨浏览一下我的博客主页【https://blog.csdn.net/weixin_51244852】 &#x1f4e2;&#xff1a;文章若有幸对你有帮助&#xff0c;可点赞 &#x1f44d;…