当前位置: 首页 > news >正文

网站建设可以买东西/网站制作公司有哪些

网站建设可以买东西,网站制作公司有哪些,网站上的广告怎么做,校园类网站模板免费下载目录 前言 项目特点及介绍 ① 简单易用 ② 软件可配置、易扩展 ③ 纯 C 语言编程 软件总框架 显示系统 1.数据结构抽象 disp_manager.h 2.Framebuffer编程 framebuffer.c 3.显示管理 disp_manager.c 4.单元测试 disp_test.c 顶层目录Makefile 顶层目录Makefil…

目录

前言

项目特点及介绍

① 简单易用

② 软件可配置、易扩展

③ 纯 C 语言编程

软件总框架

显示系统

1.数据结构抽象

disp_manager.h

2.Framebuffer编程

framebuffer.c

3.显示管理

disp_manager.c

4.单元测试

disp_test.c

顶层目录Makefile

顶层目录Makefile.build

底层目录display中的Makefile

底层目录unittest中的Makefile


前言

        今天开始学习Linux的第一个实战项目——电子产品量产测试与烧写工具,简称量产工具。这是一套软件,用在我们的实际生产中,有如下特点:


项目特点及介绍

① 简单易用

        把这套软件烧写在 SD 卡上,插到 IMX6ULL 板子里并启动,它就会自动测试各个模块、烧写 EMMC 系统。
        工人只要按照说明接入几个模块,就可以完成整个测试、烧写过程。
        测试结果一目了然:等 LCD 上所有模块的图标都变绿时,就表示测试通过。

② 软件可配置、易扩展

        通过配置文件添加测试项,可以添加不限个数的测试项。
        每个测试项有自己的测试程序,测试通过后把结果发送给 GUI 即可。各个测试程序互不影响。

③ 纯 C 语言编程

        下图是这个工具的界面,它可以一边测试一边烧写:

        上图中的 led、speaker 按钮,可以点击:
① 当你看到 LED 闪烁时,就点击 led 按钮,它变成绿色表示测试通过;
② 当你从耳机里听到声音时,就点击 speaker 按钮,它变成绿色表示测试通过。
        其他按钮无法点击,接上对应模块后会自动测试,测试通过时图标就会变绿。
        上图中的蓝色按钮表示烧写 EMMC 的进度,烧写成功后它也会变绿。
        LCD 上所有图标都变绿时,就表示测试、烧写全部完成;某项保持红色的话,就表示对应模块测试失败。

        对这个项目,我们要拆分出多个子系统,并且这些子系统与业务无关,以后还可以应用在其他项目上;我们编写各个子系统的代码时,要抽象出它的对外接口,增加它的扩展性,减少和其他模块的耦合性。通过这个项目,能锻炼我们面向对象的编程思想以及对事物的抽象能力等等。这个项目可以无限扩展,比如:


软件总框架

        要想最大程度复用我们写的代码,就需要模块化编程,拿显示系统举例,我们可以通过Framebuffer把数据显示到屏幕上,我们就可以构造出一个结构体,调用结构体里的初始化函数等等来使用这个模块;对于有些设备,它可能不需要用到屏幕,而是用到web输出,通过网络的方式显示数据,在网页打印出来,假设我们以后对于显示系统还要添加更多的模块,对于每个模块我们都要构造出它的结构体吗?显然是不用的,我们可以抽象出同一个结构体类型


显示系统

1.数据结构抽象

        来看看这个框图,我们要先获得一个buffer,我们可以自己在这个buffer里绘制我们想要的图案,绘制好后可以通过Framebuffer刷到屏幕上显示,也可以通过网络传输在浏览器上显示出来。

我们可以定义出下面这个结构体:

disp_manager.h

