input子系统框架、外设驱动开发
一、input子系统基本框架
Linux内核为了两个目的:
- 简化纯输入类外设(如:键盘、鼠标、游戏杆、轨迹球、触摸屏。。。等等)的驱动开发
- 统一输入类外设产生的数据格式(struct input_event),更加方便应用层编程
设计了输入子系统
事件处理层:接收来自核心层上报的事件,并选择对应的handler(事件处理器 struct input_handler)去处理。内核维护着多个事件处理器对象,每个input_handler对象专门处理一类事件,所有产生同类事件的设备驱动共用同一个handler。
设备驱动层:主要实现获取硬件设备的数据信息(包括触摸屏被按下、按下位置、鼠标移动、键盘按下等等),并转换为核心层定义的规范事件后提交给核心层,该层每个设备对应一个struct input_dev对象,
核心层:负责连接设备驱动层和事件处理层,为设备驱动层提供输入设备驱动的接口(struct input_dev)以及输入设备驱动的注册函数(input_register_device),为事件处理层提供输入事件驱动的接口;通知事件处理层对事件进行处理。
二、驱动开发步骤
/*init或probe函数中:
1. 创建struct input_dev对象input_allocate_device
2. 设置事件类型以及相关参数set_bit
3. 注册struct input_dev对象input_register_device
*//*exit或remove函数中:
1. 注销struct input_dev对象input_unregister_device
2. 销毁struct input_dev对象input_free_device
*//*上报事件两种事件上报方式:1. 对有中断支持的输入设备:在其中断处理函数(上半部或下半部)中上报事件2. 对无中断支持的输入设备:使用workqueue循环定时上报(struct delayed_work)主要函数:input_eventinput_report_absinput_sync
*/
相关接口:
/*_init*/
struct input_dev *input_allocate_device(void):/*创建一个输入设备对象。返回一个指向 input_dev 结构的指针,该结构用于表示输入设备。*/void set_bit(struct input_dev *dev, unsigned long whichbits):/*设置输入设备的事件类型。dev 是输入设备对象的指针,whichbits 是一个位掩码,用于指定事件类型。例如,使用 set_bit(dev, EV_KEY) 可以设置输入设备支持按键事件。whichbits:EV_KEY:按键事件。这个事件类型用于处理键盘、鼠标等输入设备的按键事件EV_ABS:绝对坐标事件。这个事件类型用于处理绝对坐标的事件,例如触摸屏的触摸位置。*/void input_set_abs_params(struct input_dev *dev, unsigned int axis, int min, int max, int fuzz, int flat)/*配置输入设备的绝对坐标参数。dev 是输入设备对象的指针,axis 是要配置的坐标轴(如ABS_X、ABS_Y等),min 和 max 分别是坐标轴的最小值和最大值,fuzz 和 flat 是用于指定坐标轴的模糊度和平坦度参数。*/int input_register_device(struct input_dev *dev)/*注册输入设备到内核。将输入设备对象注册到内核,以便它可以开始上报事件。*//*_exit*/
void input_unregister_device(struct input_dev *dev)//注销输入设备。从内核中注销输入设备,停止事件的上报。
void input_free_device(struct input_dev *dev)//释放输入设备。释放输入设备对象的内存。/*上报事件*/
void input_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)/*上报一个通用输入事件。通常,这个函数用于上报不是绝对坐标或按键事件的事件。dev 是输入设备对象的指针,type 表示事件类型,code 表示事件代码(例如,按键代码),value 表示事件的值。*/void input_report_key(struct input_dev *dev, unsigned int code, int value)/*上报按键事件。dev 是输入设备对象的指针,code 表示按键事件的代码,value 表示按键事件的值(0表示松开,1表示按下)。*/void input_report_abs(struct input_dev *dev, unsigned int code, int value)/*上报绝对坐标事件。dev 是输入设备对象的指针,code 表示绝对坐标事件的代码,value 表示绝对坐标的值。*/void input_sync(struct input_dev *dev)//上报完成后需要调用这些函数来通知系统处理完整事件, 这个函数告诉内核事件已经完整,可以处理了。/*应用层数据类型*/
struct input_event { //这是一个用于表示输入事件的结构体。它包含以下字段:struct timeval time; //事件的时间戳。__u16 type; //事件类型,如 EV_KEY(按键事件)、EV_ABS(绝对坐标事件)等。__u16 code; //事件代码,具体表示事件的含义,例如按下哪个键或是哪个绝对坐标轴。__s32 value; //事件的值,通常表示按键的状态(按下或松开)或绝对坐标的值。
}
三、key2-input版代码解析
key2.c
#include <linux/module.h> // Linux内核模块头文件
#include <linux/kernel.h> // 内核相关功能的头文件
#include <linux/fs.h> // 文件系统相关功能的头文件
#include <linux/gpio.h> // GPIO库的头文件
#include <linux/interrupt.h> // 中断处理相关功能的头文件
#include <linux/of_gpio.h> // Open Firmware GPIO相关功能的头文件
#include <linux/of_irq.h> // Open Firmware中断相关功能的头文件
#include <linux/cdev.h> // 字符设备相关功能的头文件
#include <linux/wait.h> // 等待队列相关功能的头文件
#include <linux/sched.h> // 调度相关功能的头文件
#include <linux/poll.h> // poll相关功能的头文件
#include <linux/mm.h> // 内存管理相关功能的头文件
#include <linux/input.h> // 输入子系统相关功能的头文件
#include <linux/delay.h> // 延时相关功能的头文件
#include <linux/slab.h> // 内存分配相关功能的头文件
#include <asm/uaccess.h> // 用户态内核态数据传输相关功能的头文件struct fs4412key2_dev
{struct input_dev *pdev; // 输入设备结构体指针,用于注册输入事件int gpio; // GPIO引脚的编号int irqno; // 中断编号
};struct fs4412key2_dev *pgmydev = NULL; // 指向驱动程序数据结构的指针// 中断处理函数,处理按键中断
irqreturn_t key2_irq_handle(int no, void *arg)
{struct fs4412key2_dev *pmydev = (struct fs4412key2_dev *)arg;int status1 = 0;int status2 = 0;// 读取GPIO引脚状态两次,用于防抖status1 = gpio_get_value(pmydev->gpio);mdelay(1);status2 = gpio_get_value(pmydev->gpio);// 如果两次状态不一致,认为是抖动,不处理if (status1 != status2){return IRQ_NONE;}// 根据按键状态生成输入事件if (status1){input_event(pmydev->pdev, EV_KEY, KEY_2, 0); // 按键释放事件input_sync(pmydev->pdev); // 同步输入事件}else{input_event(pmydev->pdev, EV_KEY, KEY_2, 1); // 按键按下事件input_sync(pmydev->pdev); // 同步输入事件}return IRQ_HANDLED;
}// 模块初始化函数
int __init fs4412key2_init(void)
{int ret = 0;struct device_node *pnode = NULL;// 查找设备树节点pnode = of_find_node_by_path("/mykey2_node");if (NULL == pnode){printk("find node failed\n");return -1;}// 分配驱动程序数据结构内存pgmydev = (struct fs4412key2_dev *)kmalloc(sizeof(struct fs4412key2_dev), GFP_KERNEL);if (NULL == pgmydev){printk("kmalloc for struct fs4412key2_dev failed\n");return -1;}// 从设备树中获取GPIO引脚编号pgmydev->gpio = of_get_named_gpio(pnode, "key2-gpio", 0);// 从设备树中获取中断编号pgmydev->irqno = irq_of_parse_and_map(pnode, 0);// 分配并注册输入设备pgmydev->pdev = input_allocate_device();set_bit(EV_KEY, pgmydev->pdev->evbit);set_bit(KEY_2, pgmydev->pdev->keybit);ret = input_register_device(pgmydev->pdev);// 请求中断处理函数ret = request_irq(pgmydev->irqno, key2_irq_handle, IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING, "fs4412key2", pgmydev);if (ret){printk("request_irq failed\n");input_unregister_device(pgmydev->pdev);input_free_device(pgmydev->pdev);kfree(pgmydev);pgmydev = NULL;return -1;}return 0;
}// 模块卸载函数
void __exit fs4412key2_exit(void)
{// 释放中断free_irq(pgmydev->irqno, pgmydev);// 注销输入设备input_unregister_device(pgmydev->pdev);input_free_device(pgmydev->pdev);// 释放驱动程序数据结构内存kfree(pgmydev);pgmydev = NULL;
}MODULE_LICENSE("GPL"); // 指定模块许可证
module_init(fs4412key2_init); // 指定模块初始化函数
module_exit(fs4412key2_exit); // 指定模块卸载函数
testkey2.c
#include <sys/types.h>
#include <sys/stat.h>
#include <linux/input.h>
#include <fcntl.h>
#include <unistd.h>#include <stdio.h>int main(int argc,char *argv[])
{int fd = -1;struct input_event evt;if(argc < 2){printf("Argument is too few\n");return 1;}/*open*/fd = open(argv[1],O_RDONLY);if(fd < 0){printf("open %s failed\n",argv[1]);return 2;}/*init mpu6050*/while(1){read(fd,&evt,sizeof(evt));if(evt.type == EV_KEY && evt.code == KEY_2){if(evt.value){printf("KEY2 DOWN\n");}else{printf("KEY2 UP\n");}}}/*close*/close(fd);fd = -1;return 0;
}
四、mpu6050-input版代码解析
mpu6050drv.c
#include <linux/module.h> // Linux内核模块头文件
#include <linux/kernel.h> // 内核相关功能的头文件
#include <linux/fs.h> // 文件系统相关功能的头文件
#include <linux/i2c.h> // I2C总线相关功能的头文件
#include <linux/cdev.h> // 字符设备相关功能的头文件
#include <linux/wait.h> // 等待队列相关功能的头文件
#include <linux/sched.h> // 调度相关功能的头文件
#include <linux/poll.h> // poll相关功能的头文件
#include <linux/slab.h> // 内存分配相关功能的头文件
#include <linux/mm.h> // 内存管理相关功能的头文件
#include <linux/input.h> // 输入子系统相关功能的头文件
#include <linux/io.h> // I/O内存操作相关功能的头文件
#include <asm/uaccess.h> // 用户态内核态数据传输相关功能的头文件
#include <asm/atomic.h> // 原子操作相关功能的头文件/****************MPU6050内部寄存器地址****************/#define SMPLRT_DIV 0x19 //陀螺仪采样率,典型值:0x07(125Hz)
#define CONFIG 0x1A //低通滤波频率,典型值:0x06(5Hz)
#define GYRO_CONFIG 0x1B //陀螺仪自检及测量范围,典型值:0x18(不自检,2000deg/s)
#define ACCEL_CONFIG 0x1C //加速计自检、测量范围及高通滤波频率,典型值:0x18(不自检,2G,5Hz)
#define ACCEL_XOUT_H 0x3B
#define ACCEL_XOUT_L 0x3C
#define ACCEL_YOUT_H 0x3D
#define ACCEL_YOUT_L 0x3E
#define ACCEL_ZOUT_H 0x3F
#define ACCEL_ZOUT_L 0x40
#define TEMP_OUT_H 0x41
#define TEMP_OUT_L 0x42
#define GYRO_XOUT_H 0x43
#define GYRO_XOUT_L 0x44
#define GYRO_YOUT_H 0x45
#define GYRO_YOUT_L 0x46
#define GYRO_ZOUT_H 0x47
#define GYRO_ZOUT_L 0x48
#define PWR_MGMT_1 0x6B //电源管理,典型值:0x00(正常启用)
#define WHO_AM_I 0x75 //IIC地址寄存器(默认数值0x68,只读)
#define SlaveAddress 0x68 //MPU6050-I2C地址// 定义MPU6050设备结构体
struct mpu6050_dev
{struct input_dev * pinput; // 输入设备结构体指针struct i2c_client *pclient; // I2C客户端结构体指针struct delayed_work work; // 延迟工作结构体
};struct mpu6050_dev *pgmydev = NULL; // 指向MPU6050设备数据结构的指针// 读取MPU6050寄存器的函数
int mpu6050_read_byte(struct i2c_client *pclt, unsigned char reg)
{int ret = 0;char txbuf[1] = {reg};char rxbuf[1] = {0};struct i2c_msg msg[2] = {{pclt->addr, 0, 1, txbuf},{pclt->addr, I2C_M_RD, 1, rxbuf}};ret = i2c_transfer(pclt->adapter, msg, ARRAY_SIZE(msg));if (ret < 0){printk("ret = %d, in mpu6050_read_byte\n", ret);return ret;}return rxbuf[0];
}// 写入MPU6050寄存器的函数
int mpu6050_write_byte(struct i2c_client *pclt, unsigned char reg, unsigned char val)
{int ret = 0;char txbuf[2] = {reg, val};struct i2c_msg msg[1] = {{pclt->addr, 0, 2, txbuf},};ret = i2c_transfer(pclt->adapter, msg, ARRAY_SIZE(msg));if (ret < 0){printk("ret = %d, in mpu6050_write_byte\n", ret);return ret;}return 0;
}// 延迟工作函数,用于读取MPU6050传感器数据
void mpu6050_work_func(struct work_struct *pwk)
{struct mpu6050_dev *pmydev = container_of((struct delayed_work *)pwk, struct mpu6050_dev, work);unsigned short ax = 0;unsigned short ay = 0;unsigned short az = 0;unsigned short gx = 0;unsigned short gy = 0;unsigned short gz = 0;unsigned short temp = 0;// 读取加速度和陀螺仪数据ax = mpu6050_read_byte(pmydev->pclient, ACCEL_XOUT_L);ax |= (mpu6050_read_byte(pmydev->pclient, ACCEL_XOUT_H) << 8);input_report_abs(pmydev->pinput, ABS_X, ax);ay = mpu6050_read_byte(pmydev->pclient, ACCEL_YOUT_L);ay |= (mpu6050_read_byte(pmydev->pclient, ACCEL_YOUT_H) << 8);input_report_abs(pmydev->pinput, ABS_Y, ay);az = mpu6050_read_byte(pmydev->pclient, ACCEL_ZOUT_L);az |= (mpu6050_read_byte(pmydev->pclient, ACCEL_ZOUT_H) << 8);input_report_abs(pmydev->pinput, ABS_Z, az);gx = mpu6050_read_byte(pmydev->pclient, GYRO_XOUT_L);gx |= (mpu6050_read_byte(pmydev->pclient, GYRO_XOUT_H) << 8);input_report_abs(pmydev->pinput, ABS_RX, gx);gy = mpu6050_read_byte(pmydev->pclient, GYRO_YOUT_L);gy |= (mpu6050_read_byte(pmydev->pclient, GYRO_YOUT_H) << 8);input_report_abs(pmydev->pinput, ABS_RY, gy);gz = mpu6050_read_byte(pmydev->pclient, GYRO_ZOUT_L);gz |= (mpu6050_read_byte(pmydev->pclient, GYRO_ZOUT_H) << 8);input_report_abs(pmydev->pinput, ABS_RZ, gz);temp = mpu6050_read_byte(pmydev->pclient, TEMP_OUT_L);temp |= (mpu6050_read_byte(pmydev->pclient, TEMP_OUT_H) << 8);input_report_abs(pmydev->pinput, ABS_MISC, temp);input_sync(pmydev->pinput);schedule_delayed_work(&pgmydev->work, msecs_to_jiffies(1000)); // 延迟1秒后再次读取数据
}// 初始化MPU6050传感器
void init_mpu6050(struct i2c_client *pclt)
{mpu6050_write_byte(pclt, PWR_MGMT_1, 0x00);mpu6050_write_byte(pclt, SMPLRT_DIV, 0x07);mpu6050_write_byte(pclt, CONFIG, 0x06);mpu6050_write_byte(pclt, GYRO_CONFIG, 0xF8);mpu6050_write_byte(pclt, ACCEL_CONFIG, 0x19);
}// I2C设备驱动的探测函数
static int mpu6050_probe(struct i2c_client *pclt, const struct i2c_device_id *pid)
{int ret = 0;pgmydev = (struct mpu6050_dev *)kmalloc(sizeof(struct mpu6050_dev), GFP_KERNEL);if (NULL == pgmydev){printk("kmalloc failed\n");return -1;}memset(pgmydev, 0, sizeof(struct mpu6050_dev));pgmydev->pclient = pclt;init_mpu6050(pgmydev->pclient);pgmydev->pinput = input_allocate_device();set_bit(EV_ABS, pgmydev->pinput->evbit);input_set_abs_params(pgmydev->pinput, ABS_X, -32768, 32767, 0, 0);input_set_abs_params(pgmydev->pinput, ABS_Y, -32768, 32767, 0, 0);input_set_abs_params(pgmydev->pinput, ABS_Z, -32768, 32767, 0, 0);input_set_abs_params(pgmydev->pinput, ABS_RX, -32768, 32767, 0, 0);input_set_abs_params(pgmydev->pinput, ABS_RY, -32768, 32767, 0, 0);input_set_abs_params(pgmydev->pinput, ABS_RZ, -32768, 32767, 0, 0);input_set_abs_params(pgmydev->pinput, ABS_MISC, -32768, 32767, 0, 0);ret = input_register_device(pgmydev->pinput);if (ret){printk("input_register_device failed\n");input_free_device(pgmydev->pinput);pgmydev->pinput = NULL;kfree(pgmydev);pgmydev = NULL;return -1;}INIT_DELAYED_WORK(&pgmydev->work, mpu6050_work_func);schedule_delayed_work(&pgmydev->work, msecs_to_jiffies(1000)); // 初始化后立即开始读取数据return 0;
}// I2C设备驱动的卸载函数
static int mpu6050_remove(struct i2c_client *pclt)
{cancel_delayed_work(&pgmydev->work);input_unregister_device(pgmydev->pinput);input_free_device(pgmydev->pinput);pgmydev->pinput = NULL;kfree(pgmydev);pgmydev = NULL;return 0;
}// 匹配设备树中的MPU6050节点
struct of_device_id mpu6050_dt[] =
{{.compatible = "invensense,mpu6050"},{}
};// 定义MPU6050设备驱动的ID
struct i2c_device_id mpu6050_ids[] =
{{"mpu6050", 0},{}
};// 定义MPU6050设备驱动结构体
struct i2c_driver mpu6050_driver =
{.driver = {.name = "mpu6050",.owner = THIS_MODULE,.of_match_table = mpu6050_dt,},.probe = mpu6050_probe,.remove = mpu6050_remove,.id_table = mpu6050_ids,
};// 注册MPU6050设备驱动
module_i2c_driver(mpu6050_driver);MODULE_LICENSE("GPL"); // 指定模块许可证
相关文章:

input子系统框架、外设驱动开发
一、input子系统基本框架 Linux内核为了两个目的: 简化纯输入类外设(如:键盘、鼠标、游戏杆、轨迹球、触摸屏。。。等等)的驱动开发统一输入类外设产生的数据格式(struct input_event),更加方…...

Google Chrome 浏览器以全屏模式打开
目录 前言以全屏模式打开禁止弹出无法更新的提示窗禁止翻译网页Chrome设置禁止翻译网页可能1可能2可能3 网页添加指令禁止Chrome翻译网页 禁用脚本气泡浏览器解决办法html解决办法方法1:鼠标滑过超链接时,使状态栏不出现超链接方法2:方法3&am…...
安装torch113、cuda116并运行demo【Transformer】
文章目录 01. 导读02. 显卡驱动版本03. 创建环境、下载安装必要包04. 运行参考代码: 01. 导读 安装torch113、cuda116并运行demo【Transformer】 02. 显卡驱动版本 C:\Users\Administrator>nvidia-smi -l 10 Wed Sep 13 23:35:08 2023 ----------------------…...

基于scRNA-seq的GRN分析三阴性乳腺癌的肿瘤异质性
三阴性乳腺癌即TNBC是一种肿瘤异质性高的乳腺癌亚型。最近的研究表明,TNBC患者可能包含具有不同分子亚型的细胞。此外,基于scRNA-seq数据构建的GRN已经证明了对关键调控因子研究的重要性。作者使用scRNA-seq对TNBC患者的GRN进行了全面分析。从scRNA-seq数…...
Python:二进制文件实现等间隔取相同数据量并合并
举例:每3byte为一页,每3页为一wl。将所有wl的第一页/第二页/第三页分别合并为一个文件。 data b\x01\x02\x03\x04\x05\x06\x07\x08\x09\x01\x02\x03\x04\x05\x06\x07\x08\x09\x01\x02\x03\x04\x05\x06\x07\x08\x09\x01\x02\x03\x04\x05\x06\x07\x08\x0…...
python使用openvc库进行图像数据增强
以下是使用Python和OpenCV库实现图像数据增强的简单示例代码,其中包括常用的数据增强操作: import cv2 import numpy as np import os# 水平翻转 def horizontal_flip(image):return cv2.flip(image, 1)# 垂直翻转 def vertical_flip(image):return cv2…...

