当前位置: 首页 > news >正文

Centos7 docker 容器内root身份应用自启动 /usr/sbin/init 问题


Centos7 docker 容器内root身份应用自启动 & /usr/sbin/init 问题

环境:我在一个 docker 容器内手动安装了 mysql、nginx、autotestsystem(自己的服务);
mysql 和 nginx 都做了服务脚本:mysqld.service、nginx.service,并设置了开机自启动:
systemctl enable mysqld.service
systemctl enable nginx.service

vi mysqld.service


vi nginx.service

自己的应用位置:
/opt/AutoTestSystem/ui/              #前端,前端用的nginx
/opt/AutoTestSystem/server/          #后端,后端用的python flask
/opt/AutoTestSystem/server/start.sh  #后端服务启动脚本
/opt/AutoTestSystem/server/stop.sh   #后端服务停止脚本
ln -s /opt/AutoTestSystem/server/start.sh /usr/bin/autotestsystem-start
ln -s /opt/AutoTestSystem/server/stop.sh /usr/bin/autotestsystem-stop

# cat /opt/AutoTestSystem/server/start.sh 
#!/bin/sh

pid=$(ps aux |grep  "python3 main.py" |grep -v "grep" | awk '{print $2}')
echo $pid
if [ -n "$pid" ]; then
  echo "WARNNING: main.py already is running, need not run again!"
  exit
fi

# start server
pushd /opt/AutoTestSystem/server  2>&1 >/dev/null
$(nohup python3 main.py >> log &)
sleep 2

pid=$(ps aux |grep  "python3 main.py" |grep -v "grep" | awk '{print $2}')
if [ -z "$pid" ]; then
 echo "ERROR: start failed!"
else
 echo "SUCCESS: start success!"
fi
popd 2>&1 >/dev/null

# cat /opt/AutoTestSystem/server/stop.sh  
#!/bin/sh

#pid=$(ps aux |grep  "python3 main.py" |grep -v "grep" | awk '{print $2}')
pid=$(ps aux |grep  "/opt/AutoTestSystem/server/main.py" |grep -v "grep" | awk '{print $2}')

if [ -z "$pid" ]; then
 echo "INFO: main.py is not running"
 exit
fi 

echo "INFO: to stop main.py, pid is: $pid"
$(kill -9 $pid)
sleep 3

pid2=$(ps aux |grep  "python3 main.py" |grep -v "grep" | awk '{print $2}')
if [ -n "$pid2" ]; then
 echo "ERROR: stop $pid2 failed!"
else
 echo "SUCCESS: stop $pid2 success!"
fi

执行docker commit保存持久化:

docker commit -a "hrf" -m "autotestsystem 1.0" 478394f89173 autotestsystem:1.0

注意:docker commit 时如果指定的 REPOSITORY:TAG 变化则会生成新的image,如果不变则不会生成新的image、只会合并,docker image查看会多出 REPOSITORY和TAG未空 <none> 的 IMAGE ID,这种是可以删除的(docker rmi IMAGE_ID)。

创建build目录 & Dockerfile & init_ats启动脚本,执行 docker build 把自启动脚本打包到容器里面去并设置自启动:

cd build

vi Dockerfile
FROM autotestsystem:1.0
WORKDIR /opt/AutoTestSystem
COPY init_ats /usr/bin/
RUN chmod +x /usr/bin/init_ats
ENTRYPOINT init_ats
LABEL user="hrf"
USER root

vi init_ats
#!/bin/bash
/usr/sbin/init
sleep 2
/usr/bin/autotestsystem-start


docker build -t autotestsystem:1.0 .
docker images
docker run -idt --name autotest2 -p 29090:8080 -p 23306:3306 -p 29000:80 --privileged --cap-add SYS_ADMIN --restart=always autotestsystem:1.0 

也尝试过docker run是传参替换: 
docker run -idt --name autotest2 -p 29090:8080 -p 23306:3306 -p 29000:80 --privileged --cap-add SYS_ADMIN --restart=always autotestsystem:1.0 /usr/sbin/init

docker run -idt --name autotest2 -p 29090:8080 -p 23306:3306 -p 29000:80 --privileged --cap-add SYS_ADMIN --restart=always autotestsystem:1.0 init_ats

