linux查找设备所在分片,Linux设备驱动统一模型解析

soc节点指定了<0x0 0xe0000000 0x00100000>;此属性值指定对于1024KB范围的地址空间,在物理0x0处寻址的子节点映射到物理0xe0000000的父地址。通过这种映射,串行设备节点可以通过0xe0004600地址的加载或存储、0x4600(在注册表中指定)的偏移量以及范围中指定的0xe0000000映射寻址。

dma-ranges属性名称dma-ranges值类型<empty>或编码为任意数量的(子总线地址、父总线地址、长度)三联体描述dma-range属性用于描述存储器映射总线的直接存储器访问(dma)结构,其设备树父级可以从总线的dma操作访问。它提供了一种定义总线物理地址空间与总线父级物理地址空间之间映射或转换的方法。dma-range属性的值的格式是任意数量的(子总线地址、母线地址、长度)。指定的每个三联体描述连续DMA地址范围。1. 子总线地址是子总线地址空间内的物理地址。表示地址的单元格数取决于总线,可以通过该节点(dma-range属性出现的节点)的#address-cells地址单元格确定。2. 父总线地址是父总线地址空间中的物理地址。表示父地址的单元格数取决于总线,可以通过定义父地址空间的节点的#address-cells属性确定。3. 长度指定子地址空间中范围的大小。表示大小的单元格数量可以根据该节点(dma-range属性出现的节点)的#size-cells确定。Name(已弃用)属性名称name值类型<string>描述name属性用于记录节点名字,name属性已经被弃用 ,不推荐使用 name属性,一些老的设备树文件可能会使用此属性。device_type属性名称device_type值类型<string>描述由于DTS没有FCode,因此不建议使用该属性。只能用于在cpu节点和memory节点中,以便与IEEE 1275衍生设备兼容。1.3.4.基本设备节点类型

所有设备树文件均要包含一个根文件,并且所有设备树文件均应在根节点下存在以下节点:

1个/cpus节点至少一个/memory节点

使用说明:R = 必需,O = 可选,OR = 可选但推荐,SD = 参见定义,所有其他的标准属性均可接受,但可选

1.3.4.1.Root node

devicetree有一个单独的根节点,所有其他设备节点都是它的后代。根节点的完整路径为/。

属性名称使用说明类型定义#address-cellsR<u32>root子节点的reg property地址格式。#size-cellsR<u32>root子节点的reg property大小格式。modelR<string>指定唯一标识。系统板型号。推荐格式为“制造商,型号”compatibleR<stringlist>指定平台体系结构列表。该平台兼容。这一建议可供操作系统在选择平台特定代码时使用。1.3.4.2./aliases节点

设备树文件可能具有一个别名节点(/aliases),该节点定义一个或多个别名属性。别名节点应位于设备树的根节点,并且具有节点名称/别名。/aliases节点的每个属性都定义了一个别名。属性名称指定别名。属性值指定设备树中节点的完整路径。例如,属性serial0 = "/simple-bus@fe000000/serial@llc500"定义了别名serial0。别名的命名规则如下:

字符描述0-9数字a-z小写字母-破折号1.3.4.3./memory节点

所有设备树都需要内存设备节点,并描述系统的物理内存布局。如果系统具有多个范围的内存,则可以创建多个内存节点,或者可以在单个内存节点的reg属性中指定范围。

/memory节点的属性要求如下:

属性名称使用说明类型定义device_typeRO<string>regR<prop-encoded-array>由任意数量的地址和大小对组成,它们指定内存范围的物理地址和大小initial-mapped-areaO<prop-encoded-array>指定”初始映射区域”的地址和大小,是一个由三元组组成的属性编码数组(有效地址、物理地址、大小)。有效和物理地址均应为64位(值),大小应为32位(值)

在xxx.dts中

memory {

reg =  <0x40000000 0x10000000>;   起始地址0x40000000 长度0x10000000(32MB)

};

1.3.4.4./chosen 节点

/chosen 节点不代表系统中的实际设备,而是描述了在运行时由系统固件选择或指定的参数。它应该是根节点的子节点。

