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

【Linux】遇事不决,可先点灯,LED驱动的进化之路---2

【Linux】遇事不决,可先点灯,LED驱动的进化之路---2

前言:

一、Pinctrl子系统重要概念

1.1 重要概念

1.1.1 pin controller

1.1.2 client device

1.1.3 补充概念

二、GPIO子系统重要概念

2.1 在设备树指定GPIO引脚

2.2 在驱动代码中调用GPIO子系统

三、基于GPIO子系统的LED驱动程序

3.1 修改设备树文件

3.1.1 添加Pinctrl信息

 3.1.2 设备节点信息(放在根节点下)

3.1.3 设置交叉编译工具链并编译dtbs文件

3.2 驱动程序

3.2.1 驱动代码(leddrv.c)

3.2.2 Makefile代码

 3.2.3 测试程序(ledtest.c)

3.3 上机测试


前言:

本文展示LED驱动进化升级化蝶的过程II,基于GPIO/Pinctrl子系统来实现LED驱动,解放硬件上的繁杂操作。遇到搞不明白的,就不妨先点个灯吧。

参考:韦老师课程

https://www.bilibili.com/video/BV14f4y1Q7ti

过一遍驱动框架,有大体认知后还需要进一步的实践感受。

https://blog.csdn.net/weixin_42373086/article/details/130521999

一、Pinctrl子系统重要概念

硬件上的操作方面,现在的芯片动辄有几百个引脚,一个引脚一个引脚去找对应的寄存器,是比较麻烦的,如何解决?

这里用Pinctrl子系统管理,Pinctrl子系统起到的作用主要为引脚复用和引脚配置,Pinctrl子系统的设计方面是由BSP驱动工程师实现。

一方面需要深刻理解Pinctrl子系统机制,另一方面功能实现上调用系统中的函数即可。这里使用Pinctrl子系统的方式---设备树。

1.1 重要概念

这里会涉及到两个对象,分别为pin controller和client device。

  • 前者提供服务,可以用它来复用引脚、配置引脚
  • 后者使用服务,声明自己使用哪些引脚的哪些功能,怎么配置它们。

1.1.1 pin controller

这里可以认为它对应IOMUX---用来复用引脚,还可以配置引脚(例如上下拉电阻等)。

这里注意pin controller与GPIO controller之间的区别,GPIO controller只是具有把引脚配置为输入、输出等简单功能。即先用pin controller把引脚配置为GPIO,再用GPIO Controller把引脚配置为输入或输出。

1.1.2 client device

简单来讲,就是使用Pinctrl系统的设备。这里会在设备树里定义为一个节点,在节点里声明要用哪些引脚。

1.1.3 补充概念

①pin state:

举个例子,对于UART设备来讲,它会有多个状态,如default和sleep。

  • 上图内容里的pinctrl-0,对应的配置是在pin controller里定义,状态为default
  • 上图内容里的pinctrl-1,对应的配置是在pin controller里定义,状态为sleep

当设备处于default状态时,pinctrl子系统会自动根据上述信息把所有引脚复用为uart0功能。

当设备处于sleep状态时,pinctrl子系统会根据上述信息把引脚配置为高电平。

②groups和function:

一个设备会用到一个或多个引脚,这些引脚可以归为一组(group);这些引脚可以复用为某个功能(function)。

二、GPIO子系统重要概念

以往我们通过寄存器来操作GPIO引脚,现如今可以使用BSP工程师实现的GPIO子系统来设置。

 主要有的操作:

  • 在设备树指定GPIO引脚
  • 使用GPIO子系统里的标准函数获得GPIO、设置GPIO方向、读取/设置GPIO值。

2.1 在设备树指定GPIO引脚

在使用GPIO子系统之前,就要先确定:它是哪组的?组里的哪一个?

在设备树中,“GPIO组”就是一个GPIO Controller,这通常都由芯片厂家设置好。我们要做的是找到它的名字。