docker run -idt --name autotest2 -p 29090:8080 -p 23306:3306 -p 29000:80 --privileged --cap-add SYS_ADMIN --restart=always autotestsystem:1.0 autotestsystem-start
都不行。

执行脚本,还尝试了多种,都不行:
ENTRYPOINT init_ats
ENTRYPOINT ["init_ats"]
ENTRYPOINT ["sh","init_ats"]
ENTRYPOINT ["sh","-c","init_ats"]
ENTRYPOINT autotestsystem-start
CMD init_ats
CMD autotestsystem-start

网上找了很多资料,原因是 root 身份运行docker容器,需要特权,需要加 /usr/sbin/init 运行容器。可是编写 Dockerfile 执行 docker build 的方式,无法支持启动时执行多个脚本或命令,只能执行一个或一条命令,即使写在一个shell脚本中也不行。


最后,换了一个思路,既然mysqld和nginx做成了service服务自启动可以(systemctl enable xxx),那我也尝创建自己应用的.service脚本,做成系统服务自启动。

查看当前容器:
[root@localhost build]# docker ps -a
CONTAINER ID   IMAGE      COMMAND            CREATED        STATUS        PORTS                                                                                                                           NAMES
478394f89173   centos:7   "/usr/sbin/init"   33 hours ago   Up 33 hours   0.0.0.0:9000->80/tcp, :::9000->80/tcp, 0.0.0.0:13306->3306/tcp, :::13306->3306/tcp, 0.0.0.0:9090->8080/tcp, :::9090->8080/tcp   autotest

查看镜像:
[root@localhost build]# docker images
REPOSITORY       TAG       IMAGE ID       CREATED          SIZE
autotestsystem   1.0       a781ff5a15b8   46 minutes ago   1.72GB
centos           7         eeb6ee3f44bd   2 years ago      204MB

容器 478394f89173 是以root运行的,里面的mysqld服务和nginx服务自启正常,但自己服务编写的自启动脚本 init_ats 自启不生效。


接下来,我尝试把我的 autotestsystem 做成系统服务:

进入docker容器:
docker exec -it 478394f89173 /bin/bash

创建.service文件:
[root@478394f89173 system]# vi /lib/systemd/system/autotestsystem.service

[Unit]
Description=autotestsystem
After=network.target
 
[Service]
Type=forking
ExecStart=/opt/AutoTestSystem/server/start.sh
ExecReload=/opt/AutoTestSystem/server/start.sh
ExecStop=/opt/AutoTestSystem/server/stop.sh
PrivateTmp=true
User=root
#Group=root
WorkingDirectory=/opt/AutoTestSystem/server/
RestartSec=2s
 
[Install]
WantedBy=multi-user.target


[root@478394f89173 system]# chmod 754 /lib/systemd/system/autotestsystem.service

[root@478394f89173 system]# systemctl daemon-reload    # 每次修改service后需要刷新生效

[root@478394f89173 system]# systemctl  start autotestsystem.service 
[root@478394f89173 system]# systemctl  enable autotestsystem.service 
Created symlink from /etc/systemd/system/multi-user.target.wants/autotestsystem.service to /usr/lib/systemd/system/autotestsystem.service.
[root@478394f89173 system]# ps aux |grep main.py       #启动服务成功

退出容器、停止容器、启动容器,进入容器,再查看 autotestsystem 能正常自启动:
exit
docker stop 478394f89173
docker start 478394f89173
docker exec -it 478394f89173 /bin/bash
ps aux |grep main.py
 

退出容器,在宿主机下重新 docker build 构建/保存镜像(image),即持久化:
做成.service系统服务了,用不到docker启动脚本,可以直接docker commit持久化、并删除none镜像:
 docker commit -a "hrf" -m "autotestsystem 1.0" 478394f89173 autotestsystem:1.0
 docker rmi `docker images | grep  '<none>' | awk '{print $3}'`

当然如果要使用docker build方式持久化镜像也是可以的。

如果是在宿主机上build目录下直接vi创建和编写的autotestsystem.service服务器脚本(而不是在容器内创建服务脚本和设置自启动),则可以使用docker build方式构建镜像、打脚本包到容器里面去:

cd build

vi autotestsystem.service

[Unit]
Description=autotestsystem
After=network.target
 
