Linux驱动开发 中断处理
目录
序言
1.中断的概念
2.如何使用中断
中断处理流程
中断上下文限制
屏蔽中断/使能
关键区别与选择
上半部中断
下半部中断
软中断(SoftIRQ)
小任务(Tasklet)
工作队列(Workqueue)
线程 IRQ(Threaded IRQ)
下半部机制对比
3.其余中断的一些概念
中断共享
使用 request_irq() 注册共享中断
中断处理函数中的注意事项
释放共享中断
常见问题与注意事项
中断驱动I/O
4.总结
序言
在Linux驱动开发中,有着许许多多的进程,每一个线程可以代表需要执行的函数(任务),而CPU总是在这些线程中来回切换执行不同的线程(详情看OSTEP 第四章:线程),每一个线程都需要CPU执行。
先简单的理解一下中断的概念,比如你正在玩着游戏,突然有人敲门告诉你外卖到了,这时你就需要暂时离开你的电脑,到门外去拿外卖,然后回来继续玩游戏。
这里就是我们现实中的一个中断,由外界(硬件),内部(软件)打断当前事务,有限处理紧急事务,中断是硬件或软件发出的信号,通知 CPU 需要立即处理某个事件。硬件中断由外设(如网卡、键盘)触发,软件中断由程序调用(如系统调用)触发。
1.中断的概念
在Kernel内核中,中断被分为上半部和下半部(其实也不是一定要分成两部分,实际上简短的就直接上半部执行完了,或者直接将不紧急任务放入下半部分)
上半部:用于处理比较紧急的任务,例如简单地读取寄存器中的中断状态并清除中断标志后就进行“登记中断”的工作,但是上半部分不允许被中断!
ps:为什么上半部分不能被中断?因为没有其对应的中断上下文,当其进入中断后就无法被唤醒了,轻则死锁,严重时甚至会造成内核崩溃。
下半部:用于处理时间较长的任务(是中断的重心,基本大部分任务都在这执行),下半部几乎做了中断处理程序所有的事情,而且可以被新的中断打断。
2.如何使用中断
很多文章都喜欢把被注册(被调用)的函数放在前面去讲解,这样看起来其实还是有些奇怪的,这里我将先讲解注册,再去讲解实际的调用函数。
中断处理流程
-
中断触发:设备向 CPU 发送中断信号。
-
中断服务例程(ISR):执行注册的中断处理函数(上半部)。
-
下半部机制:处理耗时操作(如
tasklet
、workqueue
)。
中断上下文限制
-
不可睡眠:禁止调用可能阻塞的函数(如
kmalloc(GFP_KERNEL),但其他参数部分可用
)。PS:为什么不能使用kmalloc(GFP_KERNEL)呢?因为当内存不足时,内核会对分配的内存进行回收,会触发中断 -
快速执行:ISR 应尽可能简短,避免延迟其他中断。
统一的irqreturn_t的返回值:
-
IRQ_NONE
:未处理该中断。 -
IRQ_HANDLED
:已处理中断。
屏蔽中断/使能
屏蔽中断是指该下半部中断程序在运行时不允许设备再次触发中断。
为什么要屏蔽中断?
-
防止中断重入:在处理当前中断时,避免同一中断反复触发
-
硬件约束:某些设备要求先禁用中断才能清除状态寄存器
-
避免中断风暴(如按键抖动导致的连续中断)
当上半部处理完后,将屏蔽中断,等待下半部处理完后使能中断,允许设备再次触发中断程序。
在 Linux 内核层面,还提供了以下 API 用于中断管理:
void disable_irq(unsigned int irq); // 禁用指定中断线(同步等待未完成中断)
void disable_irq_nosync(unsigned int irq); // 异步禁用
void enable_irq(unsigned int irq); // 重新启用中断
实际驱动中的典型用法:
static irqreturn_t my_interrupt_handler(int irq, void *dev_id)
{struct my_device *dev = dev_id;/* 1. 禁用设备硬件中断 */writel(dev->reg_base + INT_ENABLE_REG, 0x0);/* 2. 禁用内核中断线(可选)*/disable_irq_nosync(irq);/* 3. 调度下半部 */schedule_work(&dev->work);return IRQ_HANDLED;
}static void my_work_fn(struct work_struct *work)
{struct my_device *dev = container_of(work, struct my_device, work);/* 处理实际任务... *//* 重新启用中断 */writel(dev->reg_base + INT_ENABLE_REG, INT_ENABLE_BIT);enable_irq(dev->irq); // 如果之前调用了 disable_irq
}
关键区别与选择
操作对象 | 硬件级控制 | 内核级控制 |
---|---|---|
作用范围 | 只影响当前设备 | 影响共享该中断线的所有设备 |
延迟 | 立即生效 | 可能有延迟(依赖内核调度) |
典型使用场景 | 防止设备自身的中断风暴 | 协调共享中断线的多设备 |
是否需要成对调用 | 必须成对(enable/disable) | 必须成对(enable/disable) |
上半部中断
当我们要实现一个中断或者调用中断处理函数的时候,第一步应该先要在模块中注册该中断及其处理函数。
在 Linux 设备驱动中,使用中断的设备需要申请和释放对应的中断,分别使用内核提供的 request_irq()和 free_irq()函数,该注册只注册上半部分。
int request_irq(unsigned int irq, void (*handler)(int irq, void *dev_id, struct pt_regs *regs), unsigned long irqflags, const char * devname, void *dev_id);
函数返回值: 0 表示成功,或返回一个负的错误码,如 -EBUSY 表示另一个驱动已经占用了你所请求的中断线。
参数详解:
- unsigned int irq:要申请的中断号
- irqreturn_t (*handler)(int,void *,struct pt_regs *): handler是向系统登记的中断处理函数,是一个回调函数,中断发生时,系统调用这个函数,dev_id 参数将被传递给它。
irqreturn_t my_irq_handler(int irq, void *dev_id) {printk(KERN_INFO "IRQ %d triggered\n", irq);/* 快速处理中断,如读取硬件状态、清除中断标志 */return IRQ_HANDLED; }
- unsigned long flags: flags 是中断处理的属性
- const char *dev_name:传递给request_irq的字符串,用来在/proc/interrupts显示中断的拥有者。
- void *dev_id:用于共享的中断信号线,它是唯一的标识,在中断线空闲时可以使用它,驱动程序也可以用它来指向自己的私有数据区(来标识哪个设备产生中断)。若中断没有被共享,dev_id 可以设置为 NULL,但推荐用它指向设备的数据结构。
释放IRQ函数,request_irq()相对应的函数为 free_irq(),free_irq()的原型如下:
void free_irq(unsigned int irq,void *dev_id);
free_irq()中参数的定义与 request_irq()相同。
下半部中断
用于处理大部分耗时任务,有多种api和参数适应不同的场景
软中断(SoftIRQ)
-
概念
软中断是内核中实现延迟处理的一种机制,它的思想是将一些不需要在硬中断上下文中立即完成的工作延后处理。软中断是在中断上下文中执行的,属于内核调度的下半部,但仍然运行于中断上下文中,因此不允许调用可能导致睡眠的函数。 -
局限性
软中断不能睡眠,因为它运行在中断上下文中。同时,软中断通常处理的任务比较简单,比如网络包的快速处理、定时器更新等。
软中断是内核提供的一种延迟处理机制,主要用于处理网络、定时器等高频任务。
-
主要 API:
-
open_softirq()
:注册软中断处理函数。 -
raise_softirq()
:触发软中断。
-
void open_softirq(int nr, void (*action)(struct softirq_action *))
local_bh_disable() 和 local_bh_enable() 用于临界区保护,禁止/允许当前 CPU 上的软中断和 tasklet 调度。
-
功能
这两个函数用于在当前 CPU 上禁止或使能软中断和 tasklet 底半部的执行:-
local_bh_disable():禁止当前 CPU 上的软中断和 tasklet 执行,通常用于保护临界区。
-
local_bh_enable():恢复软中断和 tasklet 的执行。
-
-
使用场景
在某些情况下,你需要在执行临界区代码时确保不会被软中断打断,这时可以调用 local_bh_disable();代码执行完毕后,调用 local_bh_enable() 恢复软中断处理。
注意:
软中断通常由内核内部使用,驱动开发者很少直接使用软中断,更多是使用其上层的 Tasklet 或工作队列。
小任务(Tasklet)
Tasklet 是基于软中断实现的轻量级延迟处理机制,适合处理简单且较短的延迟任务。
其中还可以引用一个 tasklet_schedule()函数就能使系统在适当的时候进行调度运行。
主要 API:
-
初始化:
-
tasklet_init(struct tasklet_struct *t, void (*func)(unsigned long), unsigned long data);
-
或使用宏
DECLARE_TASKLET(name, func, data);
-
-
调度执行:
-
tasklet_schedule(struct tasklet_struct *t);
-
-
禁用/使能:
-
tasklet_disable(struct tasklet_struct *t);
-
tasklet_enable(struct tasklet_struct *t);
-
-
销毁:
-
tasklet_kill(struct tasklet_struct *t);
-
#include <linux/module.h>
#include <linux/interrupt.h>static void my_tasklet_handler(unsigned long data)
{printk(KERN_INFO "Tasklet handler executed, data=%lu\n", data);
}/* 声明并初始化 tasklet */
DECLARE_TASKLET(my_tasklet, my_tasklet_handler, 100);static irqreturn_t my_irq_handler(int irq, void *dev_id)
{printk(KERN_INFO "IRQ %d received, scheduling tasklet\n", irq);tasklet_schedule(&my_tasklet);return IRQ_HANDLED;
}static int __init my_driver_init(void)
{int ret;ret = request_irq(42, my_irq_handler, IRQF_SHARED | IRQF_TRIGGER_RISING,"my_tasklet_driver", (void *)"my_tasklet_driver");if (ret) {printk(KERN_ERR "Failed to request IRQ\n");return ret;}printk(KERN_INFO "Driver initialized\n");return 0;
}static void __exit my_driver_exit(void)
{free_irq(42, (void *)"my_tasklet_driver");/* 确保 tasklet 结束 */tasklet_kill(&my_tasklet);printk(KERN_INFO "Driver exited\n");
}module_init(my_driver_init);
module_exit(my_driver_exit);
MODULE_LICENSE("GPL");
说明:
上例中,中断上半部收到中断后调用 tasklet_schedule()
,调度下半部 tasklet 执行 my_tasklet_handler()
,在下半部中可以执行稍长的、允许休眠的操作(尽管 tasklet 本身仍在软中断上下文中,不能调用可能休眠的函数)。
工作队列(Workqueue)
工作队列提供一种更灵活的下半部机制,它在进程上下文中运行,可以调用可能休眠的函数。
主要 API:
-
初始化工作项:
-
INIT_WORK(struct work_struct *work, void (*func)(struct work_struct *));
-
-
调度工作项:
-
schedule_work(struct work_struct *work);
-
-
等待工作完成:
-
flush_work(struct work_struct *work);
-
-
创建和销毁自定义工作队列:
-
create_workqueue()
-
destroy_workqueue()
-
#include <linux/module.h>
#include <linux/workqueue.h>
#include <linux/interrupt.h>static struct work_struct my_work;/* 工作项处理函数 */
static void my_work_handler(struct work_struct *work)
{printk(KERN_INFO "Workqueue handler executed\n");
}static irqreturn_t my_irq_handler(int irq, void *dev_id)
{printk(KERN_INFO "IRQ %d received, scheduling workqueue\n", irq);schedule_work(&my_work);return IRQ_HANDLED;
}static int __init my_driver_init(void)
{int ret;INIT_WORK(&my_work, my_work_handler);ret = request_irq(42, my_irq_handler, IRQF_SHARED | IRQF_TRIGGER_RISING,"my_wq_driver", (void *)"my_wq_driver");if (ret) {printk(KERN_ERR "Failed to request IRQ\n");return ret;}printk(KERN_INFO "Driver with workqueue initialized\n");return 0;
}static void __exit my_driver_exit(void)
{free_irq(42, (void *)"my_wq_driver");/* 等待所有工作完成 */flush_work(&my_work);printk(KERN_INFO "Driver with workqueue exited\n");
}module_init(my_driver_init);
module_exit(my_driver_exit);
MODULE_LICENSE("GPL");
说明:
这里,INIT_WORK()
初始化工作项,schedule_work()
用于调度工作项在进程上下文中执行,从而可以调用会休眠的函数(比如内存分配、I/O 处理等)。
线程 IRQ(Threaded IRQ)
线程 IRQ 是一种特殊的中断处理方式,通过 request_threaded_irq()
将中断处理分为两部分:
-
上半部:快速响应中断,返回
IRQ_WAKE_THREAD
,由内核调度一个专用线程执行下半部。 -
下半部:在线程上下文中运行,允许休眠,执行复杂或耗时的操作。
-
功能:支持线程化中断处理,将中断处理分为上半部(快速响应)和下半部(在内核线程中执行耗时操作)。
-
优势:
-
下半部在独立内核线程中运行,允许使用阻塞操作(如睡眠或互斥锁)。
-
减少中断禁用时间,提升系统实时性。
-
适用场景:需要复杂处理或长时间任务的中断,例如涉及协议栈处理或硬件状态轮询
int request_threaded_irq(unsigned int irq, irq_handler_t handler, // 上半部irq_handler_t thread_fn, // 下半部线程函数unsigned long flags,const char *name,void *dev_id);
- irq 要注册的中断号(通常从设备树或平台数据中获取)。
- handler 上半部中断处理函数,也称为主 ISR。它在中断上下文中运行,要求执行尽可能快,不允许睡眠。如果中断处理逻辑非常简单,可以在此阶段完成。如果需要较长时间的处理,则应返回
IRQ_WAKE_THREAD
以唤醒线程化的下半部处理函数。也可以将此参数设为NULL
,这样内核会默认使用一个内置的“dummy”处理函数(相当于直接返回IRQ_WAKE_THREAD
),从而所有的处理都转到线程化部分执行。 - thread_fn 下半部线程处理函数,即线程化 IRQ 处理函数。它在一个内核线程(线程上下文)中运行,因此允许调用可能会睡眠或进行耗时操作的函数。
- 当主 ISR 返回
IRQ_WAKE_THREAD
时,内核会调度此线程处理函数执行。 - 线程函数的原型与上半部类似:
irqreturn_t thread_fn(int irq, void *dev_id);
- flags 用于指定中断注册的属性。常见的标志包括:
IRQF_SHARED
:允许该中断线被多个设备共享。如果设备共享中断,dev_id
必须非 NULL,并且在释放中断时需要传入相同的dev_id
。触发方式标志,如IRQF_TRIGGER_RISING
、IRQF_TRIGGER_FALLING
、IRQF_TRIGGER_HIGH
、IRQF_TRIGGER_LOW
等(根据硬件要求选择)。 - name 用于标识中断的名称,通常会显示在
/proc/interrupts
中。 - dev_id 设备标识指针。对于共享中断,此参数用于区分不同设备的中断处理程序,也便于在释放中断时准确匹配。
释放IRQ函数,也相对应的函数为 free_irq()。
下半部机制对比
机制 | 执行上下文 | 并发性 | 延迟 | 适用场景 |
---|---|---|---|---|
softirq | 中断上下文 | 可跨 CPU 并行 | 极低 | 高频核心任务(网络、块设备) |
tasklet | 中断上下文 | 同一 tasklet 串行 | 低 | 驱动中的通用异步任务 |
workqueue | 进程上下文 | 可睡眠、调度灵活 | 较高 | 复杂或需睡眠的任务 |
3.其余中断的一些概念
中断共享
中断共享(Interrupt Sharing)是指多个设备(或驱动实例)在同一条物理中断线上注册中断处理程序,这样当该中断发生时,内核会依次调用所有注册的处理函数。下面详细讲解其原理、实现方式、注意事项和常见问题:
-
物理限制与成本考量
在硬件设计中,中断资源通常有限(例如旧的 x86 系统可能只有 16 条 IRQ 线),为了充分利用这些有限资源,多个设备往往共享同一条 IRQ 信号线。 -
共享中断的工作机制
当一个共享中断发生时,内核会在对应的中断处理链表中调用所有注册的处理程序。每个处理程序需要检查硬件状态或标识信息,判断这次中断是否真正与自己的设备相关。如果不相关,则返回IRQ_NONE
;如果相关,则执行必要操作后返回IRQ_HANDLED
。
使用 request_irq() 注册共享中断
在注册中断时,必须在 flags 参数中加入 IRQF_SHARED
标志,并且 dev_id 参数不能为 NULL。dev_id 用于在共享中断时标识调用者,确保在释放中断时能够正确匹配。
int ret;
ret = request_irq(irq_number, my_irq_handler,IRQF_SHARED | <其他标志>,"my_device", &my_device_data);
if (ret) {printk(KERN_ERR "Failed to request IRQ %d, error %d\n", irq_number, ret);return ret;
}
中断处理函数中的注意事项
由于共享中断时,不同设备可能会在同一 IRQ 线上产生中断,每个处理程序必须:
-
检查中断来源:在 ISR 中需要读取硬件状态寄存器或者其他标识,判断这次中断是否是自己设备产生的。如果不是,则立即返回
IRQ_NONE
。 -
返回值约定:如果一个处理程序确定中断确实是由其设备产生,应返回
IRQ_HANDLED
;如果不确定或不是目标设备,则返回IRQ_NONE
。这有助于内核统计“伪中断”(spurious interrupt)。
示例:
irqreturn_t my_irq_handler(int irq, void *dev_id)
{struct my_device *dev = dev_id;/* 检查硬件状态判断是否是本设备中断 */if (!is_my_device_interrupt(dev)) {return IRQ_NONE;}/* 处理中断:例如读取数据、清除中断状态等 */handle_my_interrupt(dev);return IRQ_HANDLED;
}
释放共享中断
在释放中断时,必须调用 free_irq()
并传入与注册时相同的 irq
和 dev_id
:
free_irq(irq_number, &my_device_data);
内核会遍历共享该中断号的所有处理程序,并释放 dev_id 与传入参数匹配的那一个。
常见问题与注意事项
-
dev_id 必须非 NULL:
当使用IRQF_SHARED
时,如果传入 NULL,内核将无法区分不同设备的处理程序,可能会导致释放中断资源时出现错误。 -
竞态条件:
由于同一中断可能被多个设备共享,因此各个 ISR 必须小心设计,确保对共享硬件寄存器或数据的访问正确同步。 -
性能问题:
如果共享的中断上注册了大量处理程序,每次中断发生时内核都会调用所有处理程序,这可能会影响响应时间,因此共享中断应尽量控制注册数目,确保每个处理程序尽快返回。 -
调试:
检查/proc/interrupts
文件,可以看到各个 IRQ 线的使用情况和共享状态,这有助于确认设备是否正确共享了中断。
中断驱动I/O
优势
-
提高效率:CPU 只在设备有数据时被中断,不需要持续轮询设备状态,从而节省 CPU 资源。
-
响应及时:外设立即通知 CPU,有助于快速响应实时事件(如网络数据、输入设备事件)。
-
异步处理:中断驱动 I/O 允许数据处理在中断发生时异步进行,使系统整体性能更高。
当与驱动程序管理的硬件间的数据传送可能因为某种原因而延迟,驱动编写者应当实现缓存。一个好的缓存机制需采用中断驱动的I/O,一个输入缓存在中断时被填充,并由读取设备的进程取走缓冲区的数据,一个输出缓存由写设备的进程填充,并在中断时送出数据。
为正确进行中断驱动的数据传送,硬件应能够按照下列语义产生中断:
- 输入:当新数据到达时并处理器准备好接受时,设备中断处理器。
- 输出:当设备准备好接受新数据或确认一个成功的数据传送时,设备产生中断。
4.总结
实际开发中的常见流程:
-
设备初始化
在驱动的 probe() 中,根据平台数据或设备树获取中断号,调用request_irq()
或request_threaded_irq()
注册中断处理函数。 -
中断处理
上半部 ISR 快速响应中断,必要时调度下半部处理(如 tasklet 或工作队列)完成复杂操作。 -
数据传输
根据设备特性,中断处理可能涉及读取硬件数据,将数据存入驱动内部缓冲区,等待用户空间通过 read() 接口获取。 -
资源释放
在设备关闭或驱动卸载时,调用free_irq()
释放中断资源,并确保下半部任务(如 tasklet 或工作队列)已结束。
具体的调试需要查看 /proc/interrupts
:可以验证 IRQ 是否正确注册、共享情况及中断计数,或者使用printk(不推荐)输出调试信息,记录ISR和下半部分执行情况,最后就是使用动态调试机制,如pr_debug()和内核动态调试。
最后还是一句话,实践出真理,不自己实验一下永远只是概念,如果将来内核有朝一日更新了其中的API可以告诉我。
相关文章:
Linux驱动开发 中断处理
目录 序言 1.中断的概念 2.如何使用中断 中断处理流程 中断上下文限制 屏蔽中断/使能 关键区别与选择 上半部中断 下半部中断 软中断(SoftIRQ) 小任务(Tasklet) 工作队列(Workqueue) 线程 IRQ(Threaded IRQ…...
C++ set map
1.set和map是什么 set和map是 C STL 提供的容器,用于高效的查找数据,底层采用红黑树实现,其中set是Key模型,map是Key-Value模型 set和map的基本使用较为简单,这里不再叙述,直接进入实现环节 2.set和map的…...
Vue2和Vue3响应式的基本实现
目录 简介Vue2 响应式Vue2 响应式的局限性 Vue3 响应式Vue3 响应式的优点 Vue2 和 Vue3 响应式对比 简介 在 Vue 框架中,数据的响应式是其核心特性之一。当页面数据发生变化时,我们希望界面能自动更新,而不是手动操作 DOM。这就需要对数据进…...
PyQt6实例_批量下载pdf工具_界面开发
目录 前置: 代码: 视频: 前置: 1 本系列将以 “PyQt6实例_批量下载pdf工具”开头,放在 【PyQt6实例】 专栏 2 本系列涉及到的PyQt6知识点: 线程池:QThreadPool,QRunnable; 信号…...
FOC 控制笔记【三】磁链观测器
一、磁链观测器基础 1.1 什么是磁链 磁链(magnetic linkage)是电磁学中的一个重要概念,指导电线圈或电流回路所链环的磁通量。单位为韦伯(Wb),又称磁通匝。 公式为: 线圈匝数 穿过单匝数的…...
前端Material-UI面试题及参考答案
目录 Material-UI 的设计理念与 Material Design 规范的关系是什么? 如何通过 npm/yarn/pnpm 安装 Material-UI 的核心依赖? Material-UI 的默认主题系统如何实现全局样式管理? 如何在项目中配置自定义字体和颜色方案? 什么是 emotion 和 styled-components,它们在 Ma…...
【LeetCode基础算法】链表所有类型
1. 遍历链表 二进制链表转整数找出临界点之间的最小和最大距离 2. 删除节点 移除链表元素从链表中移除在数组中存在的节点删除排序链表中的重复元素删除排序链表中的重复元素 II 3. 插入节点 在链表中插入最大公约数 计算最大公约数的内置函数gcd(a,b),也可以m…...
备赛蓝桥杯之第十六届模拟赛第1期职业院校组第五题:回忆画廊
提示:本篇文章仅仅是作者自己目前在备赛蓝桥杯中,自己学习与刷题的学习笔记,写的不好,欢迎大家批评与建议 由于个别题目代码量与题目量偏大,请大家自己去蓝桥杯官网【连接高校和企业 - 蓝桥云课】去寻找原题࿰…...
51 驱动 INA219 电流电压功率测量
文章目录 一、INA219简介二、引脚功能三、寄存器介绍1.配置寄存器 0x002.分流电压寄存器 0x013.总线电压寄存器 0x024.功率寄存器 0x035.电流寄存器 0x046.基准寄存器 0x05 四、IIC 时序说明1.写时序2.读时序 五、程序六、实验现象1.线路图2.输出数据 一、INA219简介 INA219是…...
JavaScript弹出框的使用:对话框、确认框、提示框、弹窗操作
关于 Window对象和 Document 对象的详细使用,系列文章: 《Window对象的常用属性和方法》 《Document对象的常用属性和方法:getElementById()、getElementsByName()、createElement()方法》 《Document获取元素并修改内容:getElementById()方法、value属性、innerHTML属性、…...
【设计模式】深入解析设计模式:门面模式(外观模式)的定义、优点和代码实现
门面模式(外观模式) SLF4J是门面模式的典型应用(但不仅仅使用了门面模式)。 门面模式定义 门面模式(Facade Pattern)又称为外观模式,提供了一个统一的接口,用来访问子系统中的一群…...
UE5学习笔记 FPS游戏制作34 触发器切换关卡
文章目录 搭建关卡制作触发器传送门显示加载界面 搭建关卡 首先搭建两个关卡,每个关卡里至少要有一个角色 制作触发器传送门 1 新建一个蓝图,父类为actor,命名为portal(传送门) 2 为portal添加一个staticMesh&#…...
UE5学习笔记 FPS游戏制作26 UE中的UI
文章目录 几个概念创建一个UI蓝图添加UI获取UI的引用 切换设计器和UI蓝图将UI添加到游戏场景锚点轴点slotSizeToContent三种UI数据更新方式(Text、Image)函数绑定属性绑定事件绑定 九宫格分割图片按钮设置图片绑定按下事件 下拉框创建添加数据修改样式常用函数 滚动框创建添加数…...
Spring Boot分布式项目重试实战:九种失效场景与正确打开方式
在分布式系统架构中,网络抖动、服务瞬时过载、数据库死锁等临时性故障时有发生。本文将通过真实项目案例,深入讲解Spring Boot项目中如何正确实施重试机制,避免因简单粗暴的重试引发雪崩效应。 以下是使用Mermaid语法绘制的重试架构图和决策…...
首个物业plus系列展 2025上海国际智慧物业博览会开幕
AI赋能服务升级!首个“物业plus”系列展 2025上海国际智慧物业博览会盛大开幕 3月31日,2025上海国际智慧物业博览会(简称“上海物博会”)在上海新国际博览中心N4馆隆重开幕。本届展会由广州旭杨国际展览有限公司主办,…...
《C++多线程下单例 “锁钥” 法则》
一、概述 本文章介绍了一段 C 代码,该代码实现了在多线程环境下的单例模式。单例模式确保一个类只有一个实例,并提供全局访问点。在多线程场景中,需要额外的同步机制来保证单例对象创建的线程安全性。单例模式在许多场景中都有重要应用&#…...
WEB或移动端常用交互元素及组件 | Axure / 元件类型介绍(表单元件、菜单和表格 、流程元件、标记元件)
文章目录 引言I Axure / 元件类型介绍基本元件表单元件菜单和表格流程元件标记元件II Axure 基础Axure / 常用功能介绍Axure / 常用元素实例Axure / 动态交互实例Axure / 常用设计分辨率推荐III Axure / 创建自己的元件库元件库作用元件库的创建及使用引言 I Axure / 元件类型介…...
开发环境解决Secure Cookie导致302重定向
问题现象与根源分析 故障现象 前端本地开发时(HTTP协议),调用接口返回302 Found状态码浏览器控制台警告:“Cookie被阻止,因为设置了Secure属性但未通过HTTPS传输”登录态无法保持,页面陷入重定向循环 技…...
华为三进制逻辑与高维量子计算的对比分析
此博客深入探讨华为三进制逻辑状态的技术意义,并与高维量子计算系统进行对比。文章将全面展开技术原理、实现机制、计算能力对比、未来应用前景等方面的内容。 目录 引言 华为三进制逻辑的创新意义 2.1 二进制逻辑的局限与历史探索 2.2 三进制逻辑的优势ÿ…...
网红指路机器人是否支持环境监测功能?
嘿呀,你可知道?如今的叁仟网红指路机器人那可太牛啦!它们可不单单局限于为行人指明方向,还纷纷兼职当起了 “环境小卫士”,为咱们的城市生活注入了前所未有的超智能便利。就拿那个依托叁仟智慧杆打造的数智指路机器人来…...
【进阶】vscode 中使用 cmake 编译调试 C++ 工程
基于 MSYS2 的 MinGW-w64 GCC 工具链与 CMake 构建系统,结合VSCode及其扩展插件( ms-vscode.cmake-tools),可实现高效的全流程C开发调试。既可通过 VSCode 可视化界面(命令面板、状态栏按钮)便捷完成配置、…...
突发,国行 iPhone 17,支持 eSIM
古人云“无心生大用”,往往你感到绝望的时候,转机就莫名其妙的来了。 根据供应链的最新消息,国行 iPhone 17 Air,有望用上 eSIM。 不仅如此,国产手机厂商,也计划推出类似iPhone 17 Air的超薄机型…...
红宝书第二十二讲:详解JavaScript类型化数组与二进制数据处理
红宝书第二十二讲:详解JavaScript类型化数组与二进制数据处理 资料取自《JavaScript高级程序设计(第5版)》。 查看总目录:红宝书学习大纲 一、为什么需要类型化数组? 普通JavaScript数组(Array࿰…...
Elasticsearch安全与权限控制指南
在Elasticsearch维护中,安全管理是保障数据合规性和集群稳定性的关键。本文将详细介绍用户与角色管理、索引/字段级权限控制、HTTPS加密通信、审计日志与合规性检查等核心安全实践,希望可以帮助你构建更安全的Elasticsearch环境。 1 用户与角色管理 1.1…...
SAP 学习笔记 - 系统移行业务 - MALSY(由Excel 移行到SAP 的收费工具)
以前有关移行,也写过一些文章,比如 SAP 学习笔记 - 系统移行业务 - Migration cockpit工具 - 移行Material(品目)-CSDN博客 SAP 学习笔记 - 系统移行业务 - Migration cockpit工具2 - Lot导入_sap cockpit-CSDN博客 SAP学习笔记…...
【群智能算法改进】一种改进的蜣螂优化算法IDBO[3](立方混沌映射Cubic、融合鱼鹰勘探策略、混合高斯柯西变异)【Matlab代码#92】
文章目录 【获取资源请见文章第5节:资源获取】1. 原始DBO算法2. 改进后的IDBO算法2.1 立方混沌映射Cubic种群初始化2.2 融合鱼鹰勘探策略2.3 混合高斯柯西变异 3. 部分代码展示4. 仿真结果展示5. 资源获取 【获取资源请见文章第5节:资源获取】 1. 原始DB…...
《异常检测——从经典算法到深度学习》30. 在线服务系统中重复故障的可操作和可解释的故障定位
《异常检测——从经典算法到深度学习》 0 概论1 基于隔离森林的异常检测算法 2 基于LOF的异常检测算法3 基于One-Class SVM的异常检测算法4 基于高斯概率密度异常检测算法5 Opprentice——异常检测经典算法最终篇6 基于重构概率的 VAE 异常检测7 基于条件VAE异常检测8 Donut: …...
座舱与智驾“双轮驱动”,芯擎科技打造智能汽车“芯”标杆
在比亚迪、吉利、奇瑞等各大主机厂打响“全民智驾”的关键时期,以芯擎科技为代表中国芯片厂商开始“放大招”。 2025年3月27日,芯擎科技在南京举办了“擎随芯动、智融万象”生态科技日,重磅发布了“星辰一号”、“星辰一号Lite”,…...
观察者模式在Java单体服务中的运用
观察者模式主要用于当一个对象发生改变时,其关联的所有对象都会收到通知,属于事件驱动类型的设计模式,可以对事件进行监听和响应。下面简单介绍下它的使用: 1 定义事件 import org.springframework.context.ApplicationEvent;pu…...
html5时钟升级!支持切换深浅模式 Canvas实现现代化动态时钟
HTML5 Canvas实现现代化动态时钟 这里写目录标题 HTML5 Canvas实现现代化动态时钟项目介绍技术实现1. 项目架构2. Canvas绘图实现2.1 表盘绘制2.2 刻度绘制2.3 指针绘制 3. 动画效果4. 主题切换 项目亮点技术要点总结项目收获改进方向结语 项目介绍 本项目使用HTML5 Canvas技术…...
Scala(2)
For循环控制 循环守卫 基本语法 for(i <- 1 to 3 if i ! 2) { print(i " ") }println() 说明: 循环守卫,即循环保护式(也称条件判断式,守卫)。保护式为 true 则进入循环体内部,为false 则跳…...
DataGear 5.3.0 制作支持导出表格数据的数据可视化看板
DataGear 内置表格图表底层采用的是DataTable表格组件,默认并未引入导出数据的JS支持库,如果有导出表格数据需求,则可以在看板中引入导出相关JS支持库,制作具有导出CSV、Excel、PDF功能的表格数据看板。 在新发布的5.3.0版本中&a…...
项目-苍穹外卖(十六) Apache ECharts+数据统计
一、介绍 二、营业额统计 需求分析和设计: Controller: Service: /*** 营业额统计* param begindate* param enddate* return* */Overridepublic TurnoverReportVO turnoverStatistics(LocalDate begindate, LocalDate enddate) {//创建时间集合List<LocalDate&…...
使用 PowerShell 脚本 + FFmpeg 在 Windows 系统中批量计算 MP4视频 文件的总时长
步骤 1:安装 FFmpeg 访问 FFmpeg 官网(Download FFmpeg),下载 Windows 版编译包(如 ffmpeg-release-full.7z)。或者到(https://download.csdn.net/download/zjx2388/90539014)下载完整资料 解压文件&#…...
低成本文件共享解决方案:Go File本地Docker部署与外网访问全记录
文章目录 前言1. 安装Docker2. Go File使用演示3. 安装cpolar内网穿透4. 配置Go File公网地址5. 配置Go File固定公网地址 前言 在这个信息爆炸的时代,谁还没遇到过这样的囧事呢?正在办公室电脑上赶工报告,手机却突然蹦出一条紧急邮件&#…...
python文件的基本操作和文件读写
目录 文件的基本操作 文件读写 文件的基本操作 Python 中对文件的基本操作主要包括打开文件、读取文件、写入文件和关闭文件等操作。下面是一个简单的示例: 打开文件: file open(example.txt, r) # 使用 open() 函数打开一个名为 example.txt 的文…...
大数据与datax1.0
一、datax含义 是一个数据搬运工具 二、需要注意的点 插件(plugin)下面的reader和writer 要删除(第一步执行肯定会报错 所以请记得一定要删除reader和writer下的隐藏文件) 三、心得 做任何事要事半功倍,而不要事倍功半,好的学习方法永远比盲目的努力更重要--------谨记3.31…...
蚂蚁集团主导的ISO密码学国际标准立项,纳入国产算法
蚂蚁集团主导的ISO密码学国际标准 ISO 25330-3 立项, 国产算法Ferret成为标准方案。 近日,在美国弗吉尼亚州举行的 ISO/IEC JTC 1/SC 27 全体会议上,ISO/IEC 25330第三部分《Information Security — Oblivious Transfer — Part 3: Obliv…...
【新人系列】Golang 入门(十):错误处理详解 - 上
✍ 个人博客:https://blog.csdn.net/Newin2020?typeblog 📝 专栏地址:https://blog.csdn.net/newin2020/category_12898955.html 📣 专栏定位:为 0 基础刚入门 Golang 的小伙伴提供详细的讲解,也欢迎大佬们…...
Unity 2022.3.x部分Android设备播放视频黑屏问题
Android平台视频兼容性问题很多…类似的黑屏问题真的很头大,总结一些常见问题: 1. 视频文件不支持压缩 如果使用AssetBundle加载视频,这个AssetBundle压缩格式要选None。有人可能会说最新版Unity已经支持bundle压缩下播放视频,稳…...
基于Python的Django框架的个人博客管理系统
标题:基于Python的Django框架的个人博客管理系统 内容:1.摘要 本文围绕基于Python的Django框架构建个人博客管理系统展开。背景方面,随着互联网发展,个人博客成为信息分享与交流重要平台,传统博客管理系统在功能与灵活性上存在不足。目的是开…...
Unity加载OSGB倾斜摄影数据
Unity加载OSGB倾斜摄影数据 显而易见有一个最方便的办法就是使用CesiumForUnity确定是可以通过osgb数据转换成3dtiles进行加载的,然而有没有直接加载osgb格式数据的方法呢? 我们知道osgb的osg推出的倾斜摄影数据的数据结构,所以,…...
RabbitMQ简单介绍和安装
RabbitMQ简单介绍 一.RabbitMQ介绍二.RabbitMQ的作用1.异步解耦2.流量削峰3.消息分发4.延迟通知 三.RabbitMQ安装(Ubuntu)1.先安装Erlang2.安装RabbitMQ3.安装RabbitMQ的管理界面4.创建虚拟机5.端口号信息 四.工作原理图 一.RabbitMQ介绍 RabbitMQ 是一款…...
【清华大学】DeepSeek政务应用场景与解决方案
目录 一、政务数字化转型三阶段演进二、人工智能政务应用场景四大方向 三、技术方案核心技术 四、解决方案案例1. 公文写作2. 合同协议智能审查3. 行政执法4. 就业指导 五、风险及对策六、落地大四步法七、未来发展展望AI职业替代逻辑空间智能与具身智能人机共生 一、政务数字化…...
spring boot自动装配原理
springboot自动装配几乎是现在面试必问的面试题,要是逐行分析自动装配流程肯定是很复杂的,因此我们从大体上来梳理即可。 一、 自动装配总览 首先要搞清楚两个问题,springboot自动装配是什么?解决了什么问题? springbo…...
【SDMs分析1】基于ENMTools R包的生态位分化分析和图像绘制(identity.test())
基于ENMTools包的生态位分化 1. 写在前面2. 生态位分化检验案例13. 生态位分化检验案例21. 写在前面 最近学了一个新的内容,主要是关于两个物种之间生态位分化检验的 R 语言代码。生态位分化是物种分布模型(SDM )研究中的关键部分,许多 SCI 论文都会涉及这一分析。该方法主…...
蓝桥杯比赛python程序设计——纯职业小组
问题描述 在蓝桥王国,国王统治着一支由 nn 个小队组成的强大军队。每个小队都由相同职业的士兵组成。具体地,第 ii 个小队包含了 bibi 名职业为 aiai 的士兵。 近日,国王计划在王宫广场举行一场盛大的士兵检阅仪式,以庆祝王…...
【Git教程】将dev分支合并到master后,那么dev分支该如何处理
将 dev 合并到 master 后的分支状态与操作指南 1. 合并后的分支状态 dev 分支不会消失: Git 的 git merge 命令仅将 dev 的内容合并到 master,不会删除 dev 分支。合并后,dev 分支仍然存在,其历史记录和代码保持不变。 分支的 H…...
python系统之综合案例:用python打造智能诗词生成助手
不为失败找理由,只为成功找方法。所有的不甘,因为还心存梦想,所以在你放弃之前,好好拼一把,只怕心老,不怕路长。 python系列之综合案例 前言一、项目描述二、项目需求三、 项目实现1、开发准备2、代码实现 …...
HCIA-数据通信datacom认证
文章目录 一、数据通信简介1.1 标准协议1.2 数据传输过程 二、通用路由平台VRP2.1 VRP简介2.2 命令行基础 三 、网络层协议IP3.1 数据封装3.2 数据包传输2.3 IP地址2.4 子网划分2.5 ICMP 四、IP路由基础4.1 路由概述4.2 路由表4.3 路由转发4.4 静态路由4.5 动态路由4.6 路由高级…...