#ifndef _DISP_MANAGER_H
#define _DISP_MANAGER_H/*编译的时候报错说NULL未定义,我们干脆自己定义好了*/
#ifndef NULL
#define NULL (void *)0
#endif/*存放buffer的信息*/
typedef struct DispBuff {int iXres;/*x坐标的像素值*/int iYres;/*y坐标的像素值*/int iBpp;/*每个像素有多少位(像素的大小)*/char *buff;/*指向得到的buffer,然后就可以操作它了*/
}DispBuff, *PDispBuff;/*存放图像的区域信息*/
typedef struct Region {int iLeftUpX;/*区域左上角的x坐标*/int iLeftUpY;/*区域左上角的y坐标*/int iWidth;/*宽*/int iHeight;/*高*/
}Region, *PRegion;/*模块调用这个结构体里的函数,需要我们自己去实现里面的函数*/
typedef struct DispOpr {char *name;int (*DeviceInit)(void);//初始化函数int (*DeviceExit)(void);//退出函数int (*GetBuffer)(PDispBuff ptDispBuff);//获得buffer,以便绘制图像int (*FlushRegion)(PRegion ptRegion, PDispBuff ptDispBuff);//将buffer刷到对应的设备
(屏幕/网页),将ptDispBuff结构体指针指向的结构体里的buffer信息刷到Region结构体里(存放区域的信息)
表示你想在哪里显示?struct DispOpr *ptNext;//用链表管理这些模块
}DispOpr, *PDispOpr;/*****************************************/
/** 这些声明的函数我们后面再写,我先给出源码,先忽略这部分*/
void RegisterDisplay(PDispOpr ptDispOpr);void DisplayInit(void);
int SelectDefaultDisplay(char *name);
int InitDefaultDisplay(void);
int PutPixel(int x, int y, unsigned int dwColor);
int FlushDisplayRegion(PRegion ptRegion, PDispBuff ptDispBuff);
PDispBuff GetDisplayBuffer(void);#endif

这些结构体都是一步一步改善过来的,所以我尽量把注释写的详细一点,我们想要在屏幕或者网页(网页暂时没有实现)上显示,我们首先要实现 struct DispOpr 这个结构体里的各个函数,然后定义出各个模块的结构体,就可以调用定义出来的结构体里的函数实现各个功能。

2.Framebuffer编程

        对于Framebuffer编程不熟悉的同学可以去看我这篇博客Framebuffer应用编程,下面用到的函数都是直接复制之前写的代码,原理就不再讲解了。

framebuffer.c

        我们先定义出给LCD屏幕使用的结构体,再去实现底层的函数。以后上层APP就可以调用结构体里的 DeviceInit 等函数,不需要关心底层的驱动代码。这就是面向对象的编程思想。

源码如下:

#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <linux/fb.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <sys/ioctl.h>
#include <disp_manager.h>static int fd_fb;
static struct fb_var_screeninfo var;	/* Current var */
static int screen_size;
static unsigned char *fb_base;
static unsigned int line_width;
static unsigned int pixel_width;/*初始化函数*/
static int FbDeviceInit(void)
{/*打开设备结点,获得LCD参数等等*/fd_fb = open("/dev/fb0", O_RDWR);if (fd_fb < 0){printf("can't open /dev/fb0\n");return -1;}if (ioctl(fd_fb, FBIOGET_VSCREENINFO, &var)){printf("can't get var\n");return -1;}/*使用mmap函数获得可以直接操作LCD的buffer*/line_width  = var.xres * var.bits_per_pixel / 8;pixel_width = var.bits_per_pixel / 8;screen_size = var.xres * var.yres * var.bits_per_pixel / 8;fb_base = (unsigned char *)mmap(NULL , screen_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd_fb, 0);if (fb_base == (unsigned char *)-1){printf("can't mmap\n");return -1;}return 0;
}/*退出函数*/
static int FbDeviceExit(void)
{/*释放buffer,关闭设备结点*/munmap(fb_base, screen_size);close(fd_fb);return 0;
}/* 可以返回LCD的framebuffer, 以后上层APP可以直接操作LCD, 可以不用FbFlushRegion* 也可以malloc返回一块无关的buffer, 要使用FbFlushRegion*/
static int FbGetBuffer(PDispBuff ptDispBuff)
{ptDispBuff->iXres = var.xres;ptDispBuff->iYres = var.yres;ptDispBuff->iBpp  = var.bits_per_pixel;ptDispBuff->buff  = (char *)fb_base;return 0;
}/*为了方便,我们直接得到可以操作LCD的buffer,因此不需要Flush函数*/
static int FbFlushRegion(PRegion ptRegion, PDispBuff ptDispBuff)
{return 0;
}static DispOpr g_tFramebufferOpr = {.name        = "fb",.DeviceInit  = FbDeviceInit,.DeviceExit  = FbDeviceExit,.GetBuffer   = FbGetBuffer,.FlushRegion = FbFlushRegion,
};/*RegisterDisplay函数是将显示系统的所有设备注册到链表里统一管理,这在后面会讲,这里先忽略*/
void FramebufferInit(void)
{RegisterDisplay(&g_tFramebufferOpr);
}

        这里就是实现了底层的驱动函数,实现 DispOpr 结构里的函数。