[Service]
Type=forking
ExecStart=/opt/AutoTestSystem/server/start.sh
ExecReload=/opt/AutoTestSystem/server/start.sh
ExecStop=/opt/AutoTestSystem/server/stop.sh
PrivateTmp=true
User=root
#Group=root
WorkingDirectory=/opt/AutoTestSystem/server/
RestartSec=2s
 
[Install]
WantedBy=multi-user.target

vi Dockerfile

FROM autotestsystem:1.0
WORKDIR /opt/AutoTestSystem
#COPY  init_ats  /usr/bin/
#RUN  chmod +x /usr/bin/init_ats
#ENTRYPOINT ["init_ats"]
COPY autotestsystem.service /lib/systemd/system/
COPY autotestsystem.service /etc/systemd/system/multi-user.target.wants/
RUN chmod 754 /lib/systemd/system/autotestsystem.service
RUN chmod 754 /etc/systemd/system/multi-user.target.wants/autotestsystem.service
ENTRYPOINT ["/usr/sbin/init"]
LABEL user="hrf"
USER root

说明:
build目录下创建和编写下面2个文件:autotestsystem.service、Dockerfile。
docker build构建时会执行Dockerfile中的COPY命名,COPY是构件阶段执行的。RUN、CMD、ENTRYPOINT命令则是在容器启动阶段执行的。
COPY autotestsystem.service /lib/systemd/system/  这条命令会在docker build构件阶段把build目录下的utotestsystem.service文件拷贝到容器内的/lib/systemd/system/这个目录下。


重新构建:
docker build -t autotestsystem:1.0 . 

[root@localhost build]#  docker build -t autotestsystem:1.0 .
[+] Building 22.0s (11/11) FINISHED                                                                                                  docker:default
 => [internal] load .dockerignore                                                                                                              0.7s
 => => transferring context: 2B                                                                                                                0.0s
 => [internal] load build definition from Dockerfile                                                                                           1.8s
 => => transferring dockerfile: 550B                                                                                                           0.0s
 => [internal] load metadata for docker.io/library/autotestsystem:1.0                                                                          0.0s
 => [1/6] FROM docker.io/library/autotestsystem:1.0                                                                                            6.6s
 => [internal] load build context                                                                                                              0.8s
 => => transferring context: 461B                                                                                                              0.0s
 => [2/6] WORKDIR /opt/AutoTestSystem                                                                                                          0.7s
 => [3/6] COPY autotestsystem.service /lib/systemd/system/                                                                                     1.4s
 => [4/6] COPY autotestsystem.service /etc/systemd/system/multi-user.target.wants/                                                             1.3s
 => [5/6] RUN chmod 754 /lib/systemd/system/autotestsystem.service                                                                             2.3s
 => [6/6] RUN chmod 754 /etc/systemd/system/multi-user.target.wants/autotestsystem.service                                                     2.3s
 => exporting to image                                                                                                                         2.9s
 => => exporting layers                                                                                                                        2.9s
 => => writing image sha256:a1750b9abb21ba65b122edfdf21c37b81896ec68ffbe2f510bfff7ce97e4a95b                                                   0.0s
 => => naming to docker.io/library/autotestsystem:1.0                                                                                          0.1s
[root@localhost build]# 
[root@localhost build]# 
[root@localhost build]# 
[root@localhost build]# docker run -idt --name autotest2 -p 29090:8080 -p 23306:3306 -p 29000:80 --privileged --cap-add SYS_ADMIN --restart=always autotestsystem:1.0 
06ce37919cf068e20fdd676fa51ce1988e3a1d40ba7424d645fd5f561b758a27

[root@localhost build]# 
[root@localhost build]# 
[root@localhost build]# 
[root@localhost build]# 
[root@localhost build]# docker ps -a
CONTAINER ID   IMAGE                COMMAND            CREATED         STATUS         PORTS                                                                                                                               NAMES
06ce37919cf0   autotestsystem:1.0   "/usr/sbin/init"   7 seconds ago   Up 4 seconds   0.0.0.0:29000->80/tcp, :::29000->80/tcp, 0.0.0.0:23306->3306/tcp, :::23306->3306/tcp, 0.0.0.0:29090->8080/tcp, :::29090->8080/tcp   autotest2
478394f89173   centos:7             "/usr/sbin/init"   33 hours ago    Up 33 hours    0.0.0.0:9000->80/tcp, :::9000->80/tcp, 0.0.0.0:13306->3306/tcp, :::13306->3306/tcp, 0.0.0.0:9090->8080/tcp, :::9090->8080/tcp       autotest
[root@localhost build]# 

