可以做h5的网站/今日国内新闻最新消息
一、IO模型
- I/O 模型在操作系统中用于处理应用程序与设备驱动之间的数据传输。
- I/O 通信模型的核心是解决程序与设备之间如何高效、合理地进行数据通信。不同的模型通过阻塞、非阻塞、同步、异步的方式来控制数据流和处理 I/O 请求。
注:在驱动开发中可以定义一个全局结构体
- 用于全局管理驱动程序的状态和资源。
- 在驱动开发中,有时需要一个全局的数据结构来保存设备的状态、驱动配置、缓存、锁等信息,这样不同的驱动程序函数可以通过该结构体访问和修改共享的资源。
- 作用
- 统一管理驱动状态: 全局结构体通常保存驱动程序的各种状态信息。例如,设备的注册信息、分配的内存、硬件寄存器映射等都可以保存在这个结构体中。
- 共享资源: 驱动程序通常会有多个函数被内核调用,比如初始化函数、读写函数、中断处理函数等。使用全局结构体,可以让这些函数方便地共享和访问同样的数据或资源。
- 简化代码结构: 将驱动程序涉及的所有全局变量封装在一个结构体中,使代码更加清晰、结构化,同时也减少了全局变量命名冲突的可能性。
一、阻塞 I/O 模型
- 阻塞 I/O 是最常见的 I/O 模型。当应用程序发起 I/O 请求时,如果数据没有准备好,应用程序将进入阻塞状态,等待数据准备完毕后,驱动程序会唤醒阻塞的应用程序。此时,应用程序才能继续执行。
- 工作流程
应用程序向驱动发送读取数据的请求。
如果驱动程序中数据尚未准备好,应用程序进入 睡眠状态,等待数据到来。
当数据准备好后,驱动程序会唤醒应用程序,程序从睡眠状态恢复,继续读取数据。
完成 I/O 操作后,应用程序继续执行其他任务。
- 具体步骤
a. 定义并初始化等待队列
wait_queue_head_t wqhead;//在全局结构体中
在结构体 global_struct 中定义了 wqhead,表示等待队列头,用于管理睡眠进程的队列。在mod_init() 初始化函数中,通过 init_waitqueue_head() 初始化等待队列头。
init_waitqueue_head(&gstruct.wqhead);
b. 进程睡眠机制
在 chdev_read 函数中,当应用程序尝试从驱动读取数据时,程序会检查数据是否可用。如果数据不可用,进程就会进入睡眠状态,挂到等待队列上。
wait_event_interruptible(pt_gstruct->wqhead, pt_gstruct->data_flag);
c. 唤醒机制
当数据到达时,会通过 chdev_write 函数进行处理
pt_gstruct->data_flag = 1;//数据写入后,data_flag 被设置为 1,表示数据已准备好。
wake_up_interruptible(&pt_gstruct->wqhead);
wake_up_interruptible() 函数用于唤醒等待队列 wqhead 上的所有进程,唤醒后,之前处于睡眠状态的进程会继续执行 chdev_read 函数中的代码,读取数据。
二、非阻塞I/O实现
- 非阻塞 I/O 的实现逻辑与阻塞 I/O 类似,但不进入睡眠状态。如果数据尚未准备好,非阻塞 I/O 立即返回错误 -EAGAIN,告诉应用程序稍后重试。
if (file->f_flags & O_NONBLOCK) { // 检查文件标志是否为非阻塞模式if (pt_gstruct->data_flag == 0) // 没有数据可用return -EAGAIN; // 返回 EAGAIN 错误,表示无数据,稍后重试
}
三、异步通知
- 异步通知(Asynchronous Notification)是 Linux 内核提供的一种机制,它允许设备驱动在数据准备好或状态发生变化时,主动向应用程序发送信号(通常是 SIGIO 信号),通知应用程序及时处理。
- 这种机制在应用程序不需要不断轮询设备状态的情况下非常有用。
- 设备驱动中的结构定义
struct global_struct {struct class *cls;int major, minor;struct cdev cdev_obj;wait_queue_head_t wqhead; // 等待队列头char sharebuf[128]; // 共享缓冲区int data_flag; // 标记数据是否可用,0 表示无数据,1 表示有数据struct fasync_struct *fapp; // 异步通知结构,用于管理异步通知
};
- 驱动程序的 fasync 实现
int chdev_fasync(int fd, struct file *file, int on)
{struct global_struct *pt_gstruct = file->private_data;// fasync_helper 负责将文件描述符和进程与异步通知关联或解除关联return fasync_helper(fd, file, on, &pt_gstruct->fapp);
}
- 实现数据写入时的异步通知
//当驱动程序中有新数据时,通过 kill_fasync 向注册了异步通知的进程发送信号。
ssize_t chdev_write(struct file *file, const char __user *usr, size_t sz, loff_t *loff)
{struct global_struct *pt_gstruct = file->private_data;long ret;// 将用户数据复制到共享缓冲区ret = copy_from_user(pt_gstruct->sharebuf, usr, sz);if (ret > 0) {printk("%s-%d copy_from_user err\n", __func__, __LINE__);return -3;}// 数据写入完成后,标记数据已经准备好pt_gstruct->data_flag = 1;// 唤醒所有等待在等待队列上的进程wake_up_interruptible(&pt_gstruct->wqhead);// 发送异步通知信号,通知应用程序有数据可读kill_fasync(&pt_gstruct->fapp, SIGIO, POLL_IN);return sz;
}
二、内核中断驱动
- Linux 内核中的中断处理系统使得硬件能够通知内核发生了特定事件(如数据就绪、设备完成某项任务等),并让内核采取相应的处理措施。
1. 内核中获取中断号
- 在 ARM 等嵌入式平台上,设备通常使用设备树(Device Tree)来描述硬件信息。驱动程序可以从设备树节点中获取与设备相关的中断号。
- 直接写入
device_node {compatible = "mydevice";reg = <0x12340000 0x1000>;interrupts = <30 2>; // 中断号 30,触发类型 2(下降沿触发)
};
-
- 设备树描述了硬件信息并提供给内核使用。在编译设备树时,我们使用交叉编译工具和特定的架构。
make dtbs ARCH=arm CROSS_COMPILE=arm-none-linux-gnueabi-
- 拷贝到共享目录
编译完成的 .dtb 文件需要通过某种方式传输到开发板。通常,我们会将 .dtb 文件拷贝到一个共享目录(如 NFS、TFTP 或本地磁盘),以便通过 U-Boot 加载和烧录。
cp arch/arm/boot/dts/your_device.dtb /path/to/shared/directory/
- 通过 U-Boot 烧录设备树文件
loady 41000000
- movi write dtb 命令将 .dtb 文件写入设备存储- 验证设备树文件是否生效- 重启linux,在 /proc/device-tree/ 目录会有你的 节点文件目录
实现代码
- of_find_node_by_path(“/key2”); // 从设备树中查找路径为 /key2 的节点
- irq_of_parse_and_map(of_node, 0); // 从设备节点获取中断号
- 具体代码
// Linux 内核中断驱动程序
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/irqreturn.h>
#include <linux/of.h>
#include <linux/interrupt.h>
#include <linux/of_irq.h>/* 定义全局结构体 */
struct global_struct {int irqno; // 保存从设备树中解析出的中断号int xxx; // 其他私有数据,用户可以根据需要扩展
};/* 定义全局变量 */
struct global_struct gstruct;/* 中断处理函数 */
irqreturn_t irq_key_handle(int irqno, void *args)
{struct global_struct *pt_gstruct = args; // 从传入的参数中获取私有数据printk(KERN_INFO "%s - 中断发生,irqno = %d, 设备中断号 = %d\n", __func__, irqno, pt_gstruct->irqno);// 执行中断处理逻辑,例如:读取硬件状态、清除中断标志等return IRQ_HANDLED; // 返回 IRQ_HANDLED 表示中断已处理完成
}/* 模块初始化函数 */
int mod_init(void)
{int ret;int irqno;struct device_node *of_node;printk(KERN_INFO "中断驱动模块初始化\n");/* 1. 通过设备树路径查找设备节点 */of_node = of_find_node_by_path("/key2"); // 从设备树中查找路径为 /key2 的节点if (!of_node) {printk(KERN_ERR "%s - 无法找到设备树节点 /key2\n", __func__);return -EINVAL; // 返回错误码}/* 2. 从设备树节点解析中断号 */irqno = irq_of_parse_and_map(of_node, 0); // 从设备节点获取中断号if (irqno < 0) {printk(KERN_ERR "%s - 无法从设备树节点中解析中断号\n", __func__);return -EINVAL; // 返回错误码}printk(KERN_INFO "%s - 获取的中断号为 %d\n", __func__, irqno);/* 3. 保存中断号到全局结构体中 */gstruct.irqno = irqno;gstruct.xxx = 10086; // 示例私有数据/* 4. 注册中断处理程序 */ret = request_irq(irqno, irq_key_handle, IRQF_TRIGGER_FALLING, "key2_intr", &gstruct);if (ret < 0) {printk(KERN_ERR "%s - 注册中断处理程序失败,错误码:%d\n", __func__, ret);return ret; // 返回错误码}printk(KERN_INFO "中断处理程序注册成功,中断号为 %d\n", irqno);return 0; // 模块初始化成功
}/* 模块退出函数 */
void mod_exit(void)
{/* 释放中断 */free_irq(gstruct.irqno, &gstruct); // 释放之前注册的中断printk(KERN_INFO "中断驱动模块卸载\n");
}/* 声明模块的初始化和退出函数 */
module_init(mod_init);
module_exit(mod_exit);/* 模块的许可信息 */
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Your Name");
MODULE_DESCRIPTION("Simple IRQ Device Driver using Device Tree");
MODULE_VERSION("1.0");
简明步骤
- 编写设备树节点:在设备树(.dts 文件)中定义设备的中断号和触发类型。
- 在设备树(.dts 文件)中定义设备的中断号和触发类型。
key2: gpio-keys {compatible = "gpio-keys";interrupts = <30 IRQ_TYPE_EDGE_FALLING>; // 中断号 30,下降沿触发
};
- 编写中断驱动程序:
- 定义驱动的全局结构体,保存中断号和其他私有数据。
- 实现中断处理函数。
irqreturn_t irq_key_handle(int irqno, void *args)
{printk(KERN_INFO "中断发生,irqno = %d\n", irqno);return IRQ_HANDLED;
}
- 从设备树获取中断号
- 使用 of_find_node_by_path(“/key2”) 查找设备树节点。
- 使用 irq_of_parse_and_map() 解析设备树中的中断号。
struct device_node *of_node = of_find_node_by_path("/key2");
int irqno = irq_of_parse_and_map(of_node, 0);
- 注册中断处理程序:使用 request_irq() 函数注册中断处理函数。
request_irq(irqno, irq_key_handle, IRQF_TRIGGER_FALLING, "key2_intr", &gstruct);
- 释放中断资源(在模块退出时):在 mod_exit 函数中,使用 free_irq() 释放中断资源。
free_irq(gstruct.irqno, &gstruct);
- 编译并加载内核模块:编译驱动模块并加载到内核中,验证中断是否正常工作。
中断下半部分
- 在 Linux 内核中,中断处理分为上半部分和下半部分。上半部分(Top Half)是中断处理函数(ISR,Interrupt Service Routine),它在中断发生时立即执行,尽量简短以提高系统响应速度。为了避免在中断上下文中执行复杂或耗时的操作,Linux 提供了下半部分(Bottom Half)机制,用于延迟处理不需要立即执行的任务。
- LINUX系统中执行单元具体分别如下:
执行单元 | 优先级 | 是否允许睡眠 | 适合任务类型 |
---|---|---|---|
进程 | 低 | 可以睡眠 | 耗时或不耗时任务,不紧急任务 |
中断下半部分 | 中 | 否 | 耗时任务,紧急任务 |
中断上半部分 | 高 | 否(禁止睡眠) | 短时间任务,不耗时,紧急任务 |
中断下半部分机制
中断下半部分机制 | 优先级 | 是否允许睡眠 | 适用场景 | 使用方式 |
---|---|---|---|---|
软中断 | 很高 | 否 | 内核专用,处理大量事件 | 内核开发者使用,驱动开发者不使用 |
Tasklet | 中等 | 否 | 驱动开发中常用,处理短任务 | 1. 定义并初始化 Tasklet 对象 |
2. 在中断上半部分中调度 Tasklet | ||||
工作队列 | 低 | 是 | 处理复杂、长时间或阻塞任务 | 1. 定义并初始化 Workqueue 对象 |
2. 在中断上半部分中调度 Workqueue |
Tasklet的使用方法
- 定义tasklet_struct用于管理和定义Tasklet
struct tasklet_struct {void (*func)(unsigned long data); // Tasklet 的处理函数unsigned long data; // 传递给处理函数的私有数据
};
- 初始化Tasklet_struct
- tasklet_init() 函数用于初始化 tasklet_struct 结构体,指定 Tasklet 的处理函数和私有数据。
void tasklet_init(struct tasklet_struct *t, void (*func)(unsigned long), unsigned long data);
- 调度Tasklet
- tasklet_schedule() 用于调度 Tasklet,告诉内核这个 Tasklet 需要执行。
- tasklet_schedule() 实际上不会立即执行 Tasklet,而是将 Tasklet 标记为可执行的。
- 当中断处理完成后,内核会检测到 Tasklet 已经被调度,会在稍后的软中断上下文中执行 Tasklet。
void tasklet_schedule(struct tasklet_struct *t);
- 注意事项
- tasklet_kill():在模块卸载时,需要调用 tasklet_kill(),它会确保 Tasklet 完成后才退出,以免在卸载模块时 Tasklet 仍在执行。
- 软中断上下文:Tasklet 是在软中断上下文中执行的,因此不能进行睡眠操作,也不能执行阻塞的 I/O 操作。
- 具体代码
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/interrupt.h>// Tasklet 处理函数
void my_tasklet_func(unsigned long data)
{printk(KERN_INFO "Tasklet 执行,数据: %lu\n", data);
}// 定义 Tasklet 对象
struct tasklet_struct my_tasklet;irqreturn_t irq_handler(int irq, void *dev_id)
{printk(KERN_INFO "中断发生,调度 Tasklet\n");// 调度 Tasklet 执行tasklet_schedule(&my_tasklet);return IRQ_HANDLED;
}static int __init my_init(void)
{int irq = 19; // 假设使用中断号 19// 初始化 Tasklet,传递处理函数和私有数据tasklet_init(&my_tasklet, my_tasklet_func, 100);// 注册中断处理程序if (request_irq(irq, irq_handler, IRQF_SHARED, "my_tasklet_device", NULL)) {printk(KERN_ERR "无法注册中断处理程序\n");return -1;}printk(KERN_INFO "模块加载成功,Tasklet 初始化完成\n");return 0;
}static void __exit my_exit(void)
{// 杀掉 Tasklet 确保它已经完成tasklet_kill(&my_tasklet);// 释放中断free_irq(19, NULL);printk(KERN_INFO "模块卸载,Tasklet 资源已释放\n");
}module_init(my_init);
module_exit(my_exit);MODULE_LICENSE("GPL");
MODULE_AUTHOR("Your Name");
MODULE_DESCRIPTION("Tasklet 示例");
工作队列的使用方法
- 工作队列(Workqueue)是 Linux 内核中提供的一种机制,用于将任务推迟到进程上下文中执行。
- 与 Tasklet 和软中断不同,工作队列允许进行阻塞操作和睡眠,因此适用于处理更为复杂、耗时的任务,如文件 I/O 或长时间的计算任务。
- 工作队列是在内核线程中执行的,运行环境与普通内核线程一致,能够进行各种内核操作。
具体代码
- 定义工作队列
- 工作队列通过 struct work_struct 定义
struct work_struct workqueue_obj;
- 初始化工作队列
- 在模块初始化时,使用 INIT_WORK() 初始化工作队列对象,并关联任务函数 workqueue_handle
INIT_WORK(&gstruct.workqueue_obj, workqueue_handle);
- 调度工作队列
- 在中断处理函数的下半部分 tasklet_fun 中,通过 schedule_work() 来调度工作队列
schedule_work(&gstruct.workqueue_obj);
- 工作队列处理函数
- 工作队列函数 workqueue_handle 是实际执行任务的地方,它运行在内核线程上下文中,因此可以执行阻塞操作
void workqueue_handle(struct work_struct *work)
{struct global_struct *pt_gstruct = container_of(work, struct global_struct, workqueue_obj);/* 中断产生数据 */pt_gstruct->keycnt++;sprintf(pt_gstruct->sharebuf, "hello usrread, keycnt=%d", pt_gstruct->keycnt);/* 唤醒等待队列,通知有数据可读 */pt_gstruct->data_flag = 1;wake_up_interruptible(&pt_gstruct->wqhead);/* 发送信号给用户进程,通知数据到达 */kill_fasync(&pt_gstruct->fapp, SIGIO, POLL_IN);printk("%s-%d irqno=%d\n", __func__, __LINE__, pt_gstruct->irqno);
}
- 模块退出时的清理
- 在模块卸载时,需要确保工作队列中的任务已完成或取消,避免在模块卸载后还有未完成的任务
cancel_work_sync(&gstruct.workqueue_obj);
- 代码示例
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/interrupt.h>
#include <linux/workqueue.h>
#include <linux/gpio.h>/* 假设 GPIO 中断号为 17 */
#define GPIO_IRQ_NUM 17/* 全局工作队列对象 */
static struct work_struct my_workqueue;/* 工作队列处理函数 */
void workqueue_func(struct work_struct *work)
{printk(KERN_INFO "工作队列任务执行:处理复杂的任务\n");/* 模拟耗时操作 */msleep(2000); // 模拟阻塞操作printk(KERN_INFO "工作队列任务完成\n");
}/* 中断处理程序(上半部分) */
irqreturn_t irq_handler(int irq, void *dev_id)
{printk(KERN_INFO "中断触发:调度工作队列\n");/* 调度工作队列 */schedule_work(&my_workqueue);return IRQ_HANDLED;
}/* 模块初始化 */
static int __init my_module_init(void)
{int ret;/* 初始化工作队列 */INIT_WORK(&my_workqueue, workqueue_func);/* 注册中断处理程序 */ret = request_irq(GPIO_IRQ_NUM, irq_handler, IRQF_SHARED, "my_workqueue_device", &my_workqueue);if (ret) {printk(KERN_ERR "无法注册中断处理程序\n");return ret;}printk(KERN_INFO "工作队列模块已加载\n");return 0;
}/* 模块卸载 */
static void __exit my_module_exit(void)
{/* 确保工作队列任务已完成或被取消 */cancel_work_sync(&my_workqueue);/* 释放中断 */free_irq(GPIO_IRQ_NUM, &my_workqueue);printk(KERN_INFO "工作队列模块已卸载\n");
}/* 模块入口和出口 */
module_init(my_module_init);
module_exit(my_module_exit);MODULE_LICENSE("GPL");
MODULE_AUTHOR("Your Name");
MODULE_DESCRIPTION("工作队列使用示例");
相关文章:

Linux下的驱动开发二
一、IO模型 I/O 模型在操作系统中用于处理应用程序与设备驱动之间的数据传输。I/O 通信模型的核心是解决程序与设备之间如何高效、合理地进行数据通信。不同的模型通过阻塞、非阻塞、同步、异步的方式来控制数据流和处理 I/O 请求。 注:在驱动开发中可以定义一个全…...

【JAVA报错已解决】 Java.lang.ArrayIndexOutOfBoundsException
🎬 鸽芷咕:个人主页 🔥 个人专栏: 《C干货基地》《粉丝福利》 ⛺️生活的理想,就是为了理想的生活! 专栏介绍 在软件开发和日常使用中,BUG是不可避免的。本专栏致力于为广大开发者和技术爱好者提供一个关于BUG解决的经…...

2024 CSP 游记
J 组 初赛 早上也是五点钟就起来 打游戏 了。 考点在八达小学,除了感觉小、破、旧就没有其他感觉( 我妈也是成功的给我提前一小时到达考场。 拿到试卷后,瞄一眼,咋这么简单,和一本通的模拟卷难度一样?…...

双十一有什么推荐好物?,这些你不能错过的宝藏好物推荐
随着双十一的临近,这场盛大的购物狂欢蓄势待发!为了让大家不在琳琅满目的商品中徘徊,琪琪用心归纳了一份购物清单,分享那些我亲自使用过,觉得必须拥有的商品。 这些商品不仅价格公道,而且质量上乘…...

NSSCTF [HUBUCTF 2022 新生赛]simple_RE(变种base64编码)
文件无壳 拖入IDA中 shiftF12查看可疑字符串 发现两串字符串 一看这两个等于号就猜测是base64编码 进入主函数看看 这段代码是一个简单的 C 语言程序,主要功能是接受用户输入的字符串作为“flag”,然后通过对输入的字符串进行一些处理和比较来验证是否输…...

clickhouse使用extract提取分号之前,之后,中间的内容
Area:‘安徽;宣城;宣州’,要提取分号之前,两个分号之前,最后一个分号之后的内容作为省市区 这是最后得到的正确的结果,感谢chatgpt 刚开始本来想使用splitByString -- 宣城 select splitByString(;,安徽;宣城;宣州)[2…...

Unity3D Compute Shader同步详解
前言 在Unity3D中,Compute Shader是一种强大的工具,它利用GPU的并行处理能力来执行复杂的计算任务,从而减轻CPU的负担,提高游戏的性能和效率。然而,由于GPU的工作方式,对共享资源的访问需要特别注意同步问…...

3D模型在UI设计中应用越来越多,给UI带来了什么?
当前3D模型在UI设计中应用很多,极大地拓展了UI设计的发挥空间,也拓宽了UI的应用领域,本文分享下UI中引入3D模型到底能带来什么价值. 3D模型在UI设计中的应用可以给用户界面带来以下几个方面的好处: 更真实的视觉体验:…...

前端框架的选择与考量:一场技术的盛宴
在当今快速迭代的Web开发领域,前端框架的选择成为了项目启动初期不可忽视的重要环节。随着React、Vue、Angular等主流框架的崛起,以及Svelte、Quasar等新兴力量的加入,开发者们面临着前所未有的选择难题。本文旨在探讨前端框架的选择依据、主…...

第五部分:7---信号的捕捉
目录 信号递达期间,该信号会被屏蔽直到递达完成。 sigaction实现信号的捕捉: 案例:在处理2号信号时屏蔽3号信号。 子进程退出向父进程发送SIGCHLD信号: 信号递达期间,该信号会被屏蔽直到递达完成。 当某个信号的处…...

HarmonyOS鸿蒙开发实战( Beta5.0)页面加载效果实现详解实践案例
鸿蒙HarmonyOS开发实战往期必看文章:(持续更新......) HarmonyOS NEXT应用开发性能实践总结(持续更新......) HarmonyOS NEXT应用开发案例实践总结合集(持续更新......) 一分钟了解”纯血版&…...

计算机网络中的VLAN详解
文章目录 计算机网络中的VLAN详解一、引言二、VLAN的作用与原理1、VLAN的作用2、VLAN的工作原理2.1、VLAN标签(Tag) 三、VLAN的配置与接口类型1、VLAN的配置2、接口类型 四、VLAN的应用场景1、企业网络2、数据中心3、教育网络 五、VLAN间的通信六、总结 …...

Nacos学习
系列文章目录 JavaSE基础知识、数据类型学习万年历项目代码逻辑训练习题代码逻辑训练习题方法、数组学习图书管理系统项目面向对象编程:封装、继承、多态学习封装继承多态习题常用类、包装类、异常处理机制学习集合学习IO流、多线程学习仓库管理系统JavaSE项目员工…...

后台数据管理系统 - 项目架构设计-Vue3+axios+Element-plus(0926)
十四、文章分类添加编辑 [element-plus 弹层] Git仓库:https://gitee.com/msyycn/vue3-hei-ma.git 点击显示弹层 准备弹层 const dialogVisible ref(false)<el-dialog v-model"dialogVisible" title"添加弹层" width"30%">…...

验收测试:从需求到交付的全程把控!
在软件开发过程中,验收测试是一个至关重要的环节。它不仅是对软件质量的把关,也是对整个项目周期的全程把控。从需求分析到最终的软件交付,验收测试都需要严格进行,以确保软件能够符合预期的质量和性能要求。 一、需求分析阶段 在…...

第十七节 鼠标的操作与相应
知识点 -event代表鼠标事件类型 -EVENT_LBUTTONDOWN鼠标左键按下 -EVENT_LBUTTONUP鼠标左键抬起 -EVENT_LBUTTONMOVE鼠标及移动 Point sp(-1, -1); Point ep(-1, -1); Mat temp; static void on_draw(int event, int x, int y, int flags, void* userdata) { Mat imag…...

深圳·2025胶粘剂展会 BOND第六届胶展
BOND第六届胶展、2025大湾区国际胶粘剂及密封剂展览会 时间:2025年6月25-27日 地址:深圳国际会展中心(新馆) UV胶、快干胶、结构粘结胶、导热胶、低温黑胶、硅胶、SMT贴片红胶、底部填充胶、低温热固胶、COB黑胶、围堰填充胶、U…...

什么是网络安全自动化以及优势与挑战
目录 网络安全自动化的工作原理 网络安全自动化的好处 增强的安全功能 改善表现和姿势 降低安全成本 简化的安全合规性和审计 更好的端点管理 网络安全自动化的挑战 耗时且容易出错的安全流程 可见性降低,风险和成本增加 合规管理 有用的网络安全自动化…...

java中的ArrayList和LinkedList的底层剖析
引入: 数据结构的分类,数据结构可以分成:线性表,树形结构,图形结构。 线性结构(线性表)包括:数组、链表、栈队列 树形结构:二叉树、AVL树、红黑树、B树、堆、Trie、哈夫曼树、并查集 图形结构:邻接矩阵、邻接表 线性表是具有存…...

占领矩阵-第15届蓝桥省赛Scratch中级组真题第5题
[导读]:超平老师的《Scratch蓝桥杯真题解析100讲》已经全部完成,后续会不定期解读蓝桥杯真题,这是Scratch蓝桥杯真题解析第190讲。 如果想持续关注Scratch蓝桥真题解读,可以点击《Scratch蓝桥杯历年真题》并订阅合集,…...

[论文笔记] Chain-of-Thought Reasoning without Prompting
分析: 在CoT解码路径中,我们可以看到模型在第三个位置(𝑖? = 3)开始展示推理过程,并且给出了正确的答案“8”。模型首先识别出说话者有3个苹果,然后识别出爸爸比说话者多2个,即5个苹果,最后将这两个数量相加得到总数8个苹果。 这个例子表明,通过探索替代的解码路径…...

C++八股进阶
之前那个只是总结了一下常考点,这个是纯手打记笔记加深理解 这里写目录标题 C的四种智能指针为什么要使用智能指针?四种智能指针: C中的内存分配情况C中的指针参数传递和引用参数传递C 中 const 和 static 关键字(定义࿰…...

渗透测试--文件上传常用绕过方式
文件上传常用绕过方式 1.前端代码,限制只允许上传图片。修改png为php即可绕过前端校验。 2.后端校验Content-Type 校验文件格式 前端修改,抓取上传数据包,并且修改 Content-Type 3.服务端检测(目录路径检测) 对目…...

音视频生态下Unity3D和虚幻引擎(Unreal Engine)的区别
技术背景 好多开发者跟我们做技术交流的时候,会问我们,为什么有Unity3D的RTMP|RTSP播放模块,还有RTMP推送和轻量级RTSP服务模块,为什么不去支持虚幻引擎?二者区别在哪里?本文就Unity3D和虚幻引擎之间的差异…...

搭建基于H.265编码的RTSP推流云服务器
一、前言 网上能够找到的RTSP流地址,均是基于H.264编码的RTSP流地址,无法测试应用是否可以播放H265实时流为此,搭建本地的把H.264转码成H.265的RTSP服务器,不管是通过VLC搭建本地RTSP服务器,还是通过FFmpeg搭建本地RT…...

C++20 std::format
一、前言 1、传统 C 格式化的问题与挑战 可读性差:使用 C 中的 printf 和 scanf 家族函数进行格式化输出和输入时,它们的语法较为复杂,难以阅读。在较大的代码项目中,可读性差会导致维护困难。类型安全性差:printf 和…...

Python基础知识 (九)os模块、异常、异常的传递性
目录 OS模块 目录的具体操作 什么是异常 异常常见处理方式 异常分类: 捕获一个指定异常 捕获多个异常 捕获所有异常 异常具有传递性 OS模块 在Python中,os模块的常用函数分为两类: (a)通过os.path调用的函数…...

鸿蒙手势交互(三:组合手势)
三、组合手势 由多种单一手势组合而成,通过在GestureGroup中使用不同的GestureMode来声明该组合手势的类型,支持顺序识别、并行识别和互斥识别三种类型。 GestureGroup(mode:GestureMode, gesture:GestureType[]) //- mode:为GestureMode枚…...

【计算机方向】中科院二区TOP神刊!国人发文友好,刊文量高,录用容易!
期刊解析 🚩本 期 期 刊 看 点 🚩 中科院二区TOP期刊! 审稿友好,IF4.8,自引率6.2% 最新年度发文530。 今天小编带来计算机领域SCI快刊的解读! 如有相关领域作者有意投稿,可作为重点关注&am…...

Stable Diffusion 保姆级教程
1. 引言 近年来,Stable Diffusion 成为了图像生成领域的热门技术,它是一种基于扩散模型的生成模型,可以通过输入简单的文本描述生成高质量的图像。相比传统的生成对抗网络(GAN),Stable Diffusion 更具稳定…...