IMX6ULL学习整理篇——Linux驱动开发的基础2 老框架的一次实战:LED驱动
IMX6ULL学习整理篇——Linux驱动开发的基础2 老框架的一次实战:LED驱动
在上一篇博客中,我们实现了从0开始搭建的字符设备驱动框架,但是这个框架还是空中楼阁,没有应用,很难说明我们框架的正确性。这里,我们就准备好驱动正点原子开发板上的一个LED小灯外设。他被接在了GPIO01_IO03上。
开始之前,复习一下架构体系对外设的地址处理
毫无疑问,任何一个搞过单片机的朋友都知道:在 ARM 架构中,外设的地址处理主要通过内存映射(Memory-Mapped I/O)方式进行。这意味着,外设的寄存器被映射到处理器的内存地址空间,CPU 可以像访问内存一样访问这些外设寄存器。这个技术连x86开始就在使用了!每个外设的寄存器都被分配了特定的物理地址,处理器通过读写这些地址来控制外设的操作。这种方式简化了处理器与外设之间的通信,因为不需要专门的 I/O 指令,统一了内存和外设的访问方式。
当然,对于我们复杂的ARM芯片上的主板一般还有MMU内存管理单元。我们的地址访问都被认为是一个虚拟地址时,这个时候MMU 会根据页表将其转换为相应的物理地址。这不仅实现了内存的虚拟化,还允许操作系统为不同的应用程序提供独立的地址空间,提高了系统的安全性和稳定性。
关于虚拟内存和物理内存,复习微机原理可以帮助你理解这些知识,笔者这里是驱动笔记整理,不是计算机体系架构笔记整理,所以请你自行翻阅相关的知识!
这也就意味着,我们没法子直接拿物理地址访问我们的GPIO寄存器了,那咋办呢?答案是:Linux考虑到了这类情况,提供了一组API,让我们添加IO设备的外设地址映射,告诉我们我们操作的虚拟地址是哪个!
ioremap和iounmap函数
在 Linux 内核中,ioremap
和 iounmap
函数用于在内核虚拟地址空间中映射和解除映射物理 I/O 内存区域,以便内核能够安全地访问硬件设备的寄存器或内存。ioremap
函数用于将指定的物理地址范围映射到内核的虚拟地址空间,使内核能够通过虚拟地址访问对应的物理 I/O 内存区域。
void __iomem *ioremap(resource_size_t phys_addr, unsigned long size);
其中:phys_addr
是要映射的物理起始地址。size
:要映射的内存区域大小。成功时,返回指向映射后虚拟地址空间的指针;失败时,返回 NULL
。调用 ioremap
后,内核可以通过返回的虚拟地址指针访问对应的物理 I/O 内存区域。
iounmap
函数用于解除先前通过 ioremap
建立的映射关系,释放对应的虚拟地址空间。
void iounmap(void __iomem *addr);
这里的addr
:要解除映射的虚拟地址,即先前 ioremap
的返回值。调用 iounmap
后,内核将不再能够通过该虚拟地址访问对应的物理 I/O 内存区域。
当然笔者提醒:
- 在访问硬件设备的寄存器或内存时,必须先使用
ioremap
将物理地址映射到内核虚拟地址空间,然后通过返回的虚拟地址进行读写操作。 - 在不再需要访问该 I/O 内存区域时,应调用
iounmap
解除映射,以释放资源。 - 直接访问物理地址可能导致不可预期的行为,因此应始终通过
ioremap
和iounmap
函数进行 I/O 内存的映射和解除映射。
read蔟函数和write蔟函数——操作我们的IO设备
拿到地址了,咋写呢?别自己手搓,我们的Linux还是给我们提供了API:在 Linux 内核中,readb
、readw
、readl
以及 writeb
、writew
、writel
等函数用于在内存映射的 I/O 空间中读取和写入数据。
读取操作函数:readb
、readw
、readl
函数用于从内存映射的 I/O 空间读取 8 位、16 位和 32 位的数据。
readb
:从指定的内存映射 I/O 地址读取 8 位(1 字节)数据。
unsigned char readb(const volatile void __iomem *addr);
readw
:从指定的内存映射 I/O 地址读取 16 位(2 字节)数据。
unsigned short readw(const volatile void __iomem *addr);
readl
:从指定的内存映射 I/O 地址读取 32 位(4 字节)数据。
unsigned int readl(const volatile void __iomem *addr);
写入操作函数:writeb
、writew
、writel
函数用于向内存映射的 I/O 空间写入 8 位、16 位和 32 位的数据。
writeb
:向指定的内存映射 I/O 地址写入 8 位(1 字节)数据。
void writeb(u8 value, volatile void __iomem *addr);
writew
:向指定的内存映射 I/O 地址写入 16 位(2 字节)数据。
void writew(u16 value, volatile void __iomem *addr);
writel
:向指定的内存映射 I/O 地址写入 32 位(4 字节)数据。
void writel(u32 value, volatile void __iomem *addr);
addr
:指向内存映射 I/O 空间中目标地址的指针。value
:要写入的数据。
编程,启动!
具体是啥地址,这个事情三个字:翻手册。没了,还不懂看如何裸机驱动LED,这就跟LKM驱动开发半毛钱关系没有了
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
#include <asm/io.h>
#include <linux/types.h>MODULE_LICENSE("GPL");
MODULE_AUTHOR("charliechen<charliechen114514@demo.com>");#define LED_MAJOR_DEV_N (114)
#define LED_DEV_NAME ("charlies_led")/* LED Physical Address See the manual
*/
#define CCM_CCGR1_BASE (0x020C406C)
#define GPIO1_IOLED_BASE (0x020E0068)
#define GPIO1_IOPAD_BASE (0x020E02F4)
#define GPIO1_IODR_BASE (0x0209C000)
#define GPIO1_GDIR_BASE (0x0209C004)/* mappings of the io phe*/
static void* __iomem LED_CCGR1;
static void* __iomem LEDBASE;
static void* __iomem LEDPAD_BASE;
static void* __iomem LEDDR_BASE;
static void* __iomem LEDGDIR_BASE;/* operations cached */
static char operations_cached[20];static void __led_turn_on(void)
{u32 val = 0;val = readl(LEDDR_BASE);val &= ~(1 << 3);writel(val, LEDDR_BASE);
}static void __led_turn_off(void)
{u32 val = 0;val = readl(LEDDR_BASE);val |= (1 << 3);writel(val, LEDDR_BASE);
}static u8 __fetch_led_status(void)
{u32 val = 0;val = readl(LEDDR_BASE);return !(val & (1 << 3));
}static void __enable_led_mappings(void)
{int val = 0;pr_info("Ready to mappings the registers...\n");LED_CCGR1 = ioremap(CCM_CCGR1_BASE, 4);LEDBASE = ioremap(GPIO1_IOLED_BASE, 4);LEDPAD_BASE = ioremap(GPIO1_IOPAD_BASE, 4);LEDDR_BASE = ioremap(GPIO1_IODR_BASE, 4);LEDGDIR_BASE = ioremap(GPIO1_GDIR_BASE, 4);pr_info("mappings the registers done!\n");pr_info("LED_CCGR1 ioremap to: %p\n", LED_CCGR1);pr_info("LEDBASE ioremap to: %p\n", LEDBASE);pr_info("LEDPAD_BASE ioremap to: %p\n", LEDPAD_BASE);pr_info("LEDDR_BASE ioremap to: %p\n", LEDDR_BASE);pr_info("LEDGDIR_BASE ioremap to: %p\n", LEDGDIR_BASE);pr_info("initialize the led registers\n");val = readl(LED_CCGR1);// clear the bitsval &= ~(3 << 26);val |= (3 << 26);writel(val, LED_CCGR1);writel(0x5, LEDBASE);writel(0x10B0, LEDPAD_BASE);val = readl(LEDGDIR_BASE);val |= 1 << 3;writel(val, LEDGDIR_BASE);pr_info("operations of led is accessable!\n");
}static void __disable_led_mappings(void)
{__led_turn_off();pr_info("set the led turning off...\n");pr_info("set the led turning off done!\n");pr_info("Ready to unmappings the registers...\n"); iounmap(LED_CCGR1);iounmap(LEDBASE);iounmap(LEDPAD_BASE);iounmap(LEDDR_BASE);iounmap(LEDGDIR_BASE);pr_info("unmappings the registers done\n");
}static int led_open(struct inode* inode, struct file* filp)
{pr_info("\nled device is opened!\n");return 0;
}static int led_close(struct inode* inode, struct file* filp)
{pr_info("\nled device is released!\n");return 0;
}static ssize_t led_read(struct file* filp, char* buffer, size_t count, loff_t* ppos)
{const char* status = "opened";int ret = 0;pr_info("\nled device is reading!\n");if(!__fetch_led_status()){status = "closed";} ret = copy_to_user(buffer, status, strlen(status));if(ret < 0){pr_warn("Copy to the user failed\n");return -EFAULT;}return 0;
} static ssize_t led_write(struct file* filp,const char* buffer, size_t count, loff_t* ppos)
{int check = 0;pr_info("\nled device is ready writing!\n");check = copy_from_user(operations_cached, buffer, count);if(check < 0){pr_warn("Can not copy from user!\n");return -EFAULT;}if(!strcmp(operations_cached, "open")){__led_turn_on();}else if(!strcmp(operations_cached, "close")){__led_turn_off();}else{pr_warn("Can not find the indications operations!\n""check the business: %s", operations_cached);}return 0;
} static struct file_operations led_ops = {.owner = THIS_MODULE,.read = led_read,.write = led_write,.open = led_open,.release = led_close
};static int __init led_init(void)
{int result = 0;pr_info("LED Device is setting up\n");result = register_chrdev(LED_MAJOR_DEV_N, LED_DEV_NAME, &led_ops);if(result < 0){pr_warn("can not register the device!\n");return -EIO;}__enable_led_mappings();return 0;
}static void __exit led_exit(void)
{unregister_chrdev(LED_MAJOR_DEV_N, LED_DEV_NAME);__disable_led_mappings();pr_info("LED Device is unhooked!\n");
}module_init(led_init);
module_exit(led_exit);
书写测试程序
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>#define ISSUE_BUFFER_N (40)static void display_help(const char* app_name)
{fprintf(stderr, "do: %s <dev_file> <operations>\n""op: read : read the data from char dev\n""op: write: write the data to char dev:\n"" open: turn on the led\n"" close: turn off the led\n", app_name);
}int main(int argc, char* argv[])
{int check = 0;if(argc < 3){display_help(argv[0]);return -1;}char* filename = argv[1];check = open(filename, O_RDWR);if(check < 0){fprintf(stderr, "Hey, Error in open filename: %s!\n", filename);return -1;}int result = 0;if(!strcmp(argv[2], "read")){// process reading issueprintf("user process the read issue\n");char buffer[ISSUE_BUFFER_N];result = read(check, buffer, ISSUE_BUFFER_N);if(result < 0){fprintf(stderr, "Hey, Error in read! filename: %s!\n", filename);goto close_issue; }printf("user receive from driver: %s\n", buffer);// done!}else if(!strcmp(argv[2], "write")){// process the writeprintf("args: %d\n", argc);if(argc != 4){display_help(argv[0]);goto close_issue;}printf("user process the write issue: %s\n", argv[3]);result = write(check, argv[3], strlen(argv[3]));if(result < 0){fprintf(stderr, "Hey, Error in write! filename: %s!\n", filename);goto close_issue; } }else{fprintf(stderr, "Unknown options!\n");display_help(argv[0]);goto close_issue;}close_issue:result = close(check);if(result < 0){fprintf(stderr, "Hey, Error in close device! filename: %s!\n", filename);return -1; } return 0;
}
无比怀念CLI框架的一天.jpg
下面我们测试一下:
测试
/module_test # ls
chrdev_application led.ko
/module_test # mknod /dev/ccled c 114 0
/module_test # insmod led.ko
LED Device is setting up
Ready to mappings the registers...
mappings the registers done!
LED_CCGR1 ioremap to: f42c406c
LEDBASE ioremap to: f42e0068
LEDPAD_BASE ioremap to: f42e02f4
LEDDR_BASE ioremap to: a092e000
LEDGDIR_BASE ioremap to: a0936004
initialize the led registers
operations of led is accessable!
/module_test # ./chrdev_application /dev/ccled readled device is opened!
user process the read issue
led device is reading!user receive from driver: closed
led device is released!
v
/module_test # ./chrdev_application /dev/ccled write openled device is opened!
args: 4
led device is ready writing!user process the write issue: o
led device is released!
pen
/module_test # ./chrdev_application /dev/ccled write closeled device is opened!
args: 4
user process the write issue:
led device is ready writing!
closeled device is released!
/module_test # rmmod led.ko
set the led turning off...
set the led turning off done!
Ready to unmappings the registers...
unmappings the registers done
LED Device is unhooked!
相关文章:
IMX6ULL学习整理篇——Linux驱动开发的基础2 老框架的一次实战:LED驱动
IMX6ULL学习整理篇——Linux驱动开发的基础2 老框架的一次实战:LED驱动 在上一篇博客中,我们实现了从0开始搭建的字符设备驱动框架,但是这个框架还是空中楼阁,没有应用,很难说明我们框架的正确性。这里,…...
网络空间安全(32)Kali MSF基本介绍
前言 Metasploit Framework(简称MSF)是一款功能强大的开源安全漏洞检测工具,被广泛应用于渗透测试中。它内置了数千个已知的软件漏洞,并持续更新以应对新兴的安全威胁。MSF不仅限于漏洞利用,还包括信息收集、漏洞探测和…...
零基础上手Python数据分析 (3):Python核心语法快速入门 (下) - 程序流程控制、函数与模块
写在前面 还记得上周我们学习的 Python 基本数据类型、运算符和变量吗? 掌握了这些基础知识,我们已经能够进行一些简单的数据操作了。 但是,在实际的数据分析工作中,仅仅掌握基本语法是远远不够的。 我们需要让程序能够 根据条件做出判断,重复执行某些操作,组织和复用代…...
C++【类和对象】(超详细!!!)
C【类和对象】 1.运算符重载2.赋值运算符重载3.日期类的实现 1.运算符重载 (1).C规定类类型运算符使用时,必须转换成调用运算符重载。 (2).运算符重载是具有特殊名字的函数,名字等于operator加需要使用的运算符,具有返回类型和参数列表及函数…...
Windows-PyQt5安装+PyCharm配置QtDesigner + QtUIC
个人环境 Windows 11 pycharm 2024.2 Anaconda2024.6python 3.9 1)先使用pip命令在线安装 1)pip install PyQt5 2)pip install PyQt5-tools2)配置环境变量 1:安装成功后可以在python的安装目录Lib\site-packahes目录下看到安装包。比如我的路径是E:\anaconda3…...
qq音乐 webpack 补环境
网址: aHR0cHM6Ly95LnFxLmNvbS9uL3J5cXEvcGxheWVy 1.接口分析 接口:cgi-bin/musics.fcg 参数:sign是加密的 2.代码分析 进入调用栈 先在send位置打上断点,页面刷新 往上一个栈找 可以看到上面就有一个关键词sign是从…...
【蓝桥杯】省赛:神奇闹钟
思路 python做这题很简单,灵活用datetime库即可 code import os import sys# 请在此输入您的代码 import datetimestart datetime.datetime(1970,1,1,0,0,0) for _ in range(int(input())):ls input().split()end datetime.datetime.strptime(ls[0]ls[1],&quo…...
计算机的结构形式
微机的机构形式 台式个人微机 最开始的微机(计算机)都是台式的,到目前为止仍是个人微机的主要形式。台式机按照电脑机箱的放置形式,分为卧式和立式两种。台式机需要放在桌面上或者留有专门放置机箱位置,他的主机、键…...
C语言【内存函数】详解
目录: 1. memcpy使用和模拟实现 2. memmove使用和模拟实现 3. memset函数的使用 4. memcmp函数的使用 以上函数均包含在一个头文件<string.h>里面 一、memcpy的使用和模拟实现。 memcpy函数介绍: 函数原型: void * memcpy ( void…...
软考网络安全专业
随着信息技术的迅猛发展,网络安全问题日益凸显,成为社会各界普遍关注的焦点。在这样的背景下,软考网络安全专业应运而生,为培养高素质的网络安全人才提供了有力支撑。本文将对软考网络安全专业进行深入剖析,探讨其在信…...
Altium Designer——CHIP类元器件PCB封装绘制
文章目录 PCB封装组成元素:焊盘的属性 SS34肖特基二极管SMA(DO-214AC)封装绘制资料:步骤:1.绘制焊盘:用到的快捷键:资料: 2.绘制丝印:用到的快捷键:资料: PCB封装组成元素…...
C++ unordered_map unordered_set 模拟实现
1. 关于unordered_map 和 unordered_set 区别于C的另外两个容器map和set,map和set的底层是红黑树;而unordered_map和unordered_set的底层是哈希 因为unordered_map和unordered_set的底层是哈希,因此他们存储的数据是没有顺序unordered…...
Java使用自定义类加载器实现插件动态加载
虚拟机类加载子系统 Java虚拟机的⼀个重要子系统,主要负责将类的字节码加载到JVM内存的⽅法区,并将其转换为JVM内部的数据结构。 一个类从被加载到虚拟机开始,一直到卸载出内存为止,会经历七个阶段:加载,…...
【初级篇】如何使用DeepSeek和Dify构建高效的企业级智能客服系统
在当今数字化时代,企业面临着日益增长的客户服务需求。使用Dify创建智能客服不仅能够提升客户体验,还能显著提高企业的运营效率。关于DIfy的安装部署,大家可以参考之前的文章: 【入门级篇】Dify安装+DeepSeek模型配置保姆级教程_mindie dify deepseek-CSDN博客 AI智能客服…...
Java开发之数据库应用:记一次医疗系统数据库迁移引发的异常:从MySQL到PostgreSQL的“dual“表陷阱与突围之路
记一次医疗系统数据库迁移引发的异常:从MySQL到PostgreSQL的"dual"表陷阱与突围之路 一、惊魂时刻:数据库切换引发的系统雪崩 某医疗影像系统在进行国产化改造过程中,将原MySQL数据库迁移至PostgreSQL。迁移完成后,系…...
Langchian构建代理
文章目录 概要ReAct 代理 ReAct 使用ReAct基本用法提示词模板内存使用迭代使用返回执行每一步情况限制输出行数设置运行超时时间 不使用代理下LLM如何结合工具案例案例2 概要 单靠语言模型无法采取行动 - 它们只输出文本。 LangChain 的一个重要用例是创建 代理。 代理是使用大…...
Vim软件使用技巧
目录 Demo Vim怎么看一个文件的行号,不用打开文件的前提下?进入文件后怎么跳转到某一行? 不打开文件查看行号(查看文件的方法) 方法1、使用命令行工具统计行数 方法2、通过vim的 - 参数查看文件信息 进入文件后跳转到指定行…...
SQL与NoSQL的区别
以下是SQL与NoSQL数据库的详细对比,涵盖核心特性、适用场景及技术选型建议: 一、核心区别对比 特性SQL(关系型数据库)NoSQL(非关系型数据库)数据模型基于表格,严格预定义模式(Schem…...
1191:流感传染--BFS
这里写目录标题 题目 解析代码BFS代码 题目 解析 在同一天对一个病原体进行处理时,如果直接更改数组,将直接影响到后续的遍历 方法一:那么我们可以定义一个数组用来存储坐标:vectoir<pair<int,int>>,遍历…...
gfortran编译器调试功能选项
在使用 gfortran 编译器进行调试时,以下选项可以帮助你更好地定位和解决问题: 1. 生成调试信息 -g:生成调试信息,供调试器(如 gdb)使用。-ggdb:生成更详细的调试信息,优化 gdb 的使…...
小程序配置
注册小程序账号和安装开发工具 参考文档:注册小程序账号和安装开发工具https://blog.csdn.net/aystl_gss/article/details/127878658 HBuilder新建项目 填写项目名称,选择UNI-APP,修改路径,点击创建 manifest.json 配置 需要分别…...
【Linux】进程(1)进程概念和进程状态
🌟🌟作者主页:ephemerals__ 🌟🌟所属专栏:Linux 目录 前言 一、什么是进程 二、task_struct的内容 三、Linux下进程基本操作 四、父进程和子进程 1. 用fork函数创建子进程 五、进程状态 1. 三种重…...
MySQL(事物下)
目录 一 多版本并发控制( MVCC )是一种用来解决 读-写冲突 的无锁并发控制 1. 前置知识 示例: 二 Read View 1. 当事物进行快照读(读历史数据)会MySQL会创建一个Read Vidw类对象,用来记录和当前一起并发的事物(活跃的事物)&a…...
Springboot+mybatis实现增删改查效果
我们前面实现了增加效果,现在来写一下修改~我们首先在controller里面写update 接着在service和mapper写方法 最后我们测试一下 没问题~需要注意的是mapper的sql别写错了!...
【“以退为进“、“不得已而为之“与“风险对冲“的协同机制】
深度解析:“以退为进”、"不得已而为之"与"风险对冲"的协同机制 一、“以退为进”:空间重构的博弈艺术 1. 三维战略坐标系 权力维度:唐太宗"玄武门之变"后跪哭李渊,通过降维姿态化解道德危机&am…...
AUTOSAR 网络安全 架构
实现AUTOSAR网络安全架构的步骤指南 在当今汽车电子系统中,AUTOSAR(AUTomotive Open System ARchitecture)正在成为业界标准。结合网络安全要求,我们可以确保汽车在网络通信中保持安全。接下来,我们将讨论如何实现AUT…...
洛谷 P2801 教主的魔法 题解
之前学过 莫队 算法,其运用了分块思想;但是我居然是第一次写纯种的分块题目。 题意 给你一个长度为 n n n 的序列 a a a(一开始 ∀ a i ∈ [ 1 , 1000 ] \forall a_i\in[1,1000] ∀ai∈[1,1000])。要求执行 q q q 次操作&…...
Google最新生图模型Gemini-2.0-Flash-Exp免费用
Google发布新生图模型 Google释放出最新生图模型,在发布说明中提到: 2025年3月12日 在 Gemini-2.0-Flash-Exp 中发布原生图像输出功能 Gemini 2.0 Flash Experimental 模型发布,支持原生图像输出功能。开发者能够使用 Gemini 进行图像输出和…...
windows安装Elasticsearch
下载 下载最新版 https://www.elastic.co/downloads/elasticsearch 下载历史版本 安装 进入bin目录中 成功启动 访问 http://localhost:9200...
vulnhub靶场之stapler靶机
前言 靶机:stapler靶机,IP地址为192.168.10.12 攻击:kali,IP地址为192.168.10.6 靶机采用virtualbox,攻击机采用VMware虚拟机,都采用桥接网卡模式 文章涉及的靶机及工具,都可以自行访问官网或…...
2025年AI搜索引擎开源项目全景指南:从核心框架到生态工具
2025年AI搜索引擎开源项目全景指南:从核心框架到生态工具 在人工智能技术迅猛发展的当下,开源项目已成为构建AI搜索引擎的核心驱动力。本文整理9个具有代表性的开源项目,涵盖搜索框架、扩展生态及底层支持技术,助你快速搭建或优化…...
数字孪生像魔镜,映照出无限可能的未来
在当今科技飞速发展的时代,数字孪生作为一项极具潜力的前沿技术,正逐渐崭露头角,成为众多领域关注的焦点。它犹如一面神奇的魔镜,以数字化的方式精准映照出现实世界中的各种实体与系统,为我们开启了一扇通往无限可能未…...
PDF Reader
Acrobat Reader...
C++友元
1.什么是友元? 当我们需要在类的外部访问该类的私有成员和保护成员时,就可以利用友元来实现这一操作 在类中用 friend 关键字对函数或类进行声明 2.非成员函数友元 友元函数不是当前类的成员函数,而是当前类的外部函数,但是他可以…...
吴恩达机器学习笔记复盘(五)均方误差函数
只讲了线性回归的代价函数。 均方误差(Mean Squared Error, MSE) 均方误差(MSE)基于最小二乘法,通过计算预测值与真实值之间差值的平方的平均值来衡量模型的误差。 原理 假设我们有一组数据集,其中是第…...
使用 Docker 部署前端项目全攻略
文章目录 1. Docker 基础概念1.1 核心组件1.2 Docker 工作流程 2. 环境准备2.1 安装 Docker2.2 验证安装 3. 项目配置3.1 项目结构3.2 创建 Dockerfile 4. 构建与运行4.1 构建镜像4.2 运行容器4.3 访问应用 5. 使用 Docker Compose5.1 创建 docker-compose.yml5.2 启动服务5.3 …...
珠算与珠心算发展简介
珠算是中华传统优秀文化的科学遗产,它是我国劳动人民的伟大创造,被誉为中国的第五大发明,至今已有 1800 余年的历史。 珠算,是以算盘为工具,用手指拨动算珠进行数值计算的一门计算技术。同时,珠算又是一门科…...
基于SSM + JSP 的水果蔬菜商城
基于ssm的水果蔬菜商城系统前台和后台(源码安装视频数据库环境)计算机项目程序设计管理系统java小程序网站商城 一.相关技术 Java、Spring、Springboot、MVC、Mybatis、MySQL、SSM框架、Web、HTML、maven、JavaScript、css、vue 二.部署配置 1.IntelliJ …...
基于深度学习的蛀牙智能检测与语音提示系统【python源码+Pyqt5界面+数据集+训练代码】
《------往期经典推荐------》 一、AI应用软件开发实战专栏【链接】 项目名称项目名称1.【人脸识别与管理系统开发】2.【车牌识别与自动收费管理系统开发】3.【手势识别系统开发】4.【人脸面部活体检测系统开发】5.【图片风格快速迁移软件开发】6.【人脸表表情识别系统】7.【…...
Linux与深入HTTP序列化和反序列化
深入HTTP序列化和反序列化 本篇介绍 在上一节已经完成了客户端和服务端基本的HTTP通信,但是前面的传递并没有完全体现出HTTP的序列化和反序列化,为了更好得理解其工作流程,在本节会以更加具体的方式分析到HTTP序列化和反序列化 本节会在介绍…...
音视频入门基础:RTP专题(20)——通过FFprobe显示RTP流每个packet的信息
通过FFprobe命令: ffprobe -protocol_whitelist "file,rtp,udp" -of json -show_packets XXX.sdp 可以显示SDP描述的RTP流每个packet(数据包)的信息: 对于RTP流,上述的“packet”(数据包&#…...
Java Web 大文件上传优化:从困境到高效
文章目录 Java Web 大文件上传优化:从困境到高效一、优化前的困境(一)内存占用问题(二)上传速度缓慢(三)稳定性欠佳 二、优化后的实现方案(一)客户端(Vue&…...
C++——STL 常用的查找算法
算法简介: find //查找元素find_if //按条件查找元素adjacent_find //查找相邻重复元素binary_search //二分查找法count //统计元素个数count_if //按条件统计元素个数 1. find 功能描述: 查找指定元素,找到返回指定元素的迭…...
【一次成功】Win10本地化单机部署k8s v1.31.2版本及可视化看板
【一次成功】Win10本地化单机部署k8s v1.31.2版本及可视化看板 零、安装清单一、安装Docker Desktop软件1.1 安装前<启用或关闭Windows功能> 中的描红的三项1.2 查看软件版本1.3 配置Docker镜像 二、更新装Docker Desktop三、安装 k8s3.1 点击启动安装3.2 查看状态3.3 查…...
Vulkan视频解码decode显示display之同步
在ReleaseDisplayedPicture函数中消耗图片资源并且显示display完成,设置两个标志m_hasConsummerSignalFence true 和m_hasConsummerSignalSemaphore true virtual int32_t ReleaseDisplayedPicture(DecodedFrameRelease** pDecodedFramesRelease, uint32_t nu…...
专题|Python梯度提升实例合集:GBM、XGBoost、SMOTE重采样、贝叶斯、逻辑回归、随机森林分析信贷、破产数据...
全文链接:https://tecdat.cn/?p41051 分析师:Jiajie Shi,Yimeng Li 在当今数据驱动的时代,数据分析师和数据建模师面临着各式各样复杂且极具挑战性的任务。本专题合集便是围绕这些挑战展开的宝贵知识盛宴(点击文末“阅…...
4.0 相机引导XY轴控制螺丝枪打螺丝
假如一个产品的同一水平上要打6个螺钉,是通过伺服XY轴移动带动相机以及螺丝枪,由相机拍照,根据拍照后螺丝孔位置来引导伺服进行移动以对准螺丝孔位置的。步骤如下: 一、9点标定,即把相机与伺服的实际位置关联起来。步骤…...
【ElasticSearch】学习笔记
一、lucene的组成 segment是一个具备完整搜索功能的最小单元。 多个segment组成了一个单机文本检索库lucene。 inverted index:倒排索引,用于快速根据关键词找到对应的文章term index: 构建出关键词的目录树,解决了term dictionary数据量过大ÿ…...
Spring Boot整合RabbitMQ极简教程
一、消息队列能解决什么问题? 异步处理:解耦耗时操作(如发短信、日志记录)流量削峰:应对突发请求,避免系统过载应用解耦:服务间通过消息通信,降低依赖 二、快速整合RabbitMQ 1. 环…...
代码随想录-04-字符串-03.替换数字
替换数字 题目 给定一个字符串 s,它包含小写字母和数字字符,请编写一个函数,将字符串中的字母字符保持不变,而将每个数字字符替换为number。 例如,对于输入字符串 “a1b2c3”,函数应该将其转换为 “anum…...