最后导出、备份镜像文件:

cd release
docker save -o autotestsystem-1.0.tar autotestsystem:1.0
 

相关文章:

Centos7 docker 容器内root身份应用自启动 /usr/sbin/init 问题

Centos7 docker 容器内root身份应用自启动 & /usr/sbin/init 问题 环境&#xff1a;我在一个 docker 容器内手动安装了 mysql、nginx、autotestsystem&#xff08;自己的服务&#xff09;&#xff1b; mysql 和 nginx 都做了服务脚本&#xff1a;mysqld.service、nginx.se…...

STL学习笔记之容器

首先我们要学习的是容器 第一个是容器的初始化&#xff08;构造方式&#xff09;有三种方式 分别是 第一种 int arr[]{1,2,3} vector<int> v1(arr,arr3) 即容器存放的种类和从另外一个数组去拷贝一段数据。 第二种 vector<int> v2(3,10); 第一个3是指存放…...

Java基础---第十二篇

系列文章目录 文章目录 系列文章目录一、获取一个类Class对象的方式有哪些?二、ArrayList 和 LinkedList 的区别有哪些?三、用过 ArrayList 吗?说一下它有什么特点?一、获取一个类Class对象的方式有哪些? 搞清楚类对象和实例对象,但都是对象。 第一种:通过类对象的 get…...

Acwing 841. 字符串哈希

Acwing 841. 字符串哈希 题目描述思路讲解代码展示 题目描述 思路讲解 代码展示 #include <iostream> #include <algorithm>using namespace std;typedef unsigned long long ULL;const int N 100010, P 131; // P 131 或者13331(经验值)int n, m; char str[N]…...

NEON优化:性能优化经验总结

NEON优化&#xff1a;性能优化经验总结 1. 什么是 NEONArm Adv SIMD 历史 2. 寄存器3. NEON 命名方式4. 优化技巧5. 优化 NEON 代码(Armv7-A内容&#xff0c;但区别不大)5.1 优化 NEON 汇编代码5.1.1 Cortex-A 处理器之间的 NEON 管道差异5.1.2 内存访问优化 Reference: NEON优…...

C++ 并发编程实战 第九章

目录 9.1 线程池 9.1.1 最简易可行的线程池 9.1.2 等待提交给线程池的任务完成运行 9.1.3等待其他任务完成的任务 9.1.4 避免任务队列上的争夺 9.1.5 任务窃取 9.2 中断线程 9.2.1 发起一个线程&#xff0c;以及把他中断 9.2.2 检测线程是否被中断 9.2.3 中断条件变…...

【Java】super 关键字用法

目录 this与super区别 1.访问成员变量-示例代码 继承中构造方法的访问特点 2.访问构造方法-示例代码&#xff1a; 继承中成员方法访问特点 3.访问成员方法-示例代码&#xff1a; super 关键字的用法和 this 关键字相似 this : 代表本类对象的引用super : 代表父类存储空间…...

前端笔试题总结,带答案和解析

1. 执行以下程序&#xff0c;输出结果为&#xff08;&#xff09; var x 10; var y 20; var z x < y ? x:y; console.log(xx;yy;zz);A x11;y21;z11 B x11;y20;z10 C x11;y21;z10 D x11;y20;z11 初始化x的值为10&#xff0c;y的值为20&#xff0c;x < y返回结果为tru…...

Omniverse Machinima

Omniverse Machinima App | NVIDIA Omniverse Machinima 是 NVIDIA 推出的一款实时动画创作工具&#xff0c;可用于在虚拟世界中制作和操纵角色及其环境。该工具使用 Universal Scene Description (USD) 作为其通用场景描述格式&#xff0c;可与多种 3D 建模、动画和渲染应用程…...

【测试人生】游戏业务测试落地精准测试专项的一些思路

精准测试在互联网领域有广泛的应用。以变更为出发点&#xff0c;通过对变更内容进行分析&#xff0c;可以确定单次变更具体涉及到哪些模块和功能点&#xff0c;以及是否存在夹带风险&#xff0c;从而从QA的视角&#xff0c;可以知道哪些功能模块需要做测试&#xff0c;以及哪些…...

Redis 数据类型底层原理

