frameworks 之getEvent指令
frameworks 之getEvent指令
- 指令解析
- 源码追溯
- 源码解析
- 1.解析参数
- 2.初始化ufds数组
- 3.添加到poll 并做对应处理
通过 getEvent 可以识别按键基本命令和里面的关键信息
涉及到的类如下
- system/core/toolbox/toolbox.c
- system/core/toolbox/tools.h
- system/core/toolbox/getevent.c
指令解析
通过 getEvent -h 可打印出相关的指令帮助,对应的指令注释如下。输出的数字都为16进制。
houji:/ $ getevent -help
Usage: getevent [-t] [-n] [-s switchmask] [-S] [-v [mask]] [-d] [-p] [-i] [-l] [-q] [-c count] [-r] [device]-t: show time stamps // 打印时间戳-n: don't print newlines // 不换行-s: print switch states for given bits // 打印指定位的开关状态-S: print all switch states // 打印所有开关状态-v: verbosity mask (errs=1, dev=2, name=4, info=8, vers=16, pos. events=32, props=64) // 根据 mask 值显示相关信息,执行后会一直显示上报数据,详细掩码(错误=1,dev=2,名称=4,信息=8,错误=16,位置事件=32,道具=64)默认显示 dev| name| info| vers = 30-d: show HID descriptor, if available // 如果设备可用,显示设备隐藏的描述信息-p: show possible events (errs, dev, name, pos. events) // 显示设备支持的事件类型和编码方式-i: show all device info and possible events // 显示设备的所有信息和支持的事件,比 -p 显示更多信息-l: label event types and names in plain text // 以文本形式输出事件类型和名称,比 -t 更清楚直观-q: quiet (clear verbosity mask) // 以文本形式输出事件类型和名称,比 -t 更清楚直观-c: print given number of events then exit // 打印固定数量的事件并退出-r: print rate events are received // 显示事件上报速率
其中 -v 打印输入设备的详细信息,默认为 默认显示 dev| name| info| vers = 30。
emulator_x86_64:/ # getevent -v
add device 1: /dev/input/event0bus: 0019vendor 0000product 0001version 0000name: "Power Button"location: "LNXPWRBN/button/input0"id: ""version: 1.0.1
-l 打印的信息 分别对应 type code value。
emulator_x86_64:/ # getevent -l
/dev/input/event3: EV_ABS ABS_MT_TRACKING_ID 00000000
/dev/input/event3: EV_ABS ABS_MT_POSITION_X 000031af
/dev/input/event3: EV_ABS ABS_MT_POSITION_Y 00004447
参数可以组合使用,一次性查看需要的触摸屏信息,常用的命令组合为 getevent -ltr
emulator_x86_64:/ # getevent -ltr
[ 1384.965200] /dev/input/event3: EV_ABS ABS_MT_TRACKING_ID 00000000
源码追溯
可以执行, 则表示 system/bin 有对应的脚本。所以可以通过执行对应的打印 查看文件。通过命令 ls -l | grep event 过滤对应的关键字可以看到 该事件通过 软链接(前面开头为l开头即为软链接)。链接到 toolbox。
emulator_x86_64:/system/bin # ls -l | grep event
lrwxr-xr-x 1 root shell 7 2024-08-17 22:51 getevent -> toolbox
-rwxr-xr-x 1 root shell 3925 2024-03-18 00:26 mm_events
lrwxr-xr-x 1 root shell 6 2024-08-17 22:51 sendevent -> toybox
lrwxr-xr-x 1 root shell 4 2024-08-17 22:51 ueventd -> init
回到源码文件,一般工具类 在 system 目录下,可以先通过该目录查找。执行 find -name toolbox。可以看到在该**./core/toolbox** 文件夹下。
跳转到该文件夹下,查看对应的文件打印,查看对应的Bp文件。包含以下文件,可以看出入口为
toolbox.c 文件夹。
cc_defaults {...srcs: ["toolbox.c","getevent.c","getprop.cpp","modprobe.cpp","setprop.cpp","start.cpp",],...
}
对应的 main 入口如下,该方法通过读取参数,遍历数组 ,然后判断名称和命令是否相等,相等就执行对应的 func 方法。对应 tools[] 数组 在文件前面定义,定义了名词和执行的方法。
会根据 name 拼接对应的执行方法。如 getEvent 拼接完为 getevent_main。相关数组定义在 tools.h 头文件里面。
// system/core/toolbox/tools.c
#define TOOL(name) int name##_main(int, char**); // 拼接对应的执行方法名称
#include "tools.h"
#undef TOOL
// 定义对应的数组,数组内容来自 tools.h定义
static struct {const char* name;int (*func)(int, char**);
} tools[] = {
#define TOOL(name) { #name, name##_main },
#include "tools.h"
#undef TOOL{ 0, 0 },
};int main(int argc, char** argv) {// Let's assume that none of this code handles broken pipes. At least ls,// ps, and top were broken (though I'd previously added this fix locally// to top). We exit rather than use SIG_IGN because tools like top will// just keep on writing to nowhere forever if we don't stop them.signal(SIGPIPE, SIGPIPE_handler);// 获取第一个参数,遍历数组,判断是否和名称相等,相等执行对应的方法。char* cmd = strrchr(argv[0], '/');char* name = cmd ? (cmd + 1) : argv[0];for (size_t i = 0; tools[i].name; i++) {if (!strcmp(tools[i].name, name)) {return tools[i].func(argc, argv);}}printf("%s: no such tool\n", argv[0]);return 127;
}
头文件定义
// system/core/toolbox/tools.h
TOOL(getevent)
TOOL(getprop)
TOOL(modprobe)
TOOL(setprop)
TOOL(start)
TOOL(stop)
TOOL(toolbox)
所以运行脚本 执行的方法 在 getevent.c 下的 getevent_main方法下。
源码解析
1.解析参数
查看对应的方法 main 方法,可以看到 第一步 通过 getopt 解析对应的参数
部分参数通过 或 记录到 print_flags 中。
opterr = 0;do {c = getopt(argc, argv, "tns:Sv::dpilqc:rh"); // 解析对应的参数if (c == EOF)break;switch (c) {case 't':get_time = 1;break;case 'n':newline = "";break;case 's':get_switch = strtoul(optarg, NULL, 0);if(dont_block == -1)dont_block = 1;break;case 'S':get_switch = ~0;if(dont_block == -1)dont_block = 1;break;case 'v':if(optarg)print_flags |= strtoul(optarg, NULL, 0);elseprint_flags |= PRINT_DEVICE | PRINT_DEVICE_NAME | PRINT_DEVICE_INFO | PRINT_VERSION;print_flags_set = 1;break;case 'd':print_flags |= PRINT_HID_DESCRIPTOR;break;case 'p':print_flags |= PRINT_DEVICE_ERRORS | PRINT_DEVICE| PRINT_DEVICE_NAME | PRINT_POSSIBLE_EVENTS | PRINT_INPUT_PROPS;print_flags_set = 1;if(dont_block == -1)dont_block = 1;break;case 'i':print_flags |= PRINT_ALL_INFO;print_flags_set = 1;if(dont_block == -1)dont_block = 1;break;case 'l':print_flags |= PRINT_LABELS;break;case 'q':print_flags_set = 1;break;case 'c':event_count = atoi(optarg); //解析对应参数值dont_block = 0;break;case 'r':sync_rate = 1;break;case '?':fprintf(stderr, "%s: invalid option -%c\n",argv[0], optopt);case 'h':usage(argv[0]); // 打印帮助exit(1);}} while (1);if(dont_block == -1)dont_block = 0;if (optind + 1 == argc) {device = argv[optind];optind++;}if (optind != argc) {usage(argv[0]);exit(1);}
2.初始化ufds数组
第二步,会通过 device 判断是否 观察单个或者全部 。如如果我们 执行的命令后面加了对应的设备,则只会观察对应的设备 如 getevent -ltr /dev/input/event1。其中 inotify_init 获取了 dev/input 文件夹对应的监听。 然后通过 inotify_add_watch。进行删除和添加的监听。
nfds = 1;ufds = calloc(1, sizeof(ufds[0]));ufds[0].fd = inotify_init();ufds[0].events = POLLIN;// 打印单个设备对应信息if(device) {if(!print_flags_set)print_flags |= PRINT_DEVICE_ERRORS;// 通过 open 方法打开对应的驱动,并通过 ioctl 获取对应的信息,并放到对应的 ufds 数组res = open_device(device, print_flags);if(res < 0) {return 1;}} else { // 打印全部if(!print_flags_set)print_flags |= PRINT_DEVICE_ERRORS | PRINT_DEVICE | PRINT_DEVICE_NAME;print_device = 1;// 添加删除和添加对应文件夹的监听res = inotify_add_watch(ufds[0].fd, device_path, IN_DELETE | IN_CREATE);if(res < 0) {fprintf(stderr, "could not add watch for %s, %s\n", device_path, strerror(errno));return 1;}// 遍历该文件夹 dev/input 文件夹下所有的res = scan_dir(device_path, print_flags);if(res < 0) {fprintf(stderr, "scan dir failed for %s\n", device_path);return 1;}}
没指定对应的设备的会 将所有添加到数组中,通过 scan_dir 方法。遍历文件夹下。先通过 opendir,打开文件夹,然后 通过 readdir进行遍历。遍历到符合的 在通过 open_device 将fd 添加到 数组中。
static int scan_dir(const char *dirname, int print_flags)
{char devname[PATH_MAX];char *filename;DIR *dir;struct dirent *de;// // 打开对应的文件夹dir = opendir(dirname);if(dir == NULL)return -1;strcpy(devname, dirname);filename = devname + strlen(devname);*filename++ = '/';while((de = readdir(dir))) {if(de->d_name[0] == '.' &&(de->d_name[1] == '\0' ||(de->d_name[1] == '.' && de->d_name[2] == '\0')))continue;strcpy(filename, de->d_name);// 将fd 添加到 数组open_device(devname, print_flags);}closedir(dir);return 0;
}
最终都是通过 open_device 添加到数组,查看对应的方法,可以看到该方法通过 open 打开对应的节点,在通过 ioctl 获取对应的信息,并根据 设置的 print_flags 按需打印对应信息。最终在存放到 ufds 数组中。
static int open_device(const char *device, int print_flags)
{int version;int fd;int clkid = CLOCK_MONOTONIC;struct pollfd *new_ufds;char **new_device_names;char name[80];char location[80];char idstr[80];struct input_id id;// 打开这个节点fd = open(device, O_RDONLY | O_CLOEXEC);if(fd < 0) {if(print_flags & PRINT_DEVICE_ERRORS)fprintf(stderr, "could not open %s, %s\n", device, strerror(errno));return -1;}// 获取相关的信息if(ioctl(fd, EVIOCGVERSION, &version)) {if(print_flags & PRINT_DEVICE_ERRORS)fprintf(stderr, "could not get driver version for %s, %s\n", device, strerror(errno));return -1;}if(ioctl(fd, EVIOCGID, &id)) {if(print_flags & PRINT_DEVICE_ERRORS)fprintf(stderr, "could not get driver id for %s, %s\n", device, strerror(errno));return -1;}name[sizeof(name) - 1] = '\0';location[sizeof(location) - 1] = '\0';idstr[sizeof(idstr) - 1] = '\0';if(ioctl(fd, EVIOCGNAME(sizeof(name) - 1), &name) < 1) {//fprintf(stderr, "could not get device name for %s, %s\n", device, strerror(errno));name[0] = '\0';}if(ioctl(fd, EVIOCGPHYS(sizeof(location) - 1), &location) < 1) {//fprintf(stderr, "could not get location for %s, %s\n", device, strerror(errno));location[0] = '\0';}if(ioctl(fd, EVIOCGUNIQ(sizeof(idstr) - 1), &idstr) < 1) {//fprintf(stderr, "could not get idstring for %s, %s\n", device, strerror(errno));idstr[0] = '\0';}if (ioctl(fd, EVIOCSCLOCKID, &clkid) != 0) {fprintf(stderr, "Can't enable monotonic clock reporting: %s\n", strerror(errno));// a non-fatal error}new_ufds = realloc(ufds, sizeof(ufds[0]) * (nfds + 1));if(new_ufds == NULL) {fprintf(stderr, "out of memory\n");return -1;}ufds = new_ufds;new_device_names = realloc(device_names, sizeof(device_names[0]) * (nfds + 1));if(new_device_names == NULL) {fprintf(stderr, "out of memory\n");return -1;}device_names = new_device_names;if(print_flags & PRINT_DEVICE)printf("add device %d: %s\n", nfds, device);if(print_flags & PRINT_DEVICE_INFO)printf(" bus: %04x\n"" vendor %04x\n"" product %04x\n"" version %04x\n",id.bustype, id.vendor, id.product, id.version);if(print_flags & PRINT_DEVICE_NAME)printf(" name: \"%s\"\n", name);if(print_flags & PRINT_DEVICE_INFO)printf(" location: \"%s\"\n"" id: \"%s\"\n", location, idstr);if(print_flags & PRINT_VERSION)printf(" version: %d.%d.%d\n",version >> 16, (version >> 8) & 0xff, version & 0xff);if(print_flags & PRINT_POSSIBLE_EVENTS) {print_possible_events(fd, print_flags);}if(print_flags & PRINT_INPUT_PROPS) {print_input_props(fd);}if(print_flags & PRINT_HID_DESCRIPTOR) {print_hid_descriptor(id.bustype, id.vendor, id.product);}// 将 fd 存放到ufds 数组中 ufds[nfds].fd = fd;ufds[nfds].events = POLLIN;// 放到 device_names 数组中device_names[nfds] = strdup(device);nfds++;return 0;
}
3.添加到poll 并做对应处理
添加完数组后,通过 poll 等待消息的监听。poll 和 epoll 是一样的。但是 epoll 更加高效。因为 epoll 是监听到消息 塞到 events 数组并返回 数量。后续遍历变化的即可。但是 poll 是无论如何都要遍历全部数组 找到对应的变化,没 epoll 高效。
当有新消息来后,则做对应的处理。数组第一个为文件夹 ,所以对文件夹做单独的处理。
通过 read_notify 方法。添加对应添加和删除,添加则调用 open_device,删除则调用 close_device 移除对应的监听。
因为第0个已处理,所以下面的遍历从下标1开始。遍历到变化时候, 通过 read 读取对应信息到 变量 event 中(input_event),最后根据设置的 falg 打印相对于的信息格式。
while(1) {//int pollres =// 通过 poll 等待消息的监听poll(ufds, nfds, -1);//printf("poll %d, returned %d\n", nfds, pollres);// 第1个是文件夹的变化,对文件夹内容的监听做单独的处理if(ufds[0].revents & POLLIN) {read_notify(device_path, ufds[0].fd, print_flags);}// 因为第0个已处理,所以下面的遍历从下标1开始for(i = 1; i < nfds; i++) {if(ufds[i].revents) {// 判断到有变化if(ufds[i].revents & POLLIN) {// 读取对应的内容到变量 event中,为 input_event 结构体res = read(ufds[i].fd, &event, sizeof(event));if(res < (int)sizeof(event)) {fprintf(stderr, "could not get event\n");return 1;}if(get_time) {printf("[%8ld.%06ld] ", event.time.tv_sec, event.time.tv_usec);}if(print_device)printf("%s: ", device_names[i]);// 传进去 值,根据 对应的 print_flags 做打印print_event(event.type, event.code, event.value, print_flags);if(sync_rate && event.type == 0 && event.code == 0) {int64_t now = event.time.tv_sec * 1000000LL + event.time.tv_usec;if(last_sync_time)printf(" rate %lld", 1000000LL / (now - last_sync_time));last_sync_time = now;}printf("%s", newline);if(event_count && --event_count == 0)return 0;}}}}
相关文章:
frameworks 之getEvent指令
frameworks 之getEvent指令 指令解析源码追溯源码解析1.解析参数2.初始化ufds数组3.添加到poll 并做对应处理 通过 getEvent 可以识别按键基本命令和里面的关键信息 涉及到的类如下 system/core/toolbox/toolbox.csystem/core/toolbox/tools.hsystem/core/toolbox/getevent.c …...
tensorboard显示一片空白解决方案
OK艾瑞巴蒂 不知道看这个视频几个小土堆过来的,今天已经发了一篇博文探讨快速下载tensorboard了 下面用的时候叒出现问题了 from torch.utils.tensorboard import SummaryWriter writer SummaryWriter("logs")# writer.add_image() # Yx for i in range…...
C#编程中,如何实现一个高效的数据排序算法?
在C#编程中,可以使用内置的排序方法来实现高效的数据排序。最常用的方法是使用Array.Sort()和List<T>.Sort()。这些方法内部使用了快速排序算法(Quick Sort),它是一种非常高效的排序算法,平均时间复杂度为O(n lo…...
LookupError: Resource averaged_perceptron_tagger not found.解决方案
大家好,我是爱编程的喵喵。双985硕士毕业,现担任全栈工程师一职,热衷于将数据思维应用到工作与生活中。从事机器学习以及相关的前后端开发工作。曾在阿里云、科大讯飞、CCF等比赛获得多次Top名次。现为CSDN博客专家、人工智能领域优质创作者。喜欢通过博客创作的方式对所学的…...
Leetcode JAVA刷刷站(39)组合总和
一、题目概述 二、思路方向 为了解决这个问题,我们可以使用回溯算法来找到所有可能的组合,使得组合中的数字之和等于目标数 target。因为数组中的元素可以无限制地重复选择,所以在回溯过程中,我们不需要跳过已经选择的元素&#x…...
Spring中AbstractAutowireCapableBeanFactory
AbstractAutowireCapableBeanFactory 是 Spring 框架中的一个抽象类,位于 org.springframework.beans.factory.support 包中。它实现了 AutowireCapableBeanFactory 接口,提供了一些通用的方法和逻辑,以支持 Spring 中的自动装配功能。 主要…...
PostgreSQL的walwriter和archiver进程区别
PostgreSQL的walwriter和archiver进程区别 在PostgreSQL中,walwriter和archiver进程是两个重要的后台进程,它们负责管理WAL(Write-Ahead Logging,预写日志)文件,但它们的职责和功能有所区别。理解这两个进…...
前端字体没有授权,字体版权检测(是否为方正字体)
1.截图系统中的首页和登录页面,主要是有字体的地方 2.在线字体版权检测地址:字体版权自动检测-求字体网 3.上传照片,开始对图片进行检测,每个账号有三次免费次数 4.检测完,直接查看检测报告即可, 报告中…...
在 SOCKS 和 HTTP 代理之间如何选择?
在 SOCKS 和 HTTP 代理之间进行选择需要彻底了解每种代理的工作原理以及它们传达的配置。只有这样,您才能轻松地在不同类型的代理之间进行选择。 本文概述了 HTTP 和 SOCKS 代理是什么、它们如何运作以及它们各自带来的好处。此外,我们将比较这两种代理类…...
C++适配windows和linux下网络编程TCP简单案例
C网络编程 网络协议是计算机网络中通信双方必须遵循的一套规则和约定,用于实现数据的传输、处理和控制。这些规则包括了数据格式、数据交换顺序、数据处理方式、错误检测和纠正等。网络协议是使不同类型的计算机和网络设备能够相互通信的基础,是网络通信…...
OpenDDS的GUID是如何构造的?
1、GUID、RepoID、GUID_t概念和关系 GUID(Global Unique IDentifiers)是RTPS规范约定的DDS对象的唯一性ID;RepoId(Repository IDentifiers)是Repo服务约定的DDS对象的唯一性ID;GUID和RepoId,都是基于GUID_t结构体定义,名称不同,但实质上是一样的。题外话: 无论是GUID还…...
初识MySQL(安装与配置环境)
嗨!今天我们进入一个新的领域---数据库。 首先来个小小铺垫。 我们平时存储东西的时候,一般用到文件。为什么有文件了,还继续要这个数据库呢? 很明显,文件有一些不好的地方,需要数据库来进行补充。 文件…...
druid+logback打印sql执行日志
druid 的LogFilter 为我们准备了四种logger类型,对应打印 datasource相关、connection相关、statement相关、resultset相关的日志。 druid.sql.Datasource:打印数据源相关的字段。 druid.sql.Connection:打印应用程序获得数据库连接的过程。…...
C++编程:无锁环形队列 (LockFreeRingQueue)的简单实现、测试和分析
文章目录 0. 概述1. 无锁环形队列概述1.1 无锁环形队列的特点1.2 无锁环形队列的优势与局限 2. LockFreeRingQueue 实现2.1 Enqueue 操作流程图2.2 Dequeue 操作流程图 3. 核心实现细节3.1 环形队列的大小调整3.2 索引计算3.3 原子操作与CAS3.4 线程让步 4. 测试示例程序4.1 实…...
植物生长时为什么会扭动?科学家解开令查尔斯·达尔文困惑的千古之谜
在一项新的研究中,来自美国和以色列的物理学家可能已经弄清了植物生长过程中的一种古怪行为–也是查尔斯-达尔文本人在其生命的最后几十年里所好奇的一个谜:对于许多人类来说,植物可能看起来静止不动,甚至有点无趣。但实际上&…...
SAP LE学习笔记02 - WM和库存管理(IM)之间的关系,保管Lot(Quant)
上一章学习了LE的基础知识。 1,LE的概述,LE里面包含下面3个大的模块 - LE-WM 仓库管理 / - LE-SHP 发货/ - LE-TRA 运输 2,仓库的结构 - 仓库番号 / -保管域Type(存储区域)/ - 保管区画(存储区)/ - 棚番(Storage Bin 仓位&…...
Span<T> 是 C# 7.2 引入的重要类型
Span<T> 是 C# 7.2 引入的一个非常重要的类型,它提供了一种低开销、类型安全的方式来操作连续的内存区域。Span<T> 本质上是一个结构体,它封装了一个内存段的引用(通过指针)以及该内存段的长度。由于它直接操作内存&a…...
Python办公自动化:初识 `openpyxl`
1.1 什么是 openpyxl? openpyxl 是一个用于读写 Excel 2010 xlsx/xlsm/xltx/xltm 文件的 Python 库。它允许我们通过 Python 脚本自动化处理 Excel 文件,包括创建新的工作簿、修改现有的工作簿、格式化单元格、处理公式和图表等功能。这对于办公自动化、…...
Pocketbase实战体验:内置数据库与实时功能如何超越传统MySQL
Pocketbase 是一个开源的实时后端服务器,内置了数据库、实时订阅、用户认证、RESTful API 等功能,而 MySQL 是一个广泛使用的关系数据库管理系统。以下是 Pocketbase 相对于 MySQL 的一些潜在优点: 完整的后端解决方案 一体化:P…...
ChatGPT 3.5/4.0 新手使用手册(详细版)
1. 什么是 ChatGPT? ChatGPT是由 OpenAI 开发的先进人工智能语言模型,能够理解并生成自然语言文本。它可以帮助你进行写作、回答问题、提供建议,甚至参与对话。ChatGPT 3.5 和 4.0 是两个不同版本,它们都拥有强大的语言处理能力&…...
【Java学习】Stream流详解
所属专栏:Java学习 Stream流是JDK 8引入的一个概念,它提供了一种高效且表达力强的方式来处理数据集合(如List、Set等)或数组。Stream API可以以声明性方式(指定做什么)来处理数据序列。流操作可以被分为两大…...
Oracle(69)什么是表压缩(Table Compression)?
表压缩(Table Compression)是一种数据库优化技术,用于减少表数据的存储空间和提高I/O性能。通过压缩表数据,可以显著减少存储需求,并在某些情况下提高查询性能,特别是对于只读或主要是读取操作的表。表压缩…...
java JUC编程
Java并发工具包(JUC),全称Java Util Concurrent,是Java提供的一个用于构建多线程应用程序的工具包,位于java.util.concurrent包及其子包中。 并发编程主要解决以下三个经典问题: 1. **原子性问题…...
vue3+element-plus表格分页选中加默认回显选中
1.需求 某个表单需要选择多条数据,点击选择按钮,弹框出来一个分页列表,选择多条数据,外面表单中显示选中的数据,可以删除数据,再次点击按钮,回显当前选中的数据。 2.解决办法 1.el-table加ro…...
Erupt 项目搭建
创建Spring Boot项目 Maven依赖 Spring Boot版本为 2.7.10,erupt版本为 1.12.14 erupt版本要与Spring Boot版本适配,3.x.x版本Spring Boot暂不适用说是 <properties><erupt.version>1.12.14</erupt.version></properties> <…...
HarmonyOS Next 系列之列表下拉刷新和触底加载更多数据实现(十一)
系列文章目录 HarmonyOS Next 系列之省市区弹窗选择器实现(一) HarmonyOS Next 系列之验证码输入组件实现(二) HarmonyOS Next 系列之底部标签栏TabBar实现(三) HarmonyOS Next 系列之HTTP请求封装和Token…...
比特位的计算
给你一个整数 n ,对于 0 < i < n 中的每个 i ,计算其二进制表示中 1 的个数 ,返回一个长度为 n 1 的数组 ans 作为答案。 示例 1: 输入:n 2 输出:[0,1,1] 解释: 0 --> 0 1 --> …...
SQLAlchemy 学习笔记
通信类型:AF_INET 协议家族一般是表示TCP通信的SOC_STREAM和UDP通信的SOCK_DGRAM。对于TCP通信,建立socket连接,: s socket.socket(socket.AF_INET, socket.SOCK_STREAM)连接socket, s.connect((host,port))socket通信…...
Linux内核分析(调度类和调度实体)
文章目录 前言一、调度类1. stop_sched_class2. dl_sched_class3. rt_sched_class4. fair_sched_class5. idle_sched_class总结 二、调度类中的操作函数三、调度实体 前言 调度是操作系统内核的一个关键职责,它涉及到如何合理分配CPU时间给不同的进程或线程。在Lin…...
用输入输出流(I/O)流,递归复制和删除多级文件
一、(I/O)流递归复制一个文件 第一种: else if语句过多,看起来冗余,优点:多级文件一次性复制完整 import java.io.*;//数据源:src/main/java/day15_8_13/haha //目标;src/main/java/LaJi pub…...
kafka监控工具EFAK
kafka监控工具(EFAK) 1、下载2、解压3、配置3.1、安装数据库,需要mysql是,并创建ke数据库3.2、修改配置文件 4、启动4.1、启动zookeeper4.2、启动kafka4.3、启动EFAK 5、访问http://ip:8048 github地址:https://github…...
Page与自定义Components生命周期
自定义组件 自定义组件一般可以用component,装饰,在结构体里面用build方法定义UI,或者用builder装饰一个方法,来作为自定义组件的构造方法 而页面page一般用Entry,和component结合起来使用 页面生命周期方法: onPageShow:页面每次显示时触发 onPageHid…...
Chain of Thought (CoT) 系列论文:大模型思维链,提升 LLM 的推理能力
文章目录 1. COT:Chain of Thought1. 研究背景2. CoT的原理3. CoT Prompt 1. COT:Chain of Thought COT 是 2022.01 由 google 提出的针对提升 LLM 的推理能力的 Prompt Engineering 方法。 paper: Chain-of-Thought Prompting Elicits Re…...
已解决:java.net.BindException: 地址已在使用
1. 问题描述 java.net.BindException: 地址已在使用 是一种常见的网络异常,通常在服务器程序尝试绑定到一个已经被占用的端口或地址时出现。具体的异常信息可能如下: java.net.BindException: Address already in use: JVM_Bind或 java.net.BindExcep…...
看书标记【数据科学:R语言实战 8】
看书标记——R语言 Chapter 8 数据可视化——绘图8.1 功能包8.2 散点图8.2.1 回归线8.2.2 lowess线条8.2.3 scatterplot函数8.2.4 Scatterplot矩阵1.splom——展示矩阵数据2.cpairs——绘图矩阵图 8.2.5 密度散点图 8.3 直方图和条形图8.3.1 条形图8.3.2 直方图 8.3.3 ggplot28…...
STM32标准库学习笔记-1.基础知识
STM32介绍: STM32是ST公司基于ARM Cortex-M内核开发的32位微控制器。 ARM的含义: 公司名称:ARM公司成立于1990年,全称是Advanced RISC Machines(RISC:Reduced Instruction Set Computer 精简指令集计算机 相对应有C…...
Nginx:高效HTTP服务器与反向代理
Nginx:高效HTTP服务器与反向代理 1、核心特点2、应用场景 💖The Begin💖点点关注,收藏不迷路💖 Nginx,一个开源的HTTP服务器与反向代理工具,因其高性能、低资源消耗而备受推崇。以下是Nginx的几…...
vue3二次封装element-puls
将表单的通用信息给设置出来 如: label 的提示信息 , type 的类型 // 定义表单的配置项 const formConfig{ formItems:[ { type:"input", label:"用户ID", placeholder:"请输入用户ID" } ] } 页面配置如 <template v-for"(it…...
在CentOS 7上安装Apache Tomcat 8的方法
前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站。 介绍 Apache Tomcat 是一个用于提供 Java 应用程序的 Web 服务器和 Servlet 容器。Tomcat 是由 Apache 软件基金会发布的 Java Servlet…...
深入理解分布式事务中的三阶段提交(3PC),什么是3PC,3PC原理是怎样?3PC的优化?
在上一篇文章中,我们详细介绍了分布式事务中的两阶段提交,以及知道了两阶段提交存在一定的问题 深入理解分布式事务中的两阶段提交(2PC),什么是2PC,2PC原理是怎样?2PC有没有什么问题࿱…...
这款新的 AI 工具会消灭 ChatGPT 吗?
随着大型语言模型 (LLM) 的出现,ChatGPT迅速成为全球计算机用户的家喻户晓的名字。这款由 OpenAI 设计的深度学习聊天机器人以知识宝库而闻名——一部互联网百科全书。 继ChatGPT的脚步之后,许多其他生成式AI工具也纷纷涌现。 2023 年 3 月,一…...
谷粒商城实战笔记-214~219-商城业务-认证服务-验证码防刷校验
文章目录 一,验证码防刷校验1,第三方服务提供发送短信的接口2,登录服务提供给前端的接口 二,215-商城业务-认证服务-一步一坑的注册页环境三,商城业务-认证服务-异常机制四,217-商城业务-认证服务-MD5&…...
在华为服务器的openEuler系统中适配Pytorch调用NPU
服务器架构:aarch64 yolov7 和 mindyolo 二选一即可,yolov7是基于pytorch,mindyolo是基于mindspore 本文档基于CANN8.0RC3 , 刚发布比较新,如果有问题,可将CANN版本降低 导读 资料首页:https://www.hiasce…...
MVCC工作原理深入解析
一、事务概述 mysql事务是指一组命令操作,在执行过程中用来保证要么全部成功,要么全部失败。事务是由引擎层面来支持的,MyISM引擎不支持事务,InnoDB引擎支持事务。 事务具有ACID四大特性 原子性(Atomicity࿰…...
使用html+css+js实现完整的登录注册页面
在这篇博客中,我们将讨论如何使用简单的 HTML 和 CSS 构建一个登录与注册页面。这个页面包含两个主要部分:登录界面和注册界面。我们还会展示如何通过 JavaScript 切换这两个部分的显示状态。 页面结构 我们将创建一个页面,其中包含两个主要…...
2024年8月16日(运维自动化 ansible)
一、回顾 1、mysql和python (1)mysql5.7 1.1不需要执行mysql_ssl_rsa_setup 1.2change_master_to 不需要get public key (2)可以使用pymysql非交互的管理mysql 2.1pymysql.connect(host,user,password,database,port) 2.2 cursorconn.cursor() 2.3 cursor.execute("creat…...
荣耀Magicbook x14 扩容1TB固态
版权归作者所有,如有转发,请注明文章出处:https://cyrus-studio.github.io/blog/ 固态硬盘规格 在官网查看加装固态硬盘的接口规格 https://www.honor.com/cn/laptops/honor-magicbook-x14-2023/ https://club.honor.com/cn/thread-2847379…...
Springboot整合全文检索引擎Lucene
文章目录 前言Lucene的介绍springboot项目中如何整合Lucene简单用法1. 引入依赖2. 其它用到的类2. 创建索引3. 简单搜索4. 更新索引5. 删除索引6. 删除全部索引 Springboot整合Lucene复杂搜索1. 同时标题和内容中查找关键词2. 搜索结果高亮显示关键词3. 分页搜索4. 多关键词联合…...
【深度学习】【语音】TTS, 如何使用Python分析WAV的采样率、比特深度、通道数
文章目录 使用Python分析WAV文件的属性与可视化简介所需环境代码解析可视化音频数据结论使用Python分析WAV文件的属性与可视化 WAV文件录音要求 为了确保录制的音频文件符合TTS模型训练的质量标准,请遵循以下录音要求: 采样率要求:44.1 kHz说明:采样率44.1 kHz(即每秒采样…...
Linux的安装和使用
Linux 第一节 Linux 优势 1. 开源 为什么这么多的的设备都选择使用 Linux?因为它是开源软件(open source software),具有不同的含义。使用一个安全的操作系统工作变得必不可少的事,而 Linux 恰好满足了这个需求。因…...