3.显示管理

        我们的应用程序当然可以直接使用我们上面构造的结构体,但是我有多个显示模块,我们还需要一个公共的部分,来选择我们要使用的模块,所以需要还需要写出管理底层模块的代码。

框图如下:

        我们要写出 disp_manager.c 这个程序,它起到承上启下的作用,很多函数其实也只是调用最底层的代码,但是我们再经过一层封装,就非常方便的实现管理底层的模块 

disp_manager.c

#include <stdio.h>
#include <string.h>
#include <disp_manager.h>/* 管理底层的LCD、WEB */
static PDispOpr g_DispDevs = NULL;/*创建一个空的链表*/
static PDispOpr g_DispDefault = NULL;/*这个指针指向想要操作的模块,相当于句柄*/
static DispBuff g_tDispBuff;
static int line_width;
static int pixel_width;/*描点函数,是所有图像的基础,我之前写的Framebuffer应用编程里有讲*/
int PutPixel(int x, int y, unsigned int dwColor)
{unsigned char *pen_8 = (unsigned char *)(g_tDispBuff.buff+y*line_width+x*pixel_width);unsigned short *pen_16;	unsigned int *pen_32;	unsigned int red, green, blue;	pen_16 = (unsigned short *)pen_8;pen_32 = (unsigned int *)pen_8;switch (g_tDispBuff.iBpp){case 8:{*pen_8 = dwColor;break;}case 16:{/* 565 */red   = (dwColor >> 16) & 0xff;green = (dwColor >> 8) & 0xff;blue  = (dwColor >> 0) & 0xff;dwColor = ((red >> 3) << 11) | ((green >> 2) << 5) | (blue >> 3);*pen_16 = dwColor;break;}case 32:{*pen_32 = dwColor;break;}default:{printf("can't surport %dbpp\n", g_tDispBuff.iBpp);return -1;break;}}return 0;
}/*注册函数,把模块放进链表里统一管理*/
void RegisterDisplay(PDispOpr ptDispOpr)
{ptDispOpr->ptNext = g_DispDevs;g_DispDevs = ptDispOpr;
}/* 选择函数,传入想要操作的底层模块的名字,如"fb",表示使用Framebuffer在屏幕上显示* 遍历链表,如果模块注册进链表里并且找到了名字,g_DispDefault就会指向我们想操作的模块的结构体*/
int SelectDefaultDisplay(char *name)
{PDispOpr pTmp = g_DispDevs;while (pTmp) {if (strcmp(name, pTmp->name) == 0){g_DispDefault = pTmp;return 0;}pTmp = pTmp->ptNext;}return -1;
}/*初始化函数,其实就是调用底层的初始化*/
int InitDefaultDisplay(void)
{int ret;/*调用g_DispDefault指向的结构体,调用底层的模块初始化函数*/ret = g_DispDefault->DeviceInit();if (ret){printf("DeviceInit err\n");return -1;}/*获得buffer,参数会保存在传入的结构体里面*/ret = g_DispDefault->GetBuffer(&g_tDispBuff);if (ret){printf("GetBuffer err\n");return -1;}/*这两个参数是为了给描点函数用的,看描点函数第一行计算pen_8的地址,需要这两个参数*/line_width  = g_tDispBuff.iXres * g_tDispBuff.iBpp/8;pixel_width = g_tDispBuff.iBpp/8;return 0;
}/*把获得到的buffer返回给上层代码*/
PDispBuff GetDisplayBuffer(void)
{return &g_tDispBuff;
}/*Flush函数,底层的Flush函数我们并没有写,这里可以忽略*/
int FlushDisplayRegion(PRegion ptRegion, PDispBuff ptDispBuff)
{return g_DispDefault->FlushRegion(ptRegion, ptDispBuff);
}/*这里的初始化函数是将模块的结构体注册到链表里*/
void DisplayInit(void)
{extern void FramebufferInit(void);FramebufferInit();
}