String 内部编码有三种&#xff1a;int、embstr、raw int&#xff1a;如果一个字符串对象保存的是整数值&#xff0c;并且这个整数值可以用 long类型来表示(不超过 long 的表示范围&#xff0c;如果超过了 long 的表示范围&#xff0c;那么按照存储字符串的编码来存储&#xf…...

EasyEdge 智能边缘控制台通过sdk发布应用

离线部署SDK生成 模型部署完成后会出现下载SDK的按钮&#xff0c;点击按钮下载SDK并保存好SDK。 进入EasyDL官网的技术文档 安装智能边缘控制台 跟着教程&#xff0c;完成安装&#xff1a;点此链接 树莓派4b是Linux arm64的架构&#xff0c;点击对应的链接进行下载。 下载完成…...

centos软件设置开机启动的方式

以下以redis作为案例&#xff1a; 开机启动方式一 [Unit] Descriptionredis-server Afternetwork.target [Service] Typeforking # 这里需要修改自己的配置文件 ExecStart/usr/local/bin/redis-server /etc/redis/redis.conf PrivateTmptrue [Install] WantedBymulti-user.tar…...

二叉树和堆

二叉树不存在度大于2的结点&#xff08;每个根最多只有两个子结点&#xff09;二叉树的子树有左右之分&#xff0c;次序不能颠倒&#xff0c;因此二叉树是有序树 两个特殊的二叉树——&#xff08;满二叉树&#xff0c;完全二叉树&#xff09; 满二叉树——每个根结点都有左右…...

洛谷P5732 【深基5.习7】杨辉三角题解

目录 题目【深基5.习7】杨辉三角题目描述输入格式输出格式样例 #1样例输入 #1样例输出 #1传送门 代码解释亲测 题目 【深基5.习7】杨辉三角 题目描述 给出 n ( n ≤ 20 ) n(n\le20) n(n≤20)&#xff0c;输出杨辉三角的前 n n n 行。 如果你不知道什么是杨辉三角&#xf…...

Docker 精简安装 Nacos 2.2.1 单机版本

准备工作&#xff1a; 1&#xff09;已安装docker 2&#xff09;数据库准备&#xff0c;演示使用MySql5.7版本 1、拉取 [rootTseng-HW ~]# docker pull nacos/nacos-server:v2.2.1 v2.2.1: Pulling from nacos/nacos-server 2d473b07cdd5: Already exists 77c5a601c050: Pul…...

IntelliJ IDEA配置Cplex12.6.3详细步骤

Cplex12.6.3版IntelliJ IDEA配置详细步骤 一、Cplex12.6.3版下载地址二、Cplex安装步骤三、IDEA配置CPLEX3.1 添加CPLEX安装目录的cplex.jar包到项目文件中3.2 将CPLEX的x64_win64文件夹添加到IDEA的VM options中 四、检查IDEA中Cplex是否安装成功卸载Cplex 一、Cplex12.6.3版下…...

2023 年最佳多 GPU 深度学习系统指南

动动发财的小手&#xff0c;点个赞吧&#xff01; 本文[1]提供了有关如何构建用于深度学习的多 GPU 系统的指南&#xff0c;并希望为您节省一些研究时间和实验时间。 1. GPU 让我们从有趣&#xff08;且昂贵&#xff09;的部分开始&#xff01; 购买 GPU 时的主要考虑因素是&am…...

Kotlin异常处理runCatching,getOrNull,onFailure,onSuccess(1)

Kotlin异常处理runCatching&#xff0c;getOrNull&#xff0c;onFailure&#xff0c;onSuccess&#xff08;1&#xff09; fun main(args: Array<String>) {var s1 runCatching {1 / 1}.getOrNull()println(s1) //s11&#xff0c;打印1println("-")var s2 ru…...

【深入探究人工智能】:历史、应用、技术与未来

深入探究人工智能 前言人工智能的历史人工智能的应用人工智能的技术人工智能的未来当代的人工智能产物结语&#x1f340;小结&#x1f340; &#x1f389;博客主页&#xff1a;小智_x0___0x_ &#x1f389;欢迎关注&#xff1a;&#x1f44d;点赞&#x1f64c;收藏✍️留言 &am…...

【OSG学习笔记】Day 18: 碰撞检测与物理交互