属性名称使用说明类型定义bootargsO<string>指定程序的启动参数。如果不需要引导参数,则该值可能为空字符串stdout-pathO<string>指定到表示用于引导控制台输出的设备的节点的完整路径。如果包含’:’,则它将终止路径。该值可以是别名。stdin-pathO<string>指定到表示用于引导控制台输入的设备的节点的完整路径。如果包含’:’,则它将终止路径。该值可以是别名。

示例:

chosen {

bootargs = "root=/dev/nfs rw nfsroot=192.168.1.1 console=ttyS0,115200";

};

1.3.4.5./cpus节点属性

所有设备树均需要/cpus/cpu节点。它并不代表系统中的真实设备,而是作为代表系统cpu的子cpu节点的容器。

属性名称使用说明类型定义device_typeR<string>值应为“cpu”regR<prop-encoded-array>它为CPU节点表示的CPU/线程定义了唯一的CPU/线程ID。如果CPU支持多线程,则reg是一个数组,每个线程具有一个元素。clock-frequencyR<prop-encoded-array>以Hz为单位指定CPU的当前时钟速度,格式可以是,或timebase-frequencyR<prop-encoded-array>指定更新时基的当前频率statusSD<string>此属性应存在于对称多进程(SMP)CPU的节点中 配置。”okay”:CPU正在运行;”disable”:CPU处于静止状态。1.3.5.中断映射

在设备树中,存在逻辑中断树,该逻辑中断树表示平台硬件中断的层次结构和路由。在设备树中,使用interrupt-parent属性表示中断源与中断控制器的物理连线。代表产生中断的设备节点包含一个中断父属性,该属性具有一个虚拟值,指向给设备的中断所路由到的设备(通常是中断控制器)。

如果产生中断的设备不具有中断父属性,则假定其中断父节点为其设备父节点。每个中断产生设备都包含一个中断属性,该属性的值描述该设备的一个或多个中断源。每个源都用称为中断描述符表示。中断描述符的格式和含义是特定于中断域的,即,取决于中断域根节点上节点的属性。中断域的根使用#interrupt-cells属性定义对中断描述符进行编码所需的值数量。

中断域是解释中断描述符的上下文。中断域的根可以是中断控制器(interrupt controller)或中断连接器(interrupt nexus):

中断控制器是物理设备,需要一个驱动程序来处理通过它路由的中断。它还可能级联到另一个中断域。中断控制器由设备树中该节点上的interrupt-controller指定。中断连接器定义了一个中断域和另一个中断域之间的转换。翻译基于特定领域和总线的信息。使用interrupt-map属性在域之间进行转换。例如,PCI控制器设备节点可以是一个中断连接器,定义从PCI中断命名空间(INTA、INTB等)到具有中断请求(IRQ)编号的中断控制器的转换。

b54af6d0392aa2a2a9a91fd6ad03e23c.png

1.3.5.1.Interrupts属性名称interrupts值类型<prop-encoded-array>编码为任意数量的中断描述符描述设备节点的中断属性定义设备生成的中断。interrupts属性的值由任意数量的中断描述符组成。中断描述符的格式由中断域根定义。

示例:

interrupts = <GIC_SPI INT_DMA IRQ_TYPE_LEVEL_HIGH>;

1.3.5.2.interrupt-parent属性名称interrupt-parent值类型<phandle>描述由于中断树中节点的层次结构可能与device tree不匹配,因此interrupt-parent属性可用于明确中断父级的定义。该值是中断父级的phandle。如果设备缺少此属性,则假定其中断父级为其设备树父级。

示例:

interrupt-parent = <&gpe>;

1.3.5.3.interrupts-extended属性名称interrupts-extended值类型<phandle>描述扩展的中断属性列出了设备产生的中断。当设备连接到多个中断控制器时,应该使用interrupts-extended代替interrupts,因为它会在每一个中断描述符编码一个父代phandle

示例:

interrupts-extended = <&pic 0xA 8>, <&gic 0xda>;

1.3.5.4.#interrupt-cells属性名称#interrupt-cells值类型<u32>描述#interrupt-cells属性定义对中断域的中断描述符进行编码所需的单元数量1.3.5.5.interrupt-controller属性名称interrupt-controller值类型<empty>描述中断控制器属性的存在将节点定义为中断控制器节点。1.4.Device Tree binary格式

