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

[实战] linux驱动框架与驱动开发实战

linux驱动框架与驱动开发实战

  • Linux驱动框架与驱动开发实战
    • 一、Linux驱动框架概述
      • 1.1 Linux驱动的分类
      • 1.2 Linux驱动的基本框架
    • 二、Linux驱动关键API详解
      • 2.1 模块相关API
      • 2.2 字符设备驱动API
      • 2.3 内存管理API
      • 2.4 中断处理API
      • 2.5 PCI设备驱动API
    • 三、Xilinx XDMA驱动开发详解
      • 3.1 XDMA概述
      • 3.2 XDMA驱动开发步骤
        • 步骤1:定义PCI设备ID
        • 步骤2:定义驱动主结构体
        • 步骤3:实现PCI probe函数
        • 步骤4:实现文件操作接口
        • 步骤5:实现中断处理
        • 步骤6:实现DMA传输
        • 步骤7:实现remove函数
        • 步骤8:定义PCI驱动结构体并注册
      • 3.3 步骤总结
    • 四、XDMA驱动测试与调试
      • 4.1 加载驱动模块
      • 4.2 测试DMA传输
      • 4.3 常见问题调试
    • 五、性能优化技巧
      • 5.1 使用分散/聚集DMA
      • 5.2 实现零拷贝
      • 5.3 使用DMA池
    • 六、总结

Linux驱动框架与驱动开发实战

一、Linux驱动框架概述

Linux驱动是操作系统内核与硬件设备之间的桥梁,它使得硬件设备能够被操作系统识别和管理。Linux内核提供了一套完善的驱动框架,开发者可以基于这些框架开发各种硬件设备的驱动程序。

1.1 Linux驱动的分类

Linux驱动主要分为以下几类:

  1. 字符设备驱动:以字节流形式进行数据读写,如键盘、鼠标等
  2. 块设备驱动:以数据块为单位进行读写,如硬盘、SSD等
  3. 网络设备驱动:用于网络通信的设备,如网卡
  4. 其他特殊类型:如USB驱动、PCI驱动等框架驱动

Linux驱动模型分层:

用户空间
系统调用接口
VFS虚拟文件系统
字符设备驱动
块设备驱动
硬件设备

1.2 Linux驱动的基本框架

无论哪种类型的驱动,Linux都提供了相应的框架和接口。一个典型的Linux驱动包含以下组成部分:

  1. 模块加载和卸载函数module_init()module_exit()
  2. 文件操作接口file_operations结构体
  3. 设备注册与注销register_chrdev()等函数
  4. 中断处理request_irq()和中断处理函数
  5. 内存管理kmalloc(), ioremap()等函数
  6. 同步机制:自旋锁、信号量、互斥锁等

二、Linux驱动关键API详解

2.1 模块相关API

module_init(init_function);  // 指定模块加载时执行的函数
module_exit(exit_function);  // 指定模块卸载时执行的函数
MODULE_LICENSE("GPL");       // 声明模块许可证
MODULE_AUTHOR("Author");     // 声明模块作者
MODULE_DESCRIPTION("Desc"); // 声明模块描述

2.2 字符设备驱动API

// 注册字符设备
int register_chrdev(unsigned int major, const char *name, const struct file_operations *fops);// 注销字符设备
void unregister_chrdev(unsigned int major, const char *name);// 文件操作结构体
struct file_operations {struct module *owner;loff_t (*llseek) (struct file *, loff_t, int);ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long);int (*open) (struct inode *, struct file *);int (*release) (struct inode *, struct file *);// 其他操作...
};

2.3 内存管理API

// 内核内存分配
void *kmalloc(size_t size, gfp_t flags);
void kfree(const void *objp);// 物理地址映射
void *ioremap(phys_addr_t offset, unsigned long size);
void iounmap(void *addr);// 用户空间与内核空间数据拷贝
unsigned long copy_to_user(void __user *to, const void *from, unsigned long n);
unsigned long copy_from_user(void *to, const void __user *from, unsigned long n);

2.4 中断处理API

// 申请中断
int request_irq(unsigned int irq, irq_handler_t handler, unsigned long flags,const char *name, void *dev);// 释放中断
void free_irq(unsigned int irq, void *dev_id);// 中断处理函数原型
irqreturn_t irq_handler(int irq, void *dev_id);

2.5 PCI设备驱动API

// PCI设备ID表
static const struct pci_device_id ids[] = {{ PCI_DEVICE(VENDOR_ID, DEVICE_ID) },{ 0, }
};
MODULE_DEVICE_TABLE(pci, ids);// PCI驱动结构体
static struct pci_driver pci_driver = {.name = "xdma_driver",.id_table = ids,.probe = xdma_probe,.remove = xdma_remove,// 其他回调...
};// 注册PCI驱动
pci_register_driver(&pci_driver);// 注销PCI驱动
pci_unregister_driver(&pci_driver);

三、Xilinx XDMA驱动开发详解

3.1 XDMA概述

Xilinx DMA (XDMA) 是一种高性能的DMA控制器,用于在FPGA和主机内存之间传输数据。XDMA驱动通常作为PCIe设备驱动实现,支持DMA传输、中断处理等功能。