虽然代码封装了很多层,但是这样便于以后添加更多的模块,更加容易扩展和移植。

4.单元测试

disp_test.c

#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <linux/fb.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <sys/ioctl.h>#include <disp_manager.h>#define FONTDATAMAX 4096
/*略*/

        需要自己定义点阵字体,这里我就省略了,可以看我关于Framebuffer的博客,或者去看韦东山老师的相关课程,里面有讲到哪里可以找到这个字体库。

/*********************************************************************** 函数名称: lcd_put_ascii* 功能描述: 在LCD指定位置上显示一个8*16的字符* 输入参数: x坐标,y坐标,ascii码* 输出参数: 无* 返 回 值: 无* 修改日期        版本号     修改人	      修改内容* -----------------------------------------------* 2020/05/12	     V1.0	  zh(angenao)	      创建***********************************************************************/ 
void lcd_put_ascii(int x, int y, unsigned char c)
{unsigned char *dots = (unsigned char *)&fontdata_8x16[c*16];int i, b;unsigned char byte;for (i = 0; i < 16; i++){byte = dots[i];for (b = 7; b >= 0; b--){if (byte & (1<<b)){/* show */PutPixel(x+7-b, y+i, 0xffffff); /* 白 */}else{/* hide */PutPixel(x+7-b, y+i, 0); /* 黑 */}}}
}int main(int argc, char **argv)
{Region region;PDispBuff ptBuffer;/*调用这个函数把所有模块注册到链表里(我们暂时只用到Framebuffer)*/DisplayInit();/*然后选择要操作的模块,传入名字*/SelectDefaultDisplay("fb");/*底层的初始化(打开设备节点等操作)*/InitDefaultDisplay();/*调用显示字符的函数,在这个函数里会调用的描点函数,所以我说描点函数是基础*/lcd_put_ascii(100, 100, 'A');/*这里是初始化一下要传入Flush函数的结构体*/region.iLeftUpX = 100;region.iLeftUpY = 100;region.iWidth   = 8;region.iHeigh   = 16;/*获得buffer*/ptBuffer = GetDisplayBuffer();/*刷到硬件上(暂时只有屏幕)*/FlushDisplayRegion(&region, ptBuffer);return 0;	
}

接下来给大伙看看函数的调用流程。

        多层函数的封装看起来会很乱,但如果看过我之前一篇博客UART开发基础,这篇博客也是我第一次接触这种面向对象的编程思想,像我之前写代码,也是直接APP调用底层函数,快准狠,但是如果以后工作,这种方法显然不可行,而且也锻炼不了什么事物抽象的能力,面对一些大型的项目可能会无从下手,但是这些结构体里的参数,也不是一下子就能想出来的,都是边写边补,缺啥补啥。

上传到Ubuntu时,要整个文件上传,如下:

        并且在要编译的文件夹下添加Makefile,可以看这篇博客Makefile保姆级教程

顶层目录Makefile