gpio-controller;
#gpio-cells = <2>;

gpio-controller:表示这个节点是一个GPIO Controller,它下面有很多引脚。

#gpio-cells = <2>:表示这个控制器下要用2个32位数来描述。

用第一个cell表示是哪一个引脚,第二个cell来表示有效电平。

注:定义GPIO Controller是芯片厂家的事务,我们在自己的设备节点中使用属性“[<name>-]”gpios,来指定GPIO引脚,示例如下:

2.2 在驱动代码中调用GPIO子系统

在设备树中指定了GPIO引脚后,在驱动代码中如何使用?

应用GPIO子系统的函数接口,这里有两套,基于描述符的(descriptor-based)、老的(legacy),常用的函数如下: 

//需要包含的头文件
#include <linux/gpio/consumer.h> // descriptor-based
#include <linux/gpio.h> // legacy

注:这些函数会在驱动代码中调用,来实现获取GPIO、设置方向以及释放等操作。

三、基于GPIO子系统的LED驱动程序

这里相较于LED驱动进化之路1的内容,主要是修改设备树,编译设备树后,相应的设备树节点会被内核转换为platform_device。

实现点灯的思路步骤:

  1. 在设备树中添加Pinctrl信息、GPIO信息
  2. 驱动程序的编写,这里主要注册和实现platform_driver(probe函数-file_operations)。

3.1 修改设备树文件

3.1.1 添加Pinctrl信息

要使用某个引脚,需要使用Pinctrl子系统把引脚配置成GPIO。

对于imx6ull芯片,NXP公司有设备树生成工具,“Pins_Tool_i.MX_Processors_v6_x64.exe”,打开相应的配置文件“MCIMX6Y2xxx08.mex”,可以在GUI界面中选择引脚,配置它的功能,就可以自动生成Pinctrl的子节点信息。(这里LED对应的引脚为GPIO5_3)

 完成上述图里的过程,就可以轻松修改内核源码目录中arch/arm/boot/dts/100ask_imx6ull-14x14.dts。

引用上述生成的代码,复制到设备树文件中&iomuxc_snvs部分即可。

        myled_for_gpio: myled_for_gpio {        /*!< Function assigned for the core: Cortex-A7[ca7] */fsl,pins = <MX6ULL_PAD_SNVS_TAMPER3__GPIO5_IO03        0x000110A0>;};

 3.1.2 设备节点信息(放在根节点下)

 //compatible要跟驱动代码对应上myled {compatible = "100ask,leddrv";pinctrl-names = "default";pinctrl-0 = <&myled_for_gpio>;led-gpios = <&gpio5 3 GPIO_ACTIVE_LOW>;};

 这里GPIO5_3是也有被用于系统指示灯的,所以需要对其功能进行禁止。

3.1.3 设置交叉编译工具链并编译dtbs文件

这里编译后获得我们想要的dtb文件,并复制到nfs挂载文件夹里。

export ARCH=arm
export CROSS_COMPILE=arm-buildroot-linux-gnueabihf-
export PATH=$PATH:/home/book/100ask_imx6ull-sdk/ToolChain/arm-buildroot-linux-gnueabihf_sdk-buildroot/bin
make dtbs
cp  arch/arm/boot/dts/100ask_imx6ull-14x14.dtb ~/nfs_rootfs/

3.2 驱动程序

