Android7 Input(二)Linux 驱动层输入事件管理
概述
在Linux系统中,将键盘,鼠标,触摸屏等这类交互设备交由Linux Input子系统进行管理,Linux Input驱动子系统由于具有良好的和用户空间交互的接口。因此Linux Input驱动子系统,不止于只管理输入类型的设备。也可以将其他类型的设备归纳于Linux Input进行管理, 比如Rockchip 的Android系统平台上,将传感器数据的处理,就归纳到Linux Input进行管理。
本文主要描述了输入设备在Linux Input驱动子系统中的管理,Input设备事件管理框架和产生事件时如何上报给Linux Input子系统。本文是基于RK3288 Android7的Linux内核进行讲解,该版本使用的是Linux-4.4.y的版本,读者在阅读的时候,请注意,不同版本的内核,部分源码可能与文章涉及到的源码不一样。
Input 驱动框架
Linux input驱动框架,如下所示:
注: 本文主要描述侧重点在键盘和触摸这类输入设备,因此,框图中描述的主要涉及这两类设备的驱动框架;
Input驱动数据结构
在Input驱动子系统中, 输入设备有input_dev数据结构进行管理,核心成员如下所示:
struct input_dev {const char *name;......struct input_id id;......unsigned long evbit[BITS_TO_LONGS(EV_CNT)];unsigned long keybit[BITS_TO_LONGS(KEY_CNT)];unsigned long relbit[BITS_TO_LONGS(REL_CNT)];unsigned long absbit[BITS_TO_LONGS(ABS_CNT)];......int (*open)(struct input_dev *dev);void (*close)(struct input_dev *dev);int (*flush)(struct input_dev *dev, struct file *file);int (*event)(struct input_dev *dev, unsigned int type, unsigned int code, int value);......struct input_handle __rcu *grab;......struct list_head h_list;struct list_head node;};
主要成员:
name:设备名称
id:输入设备身份标识,比如厂家信息,设备总线类型等信息;
evbit:支持的事件类型掩码
keybit:按键事件掩码
relbit:相对坐标事件掩码
absbit:绝对坐标掩码
grab:事件Handler(这个后面进行讲解)
h_list:输入设备输入事件处理handle链表
node: 输入设备连接节点,系统将所有注册的输入设备通过一个全局的链表进行管理;
Input设备的创建和注册
1、Linux Input设备的创建可以使用input_allocate_device和devm_input_allocate_deviced两种类型API,目前推荐使用带有devm字样的接口,因为它可以在驱动probe过程中如果发生失败,自动完成内存回收,防止驱动程序处理不当,导致的物理内存的泄露。devm_input_allocate_deviced函数的实现,最终的核心部分还是input_allocate_device,如下图所示:
struct input_dev *input_allocate_device(void)
{static atomic_t input_no = ATOMIC_INIT(-1);struct input_dev *dev;dev = kzalloc(sizeof(struct input_dev), GFP_KERNEL);if (dev) {dev->dev.type = &input_dev_type;dev->dev.class = &input_class;device_initialize(&dev->dev);mutex_init(&dev->mutex);spin_lock_init(&dev->event_lock);init_timer(&dev->timer);INIT_LIST_HEAD(&dev->h_list);INIT_LIST_HEAD(&dev->node);dev_set_name(&dev->dev, "input%lu",(unsigned long)atomic_inc_return(&input_no));__module_get(THIS_MODULE);}return dev;
}
input_allocate_device完成主要如下的功能:
a、创建input_dev管理结构,并初始化部分成员变量;
b、设置Input设备的名字;
2、input设备的注册,有input_register_device()接口完成,下面只展示核心代码:
int input_register_device(struct input_dev *dev)
{....../* Every input device generates EV_SYN/SYN_REPORT events. */__set_bit(EV_SYN, dev->evbit);/* KEY_RESERVED is not supposed to be transmitted to userspace. */__clear_bit(KEY_RESERVED, dev->keybit);/* Make sure that bitmasks not mentioned in dev->evbit are clean. */input_cleanse_bitmasks(dev);......error = device_add(&dev->dev);if (error)goto err_free_vals;......list_add_tail(&dev->node, &input_dev_list);list_for_each_entry(handler, &input_handler_list, node)input_attach_handler(dev, handler);......return 0;......
}
input_register_device函数完成如下功能:
1)设置EV_SYN事件掩码,这是事件同步掩码,表示当前事件上报完成标记;
2)将input设备注册到Linux设备驱动管理框架中device_add;
3)将input设备加入到系统全局输入设备管理链表中;
4)为输入设备绑定事件处理Handler。不同的输入设备可以根据自己的特性,绑定不同的事件处理Handler;
Input Handler
在上一个章节,描述注册input设备时,会为输入设备绑定一个事件处理handler。在Input驱动子系统中,对输入设备产生的事件,由input的Handler进行处理。目前在linux-4.4.y内核中,使用input_register_handler() 接口注册事件处理Handler,因此Input子系统可以灵活开发自己的事件处理Handler, 可以将输入设备产生的事件进行灵活处理,input_register_handler函数的核心实现如下所示:
static int input_attach_handler(struct input_dev *dev, struct input_handler *handler)
{const struct input_device_id *id;int error;id = input_match_device(handler, dev);if (!id)return -ENODEV;error = handler->connect(handler, dev, id);if (error && error != -ENODEV)pr_err("failed to attach handler %s to device %s, error: %d\n",handler->name, kobject_name(&dev->dev.kobj), error);return error;
}
input_attach_handler完成的主要如下功能:
1) 将系统handler与输入设备dev进行匹配,只有匹配的handler,才能当做input设备的事件处理器;
2) dev和handler匹配完成,调用handler的connect方法绑定input 设备;
3)input对触摸屏,键盘等这类设备,使用evdev_hander进行事件处理;
evdev Handler
上一节,我们讲解了Input hander的注册方法,这一章节,我们主要描述evdev的实现。evdev handler的初始化,主要如下所示:
static struct input_handler evdev_handler = {.event = evdev_event,.events = evdev_events,.connect = evdev_connect,.disconnect = evdev_disconnect,.legacy_minors = true,.minor = EVDEV_MINOR_BASE,.name = "evdev",.id_table = evdev_ids,
};static int __init evdev_init(void)
{return input_register_handler(&evdev_handler);}
首先,我们讲解connect的处理,因为,他是input设备和handler建立联系的过程。在evdev中connect由evdev_connect实现,核心代码如下所示:
static int evdev_connect(struct input_handler *handler, struct input_dev *dev,const struct input_device_id *id)
{minor = input_get_new_minor(EVDEV_MINOR_BASE, EVDEV_MINORS, true);if (minor < 0) {error = minor;pr_err("failed to reserve new minor: %d\n", error);return error;}evdev = kzalloc(sizeof(struct evdev), GFP_KERNEL);if (!evdev) {error = -ENOMEM;goto err_free_minor;}INIT_LIST_HEAD(&evdev->client_list);spin_lock_init(&evdev->client_lock);mutex_init(&evdev->mutex);init_waitqueue_head(&evdev->wait);evdev->exist = true;dev_no = minor;/* Normalize device number if it falls into legacy range */if (dev_no < EVDEV_MINOR_BASE + EVDEV_MINORS)dev_no -= EVDEV_MINOR_BASE;dev_set_name(&evdev->dev, "event%d", dev_no);evdev->handle.dev = input_get_device(dev);evdev->handle.name = dev_name(&evdev->dev);evdev->handle.handler = handler;evdev->handle.private = evdev;evdev->dev.devt = MKDEV(INPUT_MAJOR, minor);evdev->dev.class = &input_class;evdev->dev.parent = &dev->dev;evdev->dev.release = evdev_free;device_initialize(&evdev->dev);error = input_register_handle(&evdev->handle);if (error)goto err_free_evdev;cdev_init(&evdev->cdev, &evdev_fops);evdev->cdev.kobj.parent = &evdev->dev.kobj;error = cdev_add(&evdev->cdev, evdev->dev.devt, 1);if (error)goto err_unregister_handle;error = device_add(&evdev->dev);if (error)goto err_cleanup_evdev;return 0;
}
evdev_connect函数完成的功能有:
1) 创建evdev设备,并初始化;
2) 初始化evdev设备的handle,并进行注册。在input驱动框架中,handler和handle要注意区分,这个地方的命名并不太好;
3)注册evdev字符设备,字符设备的路径为/dev/input/event*, 该设备文件与用户空间打交道,重点关注evdev_fops这个方法集合,他对应了用户空间操作输入设备文件操作对用的内核空间字符设备的函数实现;
Handle
前面在讲解evdev的connect函数中,我们提到了input handle的注册,handle主要作用就是input dev和input handler建立联系的桥梁,数据结构如下所示:
struct input_handle {......struct input_dev *dev;struct input_handler *handler;struct list_head d_node;struct list_head h_node;
};
Handle的注册由input_register_handle完成,这里不在详细描述;
Input事件上报
本章节,主要描述常用输入设备产生事件,Input子系统如何进行事件的上报。在linux input驱动子系统中:
1)按键事件使用input_report_key()接口进行上报
2)相对坐标事件使用input_report_rel()接口进行上报;
3)绝对坐标事件使用input_report_abs()接口进行上报;
4)事件同步input_sync()和input_mt_sync(),这两个事件,可以当做是一个当前事件上报完成的标记,用户层程序,通过这个事件,输入设备产生的事件,是否上报完成;
注: 其他输入类型设备的事件上报接口,这里不再描述,感兴趣的同学,可以去阅读Linux源码。
Input设备驱动开发
本章节,主要描述开发一个input设备驱动的大概步骤,以下的描述基于ft6206这个i2c接口的多点触控芯片,开发步骤如下描述.
1、创建管理ft6206 Input设备驱动结构体, 将input_dev封装在里面。
struct ft6206_data {struct i2c_client *client;struct input_dev *input;struct gpio_desc *reset_gpio;u32 max_x;u32 max_y;
};
2、创建input设备
input = devm_input_allocate_device(dev);if (!input)return -ENOMEM;ft6206->input = input;input->name = client->name;input->id.bustype = BUS_I2C;
3、设置该触摸设备支持的坐标事件
input_set_abs_params(input, ABS_MT_POSITION_X, 0,ft6206->max_x, 0, 0);input_set_abs_params(input, ABS_MT_POSITION_Y, 0,ft6206->max_y, 0, 0);error = input_mt_init_slots(input, FT6206_MAX_TOUCH_POINTS,INPUT_MT_DIRECT | INPUT_MT_DROP_UNUSED);if (error)return error;
4、触摸设备被按下,会出发硬件中断,我们注册中断处理函数,接收硬件触发的事件
error = devm_request_threaded_irq(dev, client->irq, NULL,ft6206_interrupt, IRQF_ONESHOT,client->name, ft6206);if (error) {dev_err(dev, "request irq %d failed: %d\n", client->irq, error);return error;}
5、注册input设备
error = input_register_device(input);if (error) {dev_err(dev, "failed to register input device: %d\n", error);return error;}
6、在中断处理函数中,处理硬件触发的事件,并将该事件,封装为input事件,上报给input core处理
static irqreturn_t ft6206_interrupt(int irq, void *dev_id)
{......error = ft6206_read(ft6206->client, FT6206_REG_DEV_MODE, sizeof(buf), &buf);if (error) {dev_err(dev, "read touchdata failed %d\n", error);return IRQ_HANDLED;}touches = buf.touches & 0xf;if (touches > FT6206_MAX_TOUCH_POINTS) {dev_dbg(dev,"%d touch points reported, only %d are supported\n",touches, FT6206_MAX_TOUCH_POINTS);touches = FT6206_MAX_TOUCH_POINTS;}for (i = 0; i < touches; i++) {struct ft6206_touchpoint *point = &buf.points[i];u16 x = ((point->xhi & 0xf) << 8) | buf.points[i].xlo;u16 y = ((point->yhi & 0xf) << 8) | buf.points[i].ylo;u8 event = point->event >> 6;u8 id = point->id >> 4;bool act = (event == FT6206_EVENT_PRESS_DOWN ||event == FT6206_EVENT_CONTACT);input_mt_slot(input, id);input_mt_report_slot_state(input, MT_TOOL_FINGER, act);if (!act)continue;input_report_abs(input, ABS_MT_POSITION_X, x);input_report_abs(input, ABS_MT_POSITION_Y, y);}input_mt_sync_frame(input);input_sync(input);return IRQ_HANDLED;
}
该中断处理程序完成的功能有:
1、读取硬件上报的触摸坐标;
2、将每一个坐标点封装为一个多点触控inpt事件(该设备支持多点触控硬件A协议,感兴趣的同学,可以研究下硬件多点触控协议);
3、上报多点触控事件;
4、坐标事件上报完成,最后上报一个同步事件,表示本次触摸事件上报完成;
总结
本文主要描述了在Linux系统中对于像键盘,触摸这类设备的管理和事件处理。下一篇讲解Andoid eventHub ,用户空间如何获取Input事件并进行处理;
相关文章:
Android7 Input(二)Linux 驱动层输入事件管理
概述 在Linux系统中,将键盘,鼠标,触摸屏等这类交互设备交由Linux Input子系统进行管理,Linux Input驱动子系统由于具有良好的和用户空间交互的接口。因此Linux Input驱动子系统,不止于只管理输入类型的设备。也可以将其…...
前端给后端发送数据时都需要包含哪些内容?(HTTP请求的基本组成部分)
1 [TOC](1)一、**必须传递的内容**1. **URL(请求地址)** 二、**可选内容**1. **请求方法(HTTP Method)**2. **请求头(Headers)**3. **请求体(Body)**4. **其他配置** 技术无关 一、必…...
记录vite引入sass预编译报错error during build: [vite:css] [sass] Undefined variable.问题
vite.config.ts resolve: {alias: {: path.resolve(__dirname, src),},},css: {// css预处理器preprocessorOptions: {scss: {additionalData: use "/assets/styles/block.scss" as *;,}}},block.scss $colorGreen: #00ff00;index.vue :v-deep .font-size-14{colo…...
智慧运维平台:赋能未来,开启高效运维新时代
在当今数字化浪潮下,企业IT基础设施、工业设备及智慧城市系统的复杂度与日俱增,传统人工运维方式已难以满足高效、精准、智能的管理需求。停机故障、低效响应、数据孤岛等问题直接影响企业运营效率和成本控制。大型智慧运维平台(AIOps, Smart…...
【log4j】配置Slf4j
配置Slf4j 引入lombok包 <dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.36</version><scope>provided</scope> </dependency>引入log4j相关api <dependency…...
静态网页应用开发环境搭建实战教程
1. 前言 静态网页开发是前端工程师的基础技能之一,无论是个人博客、企业官网还是简单的Web应用,都离不开HTML、CSS和JavaScript。搭建一个高效的开发环境,能够极大提升开发效率,减少重复工作,并优化调试体验。 本教程…...
AP 场景架构设计(一) :OceanBase 读写分离策略解析
说明:本文内容对应的是 OceanBase 社区版,架构部分不涉及企业版的仲裁副本功能。OceanBase社区版和企业版的能力区别详见: 官网链接。 概述 当两种类型的业务共同运行在同一个数据库集群上时,这对数据库的配置等条件提出了较高…...
未来村庄智慧灯杆:点亮乡村智慧生活
在乡村振兴与数字乡村建设的时代进程中,未来村庄智慧灯杆凭借其多功能集成与智能化特性,已成为乡村基础设施建设领域的崭新焦点,为乡村生活带来了前所未有的便利,推动着乡村生活模式的深刻变革。 多功能集成:一杆多能…...
MySQL基础语法DDLDML
目录 #1.创建和删除数据库 #2.如果有lyt就删除,没有则创建一个新的lyt #3.切换到lyt数据库下 #4.创建数据表并设置列及其属性,name是关键词要用name包围 编辑 #5.删除数据表 #5.查看创建的student表 #6.向student表中添加数据,数据要与列名一一对应 #7.查询studen…...
利用 VSCode 配置提升 vibe coding 开发效率
利用 VSCode 配置提升 vibe coding 开发效率 Vibe Coding(氛围编程)是一种基于AI的编程方法,其核心在于通过自然语言描述软件需求,再由大规模语言模型(LLM)自动生成代码,从而实现对传统手写编程…...
使用 Chromedp 监听网页请求和响应
使用 Chromedp 监听网页请求和响应 在进行网络爬虫的时候,有很多网站都有反爬机制,比如你想抓点数据,结果发现每次请求都带一堆奇奇怪怪的参数 —— 什么 timestamp 签名、AES 加密的字段,还有各种 Token 令牌,跟密码…...
AB包介绍及导出工具实现+AB包资源简单加载
Resource原理 项目中建立Resources目录,资源导入内部 生成项目包 资源文件存储路径 结论:存储在Resources下的资源,最终会存储在游戏的主体包中,发送给用户,手机系统上,如果需要做资源的更新,是…...
TCP/IP协议簇
文章目录 应用层http/httpsDNS补充 传输层TCP1. 序列号与确认机制2. 超时重传3. 流量控制(滑动窗口机制)4. 拥塞控制5. 错误检测与校验6. 连接管理总结 网络层ARP**ARP 的核心功能**ARP 的工作流程1. ARP 请求(Broadcast)2. ARP 缓…...
vector的模拟实现01
文章目录 vector的模拟实现构造函数析构函数迭代器容量sizecapacityreverse 遍历下标[] 修改push_backpop_backinsert 结语 我们大家有又见面了,给生活加点</font color red>impetus!!开启今天的编程之路 今天我们来学习vector。了解一…...
信息学奥赛一本通 1609:【例 4】Cats Transport | 洛谷 CF311B Cats Transport
【题目链接】 ybt 1609:【例 4】Cats Transport 洛谷 CF311B Cats Transport 【题目考点】 1. 动态规划:斜率优化动规 【解题思路】 解法1:设a点的前缀和 输入的 d d d序列是从 d 2 d_2 d2到 d n d_n dn,共n-1个数字。人…...
shared_ptr和 weak_ptr的详细介绍
关于 shared_ptr 和 weak_ptr 的详细介绍及使用示例: 1. shared_ptr(共享所有权智能指针) 核心特性 引用计数:记录当前有多少个 shared_ptr 共享同一个对象。自动释放:当引用计数归零时,自动释放对象内存…...
electron打包vue2项目流程
1,安装一个node vue2 的项目 2,安装electron: npm install electron -g//如果安装还是 特比慢 或 不想安装cnpn 淘宝镜像查看是否安装成功:electron -v 3,进入到项目目录:cd electron-demo 进入项目目录…...
Baklib驱动企业知识管理数字化转型
Baklib驱动知识资产激活 在信息碎片化与数据爆炸的产业环境下,企业知识中台正成为重构组织智慧的核心枢纽。Baklib通过构建全生命周期知识管理模型,将分散于邮件、文档及协作系统的非结构化数据转化为可检索、可分析的标准化资产。其内置的智能分类引擎…...
Elasticsearch 高级
Elasticsearch 高级 建议阅读顺序: Elasticsearch 入门Elasticsearch 搜索Elasticsearch 搜索高级Elasticsearch高级(本文) 1. nested 类型 1.1 介绍 Elasticsearch 中的 nested 类型允许你在文档内存储复杂的数据结构,比如一个…...
1--当「穷举」成为艺术:CTF暴力破解漏洞技术从入门到入刑指南(知识点讲解版)
当「穷举」成为艺术:CTF暴力破解漏洞技术从入门到入刑指南 引言:论暴力破解的哲学意义 “世界上本没有漏洞,密码设得简单了,便成了漏洞。” —— 鲁迅(并没有说过) 想象你是个不会撬锁的小偷,面…...
jdk 支持路线图
https://www.oracle.com/java/technologies/java-se-support-roadmap.html 按照路线图得知,在2025.09 发布openjdk 25,是一个LTS版本。...
VsCode启用右括号自动跳过(自动重写) - 自录制gif演示
VsCode启用右括号自动跳过(自动重写) - 自录制gif演示 前言 不知道大家在编程时候的按键习惯是怎样的。输入完左括号后编辑器一般会自动补全右括号,输入完左括号的内容后,是按→跳过右括号还是按)跳过右括号呢? for (int i 0; i < a.s…...
Android设计模式之模板方法模式
一、定义: 定义一个操作中的算法的框架,而将一些步骤延迟到子类中,使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。 二、结构: AbstractClass抽象类:定义算法的骨架,包含模板方法和若干…...
纯个人整理,蓝桥杯使用的算法模板day1(dfs、bfs)
算法索引 dfs(深度优先搜索)bfs(广度优先搜索)迷宫树结构 dfs(深度优先搜索) 功能: 适合搜索所有的解 代码模板: class Solution{public void dfs(int[][] graph, int i, int j){i…...
【第34节】windows原理:PE文件的导出表和导入表
目录 一、导出表 1.1 导出表概述 1.2 说明与使用 二、导入表 2.1 导入表概述 2.2 说明与使用 一、导出表 1.1 导出表概述 (1)导出行为和导出表用途:PE文件能把自身的函数、变量或者类,提供给其他PE文件使用,这…...
Spring Boot事务管理详解(附银行转账案例)
一、事务基础概念 事务的ACID特性: 原子性(Atomicity):操作要么全部成功,要么全部失败一致性(Consistency):数据在事务前后保持合法状态隔离性(Isolation)&…...
(头歌作业—python)3.2 个人所得税计算器(project)
第1关:个人所得税计算器 任务描述 本关任务:编写一个个人所得税计算器的小程序。 相关知识 个人所得税缴纳标准 2018 年 10 月 1 日以前,个税免征额为 3500 元/月,调整后,个税免征额为 5000 元/月, 7 级超…...
在一个scss文件中定义变量,在另一个scss文件中使用
_variables.scss文件 : $line-gradient-init-color: linear-gradient(90deg, #8057ff 0%, #936bff 50%, #b892ff 100%); $line-gradient-hover-color: linear-gradient(90deg, #936bff 0%, #b892ff 50%, #f781ce 100%); $line-gradient-active-color: linear-gradient(90deg, …...
【计网】网络交换技术之电路交换(复习自用)
复习自用的,处理得比较草率,复习的同学或者想看基础的同学可以看看,大佬的话可以不用浪费时间在我的水文上了 1.电路交换定义 电路交换是一种通信方法,在通信开始之前,源和目的地之间建立一条专用的物理路径…...
MacOS 安装open webui
open-webui 不是一个 Python 包,所以 pip install open-webui 会失败。它是一个独立的 Web UI 应用,通常通过 Docker 或 手动构建 来运行。 如何正确安装 Open WebUI? 你可以选择 Docker 方式(推荐)或 手动安装。 方法…...
DeepSeek 助力 Vue3 开发:打造丝滑的表格(Table)之添加行拖拽排序功能示例9,TableView16_09 嵌套表格拖拽排序
前言:哈喽,大家好,今天给大家分享一篇文章!并提供具体代码帮助大家深入理解,彻底掌握!创作不易,如果能帮助到大家或者给大家一些灵感和启发,欢迎收藏+关注哦 💕 目录 DeepSeek 助力 Vue3 开发:打造丝滑的表格(Table)之添加行拖拽排序功能示例9,TableView16_09 嵌…...
开启ipv6与关闭的区别
在运行P2P CDN时,开启IPv6与关闭IPv6存在以下核心区别,需从技术、合规、运营等维度综合评估: 一、性能与效率 开启IPv6的优势 更大地址空间:IPv6支持海量设备接入,解决IPv4地址枯竭问题,便于P2P CDN节点扩…...
Redis + Caffeine多级缓存电商场景深度解析
Redis Caffeine多级缓存 Redis Caffeine多级缓存电商场景深度解析一、实施目的二、具体实施2.1 架构设计2.2 组件配置2.3 核心代码实现 三、实施效果3.1 性能指标对比3.2 业务指标改善3.3 系统稳定性 四、关键策略4.1 缓存预热4.2 一致性保障4.3 监控配置Prometheus监控指标 …...
Leecode Hot50
文章目录 矩阵Solution73. 矩阵置零Solution54. 螺旋矩阵Solution48. 旋转图像Solution240. 搜索二维矩阵 II二叉树二叉树的四种遍历结果Solution94. 二叉树的中序遍历Solution104. 二叉树的最大深度Solution226. 翻转二叉树Solution101. 对称二叉树Solution543. 二叉树的直径S…...
解决 Gradle 构建错误:Could not get unknown property ‘withoutJclOverSlf4J’
解决 Gradle 构建错误:Could not get unknown property ‘withoutJclOverSlf4J’ 在构建 Spring 源码或其他基于 Gradle 的项目时,可能会遇到如下错误: Could not get unknown property withoutJclOverSlf4J for object of type org.gradle…...
C++ 初阶总复习 (16~30)
C 初阶总复习 (16~30) 目的16. 2009. volatile关键字的作用17. 2010.什么是多态 简单介绍下C的多态18. 2011. 什么是虚函数 介绍下C中虚函数的原理19. 2012 构造函数可以是虚函数嘛20. 2013.析构函数一定要是虚函数嘛?21. 2015. 什么是C中的虚…...
TDengine 中的异常恢复
简介 本章主要介绍在 TDengine 执行命令过程中发生异常,如何手工终于执行的任务。可以终止连接,线上查询及终止事务。 如果一个事务 在一个复杂的应用场景中,连接和查询任务等有可能进入一种错误状态或者耗时过长迟迟无法结束,…...
二层框架组合实验
实验要求: 1,内网IP地址使用172.16.0.0/16分配 2,SW1和sw2之间互为备份 3,VRRP/STP/VLAN/Eth-trunk均使用 4,所有PC均通过DHCP获取IP地址 5,ISP只能配置IP地址 6,所有电脑可以正常访问ISP路由器环回 实验思路顺序: 创建vlan eth-trunk 划分v…...
IP综合实验
1.配置eth-trunk进行绑定 [LSW1]interface Eth-Trunk 0 [LSW1-Eth-Trunk0]q [LSW1]interface g0/0/2 [LSW1-GigabitEthernet0/0/2]eth-trunk 0 [LSW1-GigabitEthernet0/0/2]int g0/0/3 [LSW1-GigabitEthernet0/0/3]eth-trunk 0 [LSW1-GigabitEthernet0/0/3]display et…...
2025年信息系统与未来教育国际学术会议(ISFE 2025)
基本信息 官网:www.icedcs.net 时间:2025年4月18-20日 地点:中国-深圳 简介 2025年信息系统与未来教育国际学术会议(ISFE 2025)作为第二届粤港澳大湾区教育数字化与计算机科学国际学术会议(EDCS 2025&…...
nacos 外置mysql数据库操作(docker 环境)
目录 一、外置mysql数据库原因: 二、数据库准备工作 三、构建nacos容器 四、效果展示 一、外置mysql数据库原因: 想知道nacos如何外置mysql数据库之前,我们首先要知道为什么要外置mysql数据库,或者说这样做有什么优点和好处&am…...
Windows 10 ARM64平台MFC串口程序开发
Windows 10 IoT ARM64平台除了支持新的UWP框架,也兼容支持老框架MFC。使得用户在Windows 10 IoT下可以对原MFC工程进行功能升级,不用在新框架下重写整个工程。熟悉MFC开发的工程师也可以在Windows 10 IoT平台下继续使用MFC进行开发。 本文展示MFC串口程序…...
怎么使用pm2启动和暂停后端程序(后端架构nodejs+koa)
首先查看自己的pm2进程 pm2 list 或者 pm2 status 如果什么进程都没有,但是你确实有后端程序运行在服务器上,使用以下查看pm2程序的启动用户 ps aux | grep pm2就可以看到具体的用户和进行的信息 接着转换到你要操作的pm2的进程用户下 sudo su - …...
AI人工智能-Jupyter NotbookPycharm:Py开发
安装 命令: pip install jupyter 启动 命令: jupyter notebook 启动成功后,下面网址会默认自动打开当前用户的根目录。 其实这个页面显示的内容,是我们电脑目录C:\Users\当前用户\下的文件夹 我们平常做实验,希望在…...
uniapp-小程序地图展示
一、当前页面直接获取 <view class"map"><map id"myMap" style"width: 100%; height: 40vh;" :latitude"latitude":longitude"longitude" :markers"markers" :scale"scale" :show-location&qu…...
使用 Python 进行链上数据监控:让区块链数据触手可及
使用 Python 进行链上数据监控:让区块链数据触手可及 区块链技术正以前所未有的速度改变着各行各业,特别是在金融、供应链、物联网和智能合约等领域的应用,已经成为了一种新常态。然而,随着区块链网络的快速扩展和去中心化特性的不断强化,数据的可视化与监控变得愈发重要…...
CentOS 7 磁盘及分区管理笔记
一、查看磁盘信息 1. lsblk 命令 作用:列出系统中所有的块设备(包括磁盘、分区等)及其相关信息,如设备名称、大小、类型等。 命令格式:lsblk 示例: lsblk NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT sd…...
python基础学习二(列表及字典的使用)
文章目录 列表列表的创建获取列表中的多个元素判断列表中元素是否存在列表元素的添加操作列表元素的删除操作列表元素的修改列表的排序列表生成式 字典字典的创建字典的常规操作字典的常用操作字典的视图操作字典元素的遍历字典的特点字典的生成式 列表 一个对象由id࿰…...
【NLP 50、损失函数 KL散度】
目录 一、定义与公式 1.核心定义 2.数学公式 3.KL散度与交叉熵的关系 二、使用场景 1.生成模型与变分推断 2.知识蒸馏 3.模型评估与优化 4.信息论与编码优化 三、原理与特性 1.信息论视角 2.优化目标 3.局限性 四、代码示例 代码运行流程 核心代码解析 抵达梦想靠的不是狂热…...
macOS Jdk1.8安装(目前主流版本的jdk)
Jdk1.8安装 1、jdk安装包下载链接2、下载安装包(根据自己是什么系统进行下载)3、下载完成之后双击安装包进行安装安装好之后查看查看安装的版本需要查看JDK的安装路径(一般在/Library/Java/JavaVirtualMachines)配置环境变量1、jdk安装包下载链接 jdk8下载链接 https://www.…...