Pinctrl子系统_04_Pinctrl子系统主要数据结构
引言
本节说明Pinctrl子系统中主要的数据结构,对这些数据结构有所了解,也就是对Pinctrl子系统有所了解了。
前面说过,要使用Pinctrl子系统,就需要去配置设备树。
以内核面向对象的思想,设备树可以分为两部分,一部分(左边)用来描述Controller,另一部分(右边)则是描述使用引脚(使用controller)的device。
对于controller的部分,内核会抽象出一个 pinctrl_dev 结构体;对于 device 的部分,内核会抽象出一个 device 结构体,device 结构体中会有 pinctrl 方面的成员。
显然,这个 pinctrl 方面的成员肯定会和左边的 pinctrl_dev 结构体产生联系。
那么,它们之间是什么样的关系呢?
答:在我们了解完Pinctrl子系统的数据结构之后,他们之间的关系也就清晰了。
首先,在了解Pinctrl子系统的数据结构前,先回忆一下Pinctrl子系统的三大作用:
- 引脚枚举与命名(Enumerating and naming ):这个pinctrl支持哪些引脚,这些引脚叫什么名字;
- 引脚复用(Multiplexing ):用作什么功能,比如用作GPIO、I2C或其他功能;
- 引脚配置(Configuration):配置具体的引脚属性,比如上拉、下拉、open drain、驱动强度等;
记住这三大作用,就可以比较形象的去理解相关的结构体了。
那么,在Pinctrl子系统中,是怎么去实现这三大作用的呢?
pinctrl_desc和pinctrl_dev
我们刚刚说,controller 的部分,内核会抽象出一个 pinctrl_dev 结构体,但是事实上我们并不需要自己构造出这个 pinctrl_dev 结构体,而是使用内核提供的注册接口(pinctrl_register函数),我们只需要提供一个pinctrl_desc,然后调用这个接口,接口的返回值就是一个指向 pinctrl_dev 结构体的指针。
通过 pinctrl_dev 和 pinctrl_desc 这两个结构体,就可以描述一个 pincontroller:
controller相关结构体说明
以 imx6ull 为例,来了解pinctrl子系统中,controller 主要的数据结构,看看代码中是如何通过这些数据结构,实现 pinctrl 的三大作用的。
以下是 imx6ull 的pinctrl节点:
在设备启动后,这个节点会被转换成一个平台设备,和对应的平台驱动匹配完成后,就会调用对应的 probe 函数。
probe函数的大致流程
根据 compatible 属性值("fsl,imx6ul-iomuxc"),可以找到对应的驱动文件是 pinctrl-imx6ul.c,对应的 probe 函数是 imx6ul_pinctrl_probe,imx6ul_pinctrl_probe中则会调用 imx_pinctrl_probe函数。
在 imx_pinctrl_probe 函数中,会定义一个结构体指针 imx_pinctrl_desc,指向一个 pinctrl_desc 结构体。
在之后的代码中,首先申请一段内存,用来保存 pinctrl_desc,然后填充 pinctrl_desc 结构体,最后调用 devm_pinctrl_register,进行注册。
三大作用的具体实现
上面是probe函数中相关操作的大致流程,下面来具体说一下,在 Pinctrl 子系统中,是怎么去实现上面说的三大作用(引脚枚举与命名,引脚复用,引脚配置)的。
实现的关键就在于 pinctrl_desc 结构体,下面依次说明。
引脚的枚举与命名
首先看第一个功能,引脚的枚举与命名。
需要注意一下,引脚的枚举与命名分为两种情况:
- 单个引脚 的枚举与命名;
- 多个引脚 的枚举与命名;
单个引脚
单个引脚的枚举和命名,主要是通过 pinctrl_desc 结构体的 pins 成员和 npins 成员来实现的。
其中,pins 成员是一个结构体指针,指向一个 pinctrl_pin_desc 结构体,主要负责引脚的枚举与命名;而 npins 成员则是一个无符号的整型数据,用来记录引脚的总个数。
在 probe 函数中,会对 pins 和 npins 赋值,大致流程如下:
其中,imx6ul_pinctrl_info 变量的类型是 imx_pinctrl_soc_info 结构体,他也有 pins 和 npins 成员:
可以看到,他的 pins 成员指向了一个 imx6ul_pinctrl_pads 变量,这个变量是一个结构体数组,我们稍后再说。
综上,相当于执行了:
imx_pinctrl_desc->pins = imx6ull_snvs_pinctrl_pads;imx_pinctrl_desc->npins = ARRAY_SIZE(imx6ull_snvs_pinctrl_pads);
下面,看一下 imx6ul_pinctrl_pads 变量,他是一个结构体数组。通过对 IMX_PINCTRL_PIN 宏的分析,可以看到,这里主要定义了两个成员:
- number(第几个引脚,引脚的枚举) ;
- name (引脚的名字,引脚的命名);
总结一下,单个引脚的枚举与命名,主要的相关结构体是:
- pinctrl_pin_desc结构体;
多个引脚
上面说 pins 和 npins,他们是描述单个引脚。而在实际使用中,有时候会需要同时操作多个引脚(group),比如i2c中我们要用到一组引脚,要如何同时操作多个引脚呢?
答:这个时候就要用到 pinctrl_ops 结构体了:
可以看到, pinctrl_ops结构体的成员全部都是函数指针,它们的功能如下:
struct pinctrl_ops {/* 返回已注册的group数* - struct pinctrl_dev *pctldev:引脚控制设备结构体指针,表示引脚控制器设备。*/int (*get_groups_count) (struct pinctrl_dev *pctldev);/* 返回指定group的名字* - struct pinctrl_dev *pctldev:引脚控制设备结构体指针,表示引脚控制器设备。* - unsigned selector:group选择器,表示选择哪个group。*/const char *(*get_group_name) (struct pinctrl_dev *pctldev,unsigned selector);/* 返回指定group的引脚数组,并在num_pins中返回数组大小。* - struct pinctrl_dev *pctldev:引脚控制设备结构体指针,表示引脚控制器设备。* - unsigned selector:group选择器,表示选择哪个group。* - const unsigned **pins:指向存储引脚数组的指针的指针。* - unsigned *num_pins:指向存储引脚数组大小的变量的指针。*/int (*get_group_pins) (struct pinctrl_dev *pctldev,unsigned selector,const unsigned **pins,unsigned *num_pins);/* 可选的debugfs钩子函数,用于在debugfs中为特定引脚提供每个设备的信息。* - struct pinctrl_dev *pctldev:引脚控制设备结构体指针,表示引脚控制器设备。* - struct seq_file *s:序列文件结构体指针,用于在debugfs中显示信息。* - unsigned offset:偏移量,表示特定引脚的偏移量。*/void (*pin_dbg_show) (struct pinctrl_dev *pctldev, struct seq_file *s,unsigned offset);/* 解析设备树中的“引脚配置节点”,并为其创建映射表条目。这些通过`map`和`num_maps`输出参数返回。此函数是可选的,对于不支持设备树的引脚控制驱动程序可以省略。* - struct pinctrl_dev *pctldev:引脚控制设备结构体指针,表示引脚控制器设备。* - struct device_node *np_config:设备树中的引脚配置节点。* - struct pinctrl_map **map:指向映射表指针的指针,用于返回映射表条目。* - unsigned *num_maps:指向存储映射表条目数量的变量的指针。*/int (*dt_node_to_map) (struct pinctrl_dev *pctldev,struct device_node *np_config,struct pinctrl_map **map, unsigned *num_maps);/* 释放通过`dt_node_to_map`创建的映射表条目。必须释放顶层`map`指针,以及映射表条目本身的任何动态分配成员。此函数是可选的,对于不支持设备树的引脚控制驱动程序可以省略。* - struct pinctrl_dev *pctldev:引脚控制设备结构体指针,表示引脚控制器设备。* - struct pinctrl_map *map:映射表指针,需要释放。* - unsigned num_maps:映射表条目数量。*/void (*dt_free_map) (struct pinctrl_dev *pctldev,struct pinctrl_map *map, unsigned num_maps);
};
这里说明一下,pinctrl_ops结构体成员中,有一个很关键的函数指针 dt_node_to_map,他是用来处理设备树的,我们以后再说,这里先点一下。
所以,对于多个引脚(group),相关的结构体是:
- pinctrl_ops 结构体;
引脚复用
类似的,引脚的复用也是由一个结构体来实现:pinmux_ops。
pinmux_ops 就是 "Pin Multiplexing Operations"的缩写,表示引脚复用操作。
可以看到,结构体内部主要也是一堆函数指针。
其中,引脚的复用主要是通过 set_mux 成员来实现的,他也是一个函数指针:
这里目前只对set_mux成员做说明,后面如果有用到其他函数指针,到时候再补充。
struct pinmux_ops {int (*request) (struct pinctrl_dev *pctldev, unsigned offset);int (*free) (struct pinctrl_dev *pctldev, unsigned offset);int (*get_functions_count) (struct pinctrl_dev *pctldev);const char *(*get_function_name) (struct pinctrl_dev *pctldev,unsigned selector);int (*get_function_groups) (struct pinctrl_dev *pctldev,unsigned selector,const char * const **groups,unsigned *num_groups);/* 启用特定的muxing功能与特定的group。驱动程序无需确定启用此功能是否与该组中pin的其他用途冲突,这种冲突由pinmux子系统处理。* - struct pinctrl_dev *pctldev: 指向pinctrl设备结构的指针,用于表示设置mux的pinctrl设备。* - unsigned func_selector: 无符号整数,表示选择什么功能。* - unsigned group_selector: 无符号整数,表示选择哪个group。*/int (*set_mux) (struct pinctrl_dev *pctldev, unsigned func_selector,unsigned group_selector);int (*gpio_request_enable) (struct pinctrl_dev *pctldev,struct pinctrl_gpio_range *range,unsigned offset);void (*gpio_disable_free) (struct pinctrl_dev *pctldev,struct pinctrl_gpio_range *range,unsigned offset);int (*gpio_set_direction) (struct pinctrl_dev *pctldev,struct pinctrl_gpio_range *range,unsigned offset,bool input);bool strict;
};
引脚配置
我们还可以将一个或一组引脚,设置成不同的配置,比如上拉,下拉,open drain(开漏)等等。
这是怎么操作的呢?
答:同样是通过一个结构体:pinconf_ops
pinconf_ops 就是"Pin Configuration Options"的缩写,表示引脚的配置操作。
可以看到,结构体内部主要还是一堆函数指针。
这里主要说明以下四个函数指针:
- pin_config_get:获取某个pin的配置;
- pin_config_set:设置某个pin的配置;
- pin_config_group_get:获取某个group的配置;
- pin_config_group_set:设置某个group的配置;
注册pinctrl_dev
填充完 pinctrl_desc 结构体之后,调用 devm_pinctrl_register 或 pinctrl_register,就可以根据 pinctrl_desc 构造出 pinctrl_dev,并且把 pinctrl_dev 放入链表:
devm_pinctrl_registerpinctrl_registerstruct pinctrl_dev *pctldev;pctldev = kzalloc(sizeof(*pctldev), GFP_KERNEL);pctldev->owner = pctldesc->owner;pctldev->desc = pctldesc;pctldev->driver_data = driver_data;/* check core ops for sanity */ret = pinctrl_check_ops(pctldev);/* If we're implementing pinmuxing, check the ops for sanity */ret = pinmux_check_ops(pctldev);/* If we're implementing pinconfig, check the ops for sanity */ret = pinconf_check_ops(pctldev);/* Register all the pins */ret = pinctrl_register_pins(pctldev, pctldesc->pins, pctldesc->npins);list_add_tail(&pctldev->node, &pinctrldev_list);
总结
综上,对于controller,涉及的结构体主要有5个:
- pinctrl_desc:用于描述一个特定的引脚控制器(pinctrl)的配置信息,包括该控制器管理的引脚数量、引脚的功能、引脚的默认状态等。
- pinctrl_dev:代表一个具体的引脚控制器设备,它与`pinctrl_desc`结构体相关联,用于在系统中表示和管理一个特定的引脚控制器。
- pinctrl_ops :定义了对引脚控制器进行操作的一组函数指针,包括引脚的配置、引脚的状态读取、引脚的状态设置等操作。
- pinmux_ops:定义了对引脚复用(pin multiplexing)进行操作的一组函数指针,用于配置引脚的不同功能模式,例如将一个引脚配置为GPIO模式或者特定外设的模式。
- pinconf_ops:定义了对引脚配置(pin configuration)进行操作的一组函数指针,用于设置和获取引脚的一些特定属性,例如引脚的电压、上下拉设置等。
device相关结构体说明
上面主要是对左边controller相关的结构体说明,下面来讨论一下右边device相关的结构体。
dev_pin_info 结构体
在设备树中,使用pinctrl时,device节点格式如下:
/* For a client device requiring named states */
device {pinctrl-names = "active", "idle";pinctrl-0 = <&state_0_node_a>;pinctrl-1 = <&state_1_node_a &state_1_node_b>;
};
设备节点要么被转换为 platform_device,要么转换为其他结构体(比如i2c_client),但是里面都会有一个 device 结构体。在 device 结构体中会有一个 pins 成员,这个 pins 成员是一个结构体指针,指向一个 dev_pin_info 结构体。
dev_pin_info 结构体保存的就是这个 device 的 pinctrl 信息。
下面是 dev_pin_info 结构体的定义:
可以看到,主要定义了:
- 一个指向 pinctrl 结构体的结构体指针p;
- 4个指向 pinctrl_state 结构体的结构体指针 default_state,init_state,sleep_state,idle_state。
结合device节点,分析理解一下 dev_pin_info 结构体,以下面的device节点为例:
右边的device节点中,定义了两种状态:
- 状态0:default(对应 controller 节点 state_0_node_a) ;
- 状态1:sleep(对应 controller 节点 state_1_node_a 和 state_1_node_b)。
那么,就会用这些节点,来构造 dev_pin_info 结构体中的 default_state 和 sleep_state:
可以看到,dev_pin_info 结构体中已经定义了 4 个pinctrl_state指针,如果要添加我们自定义的state,要怎么记录呢?
答:dev_pin_info 结构体中有一个 pinctrl 结构体,我们自定义的 state 就存放在这个 pinctrl 结构体中。
假设要添加一个自定义的state,名字叫做“plane”,意为飞行模式,那么节点会变成这样:
pinctrl 结构体中有一个 states 成员,这个成员就会以链表的形式保存所有state,根据状态的序号,依次分别是default,sleep,plane。
并且 dev_pin_info 结构体中原先就有定义的 default_state 和 sleep_state,他们也会指向 states 成员中保存的 default 和 sleep 状态信息。
综上,对应device节点,最重要的结构体当属 pinctrl_state 结构体。
当设备进入某种状态时,就要把引脚配置成对应的 state。
那么,我们如何构造 pinctrl_state 呢?
如何构造pinctrl_state?
以下图为例,device 节点中的 pinctrl-0(default状态) 使用的是 state_0_node_a 节点,那么自然就要根据 state_0_node_a 节点来构造出 default_state。
那么,怎么根据pinctrl节点构造state呢?
答:需要用到 pinctrl_ops 结构体中的 dt_node_to_map 成员了。
dt_node_to_map 就是 "device tree node ==》map",顾名思义,就是将设备树的节点转换成一系列的map结构体(即pinctrl_map结构体)的意思。
通过 dt_node_to_map,将 pinctrl 节点转换为 pinctrl_map,再由 pinctrl_map 转换为 pinctrl_setting,最后,pinctrl_setting 会被存入 pinctrl_state 中的 settings 链表。
那么,pinctrl_map 和 pinctrl_setting 中,需要保存哪些信息呢?
答:对于 pinctrl 节点,他主要有两个作用:
- pin mux,引脚复用;
- pin cfg,引脚配置;
那么,显然,pinctrl_map 和 pinctrl_setting 就需要将这两个信息(引脚的复用信息,引脚的配置信息)保存记录下来。
首先,看一下 pinctrl_map 结构体:
可以看到,pinctrl_map 内部有一个联合体(union)data,这个联合体有两个成员:
- pinctrl_map_mux,记录复用信息;
- pinctrl_map_configs,记录配置信息;
所以,pinctrl_map 既可以记录引脚的复用信息,也可以记录引脚的配置信息;
刚刚说了,pinctrl_map 还会转换出 pinctrl_setting,来看一下 pinctrl_setting 结构体:
可以看到,他也有一个联合体(union) data,并且这个data也有两个成员:
- pinctrl_setting_mux,记录复用信息;
- pinctrl_setting_configs,记录配置信息;
所以,与 pinctrl_map 一样,pinctrl_setting 也是既可以记录引脚的复用信息,也可以记录引脚的配置信息。
对比 pinctrl_map 与 pinctrl_setting,可以发现两者高度类似:都可以保存引脚的复用信息,配置信息。
综上,我们知道了, 驱动程序会把 pinctrl子节点 转换成一系列(为什么说一系列?因为一个pinctrl子节点可能包含多个引脚)的 pinctrl_map 和 pinctrl_setting 结构体,在 pinctrl_map 和 pinctrl_setting 结构体中会保存引脚的配置信息,复用信息。
并且 pinctrl_setting 结构体还会被存入 pinctrl_state,以后我们选择让这个设备进入某种状态时,就会根据这些setting,来设置那些引脚,选择引脚的功能,配置引脚的上下拉,驱动强度等等。
使用pinctr_setting
最后,我们来看一下 pinctrl_state 中的这一系列 setting,是如何被调用的,又是如何去配置引脚的。
这主要会涉及 pinmux_ops 结构体中的 set_mux(设置复用)和 pinconf_ops 结构体中的 pin_config_set(设置引脚配置),pin_config_group_set(设置group配置)。
调用的流程如下:
really_probepinctrl_bind_pinspinctrl_select_state/* Apply all the settings for the new state */list_for_each_entry(setting, &state->settings, node) {switch (setting->type) {/* 引脚复用 */case PIN_MAP_TYPE_MUX_GROUP:ret = pinmux_enable_setting(setting);ret = ops->set_mux(...);break;/* 引脚配置:单引脚,多引脚 */case PIN_MAP_TYPE_CONFIGS_PIN:case PIN_MAP_TYPE_CONFIGS_GROUP:ret = pinconf_apply_setting(setting);switch (setting->type) {case PIN_MAP_TYPE_CONFIGS_PIN:ret = ops->pin_config_set(...);break;case PIN_MAP_TYPE_CONFIGS_GROUP:ret = ops->pin_config_group_set(...);break;default:return -EINVAL;}break;default:ret = -EINVAL;break;}
这样,左右两边的结构体(controller和device)就产生了联系,当设备进入某种状态时,就可以将引脚设置为对应的配置。
当我们对上述的结构体都有了初步的了解之后,后面就可以开始进行更深入的分析了。
以上就是本节全部内容。
相关文章:

Pinctrl子系统_04_Pinctrl子系统主要数据结构
引言 本节说明Pinctrl子系统中主要的数据结构,对这些数据结构有所了解,也就是对Pinctrl子系统有所了解了。 前面说过,要使用Pinctrl子系统,就需要去配置设备树。 以内核面向对象的思想,设备树可以分为两部分&#x…...

设计模式(十):抽象工厂模式(创建型模式)
Abstract Factory,抽象工厂:提供一个创建一系列相关或相互依赖对 象的接口,而无须指定它们的具体类。 之前写过简单工厂和工厂方法模式(创建型模式),这两种模式比较简单。 简单工厂模式其实不符合开闭原则,即对修改关闭…...
计算机网络概论01
计算机系统基础知识 基本组成 计算机系统由硬件和软件组成。 硬件由五大部分,他们分别是: 运算器 执行算数运算和逻辑运算控制器 控制cpu的工作,决定了计算机运行过程的自动化。包括指令控制逻辑、时序控制逻辑、总线控制逻辑和中断控制逻辑…...

新零售SaaS架构:订单履约系统架构设计(万字图文总结)
什么是订单履约系统? 订单履约系统用来管理从接收客户订单到将商品送达客户手中的全过程。 它连接了上游交易(客户在销售平台下单环)和下游仓储配送(如库存管理、物流配送),确保信息流顺畅、操作协同&…...
Hive SQL 开发指南(三)优化及常见异常
在大数据领域,Hive SQL 是一种常用的查询语言,用于在 Hadoop上进行数据分析和处理。为了确保代码的可读性、维护性和性能,制定一套规范化的 Hive SQL 开发规范至关重要。本文将介绍 Hive SQL 的基础知识,并提供一些规范化的开发指…...

Spring Boot 自动装配的原理!!!
SpringBootApplication SpringBootConfiguration:标识启动类是一个IOC容器的配置类 EnableAutoConfiguration: AutoConfigurationPackage:扫描启动类所在包及子包中所有的组件,生…...
Linux运维_Bash脚本_编译安装Wayland-1.22.0
Linux运维_Bash脚本_编译安装Wayland-1.22.0 Bash (Bourne Again Shell) 是一个解释器,负责处理 Unix 系统命令行上的命令。它是由 Brian Fox 编写的免费软件,并于 1989 年发布的免费软件,作为 Sh (Bourne Shell) 的替代品。 您可以在 Linu…...

Python数字类型
文章目录 Python数字类型1. 数字类型1.1 数字类型概述1.2 整数类型1.3 浮点数类型1.4 复数 2. 数字类型的操作2.1 内置的数值运算操作符2.2 内置的数值运算函数2.3 内置的数字类型转换函数 思考与练习 Python数字类型 1. 数字类型 1.1 数字类型概述 数字是自然界计数活动的抽…...
每天一个数据分析题(一百九十六)
在多元线性回归模型的自变量选择方法中,关于向后回归法和逐步回归法的描述,以下哪些是正确的? A. 向后回归法开始时包含所有自变量,并逐步剔除每个不显著的变量。 B. 逐步回归法结合了向前回归法和向后回归法,可以在…...

华为北向网管NCE开发教程(1)闭坑选接口协议
华为北向网管NCE开发教程(1)闭坑选接口协议 华为北向网管NCE开发教程(2)REST接口开发 华为北向网管NCE开发教程(3)CORBA协议开发 本文一是记录自己开发华为北向网管遇到的坑,二是给需要的人&…...

JavaScript极速入门-综合案例(3)
综合案例 猜数字 预期效果 代码实现 <button type"button" id"reset">重新开始一局游戏</button><br>请输入要猜的数字:<input type"text" id"number"><button type"button" id"button&q…...

RabbitMQ架构详解
文章目录 概述架构详解核心组件虚拟主机(Virtual Host)RabbitMQ 有几种广播类型 概述 RabbitMQ是⼀个高可用的消息中间件,支持多种协议和集群扩展。并且支持消息持久化和镜像队列,适用于对消息可靠性较高的场合 官网https://www.…...

编译内核错误 multiple definition of `yylloc‘
编译内核错误 # make ARCHarm CROSS_COMPILEarm-mix410-linux- uImageHOSTLD scripts/dtc/dtc /usr/bin/ld: scripts/dtc/dtc-parser.tab.o:(.bss0x10): multiple definition of yylloc; scripts/dtc/dtc-lexer.lex.o:(.bss0x0): first defined here collect2: error: ld ret…...

深度学习模型部署(四)常用模型及推理平台评估指标
判断选择什么模型,什么量化方案,什么推理框架,最基础的知识就是如何评估自己的模型以及推理平台。 模型衡量标准 衡量一个模型的最直接标准就是运算速度,但是运算速度是无法计算的,所以定义了一些间接标准来推测模型的…...

【控制台警告】npm WARN EBADENGINE Unsupported engine
今天用webpack下载几个loader依赖,爆出了三个警告,大概的意思就是本地安装的node和npm的版本不是很匹配? 我的解决思路是: 先检查node和npm版本 然后去官网查找版本的对应 靠,官网404 Node.js (nodejs.org) 就找到…...

ArmSoM Rockchip系列产品 通用教程 之 GPIO 使用
1. GPIO简介 GPIO,全称 General-Purpose Input/Output(通用输入输出),是一种在计算机和嵌入式系统中常见的数字输入输出接口。它允许软件控制硬件的数字输入和输出,例如开关、传感器、LED灯等。GPIO通常由一个芯片或…...
npm镜像源地址
镜像源地址替换问题(重要) 2024 年 1 月 22 日 ,registry.npm.taobao.org 的 SSL 证书正式过期。 2022 年 5 月 淘宝源发布了公告: (大家应该没有太多关注哦,也包括我,哈哈) &am…...

Java的Writer类详解
咦咦咦,各位小可爱,我是你们的好伙伴——bug菌,今天又来给大家普及Java SE相关知识点了,别躲起来啊,听我讲干货还不快点赞,赞多了我就有动力讲得更嗨啦!所以呀,养成先点赞后阅读的好…...

R语言基础的代码语法解译笔记
1、双冒号,即:“::” 要使用某个包里的函数,通常做法是先加载(library)包,再调用函数。最新加载的包的namespace会成为最新的enviroment,某些情况下可能影响函数的结果。而package name::funct…...

【蓝桥杯】蓝桥杯算法复习(一)
😀大家好,我是白晨,一个不是很能熬夜😫,但是也想日更的人✈。如果喜欢这篇文章,点个赞👍,关注一下👀白晨吧!你的支持就是我最大的动力!Ǵ…...

龙虎榜——20250610
上证指数放量收阴线,个股多数下跌,盘中受消息影响大幅波动。 深证指数放量收阴线形成顶分型,指数短线有调整的需求,大概需要一两天。 2025年6月10日龙虎榜行业方向分析 1. 金融科技 代表标的:御银股份、雄帝科技 驱动…...
【网络】每天掌握一个Linux命令 - iftop
在Linux系统中,iftop是网络管理的得力助手,能实时监控网络流量、连接情况等,帮助排查网络异常。接下来从多方面详细介绍它。 目录 【网络】每天掌握一个Linux命令 - iftop工具概述安装方式核心功能基础用法进阶操作实战案例面试题场景生产场景…...
线程同步:确保多线程程序的安全与高效!
全文目录: 开篇语前序前言第一部分:线程同步的概念与问题1.1 线程同步的概念1.2 线程同步的问题1.3 线程同步的解决方案 第二部分:synchronized关键字的使用2.1 使用 synchronized修饰方法2.2 使用 synchronized修饰代码块 第三部分ÿ…...

学习STC51单片机31(芯片为STC89C52RCRC)OLED显示屏1
每日一言 生活的美好,总是藏在那些你咬牙坚持的日子里。 硬件:OLED 以后要用到OLED的时候找到这个文件 OLED的设备地址 SSD1306"SSD" 是品牌缩写,"1306" 是产品编号。 驱动 OLED 屏幕的 IIC 总线数据传输格式 示意图 …...

蓝桥杯3498 01串的熵
问题描述 对于一个长度为 23333333的 01 串, 如果其信息熵为 11625907.5798, 且 0 出现次数比 1 少, 那么这个 01 串中 0 出现了多少次? #include<iostream> #include<cmath> using namespace std;int n 23333333;int main() {//枚举 0 出现的次数//因…...

基于TurtleBot3在Gazebo地图实现机器人远程控制
1. TurtleBot3环境配置 # 下载TurtleBot3核心包 mkdir -p ~/catkin_ws/src cd ~/catkin_ws/src git clone -b noetic-devel https://github.com/ROBOTIS-GIT/turtlebot3.git git clone -b noetic https://github.com/ROBOTIS-GIT/turtlebot3_msgs.git git clone -b noetic-dev…...

Mysql中select查询语句的执行过程
目录 1、介绍 1.1、组件介绍 1.2、Sql执行顺序 2、执行流程 2.1. 连接与认证 2.2. 查询缓存 2.3. 语法解析(Parser) 2.4、执行sql 1. 预处理(Preprocessor) 2. 查询优化器(Optimizer) 3. 执行器…...

day36-多路IO复用
一、基本概念 (服务器多客户端模型) 定义:单线程或单进程同时监测若干个文件描述符是否可以执行IO操作的能力 作用:应用程序通常需要处理来自多条事件流中的事件,比如我现在用的电脑,需要同时处理键盘鼠标…...
Caliper 配置文件解析:fisco-bcos.json
config.yaml 文件 config.yaml 是 Caliper 的主配置文件,通常包含以下内容: test:name: fisco-bcos-test # 测试名称description: Performance test of FISCO-BCOS # 测试描述workers:type: local # 工作进程类型number: 5 # 工作进程数量monitor:type: - docker- pro…...

抽象类和接口(全)
一、抽象类 1.概念:如果⼀个类中没有包含⾜够的信息来描绘⼀个具体的对象,这样的类就是抽象类。 像是没有实际⼯作的⽅法,我们可以把它设计成⼀个抽象⽅法,包含抽象⽅法的类我们称为抽象类。 2.语法 在Java中,⼀个类如果被 abs…...