实际主体步骤如下:

  • 第一步 定义、注册一个platform_driver
  • 第二步 在probe函数里
    • 根据platform_device的设备树信息确定GPIO:gpio_get
    • 定义、注册一个file_operations结构体
    • 在file_operations中使用GPIO子系统的函数操作(gpiod_direction_outputgpiod_set_value

3.2.1 驱动代码(leddrv.c)

相较于LED驱动的进化之路---1中简单框架下的驱动代码,主要是进行probe函数以及相应file_operations函数的修改。

#include <linux/module.h>
#include <linux/platform_device.h>#include <linux/fs.h>
#include <linux/errno.h>
#include <linux/miscdevice.h>
#include <linux/kernel.h>
#include <linux/major.h>
#include <linux/mutex.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <linux/stat.h>
#include <linux/init.h>
#include <linux/device.h>
#include <linux/tty.h>
#include <linux/kmod.h>
#include <linux/gfp.h>
#include <linux/gpio/consumer.h>
#include <linux/of.h>/* 1. 确定主设备号                                                                 */
static int major = 0;
static struct class *led_class;
static struct gpio_desc *led_gpio;/* 3. 实现对应的open/read/write等函数,填入file_operations结构�?                  */
static ssize_t led_drv_read (struct file *file, char __user *buf, size_t size, loff_t *offset)
{printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);return 0;
}/* write(fd, &val, 1); */
static ssize_t led_drv_write (struct file *file, const char __user *buf, size_t size, loff_t *offset)
{int err;char status;//struct inode *inode = file_inode(file);//int minor = iminor(inode);printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);err = copy_from_user(&status, buf, 1);/* 根据次设备号和status(逻辑值)控制LED 高电平有效*/gpiod_set_value(led_gpio, status);return 1;
}static int led_drv_open (struct inode *node, struct file *file)
{//int minor = iminor(node);printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);/* 根据次设备号初始化LED */gpiod_direction_output(led_gpio, 0);return 0;
}static int led_drv_close (struct inode *node, struct file *file)
{printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);return 0;
}/* 定义自己的file_operations结构�?                                             */
static struct file_operations led_drv = {.owner	 = THIS_MODULE,.open    = led_drv_open,.read    = led_drv_read,.write   = led_drv_write,.release = led_drv_close,
};/* 4. 从platform_device获得GPIO*    把file_operations结构体告诉内核:注册驱动程序*/
static int chip_demo_gpio_probe(struct platform_device *pdev)
{//int err;printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);/* 4.1 设备树中定义�? led-gpios=<...>;	*/led_gpio = gpiod_get(&pdev->dev, "led", 0);				/*获得引脚,这里不设置引脚的方向*/if (IS_ERR(led_gpio)) {dev_err(&pdev->dev, "Failed to get GPIO for led\n");return PTR_ERR(led_gpio);}/* 4.2 注册file_operations 	*/major = register_chrdev(0, "100ask_led", &led_drv);  /* /devices/100ask_led(关注一下文件在哪里) *//*生成设备节点 class device create*/led_class = class_create(THIS_MODULE, "100ask_led_class");if (IS_ERR(led_class)) {printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);unregister_chrdev(major, "led");gpiod_put(led_gpio);return PTR_ERR(led_class);}device_create(led_class, NULL, MKDEV(major, 0), NULL, "100ask_led%d", 0); /* /dev/100ask_led0 */return 0;}static int chip_demo_gpio_remove(struct platform_device *pdev)
{device_destroy(led_class, MKDEV(major, 0));class_destroy(led_class);unregister_chrdev(major, "100ask_led");gpiod_put(led_gpio);                    return 0;
}static const struct of_device_id ask100_leds[] = {{ .compatible = "100ask,leddrv" },{ },
};/* 1. 定义platform_driver */
static struct platform_driver chip_demo_gpio_driver = {.probe      = chip_demo_gpio_probe,.remove     = chip_demo_gpio_remove,.driver     = {.name   = "100ask_led",.of_match_table = ask100_leds,},
};/* 2. 在入口函数注册platform_driver */
static int __init led_init(void)
{int err;printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);err = platform_driver_register(&chip_demo_gpio_driver); return err;
}/* 3. 有入口函数就应该有出口函数:卸载驱动程序时,就会去调用这个出口函�? *     卸载platform_driver*/
static void __exit led_exit(void)
{printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);platform_driver_unregister(&chip_demo_gpio_driver);
}/* 7. 其他完善:提供设备信息,自动创建设备节点                                     */module_init(led_init);
module_exit(led_exit);MODULE_LICENSE("GPL");