物理引擎&#xff08;Physics Engine&#xff09; 物理引擎 是一种通过计算机模拟物理规律&#xff08;如力学、碰撞、重力、流体动力学等&#xff09;的软件工具或库。 它的核心目标是在虚拟环境中逼真地模拟物体的运动和交互&#xff0c;广泛应用于 游戏开发、动画制作、虚…...

【入坑系列】TiDB 强制索引在不同库下不生效问题

文章目录 背景SQL 优化情况线上SQL运行情况分析怀疑1:执行计划绑定问题?尝试:SHOW WARNINGS 查看警告探索 TiDB 的 USE_INDEX 写法Hint 不生效问题排查解决参考背景 项目中使用 TiDB 数据库,并对 SQL 进行优化了,添加了强制索引。 UAT 环境已经生效,但 PROD 环境强制索…...

Java如何权衡是使用无序的数组还是有序的数组

在 Java 中,选择有序数组还是无序数组取决于具体场景的性能需求与操作特点。以下是关键权衡因素及决策指南: ⚖️ 核心权衡维度 维度有序数组无序数组查询性能二分查找 O(log n) ✅线性扫描 O(n) ❌插入/删除需移位维护顺序 O(n) ❌直接操作尾部 O(1) ✅内存开销与无序数组相…...

【机器视觉】单目测距——运动结构恢复

ps&#xff1a;图是随便找的&#xff0c;为了凑个封面 前言 在前面对光流法进行进一步改进&#xff0c;希望将2D光流推广至3D场景流时&#xff0c;发现2D转3D过程中存在尺度歧义问题&#xff0c;需要补全摄像头拍摄图像中缺失的深度信息&#xff0c;否则解空间不收敛&#xf…...

论文浅尝 | 基于判别指令微调生成式大语言模型的知识图谱补全方法(ISWC2024)

笔记整理&#xff1a;刘治强&#xff0c;浙江大学硕士生&#xff0c;研究方向为知识图谱表示学习&#xff0c;大语言模型 论文链接&#xff1a;http://arxiv.org/abs/2407.16127 发表会议&#xff1a;ISWC 2024 1. 动机 传统的知识图谱补全&#xff08;KGC&#xff09;模型通过…...

Spring Boot面试题精选汇总

&#x1f91f;致敬读者 &#x1f7e9;感谢阅读&#x1f7e6;笑口常开&#x1f7ea;生日快乐⬛早点睡觉 &#x1f4d8;博主相关 &#x1f7e7;博主信息&#x1f7e8;博客首页&#x1f7eb;专栏推荐&#x1f7e5;活动信息 文章目录 Spring Boot面试题精选汇总⚙️ **一、核心概…...

Linux-07 ubuntu 的 chrome 启动不了

文章目录 问题原因解决步骤一、卸载旧版chrome二、重新安装chorme三、启动不了&#xff0c;报错如下四、启动不了&#xff0c;解决如下 总结 问题原因 在应用中可以看到chrome&#xff0c;但是打不开(说明&#xff1a;原来的ubuntu系统出问题了&#xff0c;这个是备用的硬盘&a…...

Spring AI 入门:Java 开发者的生成式 AI 实践之路

一、Spring AI 简介 在人工智能技术快速迭代的今天&#xff0c;Spring AI 作为 Spring 生态系统的新生力量&#xff0c;正在成为 Java 开发者拥抱生成式 AI 的最佳选择。该框架通过模块化设计实现了与主流 AI 服务&#xff08;如 OpenAI、Anthropic&#xff09;的无缝对接&…...

论文笔记——相干体技术在裂缝预测中的应用研究

目录 相关地震知识补充地震数据的认识地震几何属性 相干体算法定义基本原理第一代相干体技术&#xff1a;基于互相关的相干体技术&#xff08;Correlation&#xff09;第二代相干体技术&#xff1a;基于相似的相干体技术&#xff08;Semblance&#xff09;基于多道相似的相干体…...

STM32HAL库USART源代码解析及应用

STM32HAL库USART源代码解析 前言STM32CubeIDE配置串口USART和UART的选择使用模式参数设置GPIO配置DMA配置中断配置硬件流控制使能生成代码解析和使用方法串口初始化__UART_HandleTypeDef结构体浅析HAL库代码实际使用方法使用轮询方式发送使用轮询方式接收使用中断方式发送使用中…...