如何利用Api接口获取手机当前的网络位置信息
在移动互联网时代,手机定位已经成为了一个日常化的需求,无论是导航、社交还是打车等服务都需要获取手机的位置信息。而获取手机位置信息最基础的一步就是获取手机当前的网络位置信息,本文将介绍如何利用API接口获取手机当前的网络位置信息。 …...

vue-elementPlus自动按需导入和主题定制
elementPlus自动按需导入 装包 -> 配置 1. 装包(主包和两个插件包) $ npm install element-plus --save npm install -D unplugin-vue-components unplugin-auto-import 2. 配置 在vite.config.js文件中配置,配置完重启(n…...
idea中dataBase模板生成
controller.java.vm ##定义初始变量 #set($tableName $tool.append($tableInfo.name, "Controller")) ##设置回调 $!callback.setFileName($tool.append($tableName, ".java")) $!callback.setSavePath($tool.append($tableInfo.savePath, "/contro…...

pc端测试手机浏览器运行情况,主要是测试硬件功能
测试h5震动摇晃等功能时不方便测试,需要连电脑显示调试数据 方法: 1.需要手机下载谷歌浏览器,pc端用edge或这谷歌浏览器 2.手机打开USB调试,打开要测试的网页 3.pc端地址栏输入edge://inspect/#devices(这里用的edge浏…...
软件概要设计-架构真题(二十五)
软件概要设计包括软件设计的结构、确定系统功能模块及其相互关系,主要采用()描述程序的结构。(2018年) 程序流程图、PAD图和伪代码模块结构图、数据流图和盒图模块结构图、层次图和HIPO图程序流程图、数据流图和层次图…...
CSDN发文表情包整理
文章目录 简介部分Emoji表情符号简表人物自然物品地点符号 各种Emoji表情链接 简介 CSDN支持Markdown语法及Emoji表情,使用各种Emoji表情可以使得自己的博文更加生动多彩。一般有两种在支持Markdown的语法环境中添加Emoji表情:1.直接将表情包复制到文档…...

springBoot对接Apache POI 实现excel下载和上传
搭建springboot项目 此处可以参考 搭建最简单的SpringBoot项目_Steven-Russell的博客-CSDN博客 配置Apache POI 依赖 <dependency><groupId>org.apache.poi</groupId><artifactId>poi</artifactId><version>5.2.2</version> </…...

定积分的计算:牛顿-莱布尼茨公式
目录 牛顿-莱布尼茨公式 用C语言代码实现 利用换元积分法和分部积分法 利用奇偶性和周期性求积分 利用已有公式求积分 牛顿-莱布尼茨公式 牛顿-莱布尼茨公式(Newton-Leibniz formula)是微积分学中的基本定理之一,它反映了定积分与被积函…...
shell脚本之case 的用法
shell脚本之case case是Shell脚本中的一种控制流语句,它允许根据变量的值选择不同的执行路径。case语句的语法如下: case word in pattern [| pattern]...) command-list ;; pattern [| pattern]...) command-list ;; ... *) command-list ;; esa…...
第3章 helloworld 驱动实验(iTOP-RK3568开发板驱动开发指南 )
在学习C语言或者其他语言的时候,我们通常是打印一句“helloworld”来开启编程世界的大门。学习驱动程序编程亦可以如此,使用helloworld作为我们的第一个驱动程序。 接下来开始编写第一个驱动程序—helloworld。 3.1 驱动编写 本小节来编写一个最简单的…...