CROSS_COMPILE ?= 
AS        = $(CROSS_COMPILE)as
LD        = $(CROSS_COMPILE)ld
CC        = $(CROSS_COMPILE)gcc
CPP        = $(CC) -E
AR        = $(CROSS_COMPILE)ar
NM        = $(CROSS_COMPILE)nm
 
STRIP        = $(CROSS_COMPILE)strip
OBJCOPY        = $(CROSS_COMPILE)objcopy
OBJDUMP        = $(CROSS_COMPILE)objdump
 
export AS LD CC CPP AR NM
export STRIP OBJCOPY OBJDUMP
 
CFLAGS := -Wall -O2 -g
CFLAGS += -I $(shell pwd)/include
 
LDFLAGS := 
 
export CFLAGS LDFLAGS
 
TOPDIR := $(shell pwd)
export TOPDIR
 
TARGET := test
 
 
obj-y += display/
obj-y += unittest/
 
all : start_recursive_build $(TARGET)
    @echo $(TARGET) has been built!
 
start_recursive_build:
    make -C ./ -f $(TOPDIR)/Makefile.build
 
$(TARGET) : built-in.o
    $(CC) -o $(TARGET) built-in.o $(LDFLAGS)
 
clean:
    rm -f $(shell find -name "*.o")
    rm -f $(TARGET)
 
distclean:
    rm -f $(shell find -name "*.o")
    rm -f $(shell find -name "*.d")
    rm -f $(TARGET)

顶层目录Makefile.build

PHONY := __build
__build:
 
 
obj-y :=
subdir-y :=
EXTRA_CFLAGS :=
 
include Makefile
 
# obj-y := a.o b.o c/ d/
# $(filter %/, $(obj-y))   : c/ d/
# __subdir-y  : c d
# subdir-y    : c d
__subdir-y    := $(patsubst %/,%,$(filter %/, $(obj-y)))
subdir-y    += $(__subdir-y)
 
# c/built-in.o d/built-in.o
subdir_objs := $(foreach f,$(subdir-y),$(f)/built-in.o)
 
# a.o b.o
cur_objs := $(filter-out %/, $(obj-y))
dep_files := $(foreach f,$(cur_objs),.$(f).d)
dep_files := $(wildcard $(dep_files))
 
ifneq ($(dep_files),)
  include $(dep_files)
endif
 
 
PHONY += $(subdir-y)
 
 
__build : $(subdir-y) built-in.o
 
$(subdir-y):
    make -C $@ -f $(TOPDIR)/Makefile.build
 
built-in.o : $(cur_objs) $(subdir_objs)
    $(LD) -r -o $@ $^
 
dep_file = .$@.d
 
%.o : %.c
    $(CC) $(CFLAGS) $(EXTRA_CFLAGS) $(CFLAGS_$@) -Wp,-MD,$(dep_file) -c -o $@ $<
    
.PHONY : $(PHONY) 

底层目录display中的Makefile

EXTRA_CFLAGS  := 
CFLAGS_file.o := 
 
obj-y += disp_manager.o
obj-y += framebuffer.o 

底层目录unittest中的Makefile

EXTRA_CFLAGS  := 
CFLAGS_file.o := 
 
obj-y += disp_test.o 


        量产工具的第一篇博客就到此为止,下一篇是量产工具的输入系统,希望大伙多多关注支持。

相关文章:

Linux应用项目之量产工具(一)——显示系统

目录 前言 项目特点及介绍 ① 简单易用 ② 软件可配置、易扩展 ③ 纯 C 语言编程 软件总框架 显示系统 1.数据结构抽象 disp_manager.h 2.Framebuffer编程 framebuffer.c 3.显示管理 disp_manager.c 4.单元测试 disp_test.c 顶层目录Makefile 顶层目录Makefil…...

Python小白学习教程从入门到入坑------第二十九课 访问模式(语法进阶)

目录 一、访问模式 1.1 r 1.2 w 1.3 1.3.1 r 1.3.2 w 1.3.3 a 1.4 a 一、访问模式 模式可做操作若文件不存在是否覆盖r只能读报错-r可读可写报错是w只能写创建是w可读可写创建是a只能写创建否&#xff0c;追加写a可读可写创建否&#xff0c;追加写 1.1 r r&…...