Devicetree Blob (DTB)格式是Devicetree数据的平面二进制编码。它用来在软件程序之间交换设备数据。例如,在引导操作系统时,固件将向操作系统内核传递一个DTB。

DTB格式将devicetree数据编码为一个单一的、线性的、无指针的数据结构。它由一个小标题组成,接下来是三个大小可变的部分:内存保留块、结构块和字符串块这些应该按照这个顺序出现在扁平的devicetree中。

因此。当按地址加载到内存中时,设备树结构作为一个整体。将类似于图中的图表。

1.4.1.dt_header

设备树的头部是由以下C结构体定义的。所有字段都是32位整数,以big-endian格式存储。

struct fdt_header {

此字段应包含值0xd00dfeed(big-endian)

uint32_t magic;     magic word FDT_MAGIC

此字段应包含设备数据结构的总大小(字节)。该大小应包含结构的所有部分:报头、内存预留块、结构块和字符串块,以及块之间或最终块之后的自由空间间隙。

uint32_t totalsize;    total size of DT block

此字段应包含结构块从标题开始的字节偏移

uint32_t off_dt_struct;    offset to structure

此字段应包含从标题开始的字符串块的字节偏移量

uint32_t off_dt_strings;   offset to strings

此字段应包含从标题开始的内存保留块的字节偏移量

uint32_t off_mem_rsvmap;   offset to memory reserve map

此字段应包含设备数据结构的版本

uint32_t version;    format version

此字段应包含设备所用版本向后兼容的最低版本数据结构

uint32_t last_comp_version;   last compatible version

version 2 fields below

此字段应包含系统引导CPU的物理ID。它应与设备树中CPU节点的reg属性中给定的物理ID相同

uint32_t boot_cpuid_phys;   Which physical CPU id we're booting on

version 3 fields below

此字段应包含字符串块部分的字节长度

uint32_t size_dt_strings;   size of the strings block

version 17 fields below

此字段应包含结构块部分的字节长度

uint32_t size_dt_struct;   size of the structure block

};

1.4.2.memory reservation block

内存保留块向客户端程序提供物理内存中被保留的区域的列表,这些内存不用于一般的内存分配,目的是保护重要的数据结构不被客户端程序覆盖。这个区域包括了若干的reserve memory描述符。每个reserve memory描述符是由address和size组成。其中address和size都是用U64来描述:

struct fdt_reserve_entry {

uint64_t address;

uint64_t size;

};

1.4.3.Structure block

结构块描述了设备树本身的结构和内容。它由若干的分片组成,每个分片开始位置都是保存了令牌(token),以此来描述该分片的属性和内容。