基于PyTorch使用LSTM实现新闻文本分类任务
本文参考 PyTorch深度学习项目实战100例 https://weibaohang.blog.csdn.net/article/details/127154284?spm1001.2014.3001.5501 文章目录 本文参考任务介绍做数据的导入 环境介绍导入必要的包介绍torchnet和keras做数据的导入给必要的参数命名加载文本数据数据前处理模型训…...

Flutter插件的制作和发布
Flutter制作插件有两种方式(以下以android和ios为例): 目录 1.直接在主工程下的android和ios项目内写插件代码:2.创建独立Flutter Plugin项目,制作各端插件后,再引入项目:1. 创建Flutter Plugin…...

【JAVA】异常
作者主页:paper jie 的博客 本文作者:大家好,我是paper jie,感谢你阅读本文,欢迎一建三连哦。 本文录入于《JAVASE语法系列》专栏,本专栏是针对于大学生,编程小白精心打造的。笔者用重金(时间和…...
合同矩阵充要条件
两个实对称矩阵合同的充要条件是它们的正负惯性指数相同。 正惯性指数是矩阵正特征值个数,负惯性指数是矩阵负特征值个数。 即合同矩阵的充分必要条件是特征值的正负号个数相同。 证明: 本论证中的所有矩阵都是对称矩阵。 根据定义,若矩…...

shell脚本--常见案例
1、自动备份文件或目录 2、批量重命名文件 3、查找并删除指定名称的文件: 4、批量删除文件 5、查找并替换文件内容 6、批量创建文件 7、创建文件夹并移动文件 8、在文件夹中查找文件...

关于nvm与node.js
1 安装nvm 安装过程中手动修改 nvm的安装路径, 以及修改 通过nvm安装node后正在使用的node的存放目录【这句话可能难以理解,但接着往下看你就了然了】 2 修改nvm中settings.txt文件配置 nvm安装成功后,通常在该文件中会出现以下配置&…...
css3笔记 (1) 自用
outline: none 用于移除元素获得焦点时默认的轮廓线 broder:0 用于移除边框 font-size:0 用于设置字体不显示 list-style: none 消除<li> 标签默认样式 margin: xx auto 版心居中 width:100% 通栏 vertical-align 作用于行内元素 / 表格单元格ÿ…...

Maven 概述、安装、配置、仓库、私服详解
目录 1、Maven 概述 1.1 Maven 的定义 1.2 Maven 解决的问题 1.3 Maven 的核心特性与优势 2、Maven 安装 2.1 下载 Maven 2.2 安装配置 Maven 2.3 测试安装 2.4 修改 Maven 本地仓库的默认路径 3、Maven 配置 3.1 配置本地仓库 3.2 配置 JDK 3.3 IDEA 配置本地 Ma…...
Kubernetes 网络模型深度解析:Pod IP 与 Service 的负载均衡机制,Service到底是什么?
Pod IP 的本质与特性 Pod IP 的定位 纯端点地址:Pod IP 是分配给 Pod 网络命名空间的真实 IP 地址(如 10.244.1.2)无特殊名称:在 Kubernetes 中,它通常被称为 “Pod IP” 或 “容器 IP”生命周期:与 Pod …...

实战三:开发网页端界面完成黑白视频转为彩色视频
一、需求描述 设计一个简单的视频上色应用,用户可以通过网页界面上传黑白视频,系统会自动将其转换为彩色视频。整个过程对用户来说非常简单直观,不需要了解技术细节。 效果图 二、实现思路 总体思路: 用户通过Gradio界面上…...
深度学习之模型压缩三驾马车:模型剪枝、模型量化、知识蒸馏
一、引言 在深度学习中,我们训练出的神经网络往往非常庞大(比如像 ResNet、YOLOv8、Vision Transformer),虽然精度很高,但“太重”了,运行起来很慢,占用内存大,不适合部署到手机、摄…...

数学建模-滑翔伞伞翼面积的设计,运动状态计算和优化 !
我们考虑滑翔伞的伞翼面积设计问题以及运动状态描述。滑翔伞的性能主要取决于伞翼面积、气动特性以及飞行员的重量。我们的目标是建立数学模型来描述滑翔伞的运动状态,并优化伞翼面积的设计。 一、问题分析 滑翔伞在飞行过程中受到重力、升力和阻力的作用。升力和阻力与伞翼面…...
【系统架构设计师-2025上半年真题】综合知识-参考答案及部分详解(回忆版)
更多内容请见: 备考系统架构设计师-专栏介绍和目录 文章目录 【第1题】【第2题】【第3题】【第4题】【第5题】【第6题】【第7题】【第8题】【第9题】【第10题】【第11题】【第12题】【第13题】【第14题】【第15题】【第16题】【第17题】【第18题】【第19题】【第20~21题】【第…...
【R语言编程——数据调用】
这里写自定义目录标题 可用库及数据集外部数据导入方法查看数据集信息 在R语言中,有多个库支持调用内置数据集或外部数据,包括studentdata等教学或示例数据集。以下是常见的库和方法: 可用库及数据集 openintro库 该库包含多个教学数据集&a…...