嵌入式Linux按键监控模块详解:实现设备重启与长按检测
嵌入式Linux按键监控模块详解:实现设备重启与长按检测
在嵌入式Linux设备开发中,物理按键仍然是用户与设备交互的重要方式。本文将分享一个轻量级但功能完整的按键监控模块,它可以精确识别按键的短按和长按事件,并执行对应操作如系统重启。
需求背景
许多嵌入式设备需要提供物理重启按钮,一般有两种常见的交互模式:
- 短按:重启设备(常见操作)
- 长按:执行特殊功能,如恢复出厂设置(避免误触发)
这些看似简单的需求,实现起来需要考虑多线程、事件检测、资源管理等多方面因素。
技术方案
我们的方案基于以下技术组件:
- Linux Input子系统:捕获设备按键事件
- epoll机制:高效IO复用,降低资源消耗
- pthread:创建独立线程处理按键事件
- 回调函数:灵活处理不同类型的按键事件
代码实现
1. 模块头文件定义
首先,定义模块对外接口和数据类型:
// sl_key.h
#ifndef SL_KEY_H
#define SL_KEY_H#include <stdint.h>// 按键事件类型
typedef enum {KEY_EVENT_SHORT_PRESS, // 短按事件KEY_EVENT_LONG_PRESS, // 长按事件
} key_event_type_t;// 按键事件回调函数类型
typedef void (*key_callback_t)(key_event_type_t event);// 初始化按键检测模块
int sl_key_init(const char *gpio_path, key_callback_t callback);// 停止按键检测
void sl_key_deinit(void);// 快速初始化函数
void reset_key_listen_init(void);#endif // SL_KEY_H
这个简洁的接口定义了两种按键事件类型和必要的初始化/反初始化函数。
2. 核心模块实现
模块主体实现包含以下几个关键部分:
2.1 配置参数与全局状态
// 配置参数
#define KEY_LONG_PRESS_TIME 5000 // 长按阈值(毫秒)
#define KEY_SHORT_PRESS_TIME 1000 // 短按最小时间(毫秒)
#define EPOLL_TIMEOUT 500 // epoll超时时间(毫秒)// 模块状态
static struct {int fd; // 设备文件描述符int epoll_fd; // epoll文件描述符pthread_t thread; // 监听线程volatile int running; // 运行标志key_callback_t callback; // 回调函数
} g_key_ctx = {.fd = -1,.epoll_fd = -1,.running = 0,.callback = NULL
};
这里定义了短按和长按的时间阈值:短按至少1秒,长按需要5秒以上。同时使用静态结构体集中管理模块状态,便于维护。
2.2 按键监听线程
static void *key_monitor_thread(void *arg)
{struct epoll_event events[1];struct input_event ev;uint64_t press_time = 0;int key_pressed = 0;while (g_key_ctx.running) {int ret = epoll_wait(g_key_ctx.epoll_fd, events, 1, EPOLL_TIMEOUT);if (ret < 0) {if (errno != EINTR) {SL_ERR("epoll_wait failed: %s\n", strerror(errno));break;}continue;}if (ret == 0) {continue; // 超时,继续等待}if (events[0].events & (EPOLLERR | EPOLLHUP)) {SL_ERR("epoll error event\n");break;}if (!(events[0].events & EPOLLIN)) {continue;}// 读取按键事件if (read(g_key_ctx.fd, &ev, sizeof(ev)) != sizeof(ev)) {if (errno != EAGAIN && errno != EWOULDBLOCK) {SL_ERR("read event failed: %s\n", strerror(errno));break;}continue;}// 只处理按键事件if (ev.type != EV_KEY) {continue;}// 按键按下if (ev.value == 1 && !key_pressed) {press_time = get_current_ms();key_pressed = 1;SL_LOG("Key pressed\n");}// 按键释放else if (ev.value == 0 && key_pressed) {uint64_t duration = get_current_ms() - press_time;key_pressed = 0;SL_LOG("Key released, duration: %lu ms\n", duration);// 回调处理if (g_key_ctx.callback) {if (duration >= KEY_LONG_PRESS_TIME) {g_key_ctx.callback(KEY_EVENT_LONG_PRESS);} else if (duration >= KEY_SHORT_PRESS_TIME) {g_key_ctx.callback(KEY_EVENT_SHORT_PRESS);}}}}return NULL;
}
这是模块的核心逻辑,通过epoll高效等待按键事件,记录按下时间并计算持续时间,然后根据时长判断按键类型并触发回调。
2.3 模块初始化与清理
int sl_key_init(const char *gpio_path, key_callback_t callback)
{if (!gpio_path || !callback) {return -1;}// 防止重复初始化if (g_key_ctx.running) {return -1;}// 打开设备g_key_ctx.fd = open(gpio_path, O_RDONLY | O_NONBLOCK);if (g_key_ctx.fd < 0) {SL_ERR("Failed to open %s: %s\n", gpio_path, strerror(errno));return -1;}// 创建epoll实例g_key_ctx.epoll_fd = epoll_create1(0);if (g_key_ctx.epoll_fd < 0) {SL_ERR("Failed to create epoll: %s\n", strerror(errno));close(g_key_ctx.fd);g_key_ctx.fd = -1;return -1;}// 添加到epoll监听struct epoll_event ev = {.events = EPOLLIN,.data.fd = g_key_ctx.fd};if (epoll_ctl(g_key_ctx.epoll_fd, EPOLL_CTL_ADD, g_key_ctx.fd, &ev) < 0) {SL_ERR("Failed to add to epoll: %s\n", strerror(errno));close(g_key_ctx.epoll_fd);close(g_key_ctx.fd);g_key_ctx.fd = -1;g_key_ctx.epoll_fd = -1;return -1;}// 设置回调和运行标志g_key_ctx.callback = callback;g_key_ctx.running = 1;// 创建监听线程if (pthread_create(&g_key_ctx.thread, NULL, key_monitor_thread, NULL) != 0) {SL_ERR("Failed to create thread: %s\n", strerror(errno));close(g_key_ctx.epoll_fd);close(g_key_ctx.fd);g_key_ctx.fd = -1;g_key_ctx.epoll_fd = -1;g_key_ctx.running = 0;return -1;}SL_LOG("Key module initialized successfully\n");return 0;
}void sl_key_deinit(void)
{if (!g_key_ctx.running) {return;}// 停止线程g_key_ctx.running = 0;pthread_join(g_key_ctx.thread, NULL);// 关闭文件描述符if (g_key_ctx.epoll_fd >= 0) {close(g_key_ctx.epoll_fd);g_key_ctx.epoll_fd = -1;}if (g_key_ctx.fd >= 0) {close(g_key_ctx.fd);g_key_ctx.fd = -1;}g_key_ctx.callback = NULL;SL_LOG("Key module deinitialized\n");
}
初始化函数完成资源分配和线程创建,每一步都有错误检查和资源释放,确保不会出现资源泄露。反初始化函数则负责清理所有资源。
2.4 按键事件处理函数
void key_handler(key_event_type_t event)
{switch (event) {case KEY_EVENT_SHORT_PRESS:SL_LOG("Short press detected\r\n");sl_reboot(); // 短按重启系统break;case KEY_EVENT_LONG_PRESS:SL_LOG("Long press detected\r\n");// 处理长按(预留)break;}
}void reset_key_listen_init(void)
{// 初始化按键模块if (sl_key_init("/dev/input/event1", key_handler) < 0) {SL_ERR("Failed to initialize key module\n");}
}
这部分定义了具体的按键处理逻辑:短按触发系统重启,长按目前只记录日志(预留扩展)。reset_key_listen_init
是一个便捷的初始化函数,使用固定路径和处理函数。
技术要点解析
1. 为什么使用epoll而非轮询?
在嵌入式系统中,资源通常受限,使用epoll机制有以下优势:
- 资源效率高:只在有事件时才被唤醒,降低CPU占用
- 扩展性好:即使监控多个按键,性能也不会明显下降
- 响应及时:事件触发立即被通知,不依赖轮询间隔
2. 为什么使用独立线程?
按键处理使用独立线程的好处:
- 不阻塞主程序:即使按键处理耗时,也不影响主程序执行
- 实时性好:按键事件能够及时处理,不依赖主程序调度
- 模块化设计:按键模块可以独立工作,便于集成和移植
3. 按键时间阈值选择
- 短按最小时间(1秒):过滤意外触碰,确保是有意识的操作
- 长按阈值(5秒):足够长以区分短按,避免误触发重要功能
- 超时时间(500毫秒):平衡响应速度和资源占用
使用方法
使用该模块很简单,只需在系统初始化时调用:
#include "sl_key.h"int main()
{// 方法1:使用便捷函数(固定设备路径)reset_key_listen_init();// 或者方法2:自定义设备路径和回调// sl_key_init("/dev/input/eventX", custom_key_handler);// 主程序逻辑...// 退出前清理sl_key_deinit();return 0;
}
应用场景
该按键模块适用于多种嵌入式设备场景:
- 网络设备:路由器、交换机等需要重启/复位功能
- 智能家居:需要物理按键控制的智能设备
- 工控设备:需要紧急重启或模式切换的控制设备
- 医疗设备:需要物理按键操作的设备
改进方向
虽然这个模块已经能满足基本需求,但仍有以下改进空间:
- 多按键支持:扩展为支持多个按键及组合按键
- 按键防抖:添加软件防抖动算法,提高可靠性
- 更多事件类型:如双击、三击等复杂操作
- 动态配置:支持运行时调整按键时间阈值
- 低功耗优化:结合系统电源管理,降低待机功耗
总结
这个按键监控模块虽然代码量不大,但涵盖了Linux设备交互、事件处理、多线程编程等多个技术要点。它通过精心设计,在资源消耗与功能实现之间取得了很好的平衡,适合在各类嵌入式Linux系统中使用。
对于需要物理按键交互的嵌入式设备,这个模块提供了一个可靠、高效、易于集成的解决方案。它不仅支持基本的短按重启功能,还预留了长按接口,可根据实际需求进行扩展。
参考资源
- Linux Input子系统文档
- epoll机制详解
- Linux设备驱动开发指南
相关文章:
嵌入式Linux按键监控模块详解:实现设备重启与长按检测
嵌入式Linux按键监控模块详解:实现设备重启与长按检测 在嵌入式Linux设备开发中,物理按键仍然是用户与设备交互的重要方式。本文将分享一个轻量级但功能完整的按键监控模块,它可以精确识别按键的短按和长按事件,并执行对应操作如…...
[错误经验 坑]关于UDP服务器和客户端通信使用的recvfrom的输出型参数len没有被初始化导致的问题
[错误经验 坑]关于UDP服务器和客户端通信使用的recvfrom的输出型参数len没有被初始化导致的问题 水墨不写bug 文章目录 一、困惑:二、解答:(1)函数原型1. int sockfd2. void *buf3. size_t len4. int flags5. struct sockaddr *sr…...
KaiwuDB:面向AIoT场景的多模融合数据库,赋能企业数字化转型
引言 在万物互联的AIoT时代,企业面临着海量时序数据处理、多模数据融合和实时分析等挑战。KaiwuDB应运而生,作为一款面向AIoT场景的分布式、多模融合、支持原生AI的数据库产品,为企业提供了一站式数据管理解决方案。 产品概述 KaiwuDB是一…...
Web3 的云基础设施正在成型,Polkadot 2.0 用三项技术改写“上链成本”
在Web3基础设施内卷加剧的今天,“如何以更低成本、更大灵活性部署一条高性能应用链”正成为开发者们最关心的问题。而刚刚走出“技术慢热”误区的Polkadot,正在用一套名为 Polkadot 2.0 的架构升级方案,重新定义这一问题的解法。 这套升级最…...
Elasticsearch 学习规划
Elasticsearch 学习规划 明确学习目标与动机 场景化需求分析 - **S**:掌握Elasticsearch架构体系,熟练使用Elasticsearch 进行数据分析,Elasticsearch结合java 项目落地案例 - **M**:搜索和Elasticsearch相关GitHub项目 - **A**:每…...
OpenHarmony如何编译安装系统应用(以settings设置为例)
开发环境 1.OpenHarmony 2.DevEco Studio 3 .Full Sdk 实现步骤 1.获取设置应用源码 https://gitee.com/openharmony/applications_settings/tree/OpenHarmony-v5.0.0-Release/ 2,使用 DevEco Studio 和 Full SDK对系统应用进行签名,默认工程是未配置签名的状态,所构建…...
手撕 STL 之—— list
目录 引言 1, list_node类及其构造函数 2, list类的创建 3, list基本功能函数 3_1, 构造函数 3_2,push_back 3_3,push_front 3_4, pop_back 3_5,pop_front 4,迭代器 (重点) 4_1,如何设…...
Med-R1论文阅读理解
论文介绍 这篇论文介绍了一个名为 Med-R1 的新方法,用于提升多模态视觉语言模型(VLM)在医学图像理解和推理任务中的泛化能力和可解释性。下面是对整篇论文的简洁总结: ⸻ 🧠 核心思想 • 当前医学 VLM 多依赖于监督…...
微服务相关
1.SpringCloud有哪些常用组件?分别是什么作用? 注册中心:nacos 负载均衡:rabbion/LoadBalancer 网关:gateway 服务熔断:sential 服务调用:Feign 2.服务注册发现的基本流程是怎样的&#x…...
Linux vagrant 导入Centos到virtualbox
前言 vagrant 导入centos 虚拟机 前提要求 安装 virtualbox 和vagrant<vagrant-disksize> (Linux 方式 Windows 方式) 创建一键部署centos 虚拟机 /opt/vagrant 安装目录/opt/VirtualBox 安装目录/opt/centos8/Vagrantfile (可配置网络IP,内存…...
Spring Boot MongoDB 分页工具类封装 (新手指南)
Spring Boot MongoDB 分页工具类封装 (新手指南) 目录 引言:为何需要分页工具类?工具类一:PaginationUtils - 简化 Pageable 创建 设计目标代码实现 (PaginationUtils.java)如何使用 PaginationUtils 工具类二:PageResponse<…...
第七章 指针
2024-04 2023-10 A 2023-04 2022-10 2022-04 2021-10 2021-04 2020-10 2020-04...
20年AB1解码java
P8706 [蓝桥杯 2020 省 AB1] 解码 - 洛谷 详细代码如下: import java.util.Scanner;public class Main {public static void main(String[] args) {Scanner innew Scanner(System.in); // 接收输入的字符串char [] c in.next().toCharArray(); // 接收 还原的字符…...
《Java实战:密码加密算法实现与代码解析》
文章目录 一、需求背景二、代码逐模块解析1. 主程序入口2. 密码输入模块3. 加密处理模块4. 结果拼接模块 三、完整代码示例四、运行示例五、优化方向(下篇预告) 一、需求背景 实现一个4位数字密码的简单加密系统,规则如下: 输入…...
AllData数据中台升级发布 | 支持K8S数据平台2.0版本
🔥🔥 AllData大数据产品是可定义数据中台,以数据平台为底座,以数据中台为桥梁,以机器学习平台为中层框架,以大模型应用为上游产品,提供全链路数字化解决方案。 ✨杭州奥零数据科技官网…...
Jupyter notebook使用技巧
一、打开指定文件夹 在快捷方式目标中,使用如下代码 anaconda3\python.exe anaconda3\cwp.py anaconda3 anaconda3\python.exe anaconda3\Scripts\jupyter-notebook-script.py --notebook-dirD:\code\python...
6.3es新特性web worker
Web Worker 是 HTML5 提供的多线程技术,允许在浏览器后台创建独立线程执行 JavaScript 代码,解决主线程因耗时任务导致的 界面卡顿 问题。 核心特性 线程隔离:Worker 线程无法直接操作 DOM 或访问 window 对象通信机制:通过 pos…...
基于 OpenHarmony 5.0 的星闪轻量型设备应用开发——Ch3 设备驱动开发
写在前面:本篇是系列文章《基于 OpenHarmony 5.0 的星闪轻量型设备应用开发》的第 3 章。本篇从 GPIO、PWM、I2C、UART 以及 ADC 等方面对基于 OpenHarmony 5.0 的 WS63 设备驱动开发进行了详细的介绍。本篇的篇幅较长,建议先收藏再阅读。 3.1 OpenHarmo…...
iphone各个机型尺寸
以下是苹果(Apple)历代 iPhone 机型 的屏幕尺寸、分辨率及其他关键参数汇总(截至 2023年10月,数据基于官方发布信息): 一、标准屏 iPhone(非Pro系列) 机型屏幕尺寸(英寸…...
OfficePlus去掉PDF文件右键菜单里的PDF转换
今天在吾爱破解论坛看到一个求助帖,说是OfficePlus,安装后,PDF文件的右键菜单里多了PDF转换,想去掉,不知道怎么弄。底下的回复基本都是百度复制或者AI搜索出的答案,大致就是找注册表里CLASSID下的菜单栏相关…...
Linux驱动开发进阶(七)- DRM驱动程序设计
文章目录 1、前言2、DRAM(KMS、GEM)2.1、KMS2.2、GEM 3、DRM3.1、驱动结构体3.2、设备结构体3.3、DRM驱动注册3.4、DRM模式设置3.4.1、plane初始化3.4.2、crtc初始化3.4.3、encoder初始化3.4.4、connect初始化 4、示例说明5、DRM Simple Display框架6、DRM热插拔7、DRM中的plan…...
Parasoft C++Test软件单元测试_条件宏和断言宏使用方法的详细介绍
系列文章目录 Parasoft C++Test软件静态分析:操作指南(编码规范、质量度量)、常见问题及处理 Parasoft C++Test软件单元测试:操作指南、实例讲解、常见问题及处理 Parasoft C++Test软件集成测试:操作指南、实例讲解、常见问题及处理 进阶扩展:自动生成静态分析文档、自动…...
vue辅助工具(vue系列二)
目录 第一章、安装周边库1.1)状态管理:Pinia1.2)路由管理:Router1.3)HTTP 客户端:Axios1.4)UI 组件库:Element 第二章、下载Vue插件并安装2.1)安装开发者工具2.1.1&#…...
WPF 五子棋项目文档
WPF 五子棋项目文档 1. 项目概述 本项目是一个使用 Windows Presentation Foundation (WPF) 技术栈和 C# 语言实现的桌面版五子棋(Gomoku)游戏。它遵循 MVVM(Model-View-ViewModel)设计模式,旨在提供一个结构清晰、可…...
UniApp 实现兼容 H5 和小程序的拖拽排序组件
如何使用 UniApp 实现一个兼容 H5 和小程序的 九宫格拖拽排序组件,实现思路和关键步骤。 一、实现目标 支持拖动菜单项改变顺序拖拽过程实时预览移动位置拖拽松开后自动吸附回网格兼容 H5 和小程序平台 二、功能结构拆解以及完整代码 完整代码: <…...
谷歌推出统一安全平台-一个平台实现跨云网端主动防护
👋 今天要给大家带来一个超级棒的消息!谷歌云推出了全新的“谷歌统一安全平台”,感觉我们的网络安全问题有救啦!😄 随着企业基础设施变得越来越复杂,保护它们也变得越来越难。攻击面不断扩大,安…...
众趣科技丨沉浸式 VR 体验,助力酒店民宿数字化营销宣传
随着旅游季的到来,各地的旅游景区开始“摩拳擦掌”推出各种活动,吸引更多游客来此游玩。 自去年以来,冰雪游热度持续上升,尤其是对于满心期待的南方游客来说,哈尔滨仍是冰雪旅游的热门目的地。据美团数据显示ÿ…...
DAY05:【pytorch】图像预处理
1、torchvision 功能:计算视觉工具包 torchvision.transforms:常用的图像预处理方法torchvision.datasets:常用数据集的 dataset 实战,MINIST,CIFAR-10,ImageNet等torchvision.model:常用的模…...
真实企业级K8S故障案例:ETCD集群断电恢复与数据保障实践
背景描述 某跨境电商平台生产环境使用Kubernetes(v1.23.17)管理500微服务。某日机房突发市电中断,UPS未能及时接管导致: 3节点ETCD集群(v3.5.4)全部异常掉电 Control-Plane节点无法启动api-server 业务P…...
rbd块设备的id修改
背景 看到有这个需求,具体碰到什么场景了不太清楚,之前做过rbd的重构的研究,既然能重构,那么修改应该是比重构还要简单一点的,我们具体看下怎么操作 数据结构分析 rbd的元数据信息 [rootlab104 ~]# rbd create tes…...
WP最主题专业的wordpress主题开发
WP最主题(wpzui.com) WP最主题是一个提供高品质WordPress主题的平台。它注重主题的设计和功能,旨在为用户提供美观且实用的主题选择。其主题通常具有良好的用户体验、丰富的自定义选项以及优化的性能,能够满足不同类型的网站搭建…...
HomeAssistant本地化部署结合内网穿透打造跨网络智能家居中枢
文章目录 前言1. 添加镜像源2. 部署HomeAssistant3. HA系统初始化配置4. HA系统添加智能设备4.1 添加已发现的设备4.2 添加HACS插件安装设备 5. 安装cpolar内网穿透5.1 配置HA公网地址 6. 配置固定公网地址 推荐 前些天发现了一个巨牛的人工智能学习网站,通俗易懂…...
# 实时人脸性别与年龄识别:基于OpenCV与深度学习模型的实现
实时人脸性别与年龄识别:基于OpenCV与深度学习模型的实现 在当今数字化时代,计算机视觉技术正以前所未有的速度改变着我们的生活与工作方式。其中,人脸检测与分析作为计算机视觉领域的重要分支,已广泛应用于安防监控、智能交互、…...
SAP-ABAP:SAP的Open SQL和Native SQL详细对比
在SAP ABAP开发中,Open SQL和Native SQL是两种操作数据库的方式,它们的核心区别在于可移植性、功能范围及底层实现机制。以下是详细对比: 1. Open SQL:深入解析 1.1 核心特性 数据库抽象层 Open SQL 由 SAP 内核的 Database Interface (DBI) 转换为目标数据库的 SQL(如 …...
基于大模型构建金融客服的技术调研
OpenAI-SB api接口 https://openai-sb.com/ ChatGPT与Knowledge Graph (知识图谱)分享交流 https://www.bilibili.com/video/BV1bo4y1w72m/?spm_id_from333.337.search-card.all.click&vd_source569ef4f891360f2119ace98abae09f3f 《要研究的方向和准备》 https://ww…...
Python设计模式:命令模式
1. 什么是命令模式? 命令模式是一种行为设计模式,它将请求封装为一个对象,从而使您能够使用不同的请求、队列或日志请求,以及支持可撤销操作。 命令模式的核心思想是将请求的发送者与请求的接收者解耦,使得两者之间的…...
30天学Java第八天——设计模式
装饰器模式 Decorator Pattern 装饰器模式(Decorator Pattern)是一种结构型设计模式,它允许通过动态地添加功能来扩展对象的行为,而不需要修改原有的类。 这种模式通常用于增强对象的功能,与继承相比,使用…...
Spring事务系列 三
Spring事务的传播机制 Spring事务系列 一-CSDN博客 Spring事务系列 二-CSDN博客 文章目录 系列文章目录 目录 文章目录 前言 一、Spring事务的传播机制 Propagation.REQUIRED: Propagation.SUPPORTS: Propagation.MANDATORY: Propagation.REQUIRES_NEW: Propagation.NOT_SUPPO…...
文件上传做题记录
1,[SWPUCTF 2021 新生赛]easyupload2.0 直接上传php 再试一下phtml 用蚁剑连发现连不上 那就只要命令执行了 2,[SWPUCTF 2021 新生赛]easyupload1.0 当然,直接上传一个php是不行的 phtml也不行,看下是不是前端验证,…...
机器学习的监督学习与无监督学习
机器学习主要分为监督学习和无监督学习两大类,两者的核心区别在于数据是否带有标签(Label)。以下是它们的详细对比和说明: 1. 监督学习(Supervised Learning) 定义:通过带有标签的训练数据&…...
C++ 入门三:函数与模板
一、内联函数:编译期嵌入的 “高效函数” 1. 什么是内联函数? 核心特性:在编译阶段,内联函数的函数体会直接嵌入到调用它的代码中,避免了普通函数的调用开销(如压栈、跳转、返回)。语法&#…...
解析券商qmt的优缺点
现在已经对于大QMT进行了一步步的深入了解与学习,也已经开始积木式搭建策略,进行交易了,但是,随时不断的深入,发现的问题也越来越多。下面开始逐一解析: 首页 | 迅投知识库 这是详细的说明。 目前券商给大…...
CSE lesson2 chrony服务器
CSE lesson2 chrony服务器 timedatectl命令 NTP(network time protocal)网络时间协议,时钟服务器同步时间的时候会使用到该协议进行时间同步。 #关闭/开启时间同步服务 [rootlocalhost ~]# timedatectl set-ntp 0/1#设置时间(必须关闭时间同步服务才能…...
时光交响曲:杭州的科技与传统交响
故事背景 故事发生在中国浙江杭州,以现代科技与文化传统的交融为背景,展现了人与自然、历史的深刻联系。在晨曦中的茶园、宁静的运河书屋、科技堤坝等地方,每个场景都充满了生机与活力,展示了科技如何赋予传统文化新的生命&#x…...
【大模型智能体】Agent2Agent协议加上MCP协议也许会成为未来Agent智能体系统的标配
之前在文章《基于Claude MCP协议的智能体落地示例》、《MCP(Model Context Protocol) 大模型智能体第一个开源标准协议》我们已经对MCP协议做了介绍,MCP提供了将大模型连接到不同数据源和工具的标准方式,包括内容仓库、商业工具和开发环境。 以上解决的是…...
opencv(C++)处理图像颜色
文章目录 介绍使用策略设计模式比较颜色实现方案计算两个颜色向量之间的距离1. 简单方法:曼哈顿距离计算(Manhattan Distance)2.使用 OpenCV 的 cv::norm 函数3.使用 OpenCV 的 cv::absdiff 函数错误示例 使用 OpenCV 函数实现颜色检测实现方…...
2025年焊接与热切割作业证考试真题分享
焊接与热切割作业属于特种作业操作证考试,理论知识点专业性强、安全规范要求高,如何高效备考成为关键!【100分题库】焊接与热切割作业理论备考题库紧扣最新考试大纲,帮你系统掌握考点,一次通过考试! 1、下…...
AI 代码生成工具如何突破 Java 单元测试效能天花板?
一、传统单元测试的四大痛点 时间黑洞:根据 JetBrains 调研,Java 开发者平均花费 35% 时间编写测试代码覆盖盲区:手工测试覆盖率普遍低于 60%(Jacoco 全球统计数据)维护困境:业务代码变更导致 38% 的测试用…...
【C++游戏引擎开发】第13篇:光照模型与Phong基础实现
一、Phong模型数学原理 1.1 光照叠加公式 L = k a I a + k d I d max ( 0 , n ⋅ l ) + k s I s max ( 0 , r ⋅ v ) α L = k_a I_a + k_d I_d \max(0, \mathbf{n} \cdot \mathbf{l}) + k_s I_s \max(0, \mathbf{r} \cdot \mathbf{v})^\alpha L=kaIa+kdIdmax(0…...
如何在Android系统上单编ko?
文章目录 一、先了解编译驱动需要什么?二、配置makefile1、在Android系统编译LOG上找到编译器信息(一般都会打印出来)2、基于源MK构造 可独立运行的makefile3)进入docker,在此makefile目录下敲make4)最后根…...