3.2.2 Makefile代码

老生常谈,需要注意KERN_DIR要对应上自己内核的路径。

# 1. 使用不同的开发板内核时, 一定要修改KERN_DIR
# 2. KERN_DIR中的内核要事先配置、编译, 为了能编译内核, 要先设置下列环境变量:
# 2.1 ARCH,          比如: export ARCH=arm
# 2.2 CROSS_COMPILE, 比如: export CROSS_COMPILE=arm-buildroot-linux-gnueabihf-
# 2.3 PATH,          比如: export PATH=$PATH:/home/book/100ask_imx6ull-sdk/ToolChain/arm-buildroot-linux-gnueabihf_sdk-buildroot/bin 
# 注意: 不同的开发板不同的编译器上述3个环境变量不一定相同,
#       请参考各开发板的高级用户使用手册KERN_DIR = /home/book/100ask_imx6ull-sdk/Linux-4.9.88all:make -C $(KERN_DIR) M=`pwd` modules $(CROSS_COMPILE)gcc -o ledtest ledtest.c clean:make -C $(KERN_DIR) M=`pwd` modules cleanrm -rf modules.orderrm -f ledtest# 参考内核源码drivers/char/ipmi/Makefile
# 要想把a.c, b.c编译成ab.ko, 可以这样指定:
# ab-y := a.o b.o
# obj-m += ab.oobj-m += leddrv.o

 3.2.3 测试程序(ledtest.c)

用于点灯测试实验。


#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>/** ./ledtest /dev/100ask_led0 on* ./ledtest /dev/100ask_led0 off*/
int main(int argc, char **argv)
{int fd;char status;/* 1. 判断参数 */if (argc != 3) {printf("Usage: %s <dev> <on | off>\n", argv[0]);return -1;}/* 2. 打开文件 */fd = open(argv[1], O_RDWR);if (fd == -1){printf("can not open file %s\n", argv[1]);return -1;}/* 3. 写文件 */if (0 == strcmp(argv[2], "on")){status = 1;write(fd, &status, 1);}else{status = 0;write(fd, &status, 1);}close(fd);return 0;
}

3.3 上机测试

重启加载设备树文件

cp /mnt/100ask_imx6ull-14x14.dtb /boot/
reboot

加载模块,并点灯测试 

insmod leddrv.ko
./ledtest /dev/100ask_led0 on
./ledtest /dev/100ask_led0 off

测试结果:

总结:对于BSP工程师和驱动工程师之间工作的细分区别,会有进一步的理解。在有了GPIO子系统和Pinctrl子系统之后,我们对于硬件上的操作控制的确方便了非常多。

相关文章:

【Linux】遇事不决,可先点灯,LED驱动的进化之路---2

【Linux】遇事不决&#xff0c;可先点灯&#xff0c;LED驱动的进化之路---2 前言&#xff1a; 一、Pinctrl子系统重要概念 1.1 重要概念 1.1.1 pin controller 1.1.2 client device 1.1.3 补充概念 二、GPIO子系统重要概念 2.1 在设备树指定GPIO引脚 2.2 在驱动代码中…...

【计算机网络】数据链路层--点对点协议PPP

1.概念 2.构成 3.封装成帧 - 帧格式 4.透明传输 4.1字节填充法&#xff08;面向字节的异步链路&#xff09; 4.2.比特填充法&#xff08;面向比特的同步链路&#xff09; 5.差错检测 6.工作状态 7.小结...

【⑦MySQL】· 一文了解四大子查询