使用 PageHelper 在 Spring Boot 项目中实现分页查询

目录 前言1. 项目环境配置1.1 添加 PageHelper 依赖1.2 数据库和 MyBatis 配置 2. 统一的分页响应类3. 使用 PageHelper 实现分页查询3.1 Service 层分页查询实现3.2 PageHelper 分页注意事项 4. 控制层调用示例5. 常见问题与解决方案5.1 java.util.ArrayList cannot be cast t…...

深度学习-张量相关

一. 张量的创建 张量简介 张量是pytorch的基本数据结构 张量&#xff0c;英文为Tensor&#xff0c;是机器学习的基本构建模块&#xff0c;是以数字方式表示数据的形式。 例如&#xff0c;图像可以表示为形状为 [3, 224, 224] 的张量&#xff0c;这意味着 [colour_channels, h…...

电脑提示xinput1_3.dll丢失怎么解决,分享6种有效的解决方法

xinput1_3.dll 是一个动态链接库&#xff08;DLL&#xff09;文件&#xff0c;它在Windows操作系统中扮演着重要的角色&#xff0c;特别是在处理游戏控制器和其他输入设备的交互方面。这个文件是Microsoft DirectX软件包的一部分&#xff0c;DirectX是微软公司开发的一个多媒体…...

【计网】数据链路层笔记

【计网】数据链路层 数据链路层概述 数据链路层在网络体系结构中所处的地位 链路、数据链路和帧 链路(Link)是指从一个节点到相邻节点的一段物理线路(有线或无线)&#xff0c;而中间没有任何其他的交换节点。 数据链路(Data Link)是基于链路的。当在一条链路上传送数据时&a…...

蓝牙FTP 协议详解及 Android 实现

文章目录 前言一、什么是蓝牙 FTP 协议&#xff1f;二、FTP 的工作流程1.蓝牙设备初始化2. 设备发现与配对3. 建立OBEX FTP 连接4. 文件传输文件上传&#xff08;通过OBEX PUT命令&#xff09;文件下载&#xff08;通过OBEX GET命令&#xff09; 5. 关闭OBEX会话 三、进阶应用与…...

【前端】Svelte:动画效果

在现代前端开发中&#xff0c;动画效果可以大大提升用户体验&#xff0c;使应用更生动、易用。Svelte 提供了灵活的动画 API&#xff0c;让开发者能够快速实现从简单过渡到复杂动画的各种效果。本文将系统性地介绍 Svelte 的动画功能&#xff0c;并通过多个示例演示如何创建动感…...

2024系统架构师--论基于架构的软件设计方法(ABSD)及应用(论文范文)

题目: 基于架构的软件设计(Architecture-Based Software Design,ABSD)方法以构成软件架构的商业、质量和功能需求等要素来驱动整个软件开发过程。ABSD是一个自顶向下,递归细化的软件开发方法,它以软件系统功能的分解为基础,通过选择架构风格实现质量和商业需求,并强调在架…...

ORU 的 Open RAN 管理平面 (M 平面)

[TOC](ORU 的 Open RAN 管理平面 (M 平面)) ORU 的 Open RAN 管理平面 (M 平面) https://www.techplayon.com/open-ran-management-plane-m-plane-for-open-radio-unit/ ORU M 平面 在 ORAN 中&#xff0c;设置参数的 O-RU 管理功能是通过 M-Plane 完成的。管理功能包括 O-…...

软件缺陷等级评定综述

1. 前言 正确评估软件缺陷等级&#xff0c;在项目的生命周期中有着重要的作用&#xff1a; 指导缺陷修复的优先级和资源分配 在软件开发和维护过程中&#xff0c;资源&#xff08;包括人力、时间和资金&#xff09;是有限的。通过明确缺陷的危险等级&#xff0c;可以帮助团队合…...

Nuxt.js 应用中的 schema:extend事件钩子详解

