Linux驱动开发:设备树dts详解

news2024/10/5 1:14:01

前言:掌握设备树是 Linux 驱动开发人员必备的技能!因为在新版本的 Linux 中,ARM 相关的驱动全部采用了设备树(也有支持老式驱动的,比较少),最新出的 CPU 其驱动开发也基本都是基于设备树的,比如 ST 新出的 STM32MP157、NXP 的 I.MX8 系列等。本篇博客核心是系统性的学习设备树的语法,并懂得如何运用设备树进行 Linux 驱动开发!

实验硬件:imx6ull;Linux内核版本:4.1.15

一、什么是设备树?

1.1 设备树概述 

设备树(Device Tree),将这个词分开就是“设备”和“树”,描述设备树的文件叫做 DTS(Device Tree Source),这个 DTS 文件采用树形结构描述板级设备,也就是开发板上的设备信息,比如 CPU 数量、 内存基地址、IIC 接口上接了哪些设备、SPI 接口上接了哪些设备等等,如下图所示:

树的主干就是系统总线,IIC 控制器、GPIO 控制器、SPI 控制器等都是接到系统主线上的分支。IIC 控制器有分为 IIC1 IIC2 两种,其中 IIC1 上接了 FT5206AT24C02 这两个 IIC 设备,IIC2 上只接了 MPU6050 这个设备。DTS 文件的主要功能就是按照图所示的结构来描述板子上的设备信息,DTS 文件描述设备信息是有相应的语法规则要求的,稍后我们会详细的讲解 DTS 语法规则。

设备树由一系列的节点和属性组成,节点可包含子节点。在设备树中,可描述的信息包括:

  • CPU数量和类型
  • 内存基地址和大小
  • 总线和桥
  • 外设连接
  • 中断控制器和中断使用情况
  • GPIO控制器和GPIO使用情况
  • 时钟控制器和时钟使用情况

bootload 会将这些信息传递给内核,内核开始识别这些树,并解析成 Linux 内核中 platform_device, i2c_client, spi_device等设备,而这些设备使用的内存资源,中断等信息也传递给内核。内核会将这些资源绑定给相应的设备。

设备树相关的包含 3 部分:DTSDTCDTB

DTS 是设备树源码文件, DTB 是将 DTS 编译以后得到的二进制文件。那么将 .dts 编译为 .dtbn 需要什么工具呢?需要用到 DTC 工具

1.2 设备树语法

.dts 是一种 ASCII 文本格式的设备树描述。基本上一个 .dts 文件对应一个 ARM 设备,一般放置在arch/arm/boot/dts/ 目录中。

设备树也支持头文件,设备树的头文件扩展名为 .dtsi。在 imx6ull-alientekemmc.dts 中有如下所示内容:

#include <dt-bindings/input/input.h>//引用.h文件
#include "imx6ull.dtsi" //引用“imx6ull.dtsi”这个.dtsi 头文件

一般 .dtsi 文件用于描述 SOC 的内部外设信息,比如 CPU 架构、主频、外设寄存器地址范围,比如 UARTIIC 等等。
比如 imx6ull.dtsi 就是描述 I.MX6ULL 这颗 SOC 内部外设情况信息。

#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/interrupt-controller/arm-gic.h>
#include "imx6ull-pinfunc.h"
#include "imx6ull-pinfunc-snvs.h"
#include "skeleton.dtsi"