前言 ✨欢迎来到小K的MySQL专栏&#xff0c;本节将为大家带来MySQL标量/单行子查询、列子/表子查询的讲解✨ 目录 前言一、子查询概念二、标量/单行子查询、列子/表子查询三、总结 一、子查询概念 子查询指一个查询语句嵌套在另一个查询语句内部的查询&#xff0c;这个特性从My…...

ValSuite报告可以帮助改善您的验证过程的6种方式

热验证工艺是一项复杂而微妙的工作&#xff0c;但它是确保制药和生物技术产品的安全性和有效性的重要组成部分。同时&#xff0c;管理整个验证过程中产生的数据可能很费时&#xff0c;而且容易出错——这就是ValSuite的意义。 这款直观的验证软件简化了数据分析和报告&#xf…...

【机器学习】机器故障的二元分类模型-Kaggle竞赛

竞赛介绍 数据集描述 本次竞赛的数据集&#xff08;训练和测试&#xff09;是从根据机器故障预测训练的深度学习模型生成的。特征分布与原始分布接近&#xff0c;但不完全相同。随意使用原始数据集作为本次竞赛的一部分&#xff0c;既可以探索差异&#xff0c;也可以了解在训…...

ADB usage

查看手机设备的信息 获取设备的Android版本号 adb shell getprop ro.build.version.release 获取设备的API版本号 adb shell getprop ro.build.version.sdkAdb 获得 sdk版本 adb shell getprop ro.build.version.sdk27 Adb 获得Android版本 adb shell getprop ro.build.vers…...

利用有限元法(FEM)模拟并通过机器学习进行预测以揭示增材制造过程中热场变化:基于ABAQUS和Python的研究实践

1. 引言 增材制造&#xff08;Additive Manufacturing&#xff0c;AM&#xff09;近年来引起了大量的研究关注&#xff0c;这主要是因为它可以提供定制化、复杂结构的零件制造解决方案。在AM过程中&#xff0c;热场的分布和变化直接影响了零件的质量和性能。对此&#xff0c;采…...

Kafka与Flume的对比分析

Kafka与Flume的对比分析 一、Kafka和Flume1. Kafka架构2. Flume架构3. Kafka和Flume异同点 二、Kafka和Flume的性能对比1. 数据处理性能对比2. 大规模数据流处理的性能对比 三、性和稳定性对比1. 高可用集群的搭建KafkaFlume 2. 数据丢失和重复消费的问题处理KafkaFlume 四、适…...

docker启动redis哨兵报错(sentinel.conf is not writable: Permission denied)

Sentinel config file /usr/local/sentinel/sentinel.conf is not writable: Permission denied. Exiting… 用这个命令不报错&#xff1a;docker run --net host -p 6666:6666–name redis-sentinel -v /usr/mcc/redis/conf:/usr/local/sentinel/ -v /usr/mcc/redis/data/sent…...

如何编写优秀代码

最近在阅读别人写的代码&#xff0c;进行相应功能的修改。发现很多不规范或者比较绕的地方&#xff0c;总有那么几句看着多此一举&#xff0c;阅读别人的代码就是这样&#xff0c;有时候真的不懂写代码的人当时怎么想的。 例如有这么一段&#xff1a; 用户输入一个名字&#…...

信道编码:Matlab RS编码、译码使用方法

Matlab RS编码、译码使用方法 1. 相关函数 在MATLAB中进行RS编码的过程可以使用rsenc()函数或者comm.RSEncoder()函数。 1.1 rsenc()函数使用方法 在MATLAB中帮助中可以看到有三种使用形式&#xff0c;分别为 code rsenc(msg,n,k) code rsenc(msg,n,k,genpoly) code rs…...

数据结构第六章 图 6.1-6.3 错题整理

6.1 6.C 加上一个点实现非连通 去除每个边都是一颗不同的生成树 一共n条边 13.C n个顶点、e条边的无向图&#xff0c;森林。树的角度看&#xff0c;除了根节点没有一条边与其对应&#xff0c;其他顶点都对应一条边&#xff0c;用顶点-边得出有多少颗树 14.A II 等于 也可以…...