title: Nuxt.js 应用中的 schema:extend事件钩子详解 date: 2024/11/10 updated: 2024/11/10 author: cmdragon excerpt: schema:extend 钩子使开发者能够扩展默认数据模式,为特定业务需求添加自定义字段和验证。 categories: 前端开发tags: Nuxt钩子数据扩展自定义验证应…...

自然语言处理在客户服务中的应用

&#x1f493; 博客主页&#xff1a;瑕疵的CSDN主页 &#x1f4dd; Gitee主页&#xff1a;瑕疵的gitee主页 ⏩ 文章专栏&#xff1a;《热点资讯》 自然语言处理在客户服务中的应用 自然语言处理在客户服务中的应用 自然语言处理在客户服务中的应用 引言 自然语言处理概述 定义…...

OpenCoder:首个完全开源的顶级代码大模型,训练秘籍全公开!| LLM×MapReduce,无需训练就超越GPT-4!

大模型领域的发展日新月异&#xff0c;每天都有许多有趣的论文值得深入品读。下面是本期觉得比较有意思的论文&#xff1a; 1、OpenCoder&#xff1a;首个完全开源的顶级代码大模型&#xff0c;训练秘籍全公开&#xff01;2、超长文本处理新突破&#xff01;LLMMapReduce&…...

springboot静态资源映射不生效问题

最近有个同事问我&#xff0c;静态资源映射不生效的问题&#xff0c;很正常我想不就是配置下资源路径就可以了吗&#xff1f;类似配置如下代码 Configuration public class CorsConfig implements WebMvcConfigurer {Overridepublic void addResourceHandlers(ResourceHandlerR…...

通过 SSH 隧道将本地端口转发到远程主机

由于服务器防火墙,只开放了22端口,想要通过5901访问服务器上的远程桌面,可以通过下面的方式进行隧道转发。 一、示例命令 这条代码的作用是通过 SSH 创建一个 本地端口转发,将你本地的端口(5901)通过加密的 SSH 隧道连接到远程服务器上的端口(5901)。这种方式通常用于在…...

【北京迅为】itop-3588开发板摄像头使用手册Android12 双摄方案

本章节对应资料在网盘资料“iTOP-3588 开发板\02_【iTOP-RK3588 开发板】开发资料 \07_Android 系统开发配套资料\08_Android12 摄像头使用配套资料”目录下下载。 2.1 Android12 前摄后摄 网盘中默认的 Android12 源码支持四个摄像头单独打开&#xff0c;本小节我们来修改源码…...

初见Linux:基础开发工具

前言&#xff1a; 这篇文章我们将讲述Linux的基本开发工具&#xff0c;以及讨论Linux的生态圈&#xff0c;最后再了解vim开发工具。 Yum&#xff1a; YUM&#xff08;Yellowdog Updater Modified&#xff09;是一个在Linux系统中用于管理软件包的工具&#xff0c;特别是在基于…...

微服务架构面试内容整理-分布式配置管理-Nacos Config

Nacos Config 是 Nacos 提供的一个配置管理功能,专门用于动态管理应用的配置。在微服务架构中,Nacos Config 允许开发者集中管理和动态更新各个服务的配置,从而提升系统的灵活性和可维护性。以下是 Nacos Config 的主要特点、工作原理和使用场景: 主要特点 1. 动态配置管理…...

React官网生成Recat项目的区别

1. Next.js 特点&#xff1a; 页面级路由&#xff1a;使用文件系统路由&#xff0c;基于 /pages 文件夹的结构自动创建 URL 路径。渲染模式&#xff1a;支持三种渲染模式&#xff1a;静态生成 (SSG)、服务器端渲染 (SSR) 和客户端渲染 (CSR)&#xff0c;并允许根据页面的具体需…...

网络安全---安全见闻

网络安全—安全见闻 拓宽视野不仅能够丰富我们的知识体系&#xff0c;也是自我提升和深造学习的重要途径&#xff01;&#xff01;&#xff01; Web程序(网站) web站点、app都属于Web程序 二进制程序 与逆向分析挂钩 驱动程序 驱动程序也属于软件&#xff0c;以Windows系统…...