PCIe
AXI总线
Host CPU
XDMA引擎
FPGA逻辑

其实现DMA传输流程如下:

User Kernel DMA引擎 write()系统调用 配置源地址/目标地址 传输完成中断 唤醒等待进程 User Kernel DMA引擎

3.2 XDMA驱动开发步骤

步骤1:定义PCI设备ID
#define PCI_VENDOR_ID_XILINX 0x10ee
#define PCI_DEVICE_ID_XDMA 0x7028static const struct pci_device_id xdma_pci_ids[] = {{ PCI_DEVICE(PCI_VENDOR_ID_XILINX, PCI_DEVICE_ID_XDMA) },{ 0, }
};
MODULE_DEVICE_TABLE(pci, xdma_pci_ids);
步骤2:定义驱动主结构体
struct xdma_dev {struct pci_dev *pdev;void __iomem *bar[MAX_BARS];  // PCI BAR空间映射int irq;                     // 中断号struct cdev cdev;            // 字符设备dev_t devno;                 // 设备号struct dma_chan *dma_chan;   // DMA通道// 其他设备特定数据...
};
步骤3:实现PCI probe函数

PCI设备探测流程:

Kernel PCIe设备 驱动 扫描PCI总线 返回Vendor/Device ID 调用probe()函数 Kernel PCIe设备 驱动

具体探测函数(probe)实现:

static int xdma_probe(struct pci_dev *pdev, const struct pci_device_id *id)
{struct xdma_dev *xdev;int err, i;// 1. 分配设备结构体xdev = devm_kzalloc(&pdev->dev, sizeof(*xdev), GFP_KERNEL);if (!xdev)return -ENOMEM;xdev->pdev = pdev;pci_set_drvdata(pdev, xdev);// 2. 使能PCI设备err = pci_enable_device(pdev);if (err) {dev_err(&pdev->dev, "Failed to enable PCI device\n");goto fail;}// 3. 请求PCI资源err = pci_request_regions(pdev, "xdma");if (err) {dev_err(&pdev->dev, "Failed to request PCI regions\n");goto disable_device;}// 4. 映射BAR空间for (i = 0; i < MAX_BARS; i++) {if (!pci_resource_len(pdev, i))continue;xdev->bar[i] = pci_iomap(pdev, i, pci_resource_len(pdev, i));if (!xdev->bar[i]) {dev_err(&pdev->dev, "Failed to map BAR%d\n", i);err = -ENOMEM;goto release_regions;}}// 5. 设置DMA掩码err = pci_set_dma_mask(pdev, DMA_BIT_MASK(64));if (err) {err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));if (err) {dev_err(&pdev->dev, "No suitable DMA available\n");goto unmap_bars;}}// 6. 申请中断xdev->irq = pdev->irq;err = request_irq(xdev->irq, xdma_irq_handler, IRQF_SHARED, "xdma", xdev);if (err) {dev_err(&pdev->dev, "Failed to request IRQ\n");goto unmap_bars;}// 7. 初始化DMA引擎err = xdma_init_dma(xdev);if (err)goto free_irq;// 8. 注册字符设备err = xdma_setup_cdev(xdev);if (err)goto deinit_dma;dev_info(&pdev->dev, "XDMA driver loaded successfully\n");return 0;// 错误处理...
}// 初始化DMA引擎
static int xdma_init_dma(struct xdma_dev *xdev)
{dma_cap_mask_t mask;dma_cap_zero(mask);dma_cap_set(DMA_MEMCPY, mask);xdev->dma_chan = dma_request_channel(mask, NULL, NULL);if (!xdev->dma_chan) {dev_err(&xdev->pdev->dev, "Failed to get DMA channel\n");return -ENODEV;}return 0;
}// 设置字符设备
static int xdma_setup_cdev(struct xdma_dev *xdev)
{int err;dev_t devno;err = alloc_chrdev_region(&devno, 0, 1, "xdma");if (err < 0) {dev_err(&xdev->pdev->dev, "Failed to allocate device number\n");return err;}xdev->devno = devno;cdev_init(&xdev->cdev, &xdma_fops);xdev->cdev.owner = THIS_MODULE;err = cdev_add(&xdev->cdev, devno, 1);if (err) {dev_err(&xdev->pdev->dev, "Failed to add cdev\n");unregister_chrdev_region(devno, 1);return err;}return 0;
}
步骤4:实现文件操作接口
static const struct file_operations xdma_fops = {.owner = THIS_MODULE,.open = xdma_open,.release = xdma_release,.read = xdma_read,.write = xdma_write,.unlocked_ioctl = xdma_ioctl,.llseek = no_llseek,
};static int xdma_open(struct inode *inode, struct file *filp)
{struct xdma_dev *xdev = container_of(inode->i_cdev, struct xdma_dev, cdev);filp->private_data = xdev;return 0;
}static int xdma_release(struct inode *inode, struct file *filp)
{filp->private_data = NULL;return 0;
}static ssize_t xdma_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos)
{struct xdma_dev *xdev = filp->private_data;// 实现DMA读取操作...return count;
}static ssize_t xdma_write(struct file *filp, const char __user *buf, size_t count, loff_t *f_pos)
{struct xdma_dev *xdev = filp->private_data;// 实现DMA写入操作...return count;
}static long xdma_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{struct xdma_dev *xdev = filp->private_data;switch (cmd) {case XDMA_IOCTL_START_DMA:// 启动DMA传输break;case XDMA_IOCTL_STOP_DMA:// 停止DMA传输break;case XDMA_IOCTL_GET_STATUS:// 获取DMA状态break;default:return -ENOTTY;}return 0;
}
步骤5:实现中断处理
static irqreturn_t xdma_irq_handler(int irq, void *dev_id)
{struct xdma_dev *xdev = dev_id;u32 status;// 读取中断状态寄存器status = ioread32(xdev->bar[0] + XDMA_IRQ_STATUS_REG);if (status & XDMA_IRQ_DONE) {// DMA传输完成中断complete(&xdev->dma_complete);}if (status & XDMA_IRQ_ERROR) {// DMA错误中断dev_err(&xdev->pdev->dev, "DMA error occurred\n");}// 清除中断状态iowrite32(status, xdev->bar[0] + XDMA_IRQ_STATUS_REG);return IRQ_HANDLED;
}
步骤6:实现DMA传输
static int xdma_do_transfer(struct xdma_dev *xdev, dma_addr_t src, dma_addr_t dst, size_t len)
{struct dma_async_tx_descriptor *tx;struct dma_device *dma_dev = xdev->dma_chan->device;enum dma_ctrl_flags flags = DMA_CTRL_ACK | DMA_PREP_INTERRUPT;dma_cookie_t cookie;int err;// 准备DMA描述符tx = dma_dev->device_prep_dma_memcpy(xdev->dma_chan, dst, src, len, flags);if (!tx) {dev_err(&xdev->pdev->dev, "Failed to prepare DMA descriptor\n");return -EIO;}tx->callback = xdma_dma_callback;tx->callback_param = xdev;// 提交DMA传输cookie = dmaengine_submit(tx);err = dma_submit_error(cookie);if (err) {dev_err(&xdev->pdev->dev, "Failed to submit DMA transfer\n");return err;}// 触发DMA传输dma_async_issue_pending(xdev->dma_chan);// 等待传输完成if (!wait_for_completion_timeout(&xdev->dma_complete, msecs_to_jiffies(1000))) {dev_err(&xdev->pdev->dev, "DMA transfer timeout\n");dmaengine_terminate_all(xdev->dma_chan);return -ETIMEDOUT;}return 0;
}static void xdma_dma_callback(void *data)
{struct xdma_dev *xdev = data;complete(&xdev->dma_complete);
}
步骤7:实现remove函数
static void xdma_remove(struct pci_dev *pdev)
{struct xdma_dev *xdev = pci_get_drvdata(pdev);int i;// 1. 移除字符设备cdev_del(&xdev->cdev);unregister_chrdev_region(xdev->devno, 1);// 2. 释放DMA资源if (xdev->dma_chan)dma_release_channel(xdev->dma_chan);// 3. 释放中断free_irq(xdev->irq, xdev);// 4. 取消BAR空间映射for (i = 0; i < MAX_BARS; i++) {if (xdev->bar[i])pci_iounmap(pdev, xdev->bar[i]);}// 5. 释放PCI资源pci_release_regions(pdev);// 6. 禁用PCI设备pci_disable_device(pdev);// 7. 释放设备结构体devm_kfree(&pdev->dev, xdev);dev_info(&pdev->dev, "XDMA driver unloaded\n");
}
步骤8:定义PCI驱动结构体并注册
static struct pci_driver xdma_driver = {.name = "xdma",.id_table = xdma_pci_ids,.probe = xdma_probe,.remove = xdma_remove,
};static int __init xdma_init(void)
{return pci_register_driver(&xdma_driver);
}static void __exit xdma_exit(void)
{pci_unregister_driver(&xdma_driver);
}module_init(xdma_init);
module_exit(xdma_exit);MODULE_LICENSE("GPL");
MODULE_AUTHOR("Your Name");
MODULE_DESCRIPTION("Xilinx XDMA Driver");

3.3 步骤总结

上文以xilinx XDMA 为例介绍了Linux PCI设备驱动开发步骤,总结成流程图如下:

Yes
No
驱动模块加载
module_init调用
PCI设备探测 probe
探测成功?
资源分配
映射BAR空间
申请中断
初始化DMA引擎
注册字符设备
错误处理
模块退出
用户空间操作
open/read/write
ioctl控制
mmap内存映射
DMA传输处理
中断处理
数据传输完成
module_exit调用
释放资源
注销字符设备
释放DMA资源
解除BAR映射
释放中断
禁用PCI设备

四、XDMA驱动测试与调试

4.1 加载驱动模块

# 加载驱动
sudo insmod xdma.ko# 查看加载的模块
lsmod | grep xdma# 查看内核日志
dmesg | tail

4.2 测试DMA传输

可以使用简单的用户空间程序测试DMA功能:

// test_xdma.c
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>#define XDMA_DEV "/dev/xdma"
#define BUF_SIZE (1024 * 1024)  // 1MBint main()
{int fd = open(XDMA_DEV, O_RDWR);if (fd < 0) {perror("Failed to open device");return -1;}// 分配测试缓冲区char *src = malloc(BUF_SIZE);char *dst = malloc(BUF_SIZE);if (!src || !dst) {perror("Failed to allocate buffers");close(fd);return -1;}// 填充源缓冲区memset(src, 0xAA, BUF_SIZE);memset(dst, 0, BUF_SIZE);// 写入数据到设备ssize_t written = write(fd, src, BUF_SIZE);printf("Written %zd bytes to device\n", written);// 从设备读取数据ssize_t readed = read(fd, dst, BUF_SIZE);printf("Read %zd bytes from device\n", readed);// 验证数据if (memcmp(src, dst, BUF_SIZE) {printf("Data verification failed!\n");} else {printf("Data verification passed!\n");}free(src);free(dst);close(fd);return 0;
}

4.3 常见问题调试

  1. PCI设备未识别

    • 检查lspci -nn确认设备ID是否正确
    • 确认内核配置中启用了PCI支持
  2. DMA传输失败

    • 检查DMA掩码设置
    • 确认物理地址是否正确
    • 检查DMA引擎是否支持所需操作
  3. 中断不触发

    • 确认中断号是否正确
    • 检查中断状态寄存器
    • 确认中断处理函数已正确注册

五、性能优化技巧

5.1 使用分散/聚集DMA

static int xdma_sg_transfer(struct xdma_dev *xdev, struct scatterlist *sg_src,struct scatterlist *sg_dst,int sg_count)
{struct dma_async_tx_descriptor *tx;struct dma_device *dma_dev = xdev->dma_chan->device;enum dma_ctrl_flags flags = DMA_CTRL_ACK | DMA_PREP_INTERRUPT;dma_cookie_t cookie;int err;tx = dma_dev->device_prep_dma_sg(xdev->dma_chan, sg_dst, sg_count,sg_src, sg_count,flags);if (!tx) {dev_err(&xdev->pdev->dev, "Failed to prepare SG DMA descriptor\n");return -EIO;}tx->callback = xdma_dma_callback;tx->callback_param = xdev;cookie = dmaengine_submit(tx);err = dma_submit_error(cookie);if (err) {dev_err(&xdev->pdev->dev, "Failed to submit SG DMA transfer\n");return err;}dma_async_issue_pending(xdev->dma_chan);if (!wait_for_completion_timeout(&xdev->dma_complete, msecs_to_jiffies(1000))) {dev_err(&xdev->pdev->dev, "SG DMA transfer timeout\n");dmaengine_terminate_all(xdev->dma_chan);return -ETIMEDOUT;}return 0;
}

5.2 实现零拷贝

static int xdma_mmap(struct file *filp, struct vm_area_struct *vma)
{struct xdma_dev *xdev = filp->private_data;unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;unsigned long size = vma->vm_end - vma->vm_start;int ret;// 将BAR空间映射到用户空间if (offset >= pci_resource_len(xdev->pdev, 0) || size > pci_resource_len(xdev->pdev, 0) - offset) {return -EINVAL;}ret = remap_pfn_range(vma, vma->vm_start,(pci_resource_start(xdev->pdev, 0) + offset) >> PAGE_SHIFT,size, vma->vm_page_prot);if (ret)return -EAGAIN;return 0;
}

5.3 使用DMA池

// 初始化DMA池
xdev->dma_pool = dma_pool_create("xdma_pool", &xdev->pdev->dev,POOL_SIZE, POOL_ALIGN, 0);
if (!xdev->dma_pool) {dev_err(&xdev->pdev->dev, "Failed to create DMA pool\n");return -ENOMEM;
}// 从DMA池分配内存
void *buf = dma_pool_alloc(xdev->dma_pool, GFP_KERNEL, &dma_handle);
if (!buf) {dev_err(&xdev->pdev->dev, "Failed to allocate from DMA pool\n");return -ENOMEM;
}// 释放DMA池内存
dma_pool_free(xdev->dma_pool, buf, dma_handle);// 销毁DMA池
dma_pool_destroy(xdev->dma_pool);

六、总结

本文详细介绍了Linux驱动框架和关键API,并以Xilinx XDMA驱动为例,展示了Linux驱动开发的完整流程。关键点包括:

  1. 理解Linux驱动框架:掌握字符设备、块设备和网络设备驱动的基本结构
  2. 熟悉关键API:模块加载、文件操作、内存管理、中断处理等核心API
  3. PCI驱动开发:从设备发现到资源管理的完整流程
  4. DMA传输实现:包括标准DMA和分散/聚集DMA
  5. 驱动调试技巧:日志分析、用户空间测试程序等

通过XDMA驱动的实例,我们可以看到Linux驱动开发需要综合考虑硬件特性、内核API和性能优化等多个方面。希望本文能为Linux驱动开发者提供有价值的参考。

相关文章:

[实战] linux驱动框架与驱动开发实战

linux驱动框架与驱动开发实战 Linux驱动框架与驱动开发实战一、Linux驱动框架概述1.1 Linux驱动的分类1.2 Linux驱动的基本框架 二、Linux驱动关键API详解2.1 模块相关API2.2 字符设备驱动API2.3 内存管理API2.4 中断处理API2.5 PCI设备驱动API 三、Xilinx XDMA驱动开发详解3.1…...

【详细】MySQL 8 安装解压即用 (包含MySQL 5 卸载)

卸载MySQL 1.卸载 2.安装目录删除残余文件&#xff08;当初安装的位置&#xff09; 3.删除programData下面的mysql数据文件 4.检查mysql服务是否存在&#xff0c;如果存在则删除&#xff08;先暂停mysql服务&#xff09; sc delete mysql 5.删除注册表中残留信息 安装MySQL 8&…...

Linux:(五种IO模型)

目录 一、对IO的重新认识 二、IO的五种模型 1.阻塞IO 2.非阻塞IO 3.信号驱动IO 4.IO多路转接 5.异步IO 6.一些概念的解释 三、非阻塞IO的代码实现 1.fcntl 2.实现主程序 一、对IO的重新认识 如果有人问你IO是什么&#xff0c;你该怎么回答呢&#xff1f; 你可能会说…...

初识数据结构——Java包装类与泛型:从入门到源码解析

【深入浅出】Java包装类与泛型&#xff1a;从入门到源码解析 &#x1f31f; 一、开篇一问&#xff1a;为什么我们需要包装类&#xff1f; Java作为一门"面向对象"的语言&#xff0c;却保留了8个"非对象"的基本数据类型&#xff08;有传言说&#xff0c;是…...

【计算机网络】Linux配置SNAT策略

什么是NAT&#xff1f; NAT 全称是 Network Address Translation&#xff08;网络地址转换&#xff09;&#xff0c;是一个用来在多个设备共享一个公网 IP上网的技术。 NAT 的核心作用&#xff1a;将一个网络中的私有 IP 地址&#xff0c;转换为公网 IP 地址&#xff0c;从而…...

与 AI 共舞:解锁自我提升的无限可能

与 AI 共舞&#xff1a;解锁自我提升的无限可能 在数字化浪潮的汹涌冲击下&#xff0c;人工智能&#xff08;AI&#xff09;正以前所未有的速度重塑着世界的每一个角落。从日常生活的点滴便利到复杂工作的高效推进&#xff0c;AI 的力量无处不在。然而&#xff0c;面对 AI 的强…...

Android学习总结之算法篇五(字符串)

字符串求回文字串数目 public class CountPalindromicSubstrings {/*** 此方法用于计算字符串中回文子串的数量* param s 输入的字符串* return 回文子串的数量*/public static int countSubstrings(String s) {// 若输入字符串为空或长度为 0&#xff0c;直接返回 0if (s nu…...

使用人车关系核验API快速核验车辆一致性

一、 引言 随着车辆交易的日益频繁&#xff0c;二手车市场和金融领域的汽车抵押业务蓬勃发展。然而&#xff0c;欺诈和盗窃行为也时有发生&#xff0c;给行业带来了不小的冲击。例如&#xff0c;3月20日央视曝光的“新能源车虚假租赁骗补”产业链&#xff0c;以及某共享汽车平…...

day 8 TIM定时器

一、STM32 定时器概述 1. 定时器的概述定时器的基本功能&#xff0c;但是 STM32 的定时器除了具有定时功能之外&#xff0c;也具有定时器中断功能&#xff0c;还具有输入捕获&#xff08;检测外部信号&#xff09;以及输出比较功能&#xff08;输出不同的脉冲&#xff09;&…...

硬币找零问题

硬币找零问题&#xff1a;假设需要找零的金额为C&#xff0c;最少要用多少面值为p1<p2<…<pn的硬币&#xff08;面值种类为n&#xff0c;且假设每种面值的硬币都足够多&#xff09;​&#xff1f; 贪心算法的基本原理是&#xff1a;遵循某种既定原则&#xff0c;不断…...

【微机及接口技术】- 第四章 内部存储器及其接口(上)

文章目录 第一节一、存储器的分类二、存储器的层次结构 第二节 半导体存储器一、半导体存储器的基本结构二、半导体存储器的分类1. 只读存储器 ROM2. 随机存储器 RAM 三、内存的主要性能指标1. 存储容量2. 存取时间3. 存取周期4. 可靠性5. 性价比 四、典型的半导体存储器芯片 本…...

tomcat的web三大组件Sciidea搭建web/maven的tomcat项目

文章目录 1. web项目的搭建1. 创建web项目2.修改web.xml版本3.添加servlet、jsp依赖4.servlet示例&#xff08;使用注解&#xff09;5.配置tomcat6.添加artifact7.部署8.启动tomcat、访问9.打war包10.部署到tomcat 2.maven的项目搭建1.创建项目图解 2.tomcat启动方式图解idea打…...

《SQL赋能人工智能:解锁特征工程的隐秘力量》

在当今的科技发展进程中&#xff0c;人工智能&#xff08;AI&#xff09;已经成为推动各领域变革的核心驱动力。而在人工智能的庞大体系里&#xff0c;特征工程占据着举足轻重的地位&#xff0c;它是将原始数据转化为能够让模型有效学习的特征的关键环节。鲜有人深入探讨的是&a…...

SQLmap工具使用

1. sqlmap介绍 sqlmap是一款自动化的SQL注入工具&#xff0c;用于检测和利用web应用程序中的SQL注入漏洞。不需要我们进行手注&#xff0c;当我们输入url地址后&#xff0c;会自动进行注入指令并将payload返回显示。 在kali中自带。在本机中需要下载&#xff0c;在相应的路径…...

Kubernetes集群管理详解:从入门到精通

1. 引言 Kubernetes(简称k8s)作为当今最流行的容器编排平台,已成为云原生应用部署和管理的事实标准。本文将深入探讨k8s集群管理的各个方面,为运维工程师和开发人员提供一个全面的指南。 2. Kubernetes架构概览 在深入具体的管理任务之前,让我们先回顾一下Kubernetes的基本架…...

【含文档+PPT+源码】基于Python的全国景区数据分析以及可视化实现

项目介绍 本课程演示的是一款基于Python的全国景区数据分析以及可视化实现&#xff0c;主要针对计算机相关专业的正在做毕设的学生与需要项目实战练习的 Java 学习者。 包含&#xff1a;项目源码、项目文档、数据库脚本、软件工具等所有资料 带你从零开始部署运行本套系统 该…...

鸿蒙开发者高级认证编程题库

题目一:跨设备分布式数据同步 需求描述 开发一个分布式待办事项应用,要求: 手机与平板登录同一华为账号时,自动同步任务列表任一设备修改任务状态(完成/删除),另一设备实时更新任务数据在设备离线时能本地存储,联网后自动同步实现方案 // 1. 定义分布式数据模型 imp…...

【网络安全】安全的网络设计

网络设计是网络安全的基础&#xff0c;一个好的网络设计可以有效的防止攻击者的入侵。在本篇文章中&#xff0c;我们将详细介绍如何设计一个安全的网络&#xff0c;包括网络架构&#xff0c;网络设备&#xff0c;网络策略&#xff0c;以及如何处理网络安全事件。 一、网络架构…...

基于FLask的重庆市造价工程信息数据可视化分析系统

【FLask】基于FLask的重庆市造价工程信息数据可视化分析系统 &#xff08;完整系统源码开发笔记详细部署教程&#xff09;✅ 目录 一、项目简介二、项目界面展示三、项目视频展示 一、项目简介 在当今快速发展的建筑工程行业中&#xff0c;造价信息的准确性和时效性对于项目决…...

swift-08-属性、汇编分析inout本质

一、Swift中跟实例相关的属性可以分为2大类 1.1 存储属性&#xff08; Stored Property&#xff09; 类似于成员变量这个概念 存储在实例的内存中 结构体、类可以定义存储属性 枚举不可以定义存储属性&#xff08;因为枚举只存储关联值和case&#xff09; 1.2 计算属性&am…...

Java 大视界 -- Java 大数据在智能医疗远程护理与患者健康管理中的应用与前景(175)

&#x1f496;亲爱的朋友们&#xff0c;热烈欢迎来到 青云交的博客&#xff01;能与诸位在此相逢&#xff0c;我倍感荣幸。在这飞速更迭的时代&#xff0c;我们都渴望一方心灵净土&#xff0c;而 我的博客 正是这样温暖的所在。这里为你呈上趣味与实用兼具的知识&#xff0c;也…...

大数据技术发展与应用趋势分析

大数据技术发展与应用趋势分析 文章目录 大数据技术发展与应用趋势分析1. 大数据概述2 大数据技术架构2.1 数据采集层2.2 数据存储层2.3 数据处理层2.4 数据分析层 3 大数据发展趋势3.1 AI驱动的分析与自动化3.2 隐私保护分析技术3.3 混合云架构的普及3.4 数据网格架构3.5 量子…...

如何在Ubuntu上安装Dify

如何在Ubuntu上安装Dify 如何在Ubuntu上安装docker 使用apt安装 # Add Dockers official GPG key: sudo apt-get update sudo apt-get install ca-certificates curl sudo install -m 0755 -d /etc/apt/keyrings sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg…...

ffmpeg音频分析

对一个16k 单声道音频&#xff0c;生成频谱图 ./ffmpeg -i input.wav -lavfi "showspectrumpics800x400:modecombined:scalelin:gain1.5" spectrum.png...

每天五分钟深度学习框架pytorch:搭建LSTM完成手写字体识别任务?

本文重点 前面我们学习了LSTM的搭建,我们也学习过很多卷积神经网络关于手写字体的识别,本文我们使用LSTM来完成手写字体的识别。 网络模型的搭建 class RNN(nn.Module):def __init__(self,in_dim,hidden_dim,n_layer,n_class):super(RNN,self).__init__()self.n_layer=n_la…...

Maven工具学习使用(七)——Maven属性

内置属性 主要有两个常用的属性${basedir}表示项目的根目录,即包含pom.xml文件的目录;$[version]表示项目版本。 POM属性 使用该类属性引用POM文件中对应元素的值。例如${project.artifactId}就对应了元素的值,常用的POM属性包括: ${project.build.sourceDirectory} 项…...

【Linux网络与网络编程】05.应用层自定义协议序列化和反序列化

前言 本篇博客通过网络计算器的实现来帮助各位理解应用层自定义协议以及序列化和反序列化。 一、认识自定义协议&&序列化和反序列化 我们程序员写的一个个解决我们实际问题&#xff0c;满足我们日常需求的网络程序都是在应用层。前面我们说到&#xff1a;协议是一种…...

搭建K8S-1.23

0、简介 这里只用3台服务器来做一个简单的集群 地址主机名192.168.160.40kuber-master-1192.168.160.41kuber-master-2192.168.160.42kuber-node-1 1、关闭三个服务 &#xff08;1&#xff09;防火墙 systemctl stop firewalld &#xff08;2&#xff09;Selinux setenf…...

解决Spring Boot Test中的ByteBuddy类缺失问题

目录 解决Spring Boot Test中的ByteBuddy类缺失问题前奏问题描述问题解决第一步&#xff1a;移除ByteBuddy的特定版本号第二步&#xff1a;更新maven-surefire-plugin配置第三步&#xff1a;清理并重新构建项目 结语 解决Spring Boot Test中的ByteBuddy类缺失问题 前奏 今天&…...

npm 项目命名规则

以下是 npm 项目命名规则的详细说明&#xff1a; 一、核心命名规则 必须使用小写字母 名称中不能包含大写字母。原因&#xff1a; 跨平台兼容性&#xff08;如 Linux 区分大小写&#xff0c;而 Windows 不区分&#xff09;。避免命令行和 URL 中的大小写冲突&#xff08;例如包…...

#SVA语法滴水穿石# (012)关于 first_match、throughout、within 的用法

我们今天学习&#xff0c; SystemVerilog 断言&#xff08;SVA&#xff09;中 first_match、throughout、within 运算符。 1. first_match 定义与作用 功能&#xff1a;在可能产生 多个匹配结果 的复合序列&#xff08;如 or 或重复操作符&#xff09;中&#xff0c;仅选择第…...

基于springboot+vue的二手车交易系统

开发语言&#xff1a;Java框架&#xff1a;springbootJDK版本&#xff1a;JDK1.8服务器&#xff1a;tomcat7数据库&#xff1a;mysql 5.7&#xff08;一定要5.7版本&#xff09;数据库工具&#xff1a;Navicat11开发软件&#xff1a;eclipse/myeclipse/ideaMaven包&#xff1a;…...

洛谷P11999.投入严厉地本地

洛谷P11999.投入严厉地本地 题目 题目解析及思路 题目要求根据两个字符串s和t&#xff0c;反推出一个映射集合f&#xff0c;其中s的每一个长度为k的子串都可以映射成单个字符或空字符 算出最终映射集合有多少个空字符&#xff0c;用全排列函数去搜索所有情况&#xff0c;判断…...

低代码开发平台:飞帆中新增控件、修改他人控件

飞帆是一个自由的控件平台。所有的网页都由控件搭建而成。 在我的资源、我的控件中&#xff0c;点击新增可以新增控件 对于他人的控件&#xff0c;点击复制控件展开&#xff0c;点击复制到我的控件 飞帆中的控件是使用 Vue2 来实现的...

Openstack指南

什么是云计算 概念 云计算是一种基于互联网的计算方式&#xff0c;通过这种方式&#xff0c;共享的软硬件资源和信息&#xff0c;可以按需求提供给计算机和其他设备。用户不需要了解”云“中的基础设施细节&#xff0c;不必具有相应的专业知识&#xff0c;也无需直接控制。云…...

[自制调试工具]构建高效调试利器:Debugger 类详解

一、引言 在软件开发的漫漫征程中&#xff0c;调试就像是一位忠诚的伙伴&#xff0c;时刻陪伴着开发者解决代码里的各类问题。为了能更清晰地了解程序运行时变量的状态&#xff0c;我们常常需要输出各种变量的值。而 Debugger 类就像是一个贴心的调试助手&#xff0c;它能帮我…...

【网络IP】原生IP是什么?如何获取海外原生IP?

一、什么是原生IP 原生IP地址是互联网服务提供商&#xff08;ISP&#xff09;直接分配给用户的真实IP地址&#xff0c;无需代理或转发。这类IP的注册国家与IP所在服务器的注册地相符。这种IP地址直接与用户的设备或网络关联&#xff0c;不会被任何中间服务器或代理转发或隐藏。…...

【小沐学Web3D】three.js 加载三维模型(React Three Fiber)

文章目录 1、简介1.1 Three.js1.2 React Three Fiber 2、测试2.1 初始化环境2.2 app.js修改&#xff08;显示内置立方体&#xff09;2.3 app.js修改&#xff08;显示内置球体&#xff09;2.4 app.js修改&#xff08;显示自定义立方体&#xff09;2.5 app.js修改&#xff08;显示…...

HTTP查询参数示例(XMLHttpRequest查询参数)(带查询参数的HTTP接口示例——以python flask接口为例)flask查询接口

文章目录 HTTP查询参数请求示例接口文档——获取城市列表代码示例效果 带查询参数的HTTP接口示例——以python flask接口为例app.pyREADME.md运行应用API示例客户端示例关键实现说明&#xff1a;运行方法&#xff1a; HTTP查询参数请求示例 接口文档——获取城市列表 代码示例…...

【玩泰山派】1、mac上使用串口连接泰山派

文章目录 前言picocom工具连接泰山派安装picocom工具安装ch340的驱动串口工具接线使用picocom连接泰山派 参考 前言 windows上面有xshell这个好用的工具可以使用串口连接板子&#xff0c;在mac上好像没找到太好的工具&#xff0c;只能使用命令行工具去搞了。 之前查找说mac上…...

【玩泰山派】0、mac utm安装windows10

文章目录 前言安装过程utm安装下载windows ios镜像安装windows系统解决共享文件夹拷贝受限问题 参考 前言 使用mac开发泰山派&#xff0c;但是买的泰山派没有emmc&#xff0c;只有sd卡&#xff0c;要使用瑞芯微的sd卡烧录工具&#xff0c;这个工具好像只支持windows&#xff0…...

html 给文本两端加虚线自适应

效果图&#xff1a; <div class"separator">文本 </div>.separator {width: 40%;border-style: dashed;display: flex;align-items: center;color: #e2e2e2;font-size: 14px;line-height: 20px;border-color: #e2e2e2;border-width: 0; }.separator::bef…...

Android学习总结之应用启动流程(从点击图标到界面显示)

一、用户交互触发&#xff1a;Launcher 到 AMS 的跨进程通信 1. Launcher 处理点击事件&#xff08;应用层&#xff09; 当用户点击手机桌面上的应用图标时&#xff0c;Launcher&#xff08;桌面应用&#xff09;首先捕获点击事件。每个图标对应一个启动 Intent&#xff08;通…...

Vue2与Vue3不同

Vue3 设计思想与核心变化详解 一、Vue3 设计思想与 Vue2 差异对比 响应式系统重构Vue2 实现&#xff08;基于 Object.defineProperty&#xff09; // 在 Vue2 中&#xff0c;通过 data 选项返回一个对象&#xff0c;对象中的属性会被 Object.defineProperty 转换为响应式数据…...

《Java实战:素数检测算法优化全解析——从暴力枚举到筛法进阶》

文章目录 摘要一、需求分析二、基础实现代码与问题原始代码&#xff08;暴力枚举法&#xff09;问题分析 三、优化版代码与解析优化1&#xff1a;平方根范围剪枝优化2&#xff1a;偶数快速跳过完整优化代码 四、性能对比五、高阶优化&#xff1a;埃拉托斯特尼筛法算法思想代码实…...

解决报错:node:internal/errors:496 ErrorCaptureStackTrace(err);

报错信息 我使用npm init vuelatest创建项目时出现如下报错 node:internal/errors:496 ErrorCaptureStackTrace(err); ^ TypeError [ERR_IMPORT_ASSERTION_TYPE_MISSING]: Module “file:///D:/develop/nodejs/node_cache/_npx/2f7e7bff16d1c534/node_modules/create-vue/loc…...

【Linux笔记】进程管理章节笔记

一、进程与线程的概念 1、进程 1&#xff09;概念 进程是程序的执行实例&#xff0c;拥有独立的资源&#xff08;如内存、文件描述符等&#xff09;。每个进程在创建时会被分配唯一的进程ID&#xff0c;即为PID&#xff0c;也叫进程编号。 2&#xff09;特点 资源隔离&#…...

使用Webpack搭建React项目:从零开始

&#x1f90d; 前端开发工程师、技术日更博主、已过CET6 &#x1f368; 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 &#x1f560; 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》、《前端求职突破计划》 &#x1f35a; 蓝桥云课签约作者、…...

使用Cusor 生成 Figma UI 设计稿

一、开发环境 系统&#xff1a;MacOS 软件版本&#xff1a; Figma&#xff08;网页或APP版&#xff09; 注&#xff1a;最好是app版&#xff0c;网页版figma 没有选项 import from manifest app下载地址&#xff1a;Figma Downloads | Web Design App for Desktops & …...

前端 vs 后端:技术分工详解——从用户界面到系统逻辑的全解析

前端&#xff08;Frontend&#xff09; 和 后端&#xff08;Backend&#xff09; 是软件开发中两个核心概念&#xff0c;分别对应用户直接交互的部分和系统背后的逻辑处理部分。它们共同构成完整的应用程序&#xff0c;但分工不同。 目录 一、前端&#xff08;Frontend&#xf…...