12 MFC常用控件(一)

文章目录 button 按钮设置默认按钮按下回车后会响应禁用开启禁用设置隐藏设置显示设置图片设置Icon设置光标 Cbutton 类创建按钮创建消息单选按钮多选按钮 编辑框组合框下拉框操作 CListBox插入数据获取当前选中 CListCtrl插入数据设置表头修改删除 button 按钮 设置默认按钮按…...

Springboot搭配Redis实现接口限流

目录 介绍 限流的思路 代码示例 必需pom依赖 自定义注解 redis工具类 redis配置类 主拦截器 注册拦截器 介绍 限流的需求出现在许多常见的场景中&#xff1a; 秒杀活动&#xff0c;有人使用软件恶意刷单抢货&#xff0c;需要限流防止机器参与活动 某 api 被各式各样…...

php中的双引号与单引号的基本使用

字符串,在各类编程语言中都是一个非常重要的数据类型 网页当中的图片,文字,特殊符号,HTMl标签,英文等都属于字符串 PHP字符串变量用于存储并处理文本, 在创建字符串之后&#xff0c;我们就可以对它进行操作。我们可以直接在函数中使用字符串&#xff0c;或者把它存储在变量中 字…...

【Neo4j教程之CQL命令基本使用】

&#x1f680; Neo4j &#x1f680; &#x1f332; 算法刷题专栏 | 面试必备算法 | 面试高频算法 &#x1f340; &#x1f332; 越难的东西,越要努力坚持&#xff0c;因为它具有很高的价值&#xff0c;算法就是这样✨ &#x1f332; 作者简介&#xff1a;硕风和炜&#xff0c;C…...

Apikit 自学日记:发起文档测试-TCP/UDP

进入某个TCP/UDP协议的API文档详情页&#xff0c;点击文档上方 测试 标签&#xff0c;即可进入 API 测试页&#xff0c;系统会根据API文档的定义的求头部、Query参数、请求体自动生成测试界面并且填充测试数据。 填写/修改请求参数 1.1设置请求参数 与发起HTTP协议测试类似&am…...

坚鹏:中国邮储银行金融科技前沿技术发展与应用场景第1期培训

中国邮政储蓄银行金融科技前沿技术发展与应用场景第1期培训圆满结束 中国邮政储蓄银行拥有优良的资产质量和显著的成长潜力&#xff0c;是中国领先的大型零售银行。2016年9月在香港联交所挂牌上市&#xff0c;2019年12月在上交所挂牌上市。中国邮政储蓄银行拥有近4万个营业网点…...

HBase分布式安装配置

首先 先安装zookeeper ZooKeeper配置 解压安装 解压 tar -zxvf apache-zookeeper-3.5.7-bin.tar.gz -C /opt 改名 mv apache-zookeeper-3.5.7-bin zookeeper-3.5.7 在根目录下创建两个文件夹 mkdir Zlogs mkdir Zdata配置zoo.cfg文件&#xff0c;在解压后的ZooKeep…...

Microsoft365有用吗?2023最新版office有哪些新功能?

office自97版到现在已有20多年&#xff0c;一直是作为行业标准&#xff0c;格式和兼容性好&#xff0c;比较正式&#xff0c;适合商务使用。包含多个组件&#xff0c;除了常用的word、excel、ppt外&#xff0c;还有收发邮件的outlook、管理数据库的access、排版桌面的publisher…...

手游刚开服就被攻击怎么办?如何防御DDoS?

开服初期是手游最脆弱的阶段&#xff0c;极易成为DDoS攻击的目标。一旦遭遇攻击&#xff0c;可能导致服务器瘫痪、玩家流失&#xff0c;甚至造成巨大经济损失。本文为开发者提供一套简洁有效的应急与防御方案&#xff0c;帮助快速应对并构建长期防护体系。 一、遭遇攻击的紧急应…...