在 CSS 中,gap 是 布局容器(flex 或 grid)的属性。它用于设置容器内子元素之间的间距。

在 CSS 中&#xff0c;gap 是 布局容器&#xff08;flex 或 grid&#xff09;的属性。它用于设置容器内子元素之间的间距。以下是 gap 属性在不同布局中的应用&#xff1a; 1. 在 CSS Grid 布局中 gap 定义了网格行和列之间的间距。可以分别使用 row-gap 和 column-gap 设置行…...

[zotero]Ubuntu搭建WebDAV网盘

搭建Ubuntu Apache WebDAV网盘的综合步骤&#xff0c;使用666端口&#xff1a; 安装Apache和WebDAV模块&#xff1a; sudo apt update sudo apt install apache2 sudo a2enmod dav sudo a2enmod dav_fs创建WebDAV目录&#xff1a; sudo mkdir /var/www/webdav sudo chown www-d…...

力扣17-电话号码的数字组合

力扣17-电话号码的数字组合 思路代码 题目链接 思路 原题&#xff1a; 给定一个仅包含数字 2-9 的字符串&#xff0c;返回所有它能表示的字母组合。答案可以按 任意顺序 返回。 给出数字到字母的映射如下&#xff08;与电话按键相同&#xff09;。注意 1 不对应任何字母。 输…...

如何处理模型的过拟合和欠拟合问题

好久没有写人工智能这块的东西了&#xff0c;今天正好在家休息&#xff0c;给大家分享一下最近在训练时遇到的过拟合和欠拟合的问题&#xff0c;经过仔细的思考&#xff0c;总结如下&#xff1a; 在处理模型的过拟合和欠拟合问题时&#xff0c;我们需要根据具体情况采取不同的…...

CSRF详解

CSRF&#xff0c;全称是Cross-Site Request Forgery&#xff0c;即跨站请求伪造&#xff0c;也被称为“one click attack”或者session riding&#xff0c;是一种网络攻击方式。它允许攻击者诱导用户在已登录的Web应用程序上执行非预期的操作。 工作原理CSRF攻击通常涉及三个主…...

C# winform 的数据采集,采集周期是间隔10ms、100ms等等,但始终都有1ms的误差,并不是精准的10ms,哪些原因呢

C# winform 的数据采集&#xff0c;采集周期是间隔10ms、100ms等等&#xff0c;但始终都有1ms的误差&#xff0c;并不是精准的10ms&#xff0c;哪些原因呢 在C# WinForms应用程序中进行数据采集时&#xff0c;如果遇到采集周期存在1ms误差的问题&#xff0c;可能的原因包括&am…...

【国内中间件厂商排名及四大中间件对比分析】

国内中间件厂商排名 随着新兴技术的涌入&#xff0c;一批国产中间件厂商破土而出&#xff0c;并在短时间内迅速发展&#xff0c;我国中间件市场迎来洗牌&#xff0c;根据市占率&#xff0c;当前我国中间件厂商排名依次为&#xff1a;东方通、宝兰德、中创股份、金蝶天燕、普元…...

qt QLocale详解

1、概述 QLocale是Qt框架中的一个类&#xff0c;用于处理与本地化相关的操作。它能够方便地实现日期、时间、数字和货币的格式化和解析&#xff0c;支持不同的语言、区域设置和字符集。QLocale提供了一种跨平台的方式来获取当前系统的语言设置&#xff0c;并返回该语言的本地化…...

Node.js简介以及安装部署 (基础介绍 一)

Node.js简介 Node.js是运行在服务端的JavaScript。 Node.js是一个基于Chrome JavaScript运行时建立的一个平台。 Node.js是一个事件驱动I/O服务端JavaScript环境&#xff0c;基于Google的V8引擎&#xff0c;V8引擎执行Javascript的速度非常快&#xff0c;性能非常好。 Node.…...