linux以C方式和内核交互监听键盘[香橙派搞机日记]
最近在深入研究我的香橙派,不可避免的遇到了怎么认识和使用Linux内核的问题。 我给自己留了一个简单的任务:使用原生C来监听内核,实现读取键盘的消息。
CSDN上也有其他文章来解决这个问题,不过要么是技术不达标(直接和终端交互显然不是我们想要的,这只是一个取巧的方案),要么是收费文章🥲 。楼主也是查阅了很多资料才解决了这个问题。如果这个方案解决了你的问题,还请你点赞,评论,收藏。您的支持是我的动力
如果你要学习知识,那可以从头读下去,如果你要快速使用,可以从 evtest 这个部分开始读,源代码贴在后面
接口在哪里?
在linux中,一切都是文件。哪怕你是一个物理设备,在内核中,你也得有个文件接口!
两个关键文件夹
/dev/input/
所有的设备,都是在dev 目录下统一管理的。让我们看看
/dev/input/
orangepi@orangepi3b:/dev/input$ ls
by-id event1 event12 event15 event18 event4 event7
by-path event10 event13 event16 event2 event5 event8
event0 event11 event14 event17 event3 event6 event9
orangepi@orangepi3b:/dev/input$ ls -l
total 0
drwxr-xr-x 2 root root 220 Apr 11 11:34 by-id
drwxr-xr-x 2 root root 280 Apr 11 11:34 by-path
crw-rw---- 1 root input 13, 64 Apr 6 12:37 event0
crw-rw---- 1 root input 13, 65 Apr 6 12:37 event1
crw-rw---- 1 root input 13, 74 Apr 11 11:34 event10
crw-rw---- 1 root input 13, 75 Apr 11 11:34 event11
crw-rw---- 1 root input 13, 76 Apr 11 11:34 event12
crw-rw---- 1 root input 13, 77 Apr 11 11:34 event13
crw-rw---- 1 root input 13, 78 Apr 11 11:34 event14
crw-rw---- 1 root input 13, 79 Apr 11 11:34 event15
crw-rw---- 1 root input 13, 80 Apr 11 11:34 event16
crw-rw---- 1 root input 13, 81 Apr 11 11:34 event17
crw-rw---- 1 root input 13, 82 Apr 11 11:34 event18
crw-rw---- 1 root input 13, 66 Apr 6 12:37 event2
crw-rw---- 1 root input 13, 67 Apr 11 11:34 event3
crw-rw---- 1 root input 13, 68 Apr 11 11:34 event4
crw-rw---- 1 root input 13, 69 Apr 11 11:34 event5
crw-rw---- 1 root input 13, 70 Apr 11 11:34 event6
crw-rw---- 1 root input 13, 71 Apr 11 11:34 event7
crw-rw---- 1 root input 13, 72 Apr 11 11:34 event8
crw-rw---- 1 root input 13, 73 Apr 11 11:34 event9
每个event代表一个事件,那么,怎么知道事件和设备的对应呢? 这要借助/proc/bus
(这个部分的知识点参考了蓝天居士的博客,他是一位水平非常高的专家,大家可以学习一下)
/proc/bus/input/devices
让我们转到这个目录
orangepi@orangepi3b:/proc$ cd bus
orangepi@orangepi3b:/proc/bus$ ls
input pci
orangepi@orangepi3b:/proc/bus$ cd input
orangepi@orangepi3b:/proc/bus/input$ ls
devices handlers
orangepi@orangepi3b:/proc/bus/input$ cd devices
bash: cd: devices: Not a directory
orangepi@orangepi3b:/proc/bus/input$ cd devices
bash: cd: devices: Not a directory
orangepi@orangepi3b:/proc/bus/input$ tree
.
├── devices
└── handlers0 directories, 2 files
看看设备信息,信息比较长。我们要拆开来看
event0是什么
orangepi@orangepi3b:/proc/bus/input$ cat devices
I: Bus=0019 Vendor=0001 Product=0001 Version=0100
N: Name="hdmi_cec_key"
P: Phys=hdmi_cec_key/input0
S: Sysfs=/devices/platform/fe0a0000.hdmi/dw-hdmi-cec.1.auto/input/input0
U: Uniq=
H: Handlers=event0
B: PROP=0
B: EV=3
B: KEY=10000000000000 0
I: Bus=0019 Vendor=0001 Product=0001 Version=0100
这个信息:设备挂在总线19下,厂商ID(vendor=0001) 产品ID(Product=0001)
产品版本Version=0100
N: Name="hdmi_cec_key"
标识设备名称和用途
P: Phys=hdmi_cec_key/input0
设备的物理路径,标识设备在系统中的物理位置
S: Sysfs=/devices/platform/fe0a0000.hdmi/dw-hdmi-cec.1.auto/input/input0
设备早sysfs 文件系统中的路径,用于内核和用户空间交互
U: Uniq=
设备唯一标识符号,这里为空
H: Handlers=event0
设备对应的事件处理程序是event0 标识该设备的输入事件通过events0暴露 这个信息是关键信息
B: PROP=0
设备属性标识,这里为0 标识无特殊属性
B: EV=3
标识设备支持的事件类型
B: KEY=10000000000000 0
标识设备支持的按键键值
鼠标
可见,一个设备可以有多个输入
I: Bus=0003 Vendor=046d Product=c08b Version=0111
N: Name="Logitech G502 HERO Gaming Mouse"
P: Phys=usb-fd800000.usb-1.1/input0
S: Sysfs=/devices/platform/fd800000.usb/usb1/1-1/1-1.1/1-1.1:1.0/0003:046D:C08B.0001/input/input3
U: Uniq=0470323E3232
H: Handlers=event3
B: PROP=0
B: EV=17
B: KEY=ffff0000 0 0 0 0
B: REL=1943
B: MSC=10I: Bus=0003 Vendor=046d Product=c08b Version=0111
N: Name="Logitech G502 HERO Gaming Mouse Keyboard"
P: Phys=usb-fd800000.usb-1.1/input1
S: Sysfs=/devices/platform/fd800000.usb/usb1/1-1/1-1.1/1-1.1:1.1/0003:046D:C08B.0002/input/input4
U: Uniq=0470323E3232
H: Handlers=sysrq kbd event4
B: PROP=0
B: EV=100013
B: KEY=1000000000007 ff800000000007ff febeffdfffefffff fffffffffffffffe
B: MSC=10I: Bus=0003 Vendor=046d Product=c08b Version=0111
N: Name="Logitech G502 HERO Gaming Mouse Consumer Control"
P: Phys=usb-fd800000.usb-1.1/input1
S: Sysfs=/devices/platform/fd800000.usb/usb1/1-1/1-1.1/1-1.1:1.1/0003:046D:C08B.0002/input/input5
U: Uniq=0470323E3232
H: Handlers=kbd event5
B: PROP=0
B: EV=1f
B: KEY=306ff 0 0 483ffff17aff32d bfd4444600000000 1 130ff38b17c000 677bfad9415fed 9ed68000004400 10000002
B: REL=1040
B: ABS=100000000
B: MSC=10I: Bus=0003 Vendor=046d Product=c08b Version=0111
N: Name="Logitech G502 HERO Gaming Mouse System Control"
P: Phys=usb-fd800000.usb-1.1/input1
S: Sysfs=/devices/platform/fd800000.usb/usb1/1-1/1-1.1/1-1.1:1.1/0003:046D:C08B.0002/input/input6
U: Uniq=0470323E3232
H: Handlers=kbd event6
B: PROP=0
B: EV=13
B: KEY=c000 10000000000000 0
B: MSC=10
键盘
I: Bus=0003 Vendor=320f Product=5055 Version=0110
N: Name="VXE V87 VXE V87"
P: Phys=usb-fd800000.usb-1.3/input0
S: Sysfs=/devices/platform/fd800000.usb/usb1/1-1/1-1.3/1-1.3:1.0/0003:320F:5055.0003/input/input9
U: Uniq=2020-12-15
H: Handlers=sysrq kbd leds event7
B: PROP=0
B: EV=120013
B: KEY=1000000000007 ff9f207ac14057ff febeffdfffefffff fffffffffffffffe
B: MSC=10
B: LED=1fI: Bus=0003 Vendor=320f Product=5055 Version=0110
N: Name="VXE V87 VXE V87 Keyboard"
P: Phys=usb-fd800000.usb-1.3/input1
S: Sysfs=/devices/platform/fd800000.usb/usb1/1-1/1-1.3/1-1.3:1.1/0003:320F:5055.0004/input/input10
U: Uniq=2020-12-15
H: Handlers=kbd event8
B: PROP=0
B: EV=100013
B: KEY=ff80000000000000 80b0ffcd01cfffff febffbffdffffffe
B: MSC=10I: Bus=0003 Vendor=320f Product=5055 Version=0110
N: Name="VXE V87 VXE V87 System Control"
P: Phys=usb-fd800000.usb-1.3/input1
S: Sysfs=/devices/platform/fd800000.usb/usb1/1-1/1-1.3/1-1.3:1.1/0003:320F:5055.0004/input/input11
U: Uniq=2020-12-15
H: Handlers=kbd event9
B: PROP=0
B: EV=13
B: KEY=c000 10000000000000 0
B: MSC=10I: Bus=0003 Vendor=320f Product=5055 Version=0110
N: Name="VXE V87 VXE V87 Consumer Control"
P: Phys=usb-fd800000.usb-1.3/input1
S: Sysfs=/devices/platform/fd800000.usb/usb1/1-1/1-1.3/1-1.3:1.1/0003:320F:5055.0004/input/input12
U: Uniq=2020-12-15
H: Handlers=kbd event10
B: PROP=0
B: EV=1f
B: KEY=3f000307ff 0 0 483ffff17aff32d bfd4444600000000 1 130ff38b17d000 677bfad9415fed 19ed68000004400 10000002
B: REL=1040
B: ABS=100000000
B: MSC=10I: Bus=0003 Vendor=320f Product=5055 Version=0110
N: Name="VXE V87 VXE V87"
P: Phys=usb-fd800000.usb-1.3/input1
S: Sysfs=/devices/platform/fd800000.usb/usb1/1-1/1-1.3/1-1.3:1.1/0003:320F:5055.0004/input/input13
U: Uniq=2020-12-15
H: Handlers=event11
B: PROP=0
B: EV=9
B: ABS=10000000000I: Bus=0003 Vendor=320f Product=5055 Version=0110
N: Name="VXE V87 VXE V87 Mouse"
P: Phys=usb-fd800000.usb-1.3/input1
S: Sysfs=/devices/platform/fd800000.usb/usb1/1-1/1-1.3/1-1.3:1.1/0003:320F:5055.0004/input/input14
U: Uniq=2020-12-15
H: Handlers=event12
B: PROP=0
B: EV=17
B: KEY=1f0000 0 0 0 0
B: REL=1943
B: MSC=10I: Bus=0003 Vendor=320f Product=5088 Version=0111
N: Name="Telink VXE V87 2.4G Dongle"
P: Phys=usb-fd800000.usb-1.4/input0
S: Sysfs=/devices/platform/fd800000.usb/usb1/1-1/1-1.4/1-1.4:1.0/0003:320F:5088.0007/input/input21
U: Uniq=
H: Handlers=sysrq kbd leds event13
B: PROP=0
B: EV=120013
B: KEY=1000000000007 ff9f207ac14057ff febeffdfffefffff fffffffffffffffe
B: MSC=10
B: LED=1fI: Bus=0003 Vendor=320f Product=5088 Version=0111
N: Name="Telink VXE V87 2.4G Dongle Keyboard"
P: Phys=usb-fd800000.usb-1.4/input1
S: Sysfs=/devices/platform/fd800000.usb/usb1/1-1/1-1.4/1-1.4:1.1/0003:320F:5088.0008/input/input22
U: Uniq=
H: Handlers=kbd event14
B: PROP=0
B: EV=100013
B: KEY=ff80000000000000 80b0ffcd01cfffff febffbffdffffffe
B: MSC=10I: Bus=0003 Vendor=320f Product=5088 Version=0111
N: Name="Telink VXE V87 2.4G Dongle System Control"
P: Phys=usb-fd800000.usb-1.4/input1
S: Sysfs=/devices/platform/fd800000.usb/usb1/1-1/1-1.4/1-1.4:1.1/0003:320F:5088.0008/input/input23
U: Uniq=
H: Handlers=kbd event15
B: PROP=0
B: EV=13
B: KEY=c000 10000000000000 0
B: MSC=10I: Bus=0003 Vendor=320f Product=5088 Version=0111
N: Name="Telink VXE V87 2.4G Dongle Consumer Control"
P: Phys=usb-fd800000.usb-1.4/input1
S: Sysfs=/devices/platform/fd800000.usb/usb1/1-1/1-1.4/1-1.4:1.1/0003:320F:5088.0008/input/input24
U: Uniq=
H: Handlers=kbd event16
B: PROP=0
B: EV=1f
B: KEY=3f000307ff 0 0 483ffff17aff32d bfd4444600000000 1 130ff38b17d000 677bfad9415fed 19ed68000004400 10000002
B: REL=1040
B: ABS=100000000
B: MSC=10I: Bus=0003 Vendor=320f Product=5088 Version=0111
N: Name="Telink VXE V87 2.4G Dongle"
P: Phys=usb-fd800000.usb-1.4/input1
S: Sysfs=/devices/platform/fd800000.usb/usb1/1-1/1-1.4/1-1.4:1.1/0003:320F:5088.0008/input/input25
U: Uniq=
H: Handlers=event17
B: PROP=0
B: EV=9
B: ABS=10000000000I: Bus=0003 Vendor=320f Product=5088 Version=0111
N: Name="Telink VXE V87 2.4G Dongle Mouse"
P: Phys=usb-fd800000.usb-1.4/input1
S: Sysfs=/devices/platform/fd800000.usb/usb1/1-1/1-1.4/1-1.4:1.1/0003:320F:5088.0008/input/input26
U: Uniq=
H: Handlers=event18
B: PROP=0
B: EV=17
B: KEY=1f0000 0 0 0 0
B: REL=1943
B: MSC=10
看起来有些复杂。不过我们很容易看出event* 和设备的对应关系。你觉得有些麻烦? 已经有人为我们制作了工具!
使用evtest来测试你的输入设备
orangepi@orangepi3b:~/bop_code$ sudo apt install evtest
Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
evtest is already the newest version (1:1.34-1).
0 upgraded, 0 newly installed, 0 to remove and 1 not upgraded.
扫描设备
orangepi@orangepi3b:~/bop_code$ sudo evtest
No device specified, trying to scan all of /dev/input/event*
Available devices:
/dev/input/event0: hdmi_cec_key
/dev/input/event1: rk805 pwrkey
/dev/input/event2: rockchip-rk809 Headset
/dev/input/event3: Logitech G502 HERO Gaming Mouse
/dev/input/event4: Logitech G502 HERO Gaming Mouse Keyboard
/dev/input/event5: Logitech G502 HERO Gaming Mouse Consumer Control
/dev/input/event6: Logitech G502 HERO Gaming Mouse System Control
/dev/input/event7: VXE V87 VXE V87
/dev/input/event8: VXE V87 VXE V87 Keyboard
/dev/input/event9: VXE V87 VXE V87 System Control
/dev/input/event10: VXE V87 VXE V87 Consumer Control
/dev/input/event11: VXE V87 VXE V87
/dev/input/event12: VXE V87 VXE V87 Mouse
/dev/input/event13: Telink VXE V87 2.4G Dongle
/dev/input/event14: Telink VXE V87 2.4G Dongle Keyboard
/dev/input/event15: Telink VXE V87 2.4G Dongle System Control
/dev/input/event16: Telink VXE V87 2.4G Dongle Consumer Control
/dev/input/event17: Telink VXE V87 2.4G Dongle
/dev/input/event18: Telink VXE V87 2.4G Dongle Mouse
选取并监听
这里以键盘为例子
Select the device event number [0-18]: 7
Input driver version is 1.0.1
Input device ID: bus 0x3 vendor 0x320f product 0x5055 version 0x110
Input device name: "VXE V87 VXE V87"
Supported events:Event type 0 (EV_SYN)Event type 1 (EV_KEY)Event code 1 (KEY_ESC)Event code 2 (KEY_1)Event code 3 (KEY_2)Event code 4 (KEY_3)....Event code 190 (KEY_F20)Event code 191 (KEY_F21)Event code 192 (KEY_F22)Event code 193 (KEY_F23)Event code 194 (KEY_F24)Event code 240 (KEY_UNKNOWN)Event type 4 (EV_MSC)Event code 4 (MSC_SCAN)Event type 17 (EV_LED)Event code 0 (LED_NUML) state 0Event code 1 (LED_CAPSL) state 0Event code 2 (LED_SCROLLL) state 0Event code 3 (LED_COMPOSE) state 0Event code 4 (LED_KANA) state 0
Key repeat handling:Repeat type 20 (EV_REP)Repeat code 0 (REP_DELAY)Value 250Repeat code 1 (REP_PERIOD)Value 33
Properties:
Testing ... (interrupt to exit)
Event: time 1744374523.592185, type 4 (EV_MSC), code 4 (MSC_SCAN), value 70028
Event: time 1744374523.592185, type 1 (EV_KEY), code 28 (KEY_ENTER), value 0
Event: time 1744374523.592185, -------------- SYN_REPORT ------------
Event: time 1744374526.435125, type 4 (EV_MSC), code 4 (MSC_SCAN), value 70013
Event: time 1744374526.435125, type 1 (EV_KEY), code 25 (KEY_P), value 1
Event: time 1744374536.039071, -------------- SYN_REPORT ------------
Event: time 1744374536.207057, type 4 (EV_MSC), code 4 (MSC_SCAN), value 70006
Event: time 1744374536.207057, type 1 (EV_KEY), code 46 (KEY_C), value 1
Event: time 1744374536.207057, -------------- SYN_REPORT ------------
Event: time 1744374536.295063, type 4 (EV_MSC), code 4 (MSC_SCAN), value 70006
Event: time 1744374536.295063, type 1 (EV_KEY), code 46 (KEY_C), value 0
Event: time 1744374536.295063, -------------- SYN_REPORT ------------
使用代码实现内核监听
我们在刚刚,已经获得了键盘输入在event7的信息
!!!注意! 你必须使用evtest来观察你的键盘的正确位置!!! 否则代码会失败!
下面按照这个来写,这是源代码
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <signal.h>
#include <linux/input.h>int main(int argc, char **argv) {const char* devloc = "/dev/input/event7";int fd = open(devloc, O_RDONLY) ;if (fd == -1) {perror("无法打开输入设备");return 1;}struct input_event ev;while(true){ssize_t n = read(fd , &ev ,sizeof(ev));if(n ==-1){perror("this error \n");break;}if(n!= sizeof(ev)){continue;}if(ev.type ==EV_KEY && ev.value ==1){printf(" key!!!\n");switch ((ev.code)){case KEY_P:printf("hello");break;case KEY_K:printf(" keyboard");break; default:break;}}}close(fd);return 0;
}
让我们把代码封装成类吧
#include <iostream>
#include <thread>
#include <unordered_map>
#include <functional>#include <linux/input.h>
#include <fcntl.h> //open函数在这个库
#include <unistd.h> //read在这个库class bop_keylistener
{
private:int fd;std::unordered_map<int, std::function<void()>> keyCallbacks;std::thread listenerThread;struct input_event ev;bool running = true;int millsec_wait ;void listenkey(){while(running){ssize_t n = read(fd , &ev ,sizeof(ev));if(n ==-1){std::cerr << "this event message error "<<std::endl;}if(n!= sizeof(ev)){continue;}if(ev.type ==EV_KEY && ev.value ==1){for(const auto& pair :keyCallbacks){auto keyi=pair.first;if(keyi == ev.code){pair.second();}}std::this_thread::sleep_for(std::chrono::milliseconds(millsec_wait));}}}
public:bop_keylistener(const char* devloc , int millsecwait = 50){millsec_wait =millsecwait;fd = open(devloc, O_RDONLY) ;if (fd == -1) {perror("无法打开输入设备");}listenerThread = std::thread(&bop_keylistener::listenkey, this);}~bop_keylistener(){running = false;if (listenerThread.joinable()) {listenerThread.join();}}// 注册按键和对应的回调函数void registerKeyCallback(int key, const std::function<void()>& callback) {keyCallbacks[key] = callback;}};// 示例回调函数
void exampleCallback() {std::cout << "Example callback executed!" << std::endl;
}int main() {bop_keylistener mkeyl("/dev/input/event7" );// 注册按键 'A' 和对应的回调函数mkeyl.registerKeyCallback(KEY_1, exampleCallback);// 保持主线程运行std::this_thread::sleep_for(std::chrono::hours(1));return 0;
}
创作不易,还请多多支持
相关文章:
linux以C方式和内核交互监听键盘[香橙派搞机日记]
最近在深入研究我的香橙派,不可避免的遇到了怎么认识和使用Linux内核的问题。 我给自己留了一个简单的任务:使用原生C来监听内核,实现读取键盘的消息。 CSDN上也有其他文章来解决这个问题,不过要么是技术不达标(直接和…...
【C++初学】课后作业汇总复习(七) 指针-深浅copy
1、 HugeInt类:构造、、cout Description: 32位整数的计算机可以表示整数的范围近似为-20亿到+20亿。在这个范围内操作一般不会出现问题,但是有的应用程序可能需要使用超出上述范围的整数。C可以满足这个需求,创建功能强大的新的…...
【iOS】UIPageViewController学习
UIPageViewController学习 前言创建一个UIPageViewController最简单的使用 UIPageViewController的方法说明:效果展示 UIPageViewController的协议方法 前言 笔者最近在写项目时想实现一个翻书效果,上网学习到了UIPageViewController今天写本篇博客总结…...
GDB 调试命令详解:高效掌握常用调试技巧
🐞 GDB 调试命令详解:高效掌握常用调试技巧 GNU Debugger(GDB)是 Linux 下最强大的 C/C 调试工具。本文将系统梳理 GDB 的常用命令,覆盖运行控制、断点管理、变量查看、线程与进程调试等核心功能,助你快速掌…...
实验二 用递归下降法分析表达式实验
【实验目的】 1.掌握用递归下降分析法进行语法分析的方法。加深对自顶向下语法分析原理的理解。 2.掌握设计、编制并调试自顶向下语法分析程序的思想和方法。 3.本实验是高级语言程序设计、数据结构和编译原理中词法分析、自顶向下语法分析原理等知 识的综合。由于语法分析…...
【随身wifi】青龙面板保姆级教程
0.操作前必看 本教程基于Debian系统,从Docker环境。面板安装,到最后拉取脚本的使用。 可以拉库跑狗东京豆,elm红包等等,也可以跑写自己写的脚本,自行探索 重要的号别搞,容易黑号,黑号自己负责…...
从一到无穷大 #45:InfluxDB MCP Server 构建:从工程实践到价值重构
本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。 本作品 (李兆龙 博文, 由 李兆龙 创作),由 李兆龙 确认,转载请注明版权。 文章目录 工程实践遇到的问题MCP Host选择开发流程 结果展现可能性展望工作生活带来的变化 MCP…...
app逆向专题五:新快报app数据采集
app逆向专题五:新快报app数据采集 一、抓包寻找数据接口二、编写代码三、完整代码一、抓包寻找数据接口 打开charles,并在手机端打开新快报app,点击“广州”或者“经济”等选项卡,抓包,寻找数据接口,如图所示: 二、编写代码 这里介绍一种简便的代码编写方法,在数据…...
使用 lm-eval 评估模型时报错:TypeError: ‘NoneType’ object is not callable 的解决方案
问题描述 在使用 lm-evaluation-harness 进行多 GPU 模型评估时,使用如下命令: accelerate launch --multi-gpu --num_processes 2 \-m lm_eval --model hf \--model_args pretrained${local_model_path} \--tasks mmlu \--batch_size 8 \--log_sample…...
脉冲耦合神经网络(PCNN):图像处理中的强大工具
文章目录 一、PCNN 的起源与背景二、PCNN 的基本原理(一)模型结构(二)工作方式(三)动态阈值与脉冲特征三、PCNN 在图像处理中的应用(一)图像分割(二)边缘检测(三)纹理分析四、PCNN 的实现与优化环境准备PCNN 类定义图像分割示例在图像处理和计算机视觉领域,神经网…...
【Git】从零开始使用git --- git 的基本使用
哪怕是野火焚烧,哪怕是冰霜覆盖, 依然是志向不改,依然是信念不衰。 --- 《悟空传》--- 从零开始使用git 了解 Gitgit创建本地仓库初步理解git结构版本回退 了解 Git 开发场景中,文档可能会经历若干版本的迭代。假如我们不进行…...
React Hooks 的使用
🤍 前端开发工程师、技术日更博主、已过CET6 🍨 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 🕠 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》、《前端求职突破计划》 🍚 蓝桥云课签约作者、…...
【NIO番外篇】之组件 Channel
目录 一、什么是NIO Channel?二、常见的Channel组件及其用法1. FileChannel2. SocketChannel3. ServerSocketChannel4. DatagramChannel 🌟我的其他文章也讲解的比较有趣😁,如果喜欢博主的讲解方式,可以多多支持一下&a…...
探秘 Ruby 与 JavaScript:动态语言的多面风采
1 语法特性对比:简洁与灵活 1.1 Ruby 的语法优雅 Ruby 的语法设计旨在让代码读起来像自然语言一样流畅。它拥有简洁而富有表现力的语法结构,例如代码块、符号等。 以下是一个使用 Ruby 进行数组操作的简单示例: # 定义一个数组 numbers [1…...
高频面试题(含笔试高频算法整理)基本总结回顾21
干货分享,感谢您的阅读! (暂存篇---后续会删除,完整版和持续更新见高频面试题基本总结回顾(含笔试高频算法整理)) 备注:引用请标注出处,同时存在的问题请在相关博客留言…...
深入浅出一下Python函数的核心概念与进阶应用
本篇技术博文摘要 🌟 本文系统梳理了Python函数的核心知识点,从基础概念到高级特性,构建了完整的函数编程知识体系。内容涵盖:变量作用域的局部与全局划分、函数注释的规范写法、参数传递中值与引用的区别、匿名函数的灵活应用&am…...
【漫话机器学习系列】198.异常值(Outlier)
异常值(Outlier)全面指南 —— 检测、分析与处理 作者:Chris Albon(图源) 场景:数据清洗与特征工程必备技能 一、什么是异常值(Outlier) 定义 异常值(Outlier࿰…...
React 记账本项目实战:多页面路由、Context 全局
在本文中,我们将分享一个使用 React 开发的「记账本」项目的实战经验。该项目通过 VS Code 完成,包含首页、添加记录页、编辑页等多个功能页面,采用了 React Router 实现路由导航,使用 Context API 管理全局的交易记录状态,并引入数据可视化组件呈现不同月份的支出情况。项…...
[React] 如何用 Zustand 构建一个响应式 Enum Store?附 RTKQ 实战与 TS 架构落地
[React] 如何用 Zustand 构建一个响应式 Enum Store?附 RTKQ 实战与 TS 架构落地 本文所有案例与数据为作者自行构建,所有内容均为技术抽象示例,不涉及任何实际商业项目 自从之前尝试了一下 zustand 之后,就发现 zustand 是一个轻…...
DeepSeek在职场办公中的高效指令运用与策略优化
摘要 随着人工智能技术的飞速发展,大型语言模型在各个领域的应用日益广泛。DeepSeek作为一款具有影响力的AI产品,为职场办公带来了新的变革与机遇。本文深入剖析DeepSeek在职场办公场景下的提示词指令运用,通过对提示词概念、作用、设计原则的…...
mysql事务脏读 不可重复读 幻读 事务隔离级别关系
看了很多文档,发现针对事务并发执行过程中的数据一致性问题,即脏读、不可重复读、幻读的解释一塌糊涂,这也不能说什么,因为官方SQL标准中的定义也模糊不清。 按照mysql中遵循的事务隔离级别,可以梳理一下其中的关系 隔…...
Fork/Join框架与线程池对比分析
Fork/Join框架与线程池对比分析 1. 概述 线程池(如ThreadPoolExecutor)是Java并发编程中用于管理线程生命周期的通用工具,适用于处理大量独立任务。Fork/Join框架(基于ForkJoinPool)是Java 7引入的专用框架ÿ…...
docker 安装 Gitlab
GitLab 安装 #创建容器数据卷映射目录 mkdir -p /usr/docker/gitlab/config mkdir -p /usr/docker/gitlab/logs mkdir -p /usr/docker/gitlab/data #目录授权 chmod 777 -R /usr/docker/gitlab/*#直接复制可用(记得改下宿主机ipv4,不知道怎么看,输入i…...
【贪心之摆动序列】
题目: 分析: 这里我们使用题目中给的第二个实例来进行分析 题目中要求我们序列当中有多少个摆动序列,摆动序列满足一上一下,一下一上,这样是摆动序列,并且要输出摆动序列的最长长度 通过上面的图我们可以…...
kubectl修改资源时添加注解
kubectl修改资源时添加注解 kubectl修改资源时添加注解老版本的注解(变化注解)删除Annotations查看Annotations信息 查看发布记录回滚 kubectl修改资源时添加注解 参考: 为什么我们要使用kubectl apply 修改资源时,在命令行后添加 --save-configtrue ,就会自动添加此次修改的…...
【C++初学】课后作业汇总复习(四) 复数类与运算符重载
1、复数类输出 如题,要求实现: 1、复数类含两个参数的构造函数,一个为实部,一个为虚部 2、用Show()现实复数的值。 输出 (23i) //如题,要求实现: // //1、复数类含两个参数的构造函数&…...
十四、C++速通秘籍—函数式编程
目录 上一章节: 一、引言 一、函数式编程基础 三、Lambda 表达式 作用: Lambda 表达式捕获值的方式: 注意: 四、函数对象 函数对象与普通函数对比: 五、函数适配器 1、适配普通函数 2、适配 Lambda 表达式 …...
复刻系列-星穹铁道 3.2 版本先行展示页
复刻星穹铁道 3.2 版本先行展示页 0. 视频 手搓~星穹铁道~展示页~~~ 1. 基本信息 作者: 啊是特嗷桃系列: 复刻系列官方的网站: 《崩坏:星穹铁道》3.2版本「走过安眠地的花丛」专题展示页现已上线复刻的网…...
阿里云备案有必要选择备案管家服务吗?自己ICP备案可以吗?
阿里云备案有必要选择备案管家服务吗?新手可以选择备案管家,备案管家不需要自己手动操作,可以高效顺利通过ICP备案。自己ICP备案可以吗?自己备案也可以的,也很简单,适合动手能力强的同学。 阿里云备案管家…...
SQL语言基础(二)--以postersql为例
上次教程我们讲述了数据库中的增,删,改语句,今天我们来学习最后一个–‘改’的语句。 1.select语法 数据库查询只有select一个句子,但select语法相对复杂,其功能丰富,使用方式也很灵活 SELECT [ALL|Dist…...
探索 Rust 语言:高效、安全与并发的完美融合
在当今的编程语言领域,Rust 正以其独特的魅力吸引着越来越多开发者的目光。它诞生于 Mozilla 实验室,旨在解决系统编程中长久以来存在的难题,如今已成为构建可靠、高效软件的有力工具。 1 内存安全 Rust 通过所有权(ownership&a…...
最大公约数和最小倍数 java
在Java中,计算两个数的最大公约数(Greatest Common Divisor, GCD)和最小公倍数(Least Common Multiple, LCM)是常见的编程问题。以下是具体的实现方法和代码示例。 --- ### **1. 最大公约数 (GCD)** 最大公约数是指…...
OpenHarmony Camera开发指导(三):相机设备输入输出(ArkTS)
相机应用可通过创建相机输入流调用并控制相机设备,创建不同类型的输出流,进而实现预览、拍照、录像等基础功能。 开发步骤 在创建相机设备输入之前需要先完成相机设备管理,详细开发步骤可参考上一篇文章。 创建相机输入流 通过cameraMana…...
通过分治策略解决内存限制问题完成大型Hive表数据的去重的PySpark代码实现
在Hive集群中,有一张历史交易记录表,要从这张历史交易记录表中抽取一年的数据按某些字段进行Spark去重,由于这一年的数据超过整个集群的内存容量,需要分解成每个月的数据,分别用Spark去重,并保存为Parquet文…...
融媒体中心智能语音识别系统设计与实现
县级融媒体中心智能语音识别系统设计与实现 序言 随着融媒体时代的快速发展,新闻采编、专题节目制作对语音转写效率的要求日益提高。作为基层融媒体中心的技术工程师,我们在实际工作中常面临以下痛点: 采访录音整理耗时:传统人…...
学习笔记九——Rust所有权机制
🦀 Rust 所有权机制 📚 目录 什么是值类型和引用类型?值语义和引用语义?什么是所有权?为什么 Rust 需要它?所有权的三大原则(修正版)移动语义 vs 复制语义:变量赋值到底…...
计算机视觉算法实现——电梯禁止电瓶车进入检测:原理、实现与行业应用(主页有源码)
✨个人主页欢迎您的访问 ✨期待您的三连 ✨ ✨个人主页欢迎您的访问 ✨期待您的三连 ✨ ✨个人主页欢迎您的访问 ✨期待您的三连✨ 1. 电梯安全检测领域概述 近年来,随着电动自行车(以下简称"电瓶车"&…...
扩散模型 Diffusion Model 整体流程详解
🧠 Diffusion Model 思路、疑问和代码 文章目录 🧠 Diffusion Model 思路、疑问和代码🔄 一、核心思想:从噪声到图像📦 二、正向过程:加噪🧠 三、反向过程:学习去噪🎯 目…...
[Spark]深入解密Spark SQL源码:Catalyst框架如何优雅地解析你的SQL
本文内容组织形式 总结具体例子执行语句解析层优化层物理计划层执行层 猜你喜欢PS 总结 先写个总结,接下来会分别产出各个部分的源码解析,Spark SQL主要分为以下五个执行部分。 具体例子 接下来举个具体的例子来说明 执行语句 SELECT name, age FR…...
【数据结构_7】栈和队列(上)
一、概念 栈和队列,也是基于顺序表和链表实现的 栈是一种特殊的线性表,其只允许在固定的一段进行插入和删除元素操作。 遵循后进先出的原则 此处所见到的栈,本质上就是一个顺序表/链表,但是,实在顺序表/链表的基础…...
Linux中的cat命令常见用法
在 Linux 中,cat 命令是 concatenate(连接)的缩写,意思是“连接”或“串联”。 基本功能 cat 命令的主要功能是用于查看、合并和创建文件。它会将一个或多个文件的内容输出到标准输出设备(通常是终端屏幕)…...
css - 实现三角形 div 容器,用css画一个三角形(提供示例源码)简单粗暴几行代码搞定!
效果图 如下图所示,让一个 div 变成三角形,并且可随意更改大小, 本文提供了可运行示例源码,直接复制即可。 实现源码 建议创建一个 demo.html 文件,一键复制代码运行。 <style> .div{width: 0px;height: 0px…...
springboot 项目 jmeter简单测试流程
测试内容为 主机地址随机数 package com.hainiu.example;import lombok.extern.slf4j.Slf4j; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotat…...
设计模式实践:模板方法、观察者与策略模式详解
目录 1 模板方法1.1 模板方法基本概念1.2 实验1.2.1 未使用模板方法实现代码1.2.2 使用模板方法的代码 2 观察者模式2.1 观察者模式基本概念2.2 实验 3 策略模式3.1 策略模式基本概念3.2 实验 1 模板方法 1.1 模板方法基本概念 定义:一个操作中的算法的骨架 &…...
Google的AI模型Gemini和Gemini网络协议
粉丝私信问我:gemini如何访问? "Gemini如何访问"需明确区分两种完全不同的技术体系:Google的AI模型Gemini和Gemini网络协议。以下是两者的访问方式详解: 一、访问Google的Gemini AI模型 1. 通过Web应用 地址…...
HTTP实现心跳模块
HTTP实现心跳模块 使用轻量级的cHTTP库cpp-httplib重现实现HTTP心跳模块 头文件HttplibHeartbeat.h #ifndef HTTPLIB_HEARTBEAT_H #define HTTPLIB_HEARTBEAT_H#include <string> #include <thread> #include <atomic> #include <chrono> #include …...
基于web的民宿信息系统(源码+lw+部署文档+讲解),源码可白嫖!
摘要 随着信息时代的来临,民宿过去的民宿信息方式的缺点逐渐暴露,对过去的民宿信息的缺点进行分析,采取计算机方式构建民宿信息系统。本文通过阅读相关文献,研究国内外相关技术,提出了一种民宿信息管理、民宿信息管理…...
使用OpenSceneGraph (osg)实现一个星系漫游
简介 使用OpenSceneGraph (osg)实现了一个太阳系漫游的程序,具有以下特点: 1.通过按键控制飞行器前进后退、空间姿态; 2.星系渲染; 3.背景星空渲染; 效果 提供了一张超大的星空背景图 代码示例 int main(int a…...
笔试专题(九)
文章目录 十字爆破(暴力)题解代码 比那名居的桃子(滑动窗口/前缀和)题解代码 分组(暴力枚举 优化二分)题解代码 十字爆破(暴力) 题目链接 题解 1. 暴力 预处理 2. 如果单纯的暴…...
sklearn决策树 待更新
注意:sklearn中所有的决策树模型包括回归决策树实现的是CART决策树算法,在官方文档中有介绍。sklearn中的决策树模型最终得到的树结构都是二叉树,因为CART算法生成的就是二叉树。 DecisionTreeClassifier类 如果待预测样本有多个类别具有相同…...