将对透视变换后的图像使用Otsu进行阈值化,来分离黑色和白色像素。这句话中的Otsu是什么意思?

Otsu 是一种自动阈值化方法&#xff0c;用于将图像分割为前景和背景。它通过最小化图像的类内方差或等价地最大化类间方差来选择最佳阈值。这种方法特别适用于图像的二值化处理&#xff0c;能够自动确定一个阈值&#xff0c;将图像中的像素分为黑色和白色两类。 Otsu 方法的原…...

从 GreenPlum 到镜舟数据库:杭银消费金融湖仓一体转型实践

作者&#xff1a;吴岐诗&#xff0c;杭银消费金融大数据应用开发工程师 本文整理自杭银消费金融大数据应用开发工程师在StarRocks Summit Asia 2024的分享 引言&#xff1a;融合数据湖与数仓的创新之路 在数字金融时代&#xff0c;数据已成为金融机构的核心竞争力。杭银消费金…...

MacOS下Homebrew国内镜像加速指南(2025最新国内镜像加速)

macos brew国内镜像加速方法 brew install 加速formula.jws.json下载慢加速 &#x1f37a; 最新版brew安装慢到怀疑人生&#xff1f;别怕&#xff0c;教你轻松起飞&#xff01; 最近Homebrew更新至最新版&#xff0c;每次执行 brew 命令时都会自动从官方地址 https://formulae.…...

前端中slice和splic的区别

1. slice slice 用于从数组中提取一部分元素&#xff0c;返回一个新的数组。 特点&#xff1a; 不修改原数组&#xff1a;slice 不会改变原数组&#xff0c;而是返回一个新的数组。提取数组的部分&#xff1a;slice 会根据指定的开始索引和结束索引提取数组的一部分。不包含…...

用鸿蒙HarmonyOS5实现中国象棋小游戏的过程

下面是一个基于鸿蒙OS (HarmonyOS) 的中国象棋小游戏的实现代码。这个实现使用Java语言和鸿蒙的Ability框架。 1. 项目结构 /src/main/java/com/example/chinesechess/├── MainAbilitySlice.java // 主界面逻辑├── ChessView.java // 游戏视图和逻辑├──…...

沙箱虚拟化技术虚拟机容器之间的关系详解

问题 沙箱、虚拟化、容器三者分开一一介绍的话我知道他们各自都是什么东西&#xff0c;但是如果把三者放在一起&#xff0c;它们之间到底什么关系&#xff1f;又有什么联系呢&#xff1f;我不是很明白&#xff01;&#xff01;&#xff01; 就比如说&#xff1a; 沙箱&#…...

大数据治理的常见方式

大数据治理的常见方式 大数据治理是确保数据质量、安全性和可用性的系统性方法&#xff0c;以下是几种常见的治理方式&#xff1a; 1. 数据质量管理 核心方法&#xff1a; 数据校验&#xff1a;建立数据校验规则&#xff08;格式、范围、一致性等&#xff09;数据清洗&…...

深入解析光敏传感技术:嵌入式仿真平台如何重塑电子工程教学

一、光敏传感技术的物理本质与系统级实现挑战 光敏电阻作为经典的光电传感器件&#xff0c;其工作原理根植于半导体材料的光电导效应。当入射光子能量超过材料带隙宽度时&#xff0c;价带电子受激发跃迁至导带&#xff0c;形成电子-空穴对&#xff0c;导致材料电导率显著提升。…...

6.计算机网络核心知识点精要手册

计算机网络核心知识点精要手册 1.协议基础篇 网络协议三要素 语法&#xff1a;数据与控制信息的结构或格式&#xff0c;如同语言中的语法规则语义&#xff1a;控制信息的具体含义和响应方式&#xff0c;规定通信双方"说什么"同步&#xff1a;事件执行的顺序与时序…...