/ {
	aliases {
		can0 = &flexcan1;
		...
	};
	cpus {
		#address-cells = <1>;
		#size-cells = <0>;

		cpu0: cpu@0 {
			compatible = "arm,cortex-a7";
			device_type = "cpu";
			reg = <0>;
			clock-latency = <61036>; /* two CLK32 periods */
			operating-points = <
				/* kHz	uV */
				996000	1275000
				792000	1225000
				528000	1175000
				396000	1025000
				198000	950000
			>;
							/* kHz	uV */
				996000	1275000
				792000	1225000
				528000	1175000
				396000	1025000
			...
	};

	intc: interrupt-controller@00a01000 {
		compatible = "arm,cortex-a7-gic";
		#interrupt-cells = <3>;
		interrupt-controller;
		reg = <0x00a01000 0x1000>,
		<0x00a02000 0x100>;
	};
		...

文件描述了 CPU arm,cortex-a7 ,支持 996MHz792MHz等频率, 时钟一些信息。

  • “/”是根节点,每个设备树文件只有一个根节点
  • “/”是根节点,每个设备树文件只有一个根节点
node-name@unit-address

其中 “node-name” 是节点名字,为 ASCII 字符串,节点名字应该能够清晰的描述出节点的功能,比如 “uart1” 就表示这个节点是 UART1 外设。“unit-address” 一般表示设备的地址或寄存器首地址,如果某个节点没有地址或者寄存器的话 “unit-address” 可以不要,比如 “cpu@0”“interrupt-controller@00a01000”

label: node-name@unit-address

引入 label 的目的就是为了方便访问节点,可以直接通过 &label 来访问这个节点,比如通过&cpu0 就可以访问 “cpu@0” 这个节点。很明显通过 &intc 来访问 “interrupt-controller@00a01000” 这个节点要方便很多!

每个节点都有不同属性,不同的属性又有不同的内容,属性都是键值对,值可以为空或任意的字节流。设备树源码中常用的几种数据形式如下所示:

1、字符串

compatible = "fairchild,74hc595";

2、32 位无符号整数

reg = <0 0x123456 100>;

3、字符串列表

compatible = "fsl,imx6ul-pxp-v4l2", "fsl,imx6sx-pxp-v4l2", "fsl,imx6sl-pxp-v4l2";

二、设备树详解

2.1 标准属性

1、compatible 属性

compatible 属性也叫做“兼容性”属性,这是非常重要的一个属性! compatible 属性的值是一个字符串列表, compatible 属性用于将设备和驱动绑定起来。字符串列表用于选择设备所要使用的驱动程序,compatible 属性的值格式如下所示:

"manufacturer,model"

其中 manufacturer 表示厂商,model 一般是模块对应的驱动名字。比如 imx6ull-alientek-emmc.dts 中 sound 节点是 I.MX6U-ALPHA 开发板的音频设备节点,I.MX6U-ALPHA 开发板上的音频芯片采用的欧胜(WOLFSON)出品的 WM8960,sound 节点的 compatible 属性值如下:

compatible = "fsl,imx6ul-evk-wm8960","fsl,imx-audio-wm8960";

其中 “fsl” 表示厂商是飞思卡尔,“imx6ul-evk-wm8960” “imx-audio-wm8960” 表示驱动模块名字。设备首先使用第一个兼容值在 Linux 内核里面查找,如果没有找到的话就使用第二个兼容值查。

2、 model 属性

model 属性值也是一个字符串,一般 model 属性描述设备模块信息,比如名字什么的,比如:

model = "wm8960-audio";

3、status 属性

status 属性看名字就知道是和设备状态有关的,status 属性值也是字符串,字符串是设备的状态信息,可选的状态如下表所示:

4、★#address-cells 和#size-cells 属性

#address-cells 属性值决定了子节点 reg 属性中地址信息所占用的字长(32 位)
#size-cells 属性值决定了子节点 reg 属性中长度信息所占的字长(32 位)
#address-cells#size-cells 表明了子节点应该如何编写 reg 属性值,一般 reg 属性都是和地址有关的内容,和地址相关的信息有两种:起始地址和地址长度, reg 属性的格式一为:

reg = <address1 length1 address2 length2 address3 length3……>

每个 “address length” 组合表示一个地址范围,其中 address 是起始地址, length 是地址长度.
#address-cells 表明 address 这个数据所占用的字长, #size-cells 表明 length 这个数据所占用的字长 

aips3: aips-bus@02200000 {
	compatible = "fsl,aips-bus", "simple-bus";
	#address-cells = <1>;
	#size-cells = <1>;
	
	dcp: dcp@02280000 {
		compatible = "fsl,imx6sl-dcp";
		reg = <0x02280000 0x4000>;
	};
};

说明 aips3: aips-bus@02200000 节点起始地址长度所占用的字长为 1,地址长度所占用的字长也为 1
子节点 dcp: dcp@02280000 的 reg 属性值为<0x02280000 0x4000>相当于设置了起始地址为 0x02280000,地址长度为 0x40000,但是 dcp的地址长度(范围)并没有 0x4000 这么多

5、 ★reg 属性

reg 属性一般用于描述设备地址空间资源信息,一般都是某个外设的寄存器地址范围信息,一般是(address, length)组成,详情如上所述!

6、ranges 属性

ranges 属性值可以为空或者按照 (child-bus-address,parent-bus-address,length) 格式编写的数字矩阵, ranges 是一个地址映射/转换表, ranges 属性每个项目由子地址、父地址和地址空间长度这三部分组成:

child-bus-address:子总线地址空间的物理地址,由父节点的 #address-cells 确定此物理地址所占用的字长。
parent-bus-address:父总线地址空间的物理地址,同样由父节点的 #address-cells 确定此物理地址所占用的字长。
length:子地址空间的长度,由父节点的 #size-cells 确定此地址长度所占用的字长。

如果 ranges 属性值为空值,说明子地址空间和父地址空间完全相同,不需要进行地址转换,例程如下:

soc {
	#address-cells = <1>;
	#size-cells = <1>;
	compatible = "simple-bus";
	interrupt-parent = <&gpc>;
	ranges;//为空

ranges 属性不为空的示例代码如下所示:

soc {
	compatible = "simple-bus";
	#address-cells = <1>;
	#size-cells = <1>;
	ranges = <0x0 0xe0000000 0x00100000>;
	
	serial {
		device_type = "serial";
		compatible = "ns16550";
		reg = <0x4600 0x100>;
		clock-frequency = <0>;
		interrupts = <0xA 0x8>;
		interrupt-parent = <&ipic>;
	};
};

节点 soc 定义的 ranges 属性,值为 <0x0 0xe0000000 0x00100000>,此属性值指定了一个 1024KB(0x00100000)的地址范围,子地址空间的物理起始地址为 0x0,父地址空间的物理起始地址为 0xe0000000。

serial 是串口设备节点,reg 属性定义了 serial 设备寄存器的起始地址为 0x4600,寄存器长度为 0x100。经过地址转换,serial 设备可以从 0xe0004600 开始进行读写操作,0xe0004600=0x4600+0xe0000000

2.2 向节点追加或修改内容

imx6ull.dtsi 有以下内容,表示 I2C 节点。不同的 I2C 设备有不通的详细属性,采用追加节点方法不会对共有信息带来污染。

i2c1: i2c@021a0000 {
	#address-cells = <1>;
	#size-cells = <0>;
	compatible = "fsl,imx6ul-i2c", "fsl,imx21-i2c";
	reg = <0x021a0000 0x4000>;
	interrupts = <GIC_SPI 36 IRQ_TYPE_LEVEL_HIGH>;
	clocks = <&clks IMX6UL_CLK_I2C1>;
	status = "disabled";
};

现在要在 i2c1 节点下创建一个子节点,这个子节点就是 fxls8471,最简单的方法就是在 i2c1 下直接添加一个名为 fxls8471 的子节点,如下所示: 

&i2c1 {
	clock-frequency = <100000>;
	pinctrl-names = "default";
	pinctrl-0 = <&pinctrl_i2c1>;
	status = "okay";
	
	fxls8471@1e {
		compatible = "fsl,fxls8471";
		reg = <0x1e>;
		position = <0>;
		interrupt-parent = <&gpio5>;
		interrupts = <0 8>;
};

子节点可以修改增加一些属性;
比如子节点中 clock-frequency 新增加的属性。
status 状态由disabled变成 okay 

2.3 设备树在目录中的体现

运行 cd /proc/device-tree 后,ls -a 查询当前目录下的文本情况

1、在当前目录下执行 cat model

model 的内容是 “Freescale i.MX6 ULL 14x14 EVK Board”

compatible 的内容为 “fsl,imx6ull-14x14-evkfsl,imx6ull”

打开文件 imx6ull-alientek-emmc.dts 查看一下,这正是根节点 “/”model compatible 属性值

2、soc子节点

3、aliases 子节点

 与imx6ull.dtsi中的 aliases一致

4、chosen 子节点

chosen 并不是一个真实的设备, chosen 节点主要是为了 uboot 向 Linux 内核传递数据,重点是 bootargs 参数,一般.dts 文件中 chosen 节点通常为空或者内容很少, imx6ull-alientekemmc.dts 中 chosen 节点内容如下所示:

chosen {
	stdout-path = &uart1;
}

chosen 节点仅仅设置了属性 “stdout-path”,表示标准输出使用 uart1

root@ATK-IMX6U:/proc/device-tree/chosen# ls
bootargs  name  stdout-path

我们可以发现 chosen 内存在 boot 的启动参数 bootargs

cat 查看确实是启动信息
1,我们并没有在设备树中设置 chosen 节点的 bootargs 属性,那么 bootargs这个属性是怎么产生的如何关联起来的呢?
2,为什么和 uboot 中的参数不一致?

chosen 节点的 bootargs 属性不是我们在设备树里面设置的,那么只有一种可能,那就是 uboot 自己在 chosen 节点里面添加了 bootargs 属性,并且设置 bootargs 属性的值为 bootargs环境变量的值。

uboot 源码中搜索 “chosen”,在文件 common/fdt_support.c 

int fdt_chosen(void *fdt)
{
	 //寻找chosen节点
	nodeoffset = fdt_find_or_add_subnode(fdt, 0, "chosen");
	
	if (nodeoffset < 0)
		return nodeoffset;
	//读取bootargs环境
	str = getenv("bootargs");
}

2.4 Linux 内核解析 DTB 文件 

启动内核流程函数

start_kernel 函数中最终调用了函数为 unflatten_dt_node(很多初始化操作都在start_kernel )!

2.5 帮助文档信息

设备树是用来描述板子上的设备信息的,不同的设备其信息不同,反映到设备树中就是属性不同。那么我们在设备树中添加一个硬件对应的节点的时候从哪里查阅相关的说明呢?路径为:Linux 源码目录 /Documentation/devicetree/bindings

比如我们现在要想在 I.MX6ULL 这颗 SOC 的 I2C 下添加一个节点,那么就可以查看Documentation/devicetree/bindings/i2c/i2c-imx.txt,此文档详细的描述了 I.MX 系列的 SOC 如何在设备树中添加 I2C 设备节点,文档内容如下所示:

root@ubuntu:/home/wy/imx6ul/kernel/Documentation/devicetree/bindings/i2c# cat i2c-imx.txt
* Freescale Inter IC (I2C) and High Speed Inter IC (HS-I2C) for i.MX

Required properties:
- compatible :
  - "fsl,imx1-i2c" for I2C compatible with the one integrated on i.MX1 SoC
  - "fsl,imx21-i2c" for I2C compatible with the one integrated on i.MX21 SoC
  - "fsl,vf610-i2c" for I2C compatible with the one integrated on Vybrid vf610 SoC
- reg : Should contain I2C/HS-I2C registers location and length
- interrupts : Should contain I2C/HS-I2C interrupt
- clocks : Should contain the I2C/HS-I2C clock specifier

Optional properties:
- clock-frequency : Constains desired I2C/HS-I2C bus clock frequency in Hz.
  The absence of the propoerty indicates the default frequency 100 kHz.
- dmas: A list of two dma specifiers, one for each entry in dma-names.
- dma-names: should contain "tx" and "rx".

Examples:

i2c@83fc4000 { /* I2C2 on i.MX51 */
	compatible = "fsl,imx51-i2c", "fsl,imx21-i2c";
	reg = <0x83fc4000 0x4000>;
	interrupts = <63>;
};

i2c@70038000 { /* HS-I2C on i.MX51 */
	compatible = "fsl,imx51-i2c", "fsl,imx21-i2c";
	reg = <0x70038000 0x4000>;
	interrupts = <64>;
	clock-frequency = <400000>;
};

i2c0: i2c@40066000 { /* i2c0 on vf610 */
	compatible = "fsl,vf610-i2c";
	reg = <0x40066000 0x1000>;
	interrupts =<0 71 0x04>;
	dmas = <&edma0 0 50>,
		<&edma0 0 51>;
	dma-names = "rx","tx";
};

三、设备树节点的操作函数

Linux 驱动程序往往需要去读取到 Linux 内核中附带的 dts 文件,并操作设备树 DTS 的相关节点!接下来我们来学习一下,如何进行设备树节点操作! 

1、查找节点的 of 函数

Linux 内核使用 device_node 结构体来描述一个节点

1、 of_find_node_by_name 函数

//通过节点名字查找指定的节点
struct device_node *of_find_node_by_name(struct device_node *from, const char *name);
//from:开始查找的节点,如果为 NULL 表示从根节点开始查找整个设备树。
//name:要查找的节点名字

2、of_find_node_by_type 函数

//通过device_type查找指定的节点
struct device_node *of_find_node_by_type(struct device_node *from, const char *type)

3、 of_find_compatible_node 函数

device_type 和 compatible 这两个属性查找指定的节点
struct device_node *of_find_compatible_node(struct device_node *from,
											const char *type,
											const char *compatible)

4、of_find_matching_node_and_match 函数

//通过 of_device_id 匹配表来查找指定的节点
struct device_node *of_find_matching_node_and_match(struct device_node *from,
						const struct of_device_id *matches,
						const struct of_device_id **match)

5、of_find_node_by_path 函数

struct device_node *of_get_parent(const struct device_node *node)
//node 要查找的父节点的节点

2、查找父/子节点的 OF 函数

1、of_get_parent 函数
用于获取指定节点的父节点

struct device_node *of_get_parent(const struct device_node *node)
//node 要查找的父节点的节点

2、of_get_next_child 函数

//用迭代的查找子节点
struct device_node *of_get_next_child(const struct device_node *node,
						              struct device_node *prev)
//node:父节点。
//prev:前一个子节点,也就是从哪一个子节点开始迭代的查找下一个子//节点。可以设置为NULL,表示从第一个子节点开始。
//返回 找到的下一个子节点。

3、提取属性值的 OF 函数

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、 of_find_property 函数

property *of_find_property(const struct device_node *np,
						   const char *name,
						   int *lenp)
//np:设备节点。
//name: 属性名字。
//lenp:属性值的字节数
//返回找到的属性

2、 of_property_count_elems_of_size 函数
用于获取属性中元素的数量,比如 reg 属性值是一个数组,那么使用此函数可以获取到这个数组的大小

int of_property_count_elems_of_size(const struct device_node *np,
							        const char *propname,
							        int elem_size)
//np:设备节点。
//proname: 需要统计元素数量的属性名字。
//elem_size:元素长度。
//返回 得到的属性元素数量

3、 of_property_read_u32_index 函数
从属性中获取指定标号的 u32 类型数据值(无符号 32 位),比如某个属性有多个 u32 类型的值,那么就可以使用此函数来获取指定标号的数据值

int of_property_read_u32_index(const struct device_node *np,
					           const char *propname,
					           u32 index,
					           u32 *out_value)

4、of_property_read_u8_array 函数
      of_property_read_u16_array 函数
      of_property_read_u32_array 函数
      of_property_read_u64_array 函数

分别是读取属性中 u8、 u16、 u32 和 u64 类型的数组数据,比如大多数的 reg 属性都是数组数据,可以使用这 4 个函数一次读取出 reg 属性中的所有数据

5、 of_property_read_string 函数

//用于读取属性中字符串值
int of_property_read_string(struct device_node *np,
                            const char *propname,
                            const char **out_string)

6、 of_n_addr_cells 函数
用于获取#address-cells 属性值

7、 of_n_size_cells 函数
of_size_cells 函数用于获取#size-cells 属性值

8、of_iomap 函数
采用设备树以后就可以直接通过 of_iomap 函数来获取内存地址所对应的虚拟地址,不需要使用 ioremap 函数了

四、作者有话

设备树的熟练掌握是每个 Linux 驱动开发工程师必须掌握的技能,特别是如今的 Linux 内核版本都是支持设备树的。设备树的出现极大的方便了各种设备的驱动代码编写,同时降低了 Linux 内核的冗余。设备节点操作函数有很多,其功能也各不相同,但是常用的函数就那么几个,希望大家可以好好掌握!!!

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

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

相关文章

Stable Diffusion + EbSynth + ControlNet 解决生成视频闪烁

一、安装 1.1、安装ffmpeg 下载地址&#xff1a; 解压&#xff0c;配置环境变量 E:\AI\ffmpeg\bin 检查是否安装成功 1.2、安装SD的 EbSynth 插件 插件地址 https://github.com/s9roll7/ebsynth_utility 报错&#xff1a;ModuleNotFoundError: No module named extension…

后端查询出的数据库数字自动补零和不补零

select CAST(YTD_CHANGE*100 as decimal(18,1)), round(YTD_CHANGE*100,1) from RP where data_date 20211231补零 round(PYTD_CHANGE_PER*100,1)不补零 CAST(PYTD_CHANGE_PER*100 as decimal(18,1))

day39-Oracle分区表

0目录 Oracle分区表 1.2.3 1. Oracle分区表 1.1 作用&#xff1a; Oracle数据库的分区把表中的数据行按照分区划成几个区域&#xff0c;提高大数据量下表的性能 1.2 应用场景&#xff1a;常应用于数据量大的表 1.3 分类&#xff1a;Oracle中有范围分区&#xff08;最常见…

LCD-STM32液晶显示中英文-(5.字符编码)

目录 字符编码 字符编码说明参考网站 字符编码 ASCII编码 ASCII编码介绍 ASCII编码表 中文编码 1. GB2312标准 区位码 2. GBK编码 3. GB18030 各个标准的对比说明 4. Big5编码 字符编码 字符编码说明参考网站 字符编码及转换测试&#xff1a;导航菜单 - 千千秀字 …

代码随想录day6 | 1. 两数之和 454.四数相加II 383.赎金信 15.三数之和 18.四数之和

文章目录 1. 两数之和2. 四数相加II3. 赎金信4. 三数之和5. 四数之和 1. 两数之和 1. 两数之和 虽然是LeetCode第一题&#xff0c;但是还是挺难的&#xff01; 模拟一下&#xff1a; class Solution { public:vector<int> twoSum(vector<int> &nums, int ta…

解决appium-doctor报opencv4nodejs cannot be found

一、下载cmake 在CMake官网下载&#xff1a;cmake-3.6.1-win64-x64.msi 二、安装cmake cmake安装过程 在安装时要选择勾选为所有用户添加CMake环境变量 三、检查cmake安装 重新管理员打开dos系统cmd命令提示符&#xff0c;输入cmake -version cmake -version四、安装opencv4no…

美国某市政府出现重大数据泄露事件,疑似离职人员未删除权限

近日&#xff0c;美国得克萨斯州西部城市敖德萨市市长Javier Joven宣布&#xff0c;自2022年12月以来&#xff0c;已经有人多次使用前敖德萨市检察官Natasha Brooks的账户非法访问了该市的政府系统&#xff0c;并将大量敏感信息通过电子邮件转移到了一个私人账户&#xff0c;敖…

创建ReWorks自引导工程

自引导工程开发与集成流程 2、新建工程 3、资源配置 4、代码编写 5、构建项目 右键构件项目&#xff0c;或选择“构建按钮”构建项目 6、配置TFTP服务路径 右键IMX6Q_SMP文件夹&#xff0c;配置TFTP服务路径 或 7、打开串口终端 8、启动开发板 查看网卡 素材来源于&#xff1…

社区版、专业版、企业版、专有版,smardaten四个版本到底怎么选?

这是一篇新老用户都不容错过的文章&#xff01; 要问今年上半年smardaten最大的变化&#xff0c;轻量化版本的推出双手奉上~~ 这时每一个心痒痒的客户&#xff0c;几乎都要迷茫的问睿睿两个问题&#xff1a;“现有版本之间有什么区别&#xff1f;都怎么收费&#xff1f;”。 …

在Microsoft Excel中如何快速将上下两行数据合并为一行?

合并单元格是电子表格初学者最常用的选项之一。当一组单元格、行或列需要标题或标签时,合并单元格是一种常用的技术。 合并单元格时,仅保留区域左上角单元格中的值或公式,并将其显示在合并后的单元格中。将丢弃任何其他值或公式,那么如何在新的空白单元格中将两行数据合并…

yo!这里是类的默认成员函数

目录 前言 默认成员函数 构造函数 1.介绍 2.注意点 析构函数 1.介绍 2.注意点 拷贝构造函数 1.介绍 2.注意点 赋值运算符重载 1.介绍 2.注意点 取地址及const取地址操作符重载 1.介绍 2.注意点 后记 前言 在学习c的过程中&#xff0c;我们知道&#xff0c;c是…

Windows下PyTorch深度学习环境配置(GPU)

一&#xff1a;下载Anaconda &#xff08;路径最好全英文&#xff09; &#xff08;下载好后&#xff0c;可以创建其他虚拟环境&#xff0c;因为是自己学习&#xff0c;所以先不放步骤&#xff0c;有需要者可以参考B站up我是土堆的视频&#xff09; 二&#xff1a;利用 conda…

Stream实现List和Map互转总结

本文来说下Stream实现List和Map互转总结 文章目录 实体类Map转List代码List转Map 实体类 本篇介绍Stream流List和Map互转&#xff0c;同时在转换过程中遇到的问题分析。 package cn.wideth.collect;import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArg…

【Linux】udp服务器实现大型网络聊天室

udp终结篇~ 文章目录 前言一、udp服务器实现大型网络聊天室总结 前言 根据上一篇文章中对于英汉互译和远程操作的两个小功能大家应该已经学会了&#xff0c;我们的目的是让大家可以深刻的理解udp服务器所需要的接口已经实现的简单步骤&#xff0c;下面我们开始实现网络聊天室。…

Spring 6【DI的两种方式、自动注入】(四)-全面详解(学习总结---从入门到深化)

目录 八、DI的两种方式 九、自动注入 八、DI的两种方式 IoC是由IoC容器帮助实例化Bean&#xff0c;并且在IoC容器内部注入关联属性(对象)的过程。 在上面演示的都是如何实例化Bean&#xff0c;下面演示的是如果给Bean注入属性。也就是说在讲解IoC/DI的另 一半功能。 在前面…

实训笔记7.18

实训笔记7.18 7.18一、座右铭二、Hadoop大数据技术 大数据软件一般都要求7*24小时不宕机三、Hadoop的组成3.1 HDFS3.2 MapReduce3.3 YARN3.4 Hadoop Common 四、Hadoop生态圈五、Hadoop的安装问题5.1 Hadoop的本地安装模式-基本不用5.2 Hadoop的伪分布安装模式5.3 Hadoop的完全…

webpack插件compression-webpack-plugin

Vue配置compression-webpack-plugin实现Gzip压缩 1、为什么要压缩&#xff1f; 打包的时候开启gzip可以很大程度减少包的大小&#xff0c;页面大小可以变为原来的30%甚至更小&#xff0c;非常适合于上线部署。更小的体积对于用户体验来说就意味着更快的加载速度以及更好的用户…

SOPC之NiosⅡ系统(五)

NIOS Ⅱ系统实例 目录 2.创建BSP工程 2.1 创建BSP工程 2.2 BSP Editor 2.3 创建C代码文件 3.Nios Ⅱ实例 3.1 Hello NIOS Ⅱ 3.2 System ID与Timestamp 3.3 蜂鸣器定时鸣叫 3.4 拨码开关输入GIO控制 4.FPGA器件的代码固化 4.1 嵌入式软件HEX文件生成 4.2 程序存储…

RocketMQ环境搭建

环境搭建 环境准备 下载地址: https://downloads.apache.org/rocketmq/4.9.5/安装 上传至服务器 mkdir /usr/soft #上传至此目录/usr/softmkdir /usr/soft 解压 cd /usr/soft unzip rocketmq-all-4.9.5-bin-release.zip移动 mkdir /usr/local/rocketmq cd /usr/soft mv r…

Mysql 修改group_concat_max_len的默认值

1.前言 最近在进行递归查询组织及其下属组织时&#xff0c;发现数据查询不全&#xff0c;子组织数据查询不出来的问题。经排查发现是group_concat_max_len的长度不足引起的&#xff0c;默认情况下group_concat_max_len1024&#xff0c;所以我们需要修改这个默认参数。 2.SQL语…