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语法系列》专栏,本专栏是针对于大学生,编程小白精心打造的。笔者用重金(时间和…...
合同矩阵充要条件
两个实对称矩阵合同的充要条件是它们的正负惯性指数相同。 正惯性指数是矩阵正特征值个数,负惯性指数是矩阵负特征值个数。 即合同矩阵的充分必要条件是特征值的正负号个数相同。 证明: 本论证中的所有矩阵都是对称矩阵。 根据定义,若矩…...

大数据学习栈记——Neo4j的安装与使用
本文介绍图数据库Neofj的安装与使用,操作系统:Ubuntu24.04,Neofj版本:2025.04.0。 Apt安装 Neofj可以进行官网安装:Neo4j Deployment Center - Graph Database & Analytics 我这里安装是添加软件源的方法 最新版…...

Linux 文件类型,目录与路径,文件与目录管理
文件类型 后面的字符表示文件类型标志 普通文件:-(纯文本文件,二进制文件,数据格式文件) 如文本文件、图片、程序文件等。 目录文件:d(directory) 用来存放其他文件或子目录。 设备…...
测试markdown--肇兴
day1: 1、去程:7:04 --11:32高铁 高铁右转上售票大厅2楼,穿过候车厅下一楼,上大巴车 ¥10/人 **2、到达:**12点多到达寨子,买门票,美团/抖音:¥78人 3、中饭&a…...

《通信之道——从微积分到 5G》读书总结
第1章 绪 论 1.1 这是一本什么样的书 通信技术,说到底就是数学。 那些最基础、最本质的部分。 1.2 什么是通信 通信 发送方 接收方 承载信息的信号 解调出其中承载的信息 信息在发送方那里被加工成信号(调制) 把信息从信号中抽取出来&am…...

Cloudflare 从 Nginx 到 Pingora:性能、效率与安全的全面升级
在互联网的快速发展中,高性能、高效率和高安全性的网络服务成为了各大互联网基础设施提供商的核心追求。Cloudflare 作为全球领先的互联网安全和基础设施公司,近期做出了一个重大技术决策:弃用长期使用的 Nginx,转而采用其内部开发…...

C# 类和继承(抽象类)
抽象类 抽象类是指设计为被继承的类。抽象类只能被用作其他类的基类。 不能创建抽象类的实例。抽象类使用abstract修饰符声明。 抽象类可以包含抽象成员或普通的非抽象成员。抽象类的成员可以是抽象成员和普通带 实现的成员的任意组合。抽象类自己可以派生自另一个抽象类。例…...
CRMEB 框架中 PHP 上传扩展开发:涵盖本地上传及阿里云 OSS、腾讯云 COS、七牛云
目前已有本地上传、阿里云OSS上传、腾讯云COS上传、七牛云上传扩展 扩展入口文件 文件目录 crmeb\services\upload\Upload.php namespace crmeb\services\upload;use crmeb\basic\BaseManager; use think\facade\Config;/*** Class Upload* package crmeb\services\upload* …...

pikachu靶场通关笔记22-1 SQL注入05-1-insert注入(报错法)
目录 一、SQL注入 二、insert注入 三、报错型注入 四、updatexml函数 五、源码审计 六、insert渗透实战 1、渗透准备 2、获取数据库名database 3、获取表名table 4、获取列名column 5、获取字段 本系列为通过《pikachu靶场通关笔记》的SQL注入关卡(共10关࿰…...
全面解析各类VPN技术:GRE、IPsec、L2TP、SSL与MPLS VPN对比
目录 引言 VPN技术概述 GRE VPN 3.1 GRE封装结构 3.2 GRE的应用场景 GRE over IPsec 4.1 GRE over IPsec封装结构 4.2 为什么使用GRE over IPsec? IPsec VPN 5.1 IPsec传输模式(Transport Mode) 5.2 IPsec隧道模式(Tunne…...

蓝桥杯3498 01串的熵
问题描述 对于一个长度为 23333333的 01 串, 如果其信息熵为 11625907.5798, 且 0 出现次数比 1 少, 那么这个 01 串中 0 出现了多少次? #include<iostream> #include<cmath> using namespace std;int n 23333333;int main() {//枚举 0 出现的次数//因…...