16. 输入设备应用编程

news2024/12/23 9:42:34

16. 输入设备应用编程

  • 1. 输入类设备编程介绍
    • 1.1 什么是输入设备
    • 1.2 input 子系统
    • 1.3 读取数据的流程
    • 1.4 应用程序如何解析数据
  • 2. 读取 struct input_event 数据
  • 3. 按键应用编程
  • 4. 触摸屏应用编程
    • 4.1 解析触摸屏设备上报的数据
      • 4.1.1 单点触摸设备——事件上报顺序
      • 4.1.2 多点触摸设备——事件上报顺序
        • 4.1.2.1 TypeB 协议
        • 4.1.2.2 触摸屏上报数据分析
    • 4.2 获取触摸屏的信息
    • 4.3 单点触摸应用程序——获取一个触摸点的坐标
    • 4.4 多点触摸应用程序

1. 输入类设备编程介绍

1.1 什么是输入设备

常见的输入设备有鼠标、键盘、触摸屏、遥控器等,用户通过输入设备与系统进行交互。

1.2 input 子系统

Linux 为了管理这些输入设备,实现了一套能够兼容所有输入设备的框架,这个框架就是 input 子系统,可以屏蔽硬件的差异,向应用层提供一套统一的接口。基于子系统注册成功的输入设备,都会在 /dev/input 目录下生成对应的设备节点,名称通常为 eventX,通过读取这些设备节点可以获取输入设备上报的数据。

1.3 读取数据的流程

假设读取的设备对应的节点为 event0:

  1. 打开 /dev/input/event0 设备文件
  2. 发起读操作,如果没有数据可读则会进入休眠(阻塞 IO 情况下)
  3. 当有数据可读时,应用程序会被唤醒,读操作获取到数据返回
  4. 应用程序对读取到的数据进行解析

1.4 应用程序如何解析数据

每一次 read 操作获取的都是一个 struct input_event 结构体类型数据

struct input_event
{
	struct timeval time;
	__u16 type;
	__u16 code;
	__s32 value;
};

主要关注以下三个:

  • type: 用于描述发生了哪一中类型的事件,事件分类具体可以查看 <linux/input.h>头文件
  • code: 表示该类事件中的哪一个具体事件
  • value: 内核每次上报事件都会向应用层发送一个数据 value,对 value 值的解释随 code 变化而变化。

数据同步:
事件中有一个同步事件 EV_SYN,用于实现同步操作,告知接收者本轮上报的数据已经完整。应用程序读取输入设备上报的数据时,一次 read 只能读取一个 struct input_event 类型数据,但是如果读取触摸屏数据时,有横纵坐标,需要多次 read。内核将本轮需要上报、发送给接收者的数据全部上报完毕后,接着会上报一个同步事件,以告知应用程序本轮数据已经完整,可以进行同步了。同步事件也包含多种不同的事件:
在这里插入图片描述
所有的输入设备都需要上报同步事件,上报的同步事件通常是 SYN_REPORT,而 value 值通常为 0.

2. 读取 struct input_event 数据

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <fcntl.h>
#include <unistd.h>
#include <linux/input.h>

int main(int argc,char *argv[])	// 执行文件时需要传入参数,参数就是输入设备文件
{
	if(argc!=2)
	{
		fprintf(stderr,"usage:%s input-dev\n",argv[0]);
		return -1;
	}
	struct input_event in_ev={0};
	int fd=open(argv[1],O_RDONLY);
	for(;;)
	{
		// 循环读取数据
		if(sizeof(struct input_event)!=read(fd,&in_ev,sizeof(struct input_event)))
		{
			perror("read");
			return -1;
		}
		printf("type:%d code:%d value:%d\n",in_ev.type,in_ev.code,in_ev.value);
	}
}

3. 按键应用编程

获取按键状态,以字母 A 为例,上报 KEY_A 事件时,value=1;如果是松开,value=0;如果是长按,value=2

int main(int argc,char *argv[])
{
	if(argc!=2)
	{
		fprintf(stderr,"usage:%s input-dev\n",argv[0]);
		return -1;
	}
	struct input_event in_ev={0};
	int fd=open(argv[1],O_RDONLY);
	for(;;)
	{
		if(sizeof(struct input_event)!=read(fd, &in_ev, sizeof(struct input_event))) 
		{
			perror("read error");
			exit(-1);
		}
		if(EV_KEY == in_ev.type)
		{
			switch (in_ev.value) 
			{
				case 0:
					printf("code<%d>: 松开\n", in_ev.code);
					break;
				case 1:
					printf("code<%d>: 按下\n", in_ev.code);
					break;
				case 2:
					printf("code<%d>: 长按\n", in_ev.code);
					break;
			}
		}	
	}
}