FDT_BEGIN_NODE (0x00000001):该token描述了一个node的开始位置,紧挨着该token的就是node name(包括unit address)FDT_END_NODE (0x00000002):该token描述了一个node的结束位置FDT_PROP (0x00000003):该token描述了一个property的开始位置,该token之后是两个u32的数据。它们之后就是长度为len的具体的属性值数据。struct {

uint32_t len; 表示该property value data的size。

uint32_t nameoff; 表示该属性字符串在device tree strings block的偏移值

FDT_NOP (0x00000004):被解析设备树的程序忽略,可用于覆盖其他属性,以删除它FDT_END (0x00000009):标记结构块的结束所以,一个DTB的结构块可能如下:(optionally) any number of FDT_NOP tokens

FDT_BEGIN_NODE token:

--node’s name

--paddings

For each property of the node:

--FDT_NOP(optionally)

--FDT_PROP token

--property

all child nodes in this format

(optionally) any number of FDT_NOP tokens

FDT_END_NODE token

1.4.4.Strings Block

定义了各个node中使用的属性的字符串表。由于很多属性会出现在多个node中,因此,所有的属性字符串组成了一个string block。这样可以压缩DTB的size。

1.5.Linux解析设备树

设备树描述了设备的详细信息,这些信息包括数字类型的、字符串类型的、数组类型的,我们在编写驱动时需要去获取这些信息。Linux内核提供一系列以of_开头的函数来获取设备树信息,这些函数的原型都定义在include/linux/of.h中。设备以节点的形式挂在设备树上,Linux内核使用device_node结构体来描述一个节点,其定义在include/linux/of.h中:

struct device_node {

const char *name;     device node name

const char *type;     对应device_type的属性

phandle phandle;      对应该节点的phandle属性

const char *full_name;  从“/”开始的,表示该node的full path

Struct  property *properties;      该节点的属性列表

如果需要删除某些属性,kernel并非真的删除,而是挂入到deadprops的列表

struct  property *deadprops;  removed properties

parent、child以及sibling将所有的device node连接起来

Struct  device_node *parent;

Struct  device_node *child;

Struct  device_node *sibling;

通过该指针可以获取相同类型的下一个node

Struct  device_node *next;  next device of same type

通过该指针可以获取node global list下一个node

struct  device_node *allnext;  next in list of all nodes

struct  kobject kobj;

unsigned long _flags;

void *data;

#if defined(CONFIG_SPARC)

const char *path_component_name;

unsigned int unique_id;

struct of_irq_controller *irq_trans;

#endif

};

1.5.1.查找节点的 OF函数1.5.1.1.of_find_node_by_name

功能:Find a node by its "name" property函数

struct device_node *of_find_node_by_name(struct device_node *from,

const char *name)

参数:

@from:开始查找的节点,如果为NULL表示从根节点开始查找整个设备树。

@name::要查找的节点名字。

返回值:找到的节点,如果为NULL表示查找失败。

1.5.1.2.of_find_node_by_path

功能:Find a node matching a full OF path函数:

struct device_node *of_find_node_by_path(const char *path)

参数:@path:完整的匹配路径返回值:找到的节点,如果为NULL表示查找失败。

1.5.1.3.of_find_node_by_type

功能Find a node by its "device_type" property函数

struct device_node *of_find_node_by_type(struct device_node *from,

const char *type)

参数

@from:开始查找的节点,如果为NULL表示从根节点开始查找整个设备树

@type: 要查找的节点类型

返回值找到的节点,如果为NULL表示查找失败。

1.5.1.4.of_find_compatible_node

功能通过device_type和compatible查找指定节点函数

struct device_node *of_find_compatible_node(struct device_node *from,const char *type, const char *compatible)

参数

@from:开始查找的节点,如果为NULL表示从根节点开始查找整个设备树

@type: 要查找的节点device_type属性

@compatible:节点的compatible属性列表

返回值找到的节点,如果为NULL表示查找失败。

1.5.1.5.of_find_node_with_property

功能通过属性名查找指定节点函数

struct device_node *of_find_node_with_property(struct device_node *from,const char *prop_name)

参数

@from:开始查找的节点,如果为NULL表示从根节点开始查找整个设备树

@type: 要查找的节点属性名称

返回值找到的节点,如果为NULL表示查找失败。

1.5.2.查找父 /子节点的 OF函数1.5.2.1.of_get_parent

功能函数用于获取指定节点的父节点(如果有父节点的话 )函数

struct device_node *of_get_parent(const struct device_node *node)

参数

@node:要查找父节点的节点

返回值找到的父节点

1.5.2.2.of_get_next_available_child

功能获取子节点,并跳过status = "disabled"的节点函数

struct device_node *of_get_next_available_child(const struct device_node *node,struct device_node *prev)

参数

@node: 父节点

@prev:当前父节点的上一个子节点, 如果为空,则获取第一个子节点

返回值找到的子节点

1.5.3.提取属性值的 OF函数

Linux内核使用struct property来保存节点的属性,其定义在/include/linux/of.h中:

struct property {

char  *name;      属性的名称

int  length;      属性的长度

void  *value;     属性的值

struct property *next;   下一个属性

unsigned long _flags;

unsigned int unique_id;

struct bin_attribute attr;

};

1.5.3.1.of_find_property

功能寻找指定的属性函数

struct property *of_find_property(const struct device_node *np,

const char *name,

int *lenp)

参数

@np: 设备节点

@name:属性名称

@lenp:属性的字节数

返回值找到的属性

1.5.3.2.读取属性中u8、u16、u32和u64类型的数组数据

当设置sz为1时,就是读取一个数据,Linux内核也是这么封装的。

int of_property_read_u8_array(const struct device_node *np,

const char *propname, u8 *out_values, size_t sz)

int of_property_read_u16_array(const struct device_node *np,

const char *propname, u16 *out_values, size_t sz)

int of_property_read_u32_array(const struct device_node *np,

const char *propname, u32 *out_values,size_t sz)

int of_property_read_u64(const struct device_node *np, const char *propname,

u64 *out_value)

1.5.3.3.of_property_read_string

功能找到并读取属性字符串函数

int of_property_read_string(struct device_node *np, const char *propname,const char **out_string)

参数

@np: 设备节点

@propname:属性名称

@out_string:读取的字符串

返回值

0:读取成功

-EINVAL:属性不存在

-ENODATA:属性没有这个值

-EILSEQ:字符串不是以空字符’’结尾

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

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

相关文章

一个兼容所有浏览器的阻止事件冒泡方法

function stopBubble(event) { //阻止冒泡事件 //取消事件冒泡 var e arguments.callee.caller.arguments[0] || event; //若省略此句,下面的e改为event,IE运行可以,但是其他浏览器就不兼容 if (e && e.stopPropagation) { // this …

linux shell 脚本 supress,《linux Shell 脚本攻略》进阶学习(第一部分)

第二章命令之乐cat 不仅可以读取文件并且连接数据,它还能从标准输入中进行读取要从标准输入中读取,就要使用管道操作符echo Text through stdin | cat - file.txt。这里的-被作为来之stdin 文本的文件名称实例 在file.txt 中写入dfagfmirgjriogjrogijdfg…

xaml_XAML或JavaFx?

xaml这是使用XAML和JavaFx构建应用程序的快速,主观, 无权且非常不科学的比较。 比较是基于我与每个人合作的个人经验。 在XAML方面,这意味着WPF和Win8存储应用程序 。 在JavaFx方面,这意味着Windows 7应用程序。 JavaFX JavaFx被…

古代猪文

题意: 给定q ,n 求$q^{\sum\limits {d|n} C_{n}^{d} }mod 999911659$ 题解: 首先如果你直接算次方上的数的话会炸掉,因为欧拉定理我们可以得到 $q^{\sum\limits {d|n} C_{n}^{d} mod999911658}mod 999911659$ 因为mod的数是个合数…

linux gcc 7.3.0安装,升级gcc到7.3.0

#查看当前版本gcc --version # 先查看当前版本确认是否需要升级tar -zxvf gcc-7.3.0.tar.gzcd gcc-7.3.0#检测和安装相关依赖包,这个过程需要耐心等待,此步骤会将依赖包下载到gcc-7.3.0目录,如果因网络原因无法完成请自行使用wget下载。该步骤…

使用Envoy代理的微服务模式,第二部分:超时和重试

该博客是系列文章的一部分,该系列文章更深入地介绍了Envoy Proxy和Istio.io ,以及它如何实现更优雅的连接和管理微服务的方式。 跟随我christianposta ,紧跟这些博客文章的发布。 什么是Envoy代理 ,它如何工作? 如何…

矩阵快速幂总结

依然主要还是自用 首先矩阵一条性质的概述和证明 概述:对于一个临接矩阵$G$来说,它自乘$G^k$次方中$G[i][j]$含义为从i走到j走k步方案数. 证明:比较麻烦,我们设f[i]表示从1走到其他点方案数,那么根据矩阵递推优化,k次就是转移了k次,那么每次走一步,k次就是走了k步 最…

c语言有一个正整数加上100,c语言编程实现:一个整数,它加上100后是完全平方数,再加168又是完全平方数,求该数。...

满意答案问题:一整数,它加100后是完全平方数,再加168还是完全平方数,求该整数解题思路:设该数为x,它加100后是A,再加168为B。则因为A是完全平方数,所以A为正数,且Ay*y&am…

C语言计算分段函数pta,PTA浙大版《C语言程序设计(第3版)》题目集 练习2-11 计算分段函数[2] (10分)...

1.编程将一个字符串中所有空格替换为“%20”#define _CRT_SECURE_NO_WARNINGS#include #includeusing namespace std;const int maxd 20;//最大深度int m[1 << maxd];//最大结点个数为2的maxd次方-1//编程将字符串中的空格用%20代替…2021/5/21 3:32:25pssh是由python编写…

「PKUWC2018」Slay the Spire

国际惯例不放题干 扯淡 其实题目翻译过来是杀戮尖塔&#xff0c;某steam上的卡牌游戏&#xff0c;我也曾热衷刷榜 题解 首先题目中要求的期望是假期望,结合题目中所给的阶乘就可以看出这其实是从$2*n$张牌中选择$m$张牌使用,并且所有情况都取最大值时的和 首先排序贪心最大 再说…

java lambda使用_在Java 8 Lambda上使用Apache Commons Functor功能接口

java lambda使用Apache Commons Functor &#xff08;以下称为[functor]&#xff09;是一个Apache Commons组件&#xff0c;它提供功能性的编程API和已实现的几种模式&#xff08;访问者&#xff0c;生成器&#xff0c;聚合器等&#xff09;。 Java 8具有几个不错的新功能&…

基于svm图像分类C语言,基于SVM的图像分类算法与实现.PDF

, ( ) 计算机工程与应用40 ComputerEngineeringandApplications基于SVM的图像分类算法与实现张淑雅 赵一鸣 李均利, ,, ,ZHANGShu-yaZHAOYi-mingLIJun-li宁波大学 数字技术与应用软件研究所 浙江 宁波, 315211, , , ,InstituteofDSPandSoftwareTechniquesNingboUniversityNingb…

前端ui框架

http://frozenui.github.io/components.html#progress rozenUI是什么 Frozen UI是一个开源的简单易用&#xff0c;轻量快捷的移动端UI框架。基于手Q样式规范&#xff0c;选取最常用的组件&#xff0c; 做成手Q公用离线包减少请求&#xff0c;升级方式友好&#xff0c;文档完善…

德国留学语言c1,德国留学申请,关于语言

申请德国大学并不容易&#xff0c;语言是一大关。对于申请德国大学的人来说&#xff0c;除国际课程和个别专业外&#xff0c;各大学对申请人德语学时要求一般都在800学时以上&#xff0c;目前比较权威的德语考试有TestDaf和DSH这两种类型。TestDaF&#xff1a;“外国学生申请大…

一个iOS表单框架-UFKit

效果&#xff1a; 使用&#xff1a; pod UFKit- (void)viewDidLoad {[super viewDidLoad];__block UFFormView *formView [UFFormView makeFormView:^(UFFormViewMaker * _Nonnull make) {make.addSection([UFSection makeSection:^(UFSectionMaker * _Nonnull make) {make.ad…

c语言手写指针和乘号,C-学会使用指针(示例代码)

先说&#xff1a;唯手熟尔指针指针存储着一个内存空间的地址定义一个指针int a&#xff1b;int * p&#xff1b;定义一个指针&#xff0c;只需在变量前面加一个 * 号。这里的指针只能存储一个存放整数的内存空间的地址指针如何存储地址p &a;&叫取地址符。这样整形指针…

考后反思7.25

D1 考试时首先看的第一题&#xff0c;不会&#xff0c;然后看第二题&#xff0c;原题&#xff01;&#xff01;&#xff01;&#xff01; 第二题啥也没想&#xff0c;就只是打了一个tarjan判割点&#xff0c; 打完的时候有点慌&#xff0c;总觉得自己打错了什么&#xff0c;调了…

android getinstance 方法,Android中的'new Fragment()'和'Fragment.getInstance()'有什么区别?...

当我们片段添加到特定的布局&#xff0c;我们可以使用folloing码Fragment fragment new SampleFragment();FragmentManager fragmentManager getSupportFragmentManager();FragmentTransaction fragmentTransaction fragmentManager.beginTransaction();fragmentTransaction…

查找发布地图的 REST URL并查询相关信息

1、登录ArcGIS Server Manager 2、登录后&#xff0c;里面是以前自己发布的地图服务 3、点击自己发布的地图&#xff0c;然后按下功能选项&#xff0c;再点击箭头来找到URL 4、点击进去&#xff0c;分别能从红圈中找到相关的信息&#xff0c;分别为arcgis JavaScript&#xff0…

maven使用testng_使用Maven Failsafe和TestNG分别运行单元测试和集成测试

maven使用testng最近&#xff0c;对于我的新宠物项目&#xff0c;我决定我希望在标准mvn测试期间执行一些测试&#xff0c;而仅在不同阶段执行一些其他测试 &#xff0c;我们称其为集成阶段。 我在谷歌上搜索&#xff0c;似乎没有任何工作&#xff0c;因此在努力使安装工作顺利…