深入浅出UART驱动开发与调试:从基础调试到虚拟驱动实现
往期内容
本专栏往期内容:Uart子系统
- UART串口硬件介绍
- 深入理解TTY体系:设备节点与驱动程序框架详解
- Linux串口应用编程:从UART到GPS模块及字符设备驱动
- 解UART 子系统:Linux Kernel 4.9.88 中的核心结构体与设计详解
- IMX 平台UART驱动情景分析:注册篇
- IMX 平台UART驱动情景分析:open篇
- IMX 平台UART驱动情景分析:read篇–从硬件驱动到行规程的全链路剖析
- IMX 平台UART驱动情景分析:write篇–从 TTY 层到硬件驱动的写操作流程解析
interrupt子系统专栏:
- 专栏地址:interrupt子系统
- Linux 链式与层级中断控制器讲解:原理与驱动开发
– 末片,有专栏内容观看顺序pinctrl和gpio子系统专栏:
专栏地址:pinctrl和gpio子系统
编写虚拟的GPIO控制器的驱动程序:和pinctrl的交互使用
– 末片,有专栏内容观看顺序
input子系统专栏:
- 专栏地址:input子系统
- input角度:I2C触摸屏驱动分析和编写一个简单的I2C驱动程序
– 末片,有专栏内容观看顺序I2C子系统专栏:
- 专栏地址:IIC子系统
- 具体芯片的IIC控制器驱动程序分析:i2c-imx.c-CSDN博客
– 末篇,有专栏内容观看顺序总线和设备树专栏:
- 专栏地址:总线和设备树
- 设备树与 Linux 内核设备驱动模型的整合-CSDN博客
– 末篇,有专栏内容观看顺序
目录
- 往期内容
- 1.UART驱动调试方法
- 1.1 怎么得到UART硬件上收发的数据
- 1.1.1 接收到的原始数据(收)
- 1.1.2 发送出去的数据(发)
- 1.2 proc文件
- 1.2.1 /proc/interrupts
- 1.2.2 /proc/tty/drivers
- 1.2.3 /proc/tty/driver(非常有用)
- 1.2.4 /proc/tty/ldiscs
- 1.3 sys文件
- 2.编写虚拟UART驱动程序
- 2.1 要做的事
- 2.2 虚拟的UART
- 2.3 编程
- 2.3.1 代码说明
- 2.3.2 /proc文件
- 2.3.3. 触发中断
- 2.4 调试
1.UART驱动调试方法
1.1 怎么得到UART硬件上收发的数据
1.1.1 接收到的原始数据(收)
可以在接收中断函数里把它打印出来,这些数据也会存入UART对应的tty_port的buffer里:
imx_rxint// 读取硬件状态// 得到数据// 在对应的uart_port中更新统计信息, 比如sport->port.icount.rx++;------添加打印---------// 把数据存入tty_port里的tty_buffertty_insert_flip_char(port, rx, flg)------添加打印,确保是否接收到数据---------// 通知行规程来处理tty_flip_buffer_push(port);tty_schedule_flip(port);queue_work(system_unbound_wq, &buf->work); // 使用工作队列来处理// 对应flush_to_ldisc函数
1.1.2 发送出去的数据(发)
所有要发送出去的串口数据,都会通过uart_write函数发送,所有可以在uart_write中把它们打印出来:
1.2 proc文件
1.2.1 /proc/interrupts
查看中断次数。
1.2.2 /proc/tty/drivers
1.2.3 /proc/tty/driver(非常有用)
1.2.4 /proc/tty/ldiscs
1.3 sys文件
在drivers\tty\serial\serial_core.c
中,有如下代码:
这写代码会在/sys目录中创建串口的对应文件,查看这些文件可以得到串口的很多参数。
怎么找到这些文件?在开发板上执行:
cd /sys
find -name uartclk // 就可以找到这些文件所在目录
2.编写虚拟UART驱动程序
2.1 要做的事
-
注册一个uart_driver:它里面有名字、主次设备号等
-
对于每一个port,调用uart_add_one_port,里面的核心是uart_ops,提供了硬件操作函数
-
uart_add_one_port由platform_driver的probe函数调用
-
所以:
- 编写设备树节点
- 注册platform_driver
-
2.2 虚拟的UART
为了做实验,还要创建一个虚拟文件:/proc/virt_uart_buf
- 要发数据给虚拟串口时,执行:echo “xxx” > /proc/virt_uart_buf
- 要读取虚拟串口的数据时,执行:cat /proc/virt_uart_buf
2.3 编程
📎virtual_uart.c
📎serial_send_recv.c – 测试程序
# 1. 使用不同的开发板内核时, 一定要修改KERN_DIR
# 2. KERN_DIR中的内核要事先配置、编译, 为了能编译内核, 要先设置下列环境变量:
# 2.1 ARCH, 比如: export ARCH=arm64
# 2.2 CROSS_COMPILE, 比如: export CROSS_COMPILE=aarch64-linux-gnu-
# 2.3 PATH, 比如: export PATH=$PATH:/home/book/100ask_roc-rk3399-pc/ToolChain-6.3.1/gcc-linaro-6.3.1-2017.05-x86_64_aarch64-linux-gnu/bin
# 注意: 不同的开发板不同的编译器上述3个环境变量不一定相同,
# 请参考各开发板的高级用户使用手册KERN_DIR = /home/book/100ask_imx6ull-sdk/Linux-4.9.88all:make -C $(KERN_DIR) M=`pwd` modules clean:make -C $(KERN_DIR) M=`pwd` modules cleanrm -rf modules.orderobj-m += virtual_uart.o
/{virtual_uart: virtual_uart_100ask {compatible = "100ask,virtual_uart";interrupt-parent = <&intc>;interrupts = <GIC_SPI 99 IRQ_TYPE_LEVEL_HIGH>;};};
无非就是实现uart_driver、uart_ops、file_operations virt_uart_buf_fops、/proc/virt_uart_buf,采用plataform_driver
2.3.1 代码说明
1. 基本结构和宏定义
BUF_LEN 1024
:定义了环形缓冲区的长度,1024字节。NEXT_PLACE(i)
:计算缓冲区的下一个位置,这里通过位与操作实现循环数组(环形缓冲区)。
2. 环形缓冲区相关
代码定义了两个环形缓冲区:
txbuf
:发送缓冲区,用于存储要发送的数据。rxbuf
:接收缓冲区,用于存储接收的数据。
并定义了如下指针和变量:
tx_buf_r
,tx_buf_w
:发送缓冲区的读写位置。rx_buf_w
:接收缓冲区的写位置。
环形缓冲区的相关操作:
is_txbuf_empty()
:判断发送缓冲区是否为空。is_txbuf_full()
:判断发送缓冲区是否已满。txbuf_put()
:向发送缓冲区放入一个字节。txbuf_get()
:从发送缓冲区取出一个字节。txbuf_count()
:计算缓冲区中的有效数据字节数。
3. UART驱动结构体
uart_driver virt_uart_drv
:表示一个UART驱动结构体,其中包括驱动名称、设备名称、设备数量等信息。
struct uart_driver virt_uart_drv = {.owner = THIS_MODULE,.driver_name = "VIRT_UART",.dev_name = "ttyVIRT", //最后设备节点的名字:/dev/ttyVIRTx.major = 0, // 动态分配主设备号.minor = 0, // 动态分配次设备号.nr = 1, // UART设备数量为1
};
uart_port virt_port
:表示虚拟串口硬件信息(包含硬件资源配置),如I/O地址、IRQ、FIFO大小、操作集等。
4. proc文件系统的创建
proc_create()
:创建一个proc文件,virt_uart_buf
用来与用户空间交互。
uart_proc_file = proc_create("virt_uart_buf", 0, NULL, &virt_uart_buf_fops);
通过 /proc/virt_uart_buf
文件,可以读写虚拟UART的缓冲区。virt_uart_buf_fops
是文件操作集,定义了read和write方法。
5. 文件操作函数
virt_uart_buf_read()
:从虚拟UART的发送缓冲区读取数据,拷贝给用户空间的缓冲区。
ssize_t virt_uart_buf_read(struct file *file, char __user *buf, size_t size, loff_t *ppos) {int cnt = txbuf_count();int i;unsigned char val;cnt = (cnt > size) ? size : cnt; // 限制读取字节数for (i = 0; i < cnt; i++) {txbuf_get(&val); // 从环形缓冲区获取数据copy_to_user(buf + i, &val, 1); // 复制数据到用户空间}return cnt;
}
virt_uart_buf_write()
:从用户空间接收数据,存入接收缓冲区,并模拟触发RX中断。
static ssize_t virt_uart_buf_write(struct file *file, const char __user *buf, size_t size, loff_t *off) {copy_from_user(rxbuf, buf, size); // 从用户空间拷贝数据到接收缓冲区rx_buf_w = size; // 更新接收缓冲区写指针irq_set_irqchip_state(virt_port->irq, IRQCHIP_STATE_PENDING, 1); // 模拟RX中断return size;
}
6. UART操作函数
这些函数定义了UART操作,如启动、停止传输等:
virt_tx_empty()
:判断发送缓冲区是否为空,这里总是返回1,因为数据在缓冲区瞬间发送完毕。virt_start_tx()
:开始发送数据。它从UART内部的环形缓冲区读取数据并写入txbuf
,表示发送操作。virt_set_termios()
:配置UART波特率、停止位等参数,这里未实现。virt_startup()
:启动UART设备,这里返回0,表示不需要额外初始化。virt_set_mctrl()
和virt_get_mctrl()
:控制UART调制解调器状态,暂未实现。virt_shutdown()
:关闭UART设备。virt_type()
:返回虚拟UART类型的字符串。
7. 中断处理函数
virt_uart_rxint()
:虚拟的RX中断处理函数,处理接收的数据,将接收到的数据放入TTY层。
static irqreturn_t virt_uart_rxint(int irq, void *dev_id) {struct uart_port *port = dev_id;struct tty_port *tport = &port->state->port;unsigned long flags;int i;spin_lock_irqsave(&port->lock, flags);for (i = 0; i < rx_buf_w; i++) {port->icount.rx++; // 增加接收计数tty_insert_flip_char(tport, rxbuf[i], TTY_NORMAL); // 插入TTY缓冲区 / put data to ldisc}rx_buf_w = 0;spin_unlock_irqrestore(&port->lock, flags);tty_flip_buffer_push(tport); // 推送到用户空间return IRQ_HANDLED;
}
8. 平台设备驱动
virtual_uart_probe()
:平台设备的探测函数,用于初始化UART设备并请求中断。这个函数负责:
static int virtual_uart_probe(struct platform_device *pdev) {rxirq = platform_get_irq(pdev, 0); // 获取中断号virt_port = devm_kzalloc(&pdev->dev, sizeof(*virt_port), GFP_KERNEL); // 分配port结构体virt_port->irq = rxirq; // 设置中断号ret = devm_request_irq(&pdev->dev, rxirq, virt_uart_rxint, 0, dev_name(&pdev->dev), virt_port); // 注册中断return uart_add_one_port(&virt_uart_drv, virt_port); // 添加一个UART端口
}
- 创建proc文件。
- 从设备树中获取中断号并注册中断处理函数。
- 分配并初始化
uart_port
结构体,注册UART设备。
virtual_uart_remove()
:用于清理和移除UART设备,包括删除proc文件和反注册UART端口。
static int virtual_uart_remove(struct platform_device *pdev) {uart_remove_one_port(&virt_uart_drv, virt_port);proc_remove(uart_proc_file);return 0;
}
9. 设备树匹配
of_device_id virtual_uart_of_match[]
:定义设备树匹配表,用于匹配“100ask,virtual_uart”兼容字符串。
10. 平台驱动结构体
platform_driver virtual_uart_driver
:定义平台驱动结构体,其中包含probe
和remove
函数,以及设备名称和设备树匹配表。
11. 模块初始化与退出
virtual_uart_init()
:模块初始化函数,注册UART驱动并注册平台驱动。virtual_uart_exit()
:模块退出函数,反注册平台驱动和UART驱动。
调用关系总结:
- 模块加载时,
module_init()
调用virtual_uart_init()
,注册UART驱动并调用platform_driver_register()
注册平台驱动。 virtual_uart_probe()
会被调用,分配和初始化uart_port
,注册中断处理函数并将UART端口注册到系统中。- 中断处理函数
virt_uart_rxint()
会在接收中断时被调用,处理接收的数据。 - 用户可以通过
/proc/virt_uart_buf
文件读取和写入虚拟UART缓冲区,触发相关操作。
2.3.2 /proc文件
参考/proc/cmdline
,怎么找到它对应的驱动?在Linux内核源码下执行以下命令搜索:
grep "cmdline" * -nr | grep proc
得到:
fs/proc/cmdline.c:26: proc_create("cmdline", 0, NULL, &cmdline_proc_fops);
2.3.3. 触发中断
使用如下函数:
int irq_set_irqchip_state(unsigned int irq, enum irqchip_irq_state which,bool val);
怎么找到它的?在中断子系统中,我们知道往GIC寄存器GICD_ISPENDRn写入某一位就可以触发中断。内核代码中怎么访问这些寄存器?
在drivers\irqchip\irq-gic.c
中可以看到irq_chip中的"irq_set_irqchip_state"被用来设置中断状态:
static struct irq_chip gic_chip = {.irq_mask = gic_mask_irq,.irq_unmask = gic_unmask_irq,.irq_eoi = gic_eoi_irq,.irq_set_type = gic_set_type,.irq_get_irqchip_state = gic_irq_get_irqchip_state,.irq_set_irqchip_state = gic_irq_set_irqchip_state, /* 2. 继续搜"irq_set_irqchip_state" */.flags = IRQCHIP_SET_TYPE_MASKED |IRQCHIP_SKIP_SET_WAKE |IRQCHIP_MASK_ON_SUSPEND,
};static int gic_irq_set_irqchip_state(struct irq_data *d,enum irqchip_irq_state which, bool val)
{u32 reg;switch (which) {case IRQCHIP_STATE_PENDING:reg = val ? GIC_DIST_PENDING_SET : GIC_DIST_PENDING_CLEAR; /* 1. 找到寄存器 */break;case IRQCHIP_STATE_ACTIVE:reg = val ? GIC_DIST_ACTIVE_SET : GIC_DIST_ACTIVE_CLEAR;break;case IRQCHIP_STATE_MASKED:reg = val ? GIC_DIST_ENABLE_CLEAR : GIC_DIST_ENABLE_SET;break;default:return -EINVAL;}gic_poke_irq(d, reg);return 0;
}
继续搜"irq_set_irqchip_state",在drivers\irqchip\irq-gic.c
中可以看到:
int irq_set_irqchip_state(unsigned int irq, enum irqchip_irq_state which,bool val)
{......
}EXPORT_SYMBOL_GPL(irq_set_irqchip_state);
以后就可与使用如下代码触发某个中断:
irq_set_irqchip_state(irq, IRQCHIP_STATE_PENDING, 1);
2.4 调试
装载驱动程序后,可以知道其设备节点是:/dev/ttyVIRT0
运行测试程序后,出现了input/output error之类的错误,如何去调试查看呢?
>>>strace -o log.txt ./serial send recv /dev/ttyVIRT0
该命令会将输出信息保存到log.txt中,方便我们去查看
相关文章:
深入浅出UART驱动开发与调试:从基础调试到虚拟驱动实现
往期内容 本专栏往期内容:Uart子系统 UART串口硬件介绍深入理解TTY体系:设备节点与驱动程序框架详解Linux串口应用编程:从UART到GPS模块及字符设备驱动 解UART 子系统:Linux Kernel 4.9.88 中的核心结构体与设计详解IMX 平台UART驱…...
集成量子光子学(IQP)
IQP 正在成为量子计算的可行替代方案量子源、波导和调制器等领域的研究使这成为可能与 CMOS 技术的兼容意味着工业可扩展性将更加容易 量子光子学的基本组成部分 IQP 系统的基本组成部分包括: 来源(例如腔体中的 QD) 波导定向耦合器&#…...
【代码随想录|贪心算法02】
122.买股票的最佳时机 题目链接https://leetcode.cn/problems/best-time-to-buy-and-sell-stock-ii 好巧妙的一道题啊,做之前完全不会想到这种解法。 局部最优:收集每天正利润 全局最优:求得最大利润 这道题只让你返回最大的利润和&…...
CentOS7 使用xtrabackup备份及恢复
安装备份工具 1.安装Percona yum存储库 sudo yum install https://repo.percona.com/yum/percona-release-latest.noarch.rpm安装过程中需要按y继续安装 2.启用Percona Server 5.7存储库 sudo percona-release setup ps573、安装percona-xtrabackup-24 sudo yum -y instal…...
【网络安全设备系列】12、态势感知
0x00 定义: 态势感知(Situation Awareness,SA)能够检测出超过20大类的云上安全风险,包括DDoS攻击、暴力破解、Web攻击、后门木马、僵尸主机、异常行为、漏洞攻击、命令与控制等。利用大数据分析技术,态势感…...
VM Virutal Box的Ubuntu虚拟机与windows宿主机之间设置共享文件夹(自动挂载,永久有效)
本文参考如下链接 How to access a shared folder in VirtualBox? - Ask Ubuntu (1)安装增强功能(Guest Additions) 首先,在网上下载VBoxGuestAdditions光盘映像文件 下载地址:Index of http://…...
【docker集群应用】Docker--harbor私有仓库部署与管理
文章目录 Harbor特性Harbor构成Harbor部署与管理Harbor 部署实例环境准备1. 部署 Docker-Compose 服务2. 部署 Harbor 服务(1) 下载并解压 Harbor 安装程序(2) 修改 Harbor 配置文件 3. 启动 Harbor4. 查看 Harbor 启动镜像5. 创建一个新项目6. 在其他客户端上传镜像 维护管理 …...
【优选算法】位运算
目录 常见位运算总结1、基础位运算2、给一个数n,确定它的二进制位的第x位上是0还是13、将一个数n的二进制位的第x位改成14、将一个数n的二进制位的第x位改成05、位图的思想6、提取一个数n的二进制位中最右侧的17、将一个数n的二进制位中最右侧的1变为08、位运算的优…...
2.mybatis整体配置
文章目录 mybatis-config.xml介绍SqlSessionFactoryBuilderXMLConfigBuilderpropertiessetting类型别名(typeAliases)扫描插件(plugins)解析objectFactory(对象工厂)解析objectWrapperFactory解析reflectorFactorysettingsElement()方法环境配置…...
js中判断数组和判断对象的方法
判断数组 Array.isArray() 方法 这是最推荐的方法,简单明了。它可以检测数组的情况,并且不会误报其他类型。 const arr [1, 2, 3]; console.log(Array.isArray(arr)); // trueconst notArray { key: value }; console.log(Array.isArray(notArray))…...
【godot】如何立刻(实时)进行碰撞检测?
因为最近在做帧同步方面的内容,所以发现了这个问题。 方案1:用Area2d进行碰撞检测,绑定body_entered信号。 缺陷: Area2d的碰撞检测只会每个物理迭代中只会执行一次,即在physics_process()结束后执行一次。 场景&a…...
讨论JAVA、JVM与Spring
Q1: 作为一个JAVA开发人员,对于jvm肯定不陌生,但很多人对它不陌生也仅止于概念上,而且对概念也是模糊不清的,但jvm实际是java程序运行在其中的实际存在的环境,对它的理解应该要是具象化的。 我们还是从一项技术产生的…...
基于SpringBoot实现的民宿管理系统(代码+论文)
🎉博主介绍:Java领域优质创作者,阿里云博客专家,计算机毕设实战导师。专注Java项目实战、毕设定制/协助 📢主要服务内容:选题定题、开题报告、任务书、程序开发、项目定制、论文辅导 💖精彩专栏…...
vue2 - 22.vant 组件库
vant 组件库 vant2下载: npm i vantlatest-v2 --legacy-peer-deps 目标:认识第三方 Vue组件库 vant-ui 组件库:第三方 封装 好了很多很多的 组件,整合到一起就是一个组件库。 https://vant-contrib.gitee.io/vant/v2/#/zh-CN…...
Git简单介绍
一、 Git介绍与安装 1.1 Git简介 Git是一个开源的分布式版本控制系统,可以有效、高速地处理从很小到非常大的项目版本管理。 1.2集中式(SVN) VS 分布式(git) 集中式版本控制系统,版本库是集中存放在中央服务器的,工作时要先从中央…...
【ArcGIS Pro实操第11期】经纬度数据转化成平面坐标数据
经纬度数据转化成平面坐标数据 数据准备ArcGIS操作步骤-投影转换为 Sinusoidal1 投影2 计算几何Python 示例 另:Sinusoidal (World) 和 Sinusoidal (Sphere) 的主要区别参考 数据准备 数据投影: 目标投影:与MODIS数据相同(Sinu…...
六大排序算法:插入排序、希尔排序、选择排序、冒泡排序、堆排序、快速排序
本章讲述数据结构中的六大排序算法 欢迎大佬们踊跃讨论,感谢大家支持! 我的博客主页链接 六大排序算法 一.插入排序1.1 直接插入排序1.2 希尔排序 二.选择排序2.1 单向选择排序2.2双向选择排序2.3 堆排序 三.交换排序3.1 冒泡排序3.2 快速排序3.2.1 Hoa…...
量化交易系统开发-实时行情自动化交易-4.4.1.做市策略实现
19年创业做过一年的量化交易但没有成功,作为交易系统的开发人员积累了一些经验,最近想重新研究交易系统,一边整理一边写出来一些思考供大家参考,也希望跟做量化的朋友有更多的交流和合作。 接下来继续说说做市策略实现。 做市策…...
Unity类银河战士恶魔城学习总结(P149 Screen Fade淡入淡出菜单)
【Unity教程】从0编程制作类银河恶魔城游戏_哔哩哔哩_bilibili 教程源地址:https://www.udemy.com/course/2d-rpg-alexdev/ 本章节实现了进入游戏和死亡之后的淡入淡出动画效果 UI_FadeScreen.cs 1. Animator 组件的引用 (anim) 该脚本通过 Animator 控制 UI 元…...
线上+线下≠新零售,6大互通诠释新零售的核心要点-亿发
新零售,这个词汇在近年来频繁出现在我们的视野中,它不仅仅是线上与线下的简单相加,而是一场深刻的商业变革。本文将通过6大互通的核心要点,为您揭示新零售的真正内涵。 1. 商品的互联互通 新零售模式下,商品的互联互…...
渗透测试学习笔记(一)渗透测试方法论
一.渗透测试方法论 渗透测试方法论是制定实施信息安全审计方案时,需要遵循的规则,惯例和过程。人们在评估网络,应用,系统或者三者组合的安全状态时,不断摸索各种实务的理念和成熟的做法,并总结了一套理论-…...
国外媒体发布新闻稿/海外媒体网站发稿创历史新潮流
国外媒体发布新闻稿/海外媒体网站发稿创历史新潮流 外媒发稿谷歌 SEO 优化经典案例冲出媒体宣发新高潮在当今数字化的时代,媒体宣发的重要性日益凸显。无论是企业品牌推广、产品发布,还是个人形象塑造,有效的媒体宣发都能带来巨大的影响力和…...
Three.js渲染较大的模型之解决方案
文章目录 Three.js渲染较大的模型 解决方案视锥体剔除实例 和 遮挡剔除 实例视锥体剔除(Frustum Culling)实例原理概述代码示例解释 遮挡剔除(Occlusion Culling)实例原理概述代码示例解释 three.js 模型压缩 Three.js渲染较大的模…...
webpack 项目访问静态资源
使用 webpack dev serve 启动 react 项目后,发现无法使用 http://localhost:8080/1.png 访问到项目的 /static 目录下的 1.png 文件。我的 webpack-dev.js 配置如下: const webpack require(webpack) const webpackMerge require(webpack-merge) cons…...
Day 25
491.递增子序列 力扣题目链接(opens new window) 给定一个整型数组, 你的任务是找到所有该数组的递增子序列,递增子序列的长度至少是2。 示例: 输入: [4, 6, 7, 7]输出: [[4, 6], [4, 7], [4, 6, 7], [4, 6, 7, 7], [6, 7], [6, 7, 7], [7,7], [4,7,7]] 说明: …...
【金猿案例展】无锡征信——百望云绿色金融数据要素+数据资产入表服务方案...
百望云数据要素案例 该数据要素项目案例由百望云投递并参与“数据猿年度金猿策划活动——2024数据要素产业年度创新服务企业榜单/奖项”评选。 大数据产业创新服务媒体 ——聚焦数据 改变商业 在数字化浪潮奔涌的时代,数据要素已成为驱动经济发展的关键引擎&…...
【C++】C++新增特性解析:Lambda表达式、包装器与绑定的应用
V可变参数模板与emplace系列 C语法相关知识点可以通过点击以下链接进行学习一起加油!命名空间缺省参数与函数重载C相关特性类和对象-上篇类和对象-中篇类和对象-下篇日期类C/C内存管理模板初阶String使用String模拟实现Vector使用及其模拟实现List使用及其模拟实现…...
python学opencv|读取图像
【1】引言 前序学习了使用matplotlib模块进行画图,今天开始我们逐步尝试探索使用opencv来处理图片。 【2】学习资源 官网的学习链接如下: OpenCV: Getting Started with Images 不过读起来是英文版,可能略有难度,所以另推荐一…...
租辆酷车小程序开发(二)—— 接入微服务GRPC
vscode中golang的配置 设置依赖管理 go env -w GO111MODULEon go env -w GOPROXYhttps://goproxy.cn,direct GO111MODULEauto 在$GOPATH/src 外面且根目录有go.mod 文件时,开启模块支持 GO111MODULEoff 无模块支持,go会从GOPATH 和 vendor 文件夹寻找包…...
leetcode 208. 实现 Trie (前缀树)
Trie(发音类似 "try")或者说 前缀树 是一种树形数据结构,用于高效地存储和检索字符串数据集中的键。这一数据结构有相当多的应用情景,例如自动补全和拼写检查。 请你实现 Trie 类: Trie() 初始化前缀树对象…...
kafka进阶_3.消费消息
文章目录 一、消费消息概览1.1、消费示例代码1.2、消费过程 二、消费者组2.1、push & pull2.2、消费者组 三、调度器Coordinator四、消费者分配策略4.1、引言4.2、分配基本流程4.3、分配策略4.3.1、轮询分配策略4.3.2、轮询分配策略 五、消费偏移量5.1、起始偏移量5.2、指定…...
预测未来 | MATLAB实现Transformer时间序列预测未来
预测未来 | MATLAB实现Transformer时间序列预测未来 预测效果 基本介绍 1.Matlab实现Transformer时间序列预测未来; 2.运行环境Matlab2023b及以上,data为数据集,单变量时间序列预测; 3.递归预测未来数据,可以控制预…...
VirtualBox7.0.6安装配置
VirtualBox7.0.6安装配置 提示:这里可以添加系列文章的所有文章的目录,目录需要自己手动添加 文章目录 VirtualBox7.0.6安装配置1.安装虚拟机1.1安装虚拟机的必要条件1.1.1开启虚拟化1.1.1.1检查虚拟化是否开启1.1.1.2 开启虚拟化 1.2 安装虚拟机1.1创建…...
Spring Boot英语知识分享网站:技术与实践
2相关技术 2.1 MYSQL数据库 MySQL是一个真正的多用户、多线程SQL数据库服务器。 是基于SQL的客户/服务器模式的关系数据库管理系统,它的有点有有功能强大、使用简单、管理方便、安全可靠性高、运行速度快、多线程、跨平台性、完全网络化、稳定性等,非常…...
HarmonyOS4+NEXT星河版入门与项目实战(22)------动画(属性动画与显示动画)
文章目录 1、属性动画图解2、案例实现-小鱼移动游戏1、代码实现2、代码解释3、资源图片4、实现效果3、显示动画4、案例修改-显示动画5、总结1、属性动画图解 这里我们用一张完整的图来汇整属性动画的用法格式和使用的主要属性范围,如下所示: 2、案例实现-小鱼移动游戏 1、代…...
AI赋能公共服务转型升级 | 第十届中国行业互联网大会暨腾讯云TVP行业大使三周年庆典公共服务专场圆满举办!
引言 党的二十大报告把“基本公共服务实现均等化”作为 2035 年我国发展的总体目标之一,强调要“健全基本公共服务体系,提高公共服务水平”。AI 作为新质生产力的核心驱动力之一,正在公共服务领域发挥着越来越重要的作用。 2024 年 10 月 2…...
网络基础 - 地址篇
一、IP 地址 IP 协议有两个版本,IPv4 和 IPv6IP 地址(IPv4 地址)是一个 4 字节,32 位的正整数,通常使用 “点分十进制” 的字符串进行表示,例如 192.168.0.1,用点分割的每一个数字表示一个字节,范围是 0 ~…...
chrome允许http网站打开摄像头和麦克风
第一步 chrome://flags/#unsafely-treat-insecure-origin-as-secure 第二步 填入网址,点击启用 第三步 重启 Chrome:设置完成后,点击页面底部的 “Relaunch” 按钮,重新启动 Chrome 浏览器,使更改生效。...
uniapp前端开发,基于vue3,element plus组件库,以及axios通讯
简介 UniApp 是一个基于 Vue.js 的跨平台开发框架,旨在通过一次开发、编译后运行在多个平台上,如 iOS、Android、H5、以及小程序(微信小程序、支付宝小程序、百度小程序等)等。UniApp 为开发者提供了统一的开发体验,使…...
STM32-- 串口发送数据
while(USART_GetFlagStatus(USART2,USART_FLAG_TXE)RESET);?? 答: 这行代码: while(USART_GetFlagStatus(USART2, USART_FLAG_TXE) RESET);的作用是等待串口 USART2 的发送数据寄存器(TXE,Transmit Dat…...
网络安全提示
如果您是企业主或 IT 经理,您应该知道计算机安全的重要性。从保护密码安全的基础知识到网络钓鱼、恶意软件等的危险,本文将为您提供您需要了解的有关网络安全的信息。 每年,互联网都变得越来越大,这意味着我们为黑客和网络犯罪分…...
【计算机网络】多路转接之epoll
epoll也是一种linux中的多路转接方案(epoll也是只负责IO过程中的"等") 一、epoll相关接口的使用 1.epoll_create int epoll_create(int size); 功能:创建一个epoll模型 ① int size:没意义了 >0就行 返回值:返回一个文件…...
nextjs+nestjs+prisma写todolist全栈项目
技术栈 nextjsnestjsprisma所学知识 Nextjs组件渲染,状态,路由docker启动Mysql容器prisma操作Mysql(CRUD)允许跨域请求APITanStack Query异步状态管理fetch api服务器组件预请求数据nestjs 管道和异常处理检测id是否正整数Docker启动Mysql容器 compose.yml name: todoLis…...
重构代码之将双向关联改为单向关联
在代码重构中,双向关联改为单向关联是指将原本双向关联转变为单向关联。这种重构方式有助于简化对象模型和提高代码的可维护性,减少不必要的耦合。下面是对这个重构技巧的详细讲解。 一、为什么需要将双向关联改为单向关联? 减少耦合&#…...
Linux介绍与安装指南:从入门到精通
1. Linux简介 1.1 什么是Linux? Linux是一种基于Unix的操作系统,由Linus Torvalds于1991年首次发布。Linux的核心(Kernel)是开源的,允许任何人自由使用、修改和分发。Linux操作系统通常包括Linux内核、GNU工具集、图…...
深度学习中的正则化模型是什么意思?
一、定义 在深度学习中,正则化是一种用于防止过拟合的技术。过拟合是指模型在训练数据上表现非常好,但在新的、未见过的数据(测试数据)上表现很差的情况。正则化模型就是通过在损失函数中添加额外的项来约束模型的复杂度…...
rabbitMq两种消费应答失败处理方式
在rabbitMq消费端,有三种应答模式: none:不处理。即消息投递给消费者后立刻 ack 消息会立刻从MQ删除。非常不安全,不建议使用 manual:手动模式。需要自己在业务代码中调用api,发送 ack 或 rejectÿ…...
windows C#-使用反射访问特性
你可以定义自定义特性并将其放入源代码中这一事实,在没有检索该信息并对其进行操作的方法的情况下将没有任何价值。 通过使用反射,可以检索通过自定义特性定义的信息。 主要方法是 GetCustomAttributes,它返回对象数组,这些对象在…...
java中链表的数据结构的理解
在 Java 中,链表是一种常见的数据结构,可以通过类的方式实现自定义链表。以下是关于 Java 中链表的数据结构和实现方式的详细介绍。 1. 自定义链表结构 Java 中链表通常由一个节点类 (ListNode) 和可能的链表操作类构成。 节点类 (ListNode) 这是链表…...
ctfshow
1,web153 大小写绕过失败 使用.user.ini 来构造后⻔ php.ini是php的⼀个全局配置⽂件,对整个web服务起作⽤;⽽.user.ini和.htaccess⼀样是⽬录的配置⽂件,.user.ini就是⽤户⾃定义的⼀个php.ini,我们可以利⽤这个⽂件来构造后⻔和…...