4. 触摸屏应用编程

4.1 解析触摸屏设备上报的数据

触摸屏设备是一个绝对位移设备,可以上报绝对位移事件,绝对位移事件如下:
在这里插入图片描述
单点触摸和多点触摸:
单点触摸设备只支持单点触摸, 一轮完整的数据只包含一个触摸点信息;单点触摸设备以 ABS_XXX 事件承载、上报触摸点的信息,譬如 ABS_X(value 值对应的是 X 轴坐标值)、ABS_Y(value 值对应的是 Y 轴坐标值)等绝对位移事件,而有些设备可能还支持 Z 轴坐标(通过 ABS_Z 事件上报、 value 值对应的便是 Z 轴坐标值)、按压力大小(通过 ABS_PRESSURE 事件上报、 value 值对应的便是按压力大小) 以及接触面积等属性。 大部分的单点触摸设备都会上报 ABS_X 和 ABS_Y 事件,而其它绝对位移事件则根据具体的设备以及驱动的实现而定!
多点触摸设备可支持多点触摸,一轮完整的数据可能包含多个触摸点信息。 多点触摸设备则是以 ABS_MT_XXX(MT 是 Multi-touch, 意思为:多点触摸)事件承载、上报触摸点的信息,如 ABS_MT_POSITION_X(X 轴坐标)、ABS_MT_POSITION_Y(Y 轴坐标)等绝对位移事件。
触摸屏设备除了上报绝对位移事件之外,还可以上报按键类事件和同步类事件。同步事件很好理解,因为几乎每一个输入设备都会上报同步事件、告知应用层本轮数据是否完整;当手指点击触摸屏或手指从触摸屏离开时,此时就会上报按键类事件,用于描述按下触摸屏和松开触摸屏;具体的按键事件为 BTN_TOUCH(code=0x14a,也就是 330),当然,手指在触摸屏上滑动不会上报 BTN_TOUCH 事件。
Tips:BTN_TOUCH 事件不支持长按状态,故其 value 不会等于 2。 对于多点触摸设备来说,只有第一个点按下时上报 BTN_TOUCH 事件 value=1,当最后一个点离开触摸屏时上报 BTN_TOUCH 事件 value=0。

4.1.1 单点触摸设备——事件上报顺序

流程大致如下:

// 点击触摸屏时
BTN_TOUCH  // value=1
ABS_X
ABS_Y
SYN_REPORT

// 滑动
ABS_X
ABS_Y
SYN_REPORT

// 松开
BTN_TOUCH	// value=0
SYN_REPORT

4.1.2 多点触摸设备——事件上报顺序

在 Linux 内核中,多点触摸设备使用多点触摸协议(MT)上报各个触摸点的数据,MT 协议分为 TypeA 和 TypeB,前者几乎不用,介绍后一个。

4.1.2.1 TypeB 协议

该协议适用于能够追踪并区分触摸点的设备,是通过 ABS_MT_SLOT 事件上报各个触摸点信息的更新。这类设备通常在硬件上能够区分不同的触摸点,为每一个识别到的触摸点与一个 slot 进行关联,这个 slot 就是一个编号。底层驱动向应用层上报 ABS_MT_SLOT 事件,此事件会告诉接收者当前正在更新的是哪个触摸点的数据,ABS_MT_SLOT 事件中对应的 value 数据存放的便是一个 slot,以告知应用层当前正在更新 slot 关联的触摸点对应的信息。
每个识别出来的触摸点分配一个 slot,与该 slot 关联起来,利用这个 slot 来传递对应触点的变化。除了 ABS_MT_SLOT 事件之外,TypeB 协议还会使用到 ABS_MT_TRACTKING_ID 事件,用于触摸点的创建、替换和销毁工作,携带的 value 表示一个 ID,如果是非负数,表示一个有效的触摸点,如果是 -1,表示该触摸点已经不存在,如果是一个以前不存在的 ID 表示这是一个新的触摸点。
该协议可以减少发送到用户空间的数据,只有发生了变更的数据才会上报。

4.1.2.2 触摸屏上报数据分析

使用命令cat /proc/bus/input/devices确定触摸屏对应的设备节点。点击后先不要松开
在这里插入图片描述
首先第一行上报了绝对位移事件 EV_ABS(type=3)中的 ABS_MT_TRACKING_ID(code=57)事件,并且 value 值等于 78,也就是 ID,这个 ID 是一个非负数,所以表示这是一个新的触摸点被创建,也就意味着触摸屏上产生了一个新的触摸点(手指按下) 。
第二行上报了绝对位移事件 EV_ABS(type=3)中的 ABS_MT_POSITION_X(code=53)事件,其 value对应的便是触摸点的 X 坐标;
第三行上报了 ABS_MT_POSITION_Y(code=54)事件,其 value 值对应的便是触摸点 Y 坐标,所以由此可知该触摸点的坐标为(372, 381)。
第四行上报了按键类事件 EV_KEY(type=1)中的 BTN_TOUCH(code=330),value 值等于 1,表示这是触摸屏上最先产生的触摸点(slot=0、也就是触摸点 0)
第五行和第六行分别上报了绝对位移事件 EV_ABS(type=3)中的 ABS_X(code=0)和 ABS_Y(code=1),其 value 分别对应的是触摸点的 X 坐标和 Y 坐标。多点触摸设备也会通过 ABS_X、 ABS_Y 事件上报触摸点的 X、 Y 坐标,但通常只有触摸点 0 支持,所以可以把多点触摸设备当成单点触摸设备来使用。
最后一行上报了同步类事件 EV_SYN(type=0)中的 SYN_REPORT(code=0)事件,表示此次触摸点的信息全部上报完毕。
在第一个触摸点的基础上,增加第二个触摸点,打印信息如下所示:
在这里插入图片描述
1~7 行不再解释,第八行上报了绝对位移事件 EV_ABS(type=3)中的 ABS_MT_SLOT 事件(code=47),表示目前要更新 slot=1 所关联的触摸点(也就是触摸点 1) 对应的信息。
第九行上报了绝对位移事件 EV_ABS(type=3)中的 ABS_MT_TRACKING_ID 事件(code=57),ID=79,这是之前没有出现过的 ID,表示这是一个新的触摸点。
第十、十一行分别上报了 ABS_MT_POSITION_X 和 ABS_MT_POSITION_Y 事件。
最后一行上报同步事件(type=0、 code=0) ,告知应用层数据完整。
当手指松开时,触摸点就会被销毁,上报 ABS_MT_TRACKING_ID 事件,并将 value 设置为 -1(ID)

4.2 获取触摸屏的信息

这里需要用到 ioctl() 函数

#include <sys/ioctl.h>
int ioctl(int fd,unsigned long request,...);

第二个参数在input.h头文件中 EVIOC 相关的宏中有定义,第三个参数则是根据第二个参数来确定。譬如获取设备名称:

char name[100];
ioctl(fd,EVIOCGNAME(sizeof(name)),name);

使用最多的是EVIOCGABS(abs),可以获取到触摸屏 slot 的取值范围,参数表示一个 ABS_XXX 绝对位移事件,譬如获取 slot 信息,第三个参数是 struct input_absinfo*

在这里插入图片描述
获取触摸屏支持的最大触摸点数

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <linux/input.h>

int main(int argc,char *argv[])
{
	if (2 != argc) 
	{
		fprintf(stderr, "usage: %s <input-dev>\n", argv[0]);
		return -1;
	}
	struct input_absinfo info;
	int fd=open(argv[1],O_RDONLY);
	ioctl(fd,EVIOCGABS(ABS_MT_SLOT),&info);
	int max_slots=info.maximum+1-info.minimum;
	printf("最大触摸点数: %d\n",max_slots);
	close(fd);
	return 0;
}

4.3 单点触摸应用程序——获取一个触摸点的坐标

int main(int argc,char *argv[])
{
	if (2 != argc) 
	{
		fprintf(stderr, "usage: %s <input-dev>\n", argv[0]);
		return -1;
	}
	struct input_event in_ev;
	int x=0,y=0;
	int down=-1; 	// 记录 BTN_TOUCH 事件的 value,1 表示按下,0 表示松开,-1 表示移动
	int valid=0;	// 记录数据是否有效,更新表示有效,1 表示有效,0 表示无效
	struct input_absinfo info;
	int fd=open(argv[1],O_RDONLY);
	for(;;)
	{
		if(sizeof(struct input_event) != read(fd,&in_ev,sizeof(struct input_event)))
		{
			perror("read");
			return -1;
		}
		switch(in_ev.type)
		{
			case EV_KEY:	// 按键事件
				if(BTN_TOUCH == in_ev.code)
				{
					down = in_ev.value;
					valid=1;
				}
				break;
			case EV_ABS: //绝对位移事件
				switch (in_ev.code)
				{
					case ABS_X: //X 坐标
						x = in_ev.value;
						valid = 1;
						break;
					case ABS_Y: //Y 坐标
						y = in_ev.value;
						valid = 1;
						break;
				}
				break;
			case EV_SYN: //同步事件
				if (SYN_REPORT == in_ev.code) 
				{
					if (valid) //判断是否有效
					{
						switch (down) //判断状态
						{
							case 1:
								printf("按下(%d, %d)\n", x, y);
								break;
							case 0:
								printf("松开\n");
								break;
							case -1:
								printf("移动(%d, %d)\n", x, y);
								break;
						}
						valid = 0; //重置 valid
						down = -1; //重置 down
					}
				}
				break;
		}
	}
}

4.4 多点触摸应用程序

// 描述 MT 多点触摸每一个触摸点的信息
struct ts_mt
{
	int x;
	int y;
	int id;		// 对应 ABS_MT_TRACKING_ID
	int valid;	// 数据有效标志位
};
// 触摸点的坐标
struct tp_xy
{
	int x;
	int y;
};
int ts_read(const int fd,const int max_slots,struct ts_mt *mt)
{
	struct input_event in_ev;
	static int slot = 0;
	static struct tp_xy xy[12]={0};
	int i;

	// 对缓冲区进行初始化
	memset(mt,0x0,max_slots *sizeof(struct ts_mt));
	for(i=0;i<max_slots;i++)
	{
		mt[i].id=-2;	// 初始化为 -2,-1 表示触摸点删除,id>=0 表示创建
	}
	for(;;)
	{
		read(fd,&in_ev,sizeof(struct input_event));
		
		switch(in_ev.type)
		{
			// 按键事件对单点触摸比较有用
			case EV_ABS: //绝对位移事件
				switch (in_ev.code)
				{
					case ABS_MT_SLOT: 
						slot = in_ev.value;
						break;
					case ABS_MT_POSITION_X: 
						xy[slot].x = in_ev.value;
						mt[slot].valid = 1;
						break;
					case ABS_MT_POSITION_Y: 
						xy[slot].y = in_ev.value;
						mt[slot].valid = 1;
						break;
					case ABS_MT_TRACKING_ID: 
						mt[slot].id = in_ev.value;
						mt[slot].valid = 1;
						break;
				}
				break;
			case EV_SYN: //同步事件
				if (SYN_REPORT == in_ev.code) 
				{
					for(i=0;i<max_slots;i++)
					{
						mt[i].x=xy[i].x;
						mt[i].y=xy[i].y;
					}
				}
				return 0;
		}
	}
}
int main(int argc, char *argv[])
{
	if (2 != argc) 
	{
		fprintf(stderr,"usage: %s <input_dev>\n", argv[0]);
		exit(EXIT_FAILURE);
	}
	struct input_absinfo slot;
	struct ts_mt *mt =NULL;
	int max_slots;
	int fd;
	int i;
	fd=open(argv[1],O_RDONLY);
	ioctl(fd,EVIOCGABS(ABS_MT_SLOT),&slot)
	max_slots=slot.maximum+1-slot.minimum;
	printf("max_slots:%d\n",max_slot);
	mt=calloc(max_slots,sizeof(struct ts_mt));
	// 读数据
	for(;;)
	{
		if(ts_read(fd,max_slots,mt)<0)
		{
			break;
		}
		for(i=0;i<max_slots;i++)
		{
			if(mt[i].valid)	// 判断每一个触摸点信息是否发生更新
			{
				if(mt[i].id>=0)
					printf("slot<%d>, 按下(%d, %d)\n", i, mt[i].x, mt[i].y);
				else if (-1 == mt[i].id)
					printf("slot<%d>, 松开\n", i);
				else
					printf("slot<%d>, 移动(%d, %d)\n", i, mt[i].x, mt[i].y);
			}
		}
	}
	close(fd);
	free(mt);
	return 0;
}

在单点触摸中,是通过BTN_TOUCH事件判断手指动作的,而多点触摸中,需要通过 id 来判断多个手指的动作。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1418690.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

ARL灯塔vps云服务器安装

前提是vps服务器已经安装好docker 1、下载压缩包到本地 2、解除不能扫描edu等域名的限制 解压docker_arl.zip&#xff0c;打开docker_arl/config-docker.yaml文件 删除掉edu.cn等限制域名(图中已删除) 3、上传至vps云服务器 将docker_arl文件上传到云服务器opt目录下 这里我…

【开源之美】:cppcheck

一、项目链接 https://github.com/danmar/cppcheck/tree/main 二、效果示例

STM32 E18-D80NK红外避障传感器

E18-D80NK-N是一款红外光电传感器&#xff0c;它同时具备发射和接收功能。通过对发射光进行调制后发出&#xff0c;并通过接收头对反射光进行解调输出。 E18-D80NK-N采用了透镜来增强传感器的性能&#xff0c;使其能够检测更远的距离。根据红外光的特性&#xff0c;不同颜色的…

如何将前后端分离(vue2+SpringBoot)项目部署到腾讯云服务器

如何将前后端分离&#xff08;vue2SpringBoot&#xff09;项目部署到腾讯云服务器 目录 如何将前后端分离&#xff08;vue2SpringBoot&#xff09;项目部署到腾讯云服务器 1、在选中目录地下新建2个文件夹 2、将打包好的前端项目和后端jar包上传到相应的目录下 3、将路径切…

基于Prompt Learning的信息抽取

PTR: Prompt Tuning with Rules for Text Classification 清华&#xff1b;liuzhiyuan&#xff1b;通过规则制定subpromptRelation Extraction as Open-book Examination: Retrieval-enhanced Prompt Tuning Relation Extraction as Open-book Examination: Retrieval-enhance…

R语言【taxlist】——print_name():为发表文章准备可用的格式化名称

Package taxlist version 0.2.4 Description 在撰写关于生物多样性的文章时&#xff0c;可以使用名称自动插入到文件中&#xff0c;包括学名不同元素的典型斜体格式。函数print_name既可以应用于 Markdown 文档&#xff0c;也可以应用于图形。在 Rmarkdown 文档中&#xff0c;…

解决方案—幻兽帕鲁Palworld私服部署 一杯茶的功夫搭建部署一个属于自己的游戏私服

《幻兽帕鲁》是Pocketpair开发的一款开放世界生存制作游戏 &#xff0c;游戏于2024年1月18日发行抢先体验版本&#xff0c;游戏中&#xff0c;玩家可以在广阔的世界中收集神奇的生物“帕鲁”&#xff0c;派他们进行战斗、建造、做农活&#xff0c;工业生产&#xff0c;游戏目前…

重磅福利!23篇AI-Agents智能代理必读论文!不容错过!

会议之眼 快讯 在数字化时代&#xff0c;AI已经成为各行各业的驱动力&#xff0c;推动科技和社会快速发展。AI-Agents被称为“AI代理”或“智能代理”&#xff0c;是一项前沿应用。它们具备自主感知、决策和执行任务的能力。通过分析传感器信息或用户指令&#xff0c;AI-Agents…

一键去除视频水印,让你的视频更完美

你是否曾经因为视频中的水印而烦恼&#xff1f;现在&#xff0c;有了我们的视频剪辑工具&#xff0c;你可以轻松去除视频中的水印&#xff0c;让你的视频更加完美&#xff01;这款工具采用先进的视频处理技术&#xff0c;能够一键批量去除水印&#xff0c;让你的视频更加干净整…

【JavaScript基础入门】03 JavaScript 基础语法(一)

JavaScript 基础语法&#xff08;一&#xff09; 目录 JavaScript 基础语法&#xff08;一&#xff09;1. JS 初体验2. JavaScript注释2.1 单行注释2.2 多行注释 3. JavaScript结束符4. JavaScript输入输出语句 1. JS 初体验 JS 有3种书写位置&#xff0c;分别为内联、内部和外…

TBTOOLS标记染色体上的gene

最近碰到个问题&#xff0c;如何在染色体上标记gene, 查了下发现了个windows工具&#xff1a;TBTOOLs &#xff0c; 有点意思&#xff0c;真是简洁高效。 话不多说&#xff0c;直接干。。 工具下载 直接在github 下载即可 https://github.com/CJ-Chen/TBtools-II&#xff0c;…

【Java程序设计】【C00177】基于SSM的IT论坛管理系统(论文+PPT)

基于SSM的IT论坛管理系统&#xff08;论文PPT&#xff09; 项目简介项目获取开发环境项目技术运行截图 项目简介 这是一个基于ssm的IT论坛管理系统 本系统分为前台系统、后台管理员、后台教师以及后台用户4个功能模块。 前台系统&#xff1a;当游客打开系统的网址后&#xff0…

JavaScript定义变量及赋值

定义变量及赋值 ☞ 定义变量,未赋值var 变量名; 默认值是undefined ☞ 定义变量,且赋值var 变量名 数据;☞ 总结:1. 一个变量一次只能保存一个值&#xff1b;2. 以最后一次赋值为准3. JS变量区分大小写变量命名规范 ☞ 规则 必须遵守的&#xff0c;不遵守的话 JS引擎 发…

平安银行广州分行:用有温度的金融服务,实现健康与财富双重守护

甄选优质权益&#xff0c;守护客户身心健康   2024年1月&#xff0c;平安银行广州分行成功举办两场心理疗愈工作坊活动&#xff0c;旨在助力客户们摆脱工作和生活的喧嚣繁忙&#xff0c;在平静的疗愈气氛中拥抱自我、感受内心的平和。在“律动心弦-音乐疗愈工作坊”活动中&am…

C语言王道第八周一题

Description 初始化顺序表&#xff08;顺序表中元素为整型&#xff09;&#xff0c;里边的元素是 1,2,3&#xff0c;然后通过 scanf 读取一个元素&#xff08;假如插入的是 6&#xff09;&#xff0c;插入到第 2 个位置&#xff0c;打印输出顺序表&#xff0c;每个 元素占 3 个…

堆和堆排序【数据结构】

目录 一、堆1. 堆的存储定义2. 初始化堆3. 销毁堆4. 堆的插入向上调整算法 5. 堆的删除向下调整算法 6. 获取堆顶数据7. 获取堆的数据个数8. 堆的判空 二、Gif演示三、 堆排序1. 堆排序(1) 建大堆(2) 排序 2.Topk问题 四、完整代码1.堆的代码Heap.cHeap.htest.c 2. 堆排序的代码…

RT-Thread: STM32 SPI使用流程

1.添加驱动 ①点开设置界面 ②勾选看门 SPI 驱动 ③点击保存 ④查看添加的驱动文件 drv_spi.c 2.打开驱动头文件定义 ①打开配置文件 ②打开定义 3.打开需要开启的SPI总线 打开 drivers 目录下的 board.h 用SPI搜索&#xff0c;找到如下文字&#xff0c;打开对应的宏。 /*-…

Windows 和 Anolis 通过 Docker 安装 Milvus 2.3.4

Windows 10 通过 Docker 安装 Milvus 2.3.4 一.Windows 安装 Docker二.Milvus 下载1.下载2.安装1.Windows 下安装&#xff08;指定好Docker文件目录&#xff09;2.Anolis下安装 三.数据库访问1.ATTU 客户端下载 一.Windows 安装 Docker Docker 下载 双击安装即可&#xff0c;安…

麒麟系统—— openKylin 安装 redis

麒麟系统—— openKylin 安装 redis 一、准备工作1. 确保麒麟系统 openKylin 已经安装完毕。 二、下载安装文件三、解压安装解压安装 四、配置与运行修改配置文件以配置文件运行 五、加入到服务中最终&#xff1a;介绍配置的其他参数使用 Redis是一种开源的、基于内存的高速缓存…

NodeJs环境安装与配置

最近电脑重装了系统&#xff0c;开发环境啥的都得重装&#xff0c;顺便记录下 nodeJs 的安装与配置&#xff0c;方便需要的同学查看&#xff0c;也方便自己以后查找。 安装 下载地址&#xff1a;https://nodejs.cn/download/ 根据需要选择自己环境需要的下载即可&#xff0c;…