QCustomplot

QCustomPlot是一个用于绘图和数据可视化的Qt C++小部件。它没有进一步的依赖性,并且有很好的文档记录。该绘图库专注于制作美观、出版质量的2D绘图、图形和图表,并为实时可视化应用程序提供高性能。查看设置和基本绘图教程以开始。 QCustomPlot可以导出为各种格式,如矢量化PDF文件和光栅化图像,如PNG、JPG和BMP。QCustomPlot是在应用程序中显示实时数据以及为其他媒体生成高质量绘图的解决方案。 eg1:一个简单的带填充的衰减正弦函数及其红色指数包络 // add two new graphs and set their look: customPlot->addGraph(); customPlot->graph(0)->setPen(QPen(Qt::blue)); // line color blue for first graph customPlot->graph(0)->setBrush(QBrush(QColor(0, 0, 255, 20))); // first graph will be filled with translucent blue customPlot->addGraph(); customPlot->graph(1)->setPen(QPen(Qt::red)); // line color red for second graph // generate some points of data (y0 for first, y1 for second graph): QVector<double> x(251), y0(251), y1(251); for (int i=0; i<251; ++i) { x[i] = i; y0[i] = qExp(-i/150.

2.基于正点原子STM32F103的定时器中断实验(HAL库实现)(cubeMX)

1.简介 1.定时器介绍 基本上每一款MCU都会配备定时器这个外设,STM32 的每个通用定时器都是完全独立的,没有互相共享的任何资源。 同样,STM32F1系列的定时器功能也很强大,包括: TIM1和TIM8两个高级定时器; TIM2~TIM5是个通用寄存器; TIM7,TIM8,两个基本定时器。 由于本次实验适用于新手入门,所以选用通用定时器来操作,其中对于基本定时器而言,最主要的功能就是利用定时器计数周期性的产生一个事件,这个事件可以进一步的触发DAC转换或者更新中断等。基本定时器的主体是一个计数器,计数器的计数脉冲来自它的内部时钟(通用/高级定时器的计数脉冲则可以来自多个不同的渠道,基本计数器一般采用向上计数模式。 2.实验目的 我们会控制定时器来产生一个更新中断,在更新中断的时候翻转LED,最后达到的效果就是LED以1Hz的频率闪烁,亮0.5s,熄0.5s。 3.硬件设计 1.指示灯D0:PB5-DS0 (低电平亮) 2.定时器TIM3 4.定时器的配置步骤 1.定时器时钟使能 2.初始化定时器参数,设置自动重装值,分频系数,计数方式等 3.使能定时器更新中断,使能定时器 4.定时器中断优先级设置 5.编写中断服务函数 2.STM32cubeMX配置 1.新建文件,芯片选型 选好之后点击Start Project,创建工程模板 2.sys设置和RCC设置 3.配置时钟 设置STM32的最高主频72MHz 4.定时器的参数计算与配置 1.定时器的参数计算 由于前面设置了分频系数为72MHz,我们要达成的效果是LED以1Hz的频率闪烁,所以我们要每500ms更新一个中断,所以可以设置分频系数为7200,自动重载值为5000。 因为72MHz/7200=10kHz,10kHz/5000=2Hz,由公式T=1/f,得到T=0.5s,就是更新一次中断的时间。 2.定时器的参数配置 编号1是预分频系数; 编号2是设置为向上计数模式; 编号3是自动重载值 编号4是开启自动重载 注意:这里为什么要设置成减1,因为我们的计数都是从0开始的。 别忘了使能中断! 5.配置GPIO 6.生成代码 3.定时器中断过程和keil5代码编写 定时器中断服务函数和外部中断服务函数有着类似的结构,也有公共处理程序,用来分析中断产生的原因,然后调用回调函数,所以最重要的也是找到HAL库里面的中断回调函数: __weak void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) 这个在stm32f1xx_hal_tim.c这个文件里面 所以接下来就要在回调函数里面编程 在main.c里面 MX_GPIO_Init(); MX_TIM3_Init(); /* USER CODE BEGIN 2 */ HAL_TIM_Base_Start_IT(&htim3); //启动定时器TIM3 /* USER CODE END 2 */ /* USER CODE BEGIN 4 */ void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)//更新中断回调函数 { if(htim->Instance==TIM3)//如果发生更新中断的是TIM3 { HAL_GPIO_TogglePin(GPIOB,GPIO_PIN_5);//翻转LED(DS0) } } /* USER CODE END 4 */ 利用串口下载软件Flymcu烧录到开发板上,按下复位键,这样就实现了上面所说的功能:

LambdaQueryWrapper构建查询条件

以下文章主要介绍 LambdaQueryWrapper构建查询条件、模糊查询、范围查询、排序 一、LambdaQueryWrapper是什么? LambdaQueryWrapper是mybatis plus中的一个条件构造器对象,只是是需要使用Lambda 语法使用 Wrapper 二、代码 public Page<Merchants> shopList(Query info) { LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>(); //单字段查询 queryWrapper.eq(User::getState, 0); queryWrapper.eq(User::getSmsType, 1); //不等于 queryWrapper.ne(User::getDietTypeId,0); // 模糊搜索条件 if (StringUtils.notEmpty(info.getKeyword())) { queryWrapper.and(c -> c.like(User::getMallName, info.getKeyword()) .or().like(User::getOwnerId, info.getKeyword()) .or().like(User::getOwnerName, info.getKeyword())); } // 时间范围查询 if (StringUtils.notEmpty(info.getCreateTimeStart()) && StringUtils.notEmpty(info.getCreateTimeEnd())) { queryWrapper.ge(User::getCreateTime, info.getCreateTimeStart()); queryWrapper.le(User::getCreateTime, info.getCreateTimeEnd()); } // 不为空 queryWrapper.isNotNull(User::getStartTime); // 排序条件 if (StringUtils.notEmpty(info.getSort()) && StringUtils.notEmpty(info.getOrder())) { // sort ---> "create_time" , order -> desc,asc queryWrapper.

java 数组字符串转数组,list集合(带泛型),二维数组,或者二维数组集合(带泛型)

java 数组字符串转数组,list集合(带泛型),二维数组,或者二维数组集合(带泛型) 2022-09-03 今天在开发时遇到需要将二维数组的字符串转换成二维数组,或者二维list集合 1. 二维数组字符串例子: [[262698, 262699, 262701], [262698, 262699, 262889], [262698, 262699, 263058]] 2. 二维数组字符串转二维数组: 代码如下: String str = "[[262698, 262699, 262701], [262698, 262699, 262889], [262698, 262699, 263058]]"; //二维数组字符串转二维数组 Integer[][] cityIds = JSON.parseObject(str, Integer[][].class); 结果: 其实不仅可以转换成对应的二维数组,如果遇到了带方括号的字符串(“[262698, 262699, 262701]”)转换成数组时,一样可以使用这样的方式,就不需要再对前后方括号进行处理后再按逗号分割。 代码如下: String str = "[262698, 262699, 262701]"; Integer[] integers = JSON.parseObject(str, Integer[].class); 结果: 3. 二维数组字符串转二维list集合 在使用时,突然发现我需要直接使用转换后的list集合,然后指定了泛型是无法指定class,所以需要加一段这个代码来进行指定:new TypeReference<List<List<Integer>>>() {}: 具体代码如下: String str = "[[262698, 262699, 262701], [262698, 262699, 262889], [262698, 262699, 263058]]"

Swin-Transformer(原理 + 代码)详解

参考博文 图解Swin Transformer Swin-Transformer网络结构详解 【机器学习】详解 Swin Transformer (SwinT) 论文下载 (二)代码的下载与配置 2.1、需要的安装包 官方源码下载 学习的话,请下载Image Classification的代码,配置相对简单,其他的配置会很麻烦。如下图所示: Install : pytorch安装:感觉pytorch > 1.4版本都没问题的。 2、pip install timm==0.3.2(最新版本也行) 1、pip install Apex win 10系统下安装NVIDIA apex 这个我认为windows安装可能会很啃。 1、首先在github下载源码https://github.com/NVIDIA/apex到本地文件夹 2、打开cmd命令窗口,切换到apex所在的文件夹 3、使用命令:python setup.py install 即可完成安装 注意事项: 可能会出现的问题: setuptools有ModuleNotFoundError→更新setuptools pip install --upgrade setuptools linux系统下安装NVIDIA apex git clone https://github.com/NVIDIA/apex cd apex pip install -v --no-cache-dir --global-option="--cpp_ext" --global-option="--cuda_ext" ./ 2.2、代码运行配置 注意:不要用ImageNet数据集:显卡可能会受不了,就是为了学习swin代码对吧,可以自己找一个小的ImageNet的数据集。 2.2.1、代码配置 首先运行main.py文件,如下图: 再点击main.py配置: 最后在下图Parameters处填入: --cfg configs/swin_tiny_patch4_window7_224.yaml --data-path imagenet --local_rank 0 --batch-size 2 2.

模拟电路设计(10)--- 运算放大器简介

运算放大器的内部结构 运放的种类很多,具体的实现电路也千差万别,但是基本结构都差不多如下图所示 运算放大器基本结构 图中差分放大级主要是提高共模抑制比,电压放大级主要是提高电压放大倍数,输出级用于提高输出功率。可以说,运算放大器是差分放大器的直接应用。 运算放大器原理图 如上图所示,是一个简单的运算放大器原理图。T1、T2组成了差分放大器,构成了运放的差分放大级;T3、T4组成复合管共射极电路,构成了运放的电压放大级;T5、T6组成了两级射极跟随器构成电路输出级,提高带负载能力。 差分式输入级原理图 如图是运算放大器第一级,即差动式输入级,是一个基本的差分放大电路,这一级是集成放大器的核心和基础部分。三极管T1、T2特性相同,电路参数也对称,如Rc1=Rc2等。两三极管发射极连接在一起串联一个恒流源。 当没有输入信号时,vs1=vs2=0,由于电路完全对称ic1=ic2,Rc1和Rc2两端的压降相同,那么输出信号vo=vc1-vc2=0。当输入信号vs1、vs2不相等时,vo则有信号电压输出。 运算放大器的指标定义 运算放大器的指标有很多,这里我们说一说几个在设计中较为常用的指标: 1. 输入偏置电流(Input bias current)Iib,运放输出电压为零时,两个输入端静态电流的平均值 2. 输入失调电流(Input offset current)Iio,运放输出电压为零时,两个输入端静态电流之差。 3. 输入失调电压(Input offset voltage)Vio,运放输入电压为零时,存在一定的输出电压,为了使这个输出电压为零,在室温(25℃)及标准电源电压下,在输入端加的补偿电压称为输入失调电压。在实践中,失调电压的偏置补偿非常困难,一方面是对于高放大倍数运放,很小的错误调节也会导致过补偿或欠补偿,另一方面偏置电压对温度的依赖性导致,温度变化,误差也会变化。 4. 最大上升速度,运放在闭环状态下,输入为大信号时,输出电压对时间的最大变化速度。 5. 输入、输出电阻,输入端共模电阻Rcm和差动电阻Rd。对于运算放大器的控制,Rd电阻上的电压降被放大,需要在设计中考虑。运放搭输入电阻在低频时较大,随着频率升高而减小,输出电阻随着频率升高成感性阻值增大。 6. 开环差模电压增益,由于运放电容影响与频率有关,数据手册中的数值仅适用于直流和低频放大。 7. 单位增益带宽和开环带宽,单位增益带宽是指运放在开环差模电压增益为0db时的频率,开环带宽则是开环差模电压增益下降到3db时的频率。这两个频率说明了开环增益的频率响应。 另外整理了一些电子工程类的资料,分享给大家,目前有模拟电路、单片机、C语言、PCB设计、电源系列、FPGA、EMC、物联网、Linux相关学习资料,还有针对大学生的资料包,后续还会有更多资料分享给大家,助力大家学习,成就梦想~ 博主福利:免费获取电子工程类学习资料https://mp.weixin.qq.com/mp/appmsgalbum?__biz=MzkzOTM5NTE0OQ==&action=getalbum&album_id=2532293941282209792#wechat_redirect

idea构建spring源码项目

成功的环境 : jdk1.8.0_271/idea2019.1.3/gradle-4.4.1-bin.zip/spring-framework1-5.0.x 特别感谢借鉴的另两位博主 IntelliJ IDEA导入Spring源码_VFINE的博客-CSDN博客_idea导入spring源码 spring源码构建_l梁晴的博客-CSDN博客 1.下载源代码 源码下载地址 GitHub - spring-projects/spring-framework: Spring Framework 不建议从这个地址直接下载,太慢,可以fork到国内的码云上再下载非常快, (源码下载可以在搜索引擎中搜索github,进入后搜索spring-framework即可找到) 也可以从这里下载,这个只需要安装并在idea中配置好gradle,就可以直接导入运行的,本地测试成功: 1294480-spring-framework1-5.0.x(3).zip-互联网文档类资源-CSDN下载 我是直接下载的压缩包 找到gradle-wrapper.properties配置文件(这里指定了默认的gradle版本,下载这个版本就可以了): 2.下载gradle解压后配置环境变量 下载地址: Gradle | Releases 环境变量配置方法 : Gradle安装及环境变量配置_iBaoxing的博客-CSDN博客 3.修改配置文件 gradle-wrapper.properties修改结果: distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists distributionUrl=file:///D:\myprogram\tools\gradle-4.4.1-bin.zip distributionUrl=https\://services.gradle.org/distributions/gradle-4.4.1-bin.zip 改为 distributionUrl=file:///D:\myprogram\tools\gradle-4.4.1-bin.zip 这样就不需要再次下载了 build.gradle修改 maven { url 'http://maven.aliyun.com/nexus/content/repositories/google' } maven { url 'http://maven.aliyun.com/nexus/content/groups/public/' } maven { url 'http://maven.aliyun.com/nexus/content/repositories/jcenter'} 新增以下配置(没有以下配置,构建过程超级慢……),定义全局的国内镜像,注意该配置不能在plugins { }之前 allprojects { repositories { maven { url 'http://maven.aliyun.com/nexus/content/repositories/google' } maven { url 'http://maven.

Nacos入门使用教程

Nacos介绍 Nacos /nɑ:kəʊs/ 是 Dynamic Naming and Configuration Service的首字母简称,一个更易于构建云原生应用的动态服务发现、配置管理和服务管理平台。 在这个介绍中,可以看出Nacos至少有三个核心功能: 动态服务发现配置管理服务管理 后续会分别来介绍这三个功能是怎么回事。 下载和解压 教程制作时,Nacos的最新发行版为2.1.1 (Aug 8th, 2022)(本教程就是基于这个版本),官方当前推荐的稳定版本为2.0.3。 查看最新Nacos发行版:https://github.com/alibaba/nacos/releases 并且可以在此网页上下载安装包: 下载完了之后进行解压,解压之后的目录为: bin目录下是启动和停止的脚本conf目录下是Nacos的配置文件target目录下是Nacos的jar包(启动脚本中其实就是运行的这个jar包,停止脚步中是直接kill到进程) 启动 解压完之后就可以启动Nacos了,Nacos支持单机和集群,默认是以集群模式启动,通过添加-m standalone就会以单机模式启动。 Linux/Unix/Mac 启动命令(standalone代表着单机模式运行,非集群模式): sh startup.sh -m standalone 如果您使用的是ubuntu系统,或者运行脚本报错提示[[符号找不到,可尝试如下运行: bash startup.sh -m standalone Windows 启动命令(standalone代表着单机模式运行,非集群模式): startup.cmd -m standalone 启动日志 可以发现,默认情况下Nacos占用了8848端口。 我们可以访问http://localhost:8848/nacos,来访问Nacos: 默认的用户名和密码为:nacos/nacos 登录进来后: 这个网页相当于nacos的管理台,有: 配置管理服务管理权限控制命名空间集群管理 配置管理 配置,其实就是一个key:value,比如 spring.datasource.username=zhouyu spring.datasource.password=123456 并且我们通常会把这些配置写在application.properties或application.yml文件中,当时通过这种方式一定配置发生了改变就需要重启应用,并且通过这种方式配置的配置项仅限于当前应用,而不能做到多个应用共享。 那么nacos的配置管理功能就是来解决这些问题的,我们可以直接通过nacos管理台来新增配置,并且这些配置能够被多个应用给使用到。 新建配置 新建配置时可以指定: Data ID:相当于一个配置文件,比如相当于application.properties,或者application-dev.properties,不过要注意的是,我们在某个项目中使用application.properties文件中,那个application表示的就是当前应用,那我们在nacos进行配置时,就要尽可能的取一些有含义的Data ID,比如user.properties(表示用户应用的配置),order.properties(表示订单应用的配置),common.properties(表示多个应用共享的配置)。Group:在nacos中,一个Data ID,也就是一个或多个配置文件可以归类到同一个Group中,Group的作用就是用来区分Data ID相同的情况,不同的应用或中间件使用了相同的Data ID时就可以通过Group来进行区分,默认为DEFAULT_GROUP配置内容:写具体的配置项,可以用properties的格式,也可以用yaml的格式 比如: 拉取配置 在nacos中新建完配置后,那作为一个SpringBoot应用我们如何来获取配置呢? Java SDK 首先,我们可以直接使用Nacos提供的Java SDK来获取配置。 首先在项目中,添加如下依赖:

猿创征文|Spring5梦开始的地方:入门必看

🛒本文收录与专栏:《Spring5》专栏 📢专栏目的是记录学习攻克难点,与各位一路同行,会持续输出,欢迎免费订阅!! ✨阅己,越己,悦己✨ 目录 🔎Spring51.下载Spring52.配置IDEA工具中Java工程2.2导入 Spring5 相关 jar 包 3.通过Spring创建对象3.1创建普通类及方法3.2创建Spring配置文件并配置 🔎Spring5 Spring框架是一个开放源代码的JavaEE应用程序框架,由Rod Johnson发起,是针对bean的生命周期进行管理的轻量级容器, Spring解决了开发者在J2EE开发中遇到的许多常见的问题,提供了功能强大IOC、AOP及Web MVC等功能。Spring可以单独应用于构筑应用程序,也可以和Struts、Webwork、Tapestry等众多Web框架组合使用,并且可以与Swing等桌面应用程序AP组合。因此, Spring不仅仅能应用于J2EE应用程序之中,也可以应用于桌面应用程序以及小应用程序之中。Spring框架主要由七部分组成,分别是 Spring Core、 Spring AOP、 Spring ORM、 Spring DAO、Spring Context、 Spring Web和 Spring Web MVC 1.下载Spring5 先带大家来下载最新的Spring Spring官网 >>> 🔎https://spring.io/ 第一次可能有点慢,耐心等待哦 进来之后,查看版本 GA意思是稳定的版本,咱们就下载一样的就行 直接给大家下载地址:https://repo.spring.io/ui/native/release/org/springframework/spring/ 点击对应版本,下载第一个就行 下载后解压 2.配置IDEA工具中Java工程 2.1 创建一个普通的Java工程,这个会吧哈哈 2.2导入 Spring5 相关 jar 包 在工程下新建一个文件夹用来放置需要的jar包 在刚解压好的文件夹中libs下找到这四个jar包复制进去 第一个jar包是关于注册表的2jar包,不导入的话会报错,学了Java的都有这个jar包,没有的也可以私信我 这五个是IOC的基本jar包,后面学习需要更多的话和下面步骤一样导入就行 Level是调控jar在全局下、项目下、模块下 当然导入ja包也可以通过project structure中添加依靠 3.通过Spring创建对象 3.1创建普通类及方法 在src下简单的新建普通类,并添加一个方法 3.2创建Spring配置文件并配置 在src文件夹下创建xml配置文件 配置文件xml中代码: <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.

Rabbitmq 简单介绍

文章目录 1. 消息队列介绍1.1 MQ解决什么问题1.2 常见消息队列及比较 2. Rabbitmq 安装2.1 服务端原生安装2.2 服务端 Docker 安装 3. python 操作 rabbitmq3.1 基本使用(生产者消费者模型)3.2 消息安全之 ack 4. 持久化5. 闲置消费 1. 消息队列介绍 消息队列就是基础数据结构中的“先进先出”的一种数据机构。例如生活中买东西,需要排队,先排的人先买消费,就是典型的“先进先出” 1.1 MQ解决什么问题 MQ是一直存在,不过随着微服务架构的流行,成了解决微服务之间问题的常用工具。 应用解耦 以电商应用为例,应用中有订单系统、库存系统、物流系统、支付系统。用户创建订单后,如果耦合调用库存系统、物流系统、支付系统,任何一个子系统出了故障,都会造成下单操作异常。 当转变成基于消息队列的方式后,系统间调用的问题会减少很多,比如物流系统因为发生故障,需要几分钟来修复。在这几分钟的时间里,物流系统要处理的内存被缓存在消息队列中,用户的下单操作可以正常完成。当物流系统恢复后,继续处理订单信息即可,中单用户感受不到物流系统的故障。提升系统的可用性 流量消峰 举个栗子,如果订单系统最多能处理一万次订单,这个处理能力应付正常时段的下单时绰绰有余,正常时段我们下单一秒后就能返回结果。但是在高峰期,如果有两万次下单操作系统是处理不了的,只能限制订单超过一万后不允许用户下单。 使用消息队列做缓冲,我们可以取消这个限制,把一秒内下的订单分散成一段时间来处理,这事有些用户可能在下单十几秒后才能收到下单成功的操作,但是比不能下单的体验要好。 消息分发 多个服务队数据感兴趣,只需要监听同一类消息即可处理。 例如A产生数据,B对数据感兴趣。如果没有消息的队列A每次处理完需要调用一下B服务。过了一段时间C对数据也感性,A就需要改代码,调用B服务,调用C服务。只要有服务需要,A服务都要改动代码。很不方便。 有了消息队列后,A只管发送一次消息,B对消息感兴趣,只需要监听消息。C感兴趣,C也去监听消息。A服务作为基础服务完全不需要有改动 异步消息 有些服务间调用是异步的,例如A调用B,B需要花费很长时间执行,但是A需要知道B什么时候可以执行完,以前一般有两种方式,A过一段时间去调用B的查询api查询。或者A提供一个callback api,B执行完之后调用api通知A服务。这两种方式都不是很优雅 使用消息总线,可以很方便解决这个问题,A调用B服务后,只需要监听B处理完成的消息,当B处理完成后,会发送一条消息给MQ,MQ会将此消息转发给A服务。 这样A服务既不用循环调用B的查询api,也不用提供callback api。同样B服务也不用做这些操作。A服务还能及时的得到异步处理成功的消息 1.2 常见消息队列及比较 Kafka在于分布式架构,RabbitMQ基于AMQP协议来实现,RocketMQ思路来源于kafka,改成了主从结构,在事务性可靠性方面做了优化。广泛来说,电商、金融等对事务性要求很高的,可以考虑RabbitMQ和RocketMQ,对性能要求高的可考虑Kafka 2. Rabbitmq 安装 官网:https://www.rabbitmq.com/getstarted.html 2.1 服务端原生安装 # 安装erlang yum -y install erlang # 安装 RabbitMQ yum -y install rabbitmq-server 2.2 服务端 Docker 安装 docker pull rabbitmq:management docker run -di --name Myrabbitmq -e RABBITMQ_DEFAULT_USER=admin -e RABBITMQ_DEFAULT_PASS=admin -p 15672:15672 -p 5672:5672 rabbitmq:management 启动后访问 15672 端口,如下所示

【Timm】搭建Vision Transformer系列实践,终于见面了,Timm库!

前言:工具用不好,万事都烦恼,原本真的就是很简单的一个思路实现,偏偏绕了一圈又一圈,今天就来认识认识Timm库吧! 目录 1.百度飞桨提供的-从零开始学视觉Transformer 2.资源:视觉Transformer优秀的开源工作 3.如何发现的Timm-Debug 4 Timm库 4.1 概念 4.2 Timm库的Vision Transformer活用 4.2.1 vision_transformer.py参数解读 4.2.2 Timm库的调用搭建Vision Transformer 目前,pytorch的知名度就不用说了,vision transformer的知名度,懂的都懂。其实,自己搭建vision transformer原本就是我的初衷,奈何资料根本就是无从下手,主要就是活用问题。今天,突然发现,也没想有想象中那么糟糕,从前人的实验中,还是由迹可寻的。 先放初步学习时候看的一些手把手搭建transformer框架理念和实践的资源: 1.百度飞桨提供的-从零开始学视觉Transformer 理论还是比较详细的,代码实践则是构建在百度子的paddle库上,与pytorch有所区别,但本意还是不变的。 课程:从零开始学视觉Transformer 实践地址:BR-IDL/PaddleViT: PaddleViT: State-of-the-art Visual Transformer and MLP Models for PaddlePaddle 2.0+ (github.com) Paddle-Pytorch API对应表:paddle pytorch 对照 2.资源:视觉Transformer优秀的开源工作 视觉 Transformer 优秀开源工作:timm 库 vision transformer 代码解读 python timm库-CSDN博客_python timm 3.如何发现的Timm-Debug 一直在尝试搭建自己的网络模型,却迟迟没有得到自己想要的效果,其实,挺痛苦的。究其原因还是复现前人的工作,复现了很多,但往往也没有深入解读,因为浮在表面,怎么可能去知晓他的真实意图呢?怎么知道他是怎么引用前人的经验呢?就开始了一遍又一遍的Debug,一个点一个点的突破学习,介于空降python的我,很多知识也开始积累起来了,果然,只要思想不滑坡,办法总比困难多! 本次就是科普timm库啦!这是我复现Debug所观察到作者进行Vision Transformer模块时,所进行的操作,根本就不是完全自己搭建哇!有现成的工具,加以整改就好!一切好像又变的美好了起来哈哈哈哈! ​ 4 Timm库 4.1 概念 Timm:pyTorImageModels,简单来说,就是PyTorch的库之一,也算是torchvision.models的扩展模块,面向CV的模型,主要以分类为主。同时,所有的模型都有默认的API。 Github:rwightman/pytorch-image-models: PyTorch image models, scripts, pretrained weights -- ResNet, ResNeXT, EfficientNet, EfficientNetV2, NFNet, Vision Transformer, MixNet, MobileNet-V3/V2, RegNet, DPN, CSPNet, and more (github.

linux awk命令的使用

awk介绍 1、概述 (1)awk是一种编程语言,主要用于在linux/unix下对文本和数据进行处理,是linux/unix下的一个工具。数据可以来自标准输入、一个或多个文件,或其它命令的输出。 (2)awk的处理文本和数据的方式:逐行扫描文件,默认从第一行到最后一行,寻找匹配的特定模式的行,并在这些行上进行你想要的操作。 (3)awk分别代表其作者姓氏的第一个字母。因为它的作者是三个人,分别是Alfred Aho、Brian Kernighan、Peter Weinberger。 gawk是awk的GNU版本,它提供了Bell实验室和GNU的一些扩展。 (4)下面介绍的awk是以GNU的gawk为例的,在linux系统中已把awk链接到gawk,所以下面全部以awk进行介绍。 2、awk的作用 (1)awk用来处理文件和数据的,是类unix下的一个工具,也是一种编程语言 (2)可以用来统计数据,比如网站的访问量,访问的IP量等等 (3)支持条件判断,支持for和while循环 awk使用方式 1、命令行模式使用 (1)语法结构 awk 选项 '命令部分' 文件名 特别说明:引用shell变量需用双引号引起 (2)常用选项介绍 -F 定义字段分割符号,默认的分隔符是空格 cut -d: -f1 -v 定义变量并赋值 (3)‘命令部分说明’ ① 正则表达式,地址定位 '/root/{awk语句}' sed中: '/root/p' 'NR==1,NR==5{awk语句}' sed中: '1,5p' '/^root/,/^ftp/{awk语句}' sed中:'/^root/,/^ftp/p' ② {awk语句1;awk语句2;…} '{print $0;print $1}' sed中:'p' 'NR==5{print $0}' sed中:'5p' 注:awk命令语句间用分号间隔 ③ BEGIN…END… 'BEGIN{awk语句};{处理中};END{awk语句}' 'BEGIN{awk语句};{处理中}' '{处理中};END{awk语句}' 2、脚本模式使用 (1)脚本编写 #!/bin/awk -f 定义魔法字符 以下是awk引号里的命令清单,不要用引号保护命令,多个命令用分号间隔 BEGIN{FS=":"} NR==1,NR==3{print $1"\t"$NF} ... (2)脚本执行 方法1: awk 选项 -f awk的脚本文件 要处理的文本文件 awk -f awk.

TCP滑动窗口、流量控制及拥塞控制详解

一、TCP滑动窗口 TCP虽然是面向字节流的,但是TCP传输的单元确实报文段。一个TCP报文段分为首部和数据部分。TCP首部前20个字节是固定的,后面有4N个字节是可选的。因此,TCP首部最小字节数是20个字节。 下面我们看下一TCP首部中几个重要的字段: 源端口 和 目的端口 各占两个字节序号,占4个字节。序号范围是[0,2^32-1],可以对4GB数据进行编号,到达最大值后,序号会重新从0开始。该序号指的是本报文段所发送数据的第一个字节的序号。确认号,占4个字节。期望收到对方数据报的第一个数据字节的序号。举例:假设B收到了A的一个报文,其序列号字段是301,数据长度是200字节,这表示B正确的收到了A发送的500序号为止的所有数据。因此,B期望收到的下一个数据的序号是501,于是B把在回复A的确认报文中的确认字段设置为501。确认ACK。当ACK字段为1时,确认号字段才有效。TCP规定,在连接建立后,传输的所有报文段的ACK都必须置1。同步SYN。在连接建立时用来同步序列,也就是三次握手的时候会用到。SYN=1,ACK=0,表示这是一个连接请求报文。若对方同一连接,则回复SYN=1,ACK=1。终止FIN。当FIN=1时,表示发送方数据已发送完毕,要求释放连接(四次挥手)。窗口,表示自己的接收窗口的大小。占两个字节,最大[0,2^32-1],也就是64K。选项。长度可变,最大40个字节。当没有使用选项是TCP,首部20占个字节。 1.1 什么是MSS?为什么要有MSS? 最大报文长度MSS(Maxium Segment Size),是每一个TCP报文段中数据字段的最大长度。而一个完整的 TCP报文段 = 数据字段 + 首部长度。 为什么要有MSS?因为TCP数据至少要添加20个字节的TCP首部和20个字节的IP首部,才能发送。所以,当发送的数据量少,如一个字节。那么网络的利用率就极低。如果数据太大,会在IP层进行分片。到接收端后还要重组。如果不幸,有数据丢失或者出错,还需要重新发送,导致开销增大。 1.2 随着因特网的发展,又陆续增加了几个选项 窗口扩大选项:互联网早期,窗口大小两个字节,最大64K够用。为了满足发展需要,新增窗口扩大选项,占3个字节。其中有一个字节表示表示移位值S。新的窗口大小位数从16位增加到(16+S),S最大14,故窗口最大值增加到[0,2^30-1]. 时间戳选项:占10个字节。其中主要时间戳字段和时间戳回送回答字段各占4字节。作用:(1)计算RTT;(2)用于处理序号超过2^32的情况。 选择确认选项:适用于,收到的报文段无差错,只是未按序号,中间还缺少某些序号的数据。选择确认就可以只让发送方发送这些缺少的数据,后面还会详细介绍。 二、TCP滑动窗口 Tcp的滑动窗口是以字节为单位的。 2.1 滑动窗口收发数据流程举例 现在假设发送方A收到了接收方B的确认报文,其中确认字段是31(表示31之前的数据都已收到,需要A从31开始发数据),窗口大小是20。A会根据这两个数据构造出自己的发送窗口,如下: 发送窗口:在没有收到B的确认情况下,A可以连续把窗口内的数据都发出去。发送窗口内的序号都是允许发送的序号。 现假设A又发送了31~41的数据,如下图: B此时的接受窗口如下: 此时,B虽然收到了32、33的分组,但是没有按序接收,所以B给出的确认只能还是31。 再假设,B按序接收到了31、32、33。B把接收窗口往后往前移动3个序号,同时给A发出确认报文,窗口值仍为20,但是确认号为34。A在收到确认报文后,将自己的发送窗口也往前移动3个序号,注意,B还收到了37 38 40三个分组的数据,但是没有按照顺序,所以先暂存在自己的接收窗口。 如下: 2.2 选择确认SACK原理 假设接收方收到若干不连续的报文段。序号1~ 1000收到了,但1000 ~ 1500没收到。序号1501~ 3000收到了,但30001~ 3500没收到。序号3501~4500又收到了。如果这些序号都在接受窗口内,接受方先收下这些数据,并把这些消息告诉发送方,让发送方不在发送重复数据。 我们可以看到,每个字节块都有左右两个边界,我们只需要告诉发送方这些边界信息,让其从指定序号开始传就达到我们的预期了。 但是,TCP首部没有哪个字段是来描述这些信息的。选择确认选项就派上用场了。如果要使用选择确认,就需要在TCP首部加上允许SACK选项。由于首部选项的长度只有40个字节,每个边界需要4个字节,所以,最多只能传递8个边界。为什么不是5个字节块(10个边界信息)呢?因为这40个字节,还要分出来两个字节,一个用来开启SACK;一个字节用来指出SACK选项占几个字节。 三、TCP流量控制 所谓流量控制就是控制发送方的发送速率,不要太快,让接收方来得及接收处理。利用滑动窗口就可以很方便的在TCP连接上实现对发送方的流量控制。 接收方每次收到数据后,在发送确认的报文的时候,同时告诉发送方自己的接收窗口的大小;发送方收到确认报文之后,就会调整自己的发送速率,也就是自己的发送窗口大小。当发送方收到win=0时,就会停止发送数据,同时开启一个定时器,每隔一段时间发送探测报文询问接收方是否有空间接受数据,如果收到win>0就发送数据;如果win=0,您先忙,我待会再来问问… 四、拥塞控制 拥塞控制就是防止过多的数据注入网络,导致网络过载。注意与流量控制的区别,流量控制一般是点对点的控制。而拥塞控制是一个全局性的过程,涉及所有的主机和路由器等待。 拥塞控制方法: 4.1 慢开始、拥塞避免 发送方维持一个拥塞窗口cwnd(congestion window)的状态变量。取决于网络拥塞程度,动态变化。发送发控制cwnd的原则:只要网络没出现拥塞就增大cwnd,出现了就减小。 4.1.1 发送方如何判断网络拥塞 当网络出现拥塞时,路由器就要丢弃分组。因此,如果发送方没有按时收到应该到达的确认报文,就认为网络出现拥塞。 4.1.2 算法原理 为方便描述,我们用报文个数作为窗口大小的单位,实际上单位是字节。慢开始的思路就是,刚开始将cwnd设置为一个MSS的数值,每经过一个传输轮次cwnd就加倍。 传输轮次:拥塞窗口所允许的发送的报文都连续发出去,且收到了对已发送的最后一个字节的确认。 因为是加倍(指数)增长,为了防止增长过度引起网络阻塞,还设置一个慢开始门限ssthresh。当cwnd超过ssthresh时,就改为拥塞避免算法,也就是线性缓慢增长。 无论是在慢开始还是拥塞避免阶段,只要发送方判断网络出现拥塞,就会把ssthresh设置为拥塞时发送窗口的一半,cwnd设置为1,重新执行慢开始算法。 4.2 快重传和快恢复 快重传算法要求接收方每收到一个失序的报文段,就立即发出重复确认,目的是使发送方及早知道有报文段丢失。如果发送方连续手动三次重复的确认就立即重传对方未收到的报文。 因为可以收到连续三个重复报文的确认,发送方不认为是网络出现了拥塞。使用快恢复算法。快恢复思路是:把cwnd设置为ssthresh的一半,然后开始拥塞避免算法。

分布式事务(三)———TCC 解决方案

分布式事务(三)———TCC 解决方案 一、TCC介绍二、TCC执行过程二、优缺点三、存在的三个问题1.空回滚2.悬挂3.幂等性 四、Seata-TCC实现 系列文章 该系列参考: https://www.jianshu.com/p/962271bbf4ea https://blog.csdn.net/a745233700/article/details/122402303 https://cloud.tencent.com/developer/article/2048776 https://icyfenix.cn/ 一、TCC介绍 TCC 是“Try-Confirm-Cancel”三个单词的缩写 最核心的思想:就是在应用层将一个完整的事务操作分为三个阶段。在某种程度上讲,TCC 是一种资源,实现了 Try、Confirm、Cancel 三个操作接口。与传统的两阶段提交协议不同的是,TCC 是一种在应用层实现的两阶段提交协议,在 TCC 分布式事务中,对每个业务操作都会分为 Try、Confirm 和 Cancel 三个阶段,每个阶段所关注的重点不同。 Try:尝试执行阶段,完成所有业务可执行性的检查(保障一致性),并且预留好全部需用到的业务资源(保障隔离性)。Confirm:确认执行阶段,不进行任何业务检查,直接使用 Try 阶段准备的资源来完成业务处理。Confirm 阶段可能会重复执行,因此本阶段所执行的操作需要具备幂等性。Cancel: 取消执行阶段,释放 Try 阶段预留的业务资源。Cancel 阶段可能会重复执行,也需要满足幂等性。 二、TCC执行过程 (来自凤凰架构) 最终用户向 Fenix’s Bookstore 发送交易请求:购买一本价值 100 元的《深入理解 Java 虚拟机》。创建事务,生成事务 ID,记录在活动日志中,进入 Try 阶段: 用户服务:检查业务可行性,可行的话,将该用户的 100 元设置为“冻结”状态,通知下一步进入 Confirm 阶段;不可行的话,通知下一步进入 Cancel 阶段。仓库服务:检查业务可行性,可行的话,将该仓库的 1 本《深入理解 Java 虚拟机》设置为“冻结”状态,通知下一步进入 Confirm 阶段;不可行的话,通知下一步进入 Cancel 阶段。商家服务:检查业务可行性,不需要冻结资源。 如果第 2 步所有业务均反馈业务可行,将活动日志中的状态记录为 Confirm,进入 Confirm 阶段: 用户服务:完成业务操作(扣减那被冻结的 100 元)。仓库服务:完成业务操作(标记那 1 本冻结的书为出库状态,扣减相应库存)。商家服务:完成业务操作(收款 100 元)。 第 3 步如果全部完成,事务宣告正常结束,如果第 3 步中任何一方出现异常,不论是业务异常或者网络异常,都将根据活动日志中的记录,重复执行该服务的 Confirm 操作,即进行最大努力交付。如果第 2 步有任意一方反馈业务不可行,或任意一方超时,将活动日志的状态记录为 Cancel,进入 Cancel 阶段: 用户服务:取消业务操作(释放被冻结的 100 元)。仓库服务:取消业务操作(释放被冻结的 1 本书)。商家服务:取消业务操作(大哭一场后安慰商家谋生不易)。 第 5 步如果全部完成,事务宣告以失败回滚结束,如果第 5 步中任何一方出现异常,不论是业务异常或者网络异常,都将根据活动日志中的记录,重复执行该服务的 Cancel 操作,即进行最大努力交付。 二、优缺点 优点: 整体过程类似2PC,但却是位于代码层面,有较高的灵活性,可以根据需要设计资源锁定粒度,具有很高的性能有较强的的隔离性 缺点: 代码侵入性强,开发成本高非强一致性,属于补偿事务,实现最终一致 三、存在的三个问题 1.

分布式事务(五)———可靠消息队列解决方案

分布式事务(五)———可靠消息队列解决方案 一、本地消息事务表1.核心思想2.流程步骤3.优缺点 二、RokcetMQ一.流程步骤二、优缺点及注意事项三、示例1.RokcetMq事务消息状态2.发送事务消息3.实现TransactionListener接口 三、最大努力通知系列文章 该系列参考: https://www.jianshu.com/p/962271bbf4ea https://blog.csdn.net/a745233700/article/details/122402303 https://cloud.tencent.com/developer/article/2048776 https://icyfenix.cn/ 本地消息事务、RocketMq、最大努力通知都是基于消息队列来实现的解决方案,所以我就放一起来介绍了 一、本地消息事务表 1.核心思想 将分布式事务拆分成本地事务进行处理,通过在分布式事务主动发起方额外新建事务消息表,事务发起方把业务处理和记录事务消息在本地事务中完成,轮询事务消息表发送事务消息,事务被动方基于消息中间件消费事务消息表中的事务消息 2.流程步骤 事务主动方在同一个本地事务中处理业务和写消息表操作 (消息表状态为待处理)事务主动方通过消息中间件通知事务被动方处理事务(此过程需要加定时任务,扫描消息表内状态为待处理的消息,重新发送消息)事务被动方收到消息,处理业务后,发送事务已处理的消息给事务主动方事务主动方收到消息后,将该条事务消息状态更新为已处理 过程分析: 假设步骤1 异常或宕机:消息跟业务处理的数据一起回滚了,啥事没发生假设步骤2 消息发送失败或者消息丢失:有定时任务,定时扫描消息表重复发送消息(保证消息一定发送成功)假设步骤3业务处理失败或者消息发送失败:业务数据会回滚(必要时需要人工介入),反馈消息丢失,会有步骤2的定时任务重复唤起假设步骤4更新失败:数据会回滚,依旧依赖定时任务的重复执行 直至成功 注意事项: 消息一定要带有唯一性事务ID两边的消息处理一定要具备幂等性一个事务涉及多个服务,就要有多个状态或者多条不同业务类型的消息整个过程过于依赖主动方的定时任务,可视情况优化上述过程保证了事务一定成功,如果某些场景允许回滚,步骤3处理失败也可以发起回滚消息,主动方收到消息回滚处理,并更新事务状态为已回滚即可,即无论是正向成功还是反向回滚,保持最终一致性即可 (该方案不太建议回滚处理,毕竟核心思想就是保证第一步业务成功,后续一定成功! 但是万事看业务场景嘛) 3.优缺点 优点: 简单实现,没有过度依赖中间件 缺点: 与具体的业务场景绑定,耦合性强,不可公用消息数据与业务数据同库,占用业务系统资源业务系统在使用关系型数据库的情况下,消息服务性能会受到关系型数据库并发性能的局限每个事务入口的业务系统都需要有消息表 特点: 柔性事务,数据最终一致性,最大努力交付思想 二、RokcetMQ 基于MQ的分布式事务方案本质上是对本地消息表的封装,整体流程与本地消息表一致,唯一不同的就是将本地消息表存在了MQ内部,而不是业务数据库中 一.流程步骤 服务主动方发送半消息给Broker,Broker返回ACK服务主动方收到Broker返回的ACK后提交本地事务根据本地事务的结果向Broker发送commit消息或者回滚消息Broker收到commit消息则会向消费端投递消息,如果是回滚消息则会清掉该事务消息,无事发生 过程分析: 步骤1失败:无事发生步骤2失败:事务回滚,并向broker发送rollback消息,broker清掉消息,无事发生步骤3消息发送失败或消息丢失(broker没收到消息):borker会回调checkLocalTransaction检查事务的结果(也有检测次数阈值),如果事务已经成功则Commit消息,如果失败则rollback消息,无事发生 (上图的5.6.7步骤)步骤4投递消息失败或者消费消息失败:会重试,RokcetMq的重试机制,达到默认次数则进死信队列,人工处理 二、优缺点及注意事项 优点: 业务系统和消息系统解耦,无需在新建消息表以及额外的定时处理,性能比消息表高 缺点: 额外的网络请求开销,要有额外的事务检查接口 注意事项: 要保证幂等性 三、示例 1.RokcetMq事务消息状态 TransactionStatus.CommitTransaction:提交事务,表示允许消费者消费该消息。TransactionStatus.RollbackTransaction:回滚事务,表示该消息将被删除,不允许消费。TransactionStatus.Unknown:中间状态,表示需要MQ回查才能确定状态。 2.发送事务消息 使用TransactionMQProducer类创建生产者客户端,并指定唯一的producerGroup,可以设置自定义线程池来处理检查请求。本地事务执行后,需要根据执行结果回复MQ public class TransactionProducer { public static void main(String[] args) throws MQClientException, InterruptedException { TransactionListener transactionListener = new TransactionListenerImpl(); TransactionMQProducer producer = new TransactionMQProducer("

C语言 - 三子棋(井字棋)

C语言 - 三子棋(井字棋) 目录 C语言 - 三子棋(井字棋)一、基本描述二、运行逻辑+代码实现Step 1 游戏菜单运行逻辑⇣代码实现⇣ Step 2 打印棋盘运行逻辑⇣代码实现⇣ Step 3 玩游戏运行逻辑⇣代码实现⇣ Step 4 判断游戏状态运行逻辑⇣ 三、运行结果结尾:完整源码 一、基本描述 三子成线为胜 二、运行逻辑+代码实现 Step 1 游戏菜单 运行逻辑⇣ 代码实现⇣ 🔔//test.c #include <stdio.h> void menu()//打印菜单 { printf("******1.开始游戏*******\n"); printf("**********************\n"); printf("******0.退出游戏*******\n"); printf("**********************\n"); } void game() { } int main() { int input = 0; do { menu(); printf("请选择:"); scanf("%d", &input); switch (input) { case 1: printf("\n游戏开始\n"); game();//游戏运行 printf("\n游戏结束\n"); break; case 0: printf("退出游戏"); break; default: printf("

Git笔记 从入门到精通

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言1. Git工作机制和托管中心1.1 工作机制1.2 托管中心 2. Git常用命令2.1 设置用户签名2.2 初始化本地库2.3 查看本地库状态2.4 添加到缓存区2.5 提交到本地库2.6 历史版本2.6.1 版本穿梭2.7 Git常用命令速查表 3. Git的分支操作4. GitHub操作GitHub网址远程仓库命令查看、创建别名SSH免密登录 5. IDEA 集成 Git5.1配置Git忽略文件5.2 定位Git程序5.3 初始化本地库5.4 添加到暂存区5.5 提交到本地库5.6 切换版本5.6.1 查看版本信息5.6.2 切换版本 5.7 创建分支5.8 切换分支5.9 合并分支5.10 解决冲突 总结 前言 Git是一个开源的分布式版本控制系统,可以有效高速的处理从很小到很大的项目版本管理。 1. Git工作机制和托管中心 1.1 工作机制 历史版本→本地库 ​ ↑ ​ git commmit ​ ↑ 暂时储存→暂存区 ​ ↑ ​ git add ​ ↑ 写代码 →工作区 1.2 托管中心 代码托管中心是基于网络服务器的远程代码仓库,一般我们简单称为远程库 局域网 GitLab 互联网 GitHub(外国网站) Gitee 码云(国内网站)

完全背包---java小知识

💬推荐一款模拟面试、刷题神器,从基础到大厂面试题👉点击跳转刷题网站进行注册学习 文章目录 前言一、完全背包是什么?二、解题技巧1.二维数组dp[][]代码2.一维数组 总结 前言 `背包问题分为:01背包,完全背包以及多重背包,本文主要讲解完全背包。 01背包以及01背包的优化讲解: 01背包:https://blog.csdn.net/m0_55486529/article/details/123806820 01背包优化:https://blog.csdn.net/m0_55486529/article/details/123831655 提示:以下是本篇文章正文内容,下面案例可供参考 一、完全背包是什么? 完全背包的物品数量是没有限制的,而01背包的物品个数为一,所以完全背包与01背包最大的区别就是物品数量不同。 二、解题技巧 题目:有5个物品,背包的容量为10。求放入背包的最大价值 01背包推导: 完全背包推导: 因为恰巧第一个重量小,且价值高,所以推导不明显,我们把第一个价值改为2.(仅仅为了展示推导过程更明显) 0-1背包状态转移方程: f[i][j]=max(f[i-1][j],f[i-1][j-w[i]]+v[i]) 完全背包状态转移方程: f[i][j]=max(f[i-1][j],f[i][j-w[i]]+v[i]) 为什么一个是i-1,一个是i呢? 因为01背包物品个数为一,假设此时推导第i个物品,我们以i-1行作为递推依据,那么我们可以保证第i个物品只放入一次,如果我们以第i行作为递推依据,那么我们是在前面放入过i物品的前提下放入物品(当i=1时,第一个物品,j=2时我们放入一个,此时价值为6,j=4时我们又放入一个是在前一个的基础之上,价值为12)。 1.二维数组dp[][]代码 代码如下(示例): public class test { public static void main(String[] args) { // TODO 自动生成的方法存根 int[] w= {2,5,4,2,3}; int[] v= {6,3,5,4,6}; System.out.println(bagkiller(w,v,10)); } public static int bagkiller(int[] w,int[] v,int n) { int [][] dp=new int[w.length+1][n+1]; for (int i=1;i<=w.length;i++) { for (int j=1;j<=n;j++) { if(j<w[i-1]) //装不下 dp[i][j]=dp[i-1][j]; //就等于i-1件物品容量等于j时候的价值 else dp[i][j]=Math.

程序员应了解的那些事(111)~进程、线程及堆栈关系

​进程在虚拟内存中的标准内存段布局​ 在多任务操作系统中,每个进程都运行在属于自己的内存沙盘中,这个沙盘就是虚拟地址空间(Virtual Address Space),在32位模式下它是一个4GB的内存地址块。在Linux系统中, 内核进程和用户进程所占的虚拟内存比例是1:3,而Windows系统为2:2(通过设置Large-Address-Aware Executables标志也可为1:3)。这并不意味着内核使用那么多物理内存,仅表示它可支配这部分地址空间,根据需要将其映射到物理内存。 虚拟地址通过页表(Page Table)映射到物理内存,页表由操作系统维护并被处理器引用。内核空间在页表中拥有较高特权级,因此用户态程序试图访问这些页时会导致一个页错误(page fault)。在Linux中,内核空间是持续存在的,并且在所有进程中都映射到同样的物理内存。内核代码和数据总是可寻址,随时准备处理中断和系统调用。与此相反,用户模式地址空间的映射随进程切换的发生而不断变化。 系统空间为所有进程共享,而用户空间是独立的。 Linux进程在虚拟内存中的标准内存段布局如下图所示: 其中,用户地址空间中的蓝色条带对应于映射到物理内存的不同内存段,灰白区域表示未映射的部分。这些段只是简单的内存地址范围,与Intel处理器的段没有关系。 上图中Random stack offset和Random mmap offset等随机值意在防止恶意程序。Linux通过对栈、内存映射段、堆的起始地址加上随机偏移量来打乱布局,以免恶意程序通过计算访问栈、库函数等地址。execve(2)负责为进程代码段和数据段建立映射,真正将代码段和数据段的内容读入内存是由系统的缺页异常处理程序按需完成的。另外,execve(2)还会将BSS段清零。 用户进程部分分段存储内容如下表所示(按地址递减顺序): 名称 存储内容 栈 局部变量、函数参数、返回地址等 堆 动态分配的内存 BSS段 未初始化或初值为0的全局变量和静态局部变量 数据段 已初始化且初值非0的全局变量和静态局部变量 代码段 可执行代码、字符串字面值、只读变量 在将应用程序加载到内存空间执行时,操作系统负责代码段、数据段和BSS段的加载,并在内存中为这些段分配空间。栈也由操作系统分配和管理;堆由程序员自己管理,即显式地申请和释放空间。 BSS段、数据段和代码段是可执行程序编译时的分段,运行时还需要栈和堆。 内核空间 内核总是驻留在内存中,是操作系统的一部分。内核空间为内核保留,不允许应用程序读写该区域的内容或直接调用内核代码定义的函数。 栈(stack) 栈又称堆栈,由编译器自动分配释放,行为类似数据结构中的栈(先进后出)。堆栈主要有三个用途: 为函数内部声明的非静态局部变量(C语言中称“自动变量”)提供存储空间。记录函数调用过程相关的维护性信息,称为栈帧(Stack Frame)或过程活动记录(Procedure Activation Record)。它包括函数返回地址,不适合装入寄存器的函数参数及一些寄存器值的保存。除递归调用外,堆栈并非必需。因为编译时可获知局部变量,参数和返回地址所需空间,并将其分配于BSS段。临时存储区,用于暂存长算术表达式部分计算结果或alloca()函数分配的栈内内存。 持续地重用栈空间有助于使活跃的栈内存保持在CPU缓存中,从而加速访问。进程中的每个线程都有属于自己的栈。向栈中不断压入数据时,若超出其容量就会耗尽栈对应的内存区域,从而触发一个页错误。此时若栈的大小低于堆栈最大值RLIMIT_STACK(通常是8M),则栈会动态增长,程序继续运行。映射的栈区扩展到所需大小后,不再收缩。 Linux中ulimit -s命令可查看和设置堆栈最大值,当程序使用的堆栈超过该值时, 发生栈溢出(Stack Overflow),程序收到一个段错误(Segmentation Fault)。注意,调高堆栈容量可能会增加内存开销和启动时间。 堆栈既可向下增长(向内存低地址)也可向上增长, 这依赖于具体的实现。本文所述堆栈向下增长。 堆栈的大小在运行时由内核动态调整。 内存映射段(mmap) 此处,内核将硬盘文件的内容直接映射到内存, 任何应用程序都可通过Linux的mmap()系统调用或Windows的CreateFileMapping()/MapViewOfFile()请求这种映射。内存映射是一种方便高效的文件I/O方式, 因而被用于装载动态共享库。用户也可创建匿名内存映射,该映射没有对应的文件, 可用于存放程序数据。在 Linux中,若通过malloc()请求一大块内存,C运行库将创建一个匿名内存映射,而不使用堆内存。”大块” 意味着比阈值 MMAP_THRESHOLD还大,缺省为128KB,可通过mallopt()调整。 该区域用于映射可执行文件用到的动态链接库。在Linux 2.4版本中,若可执行文件依赖共享库,则系统会为这些动态库在从0x40000000开始的地址分配相应空间,并在程序装载时将其载入到该空间。在Linux 2.6内核中,共享库的起始地址被往上移动至更靠近栈区的位置。 从进程地址空间的布局可以看到,在有共享库的情况下,留给堆的可用空间还有两处:一处是从.bss段到0x40000000,约不到1GB的空间;另一处是从共享库到栈之间的空间,约不到2GB。这两块空间大小取决于栈、共享库的大小和数量。这样来看,是否应用程序可申请的最大堆空间只有2GB?事实上,这与Linux内核版本有关。在上面给出的进程地址空间经典布局图中,共享库的装载地址为0x40000000,这实际上是Linux kernel 2.6版本之前的情况了,在2.6版本里,共享库的装载地址已经被挪到靠近栈的位置,即位于0xBFxxxxxx附近,因此,此时的堆范围就不会被共享库分割成2个“碎片”,故kernel 2.6的32位Linux系统中,malloc申请的最大内存理论值在2.9GB左右。 堆(heap) 堆用于存放进程运行时动态分配的内存段,可动态扩张或缩减。堆中内容是匿名的,不能按名字直接访问,只能通过指针间接访问。当进程调用malloc(C)/new(C++)等函数分配内存时,新分配的内存动态添加到堆上(扩张);当调用free(C)/delete(C++)等函数释放内存时,被释放的内存从堆中剔除(缩减) 。 分配的堆内存是经过字节对齐的空间,以适合原子操作。堆管理器通过链表管理每个申请的内存,由于堆申请和释放是无序的,最终会产生内存碎片。堆内存一般由应用程序分配释放,回收的内存可供重新使用。若程序员不释放,程序结束时操作系统可能会自动回收。 堆的末端由break指针标识,当堆管理器需要更多内存时,可通过系统调用brk()和sbrk()来移动break指针以扩张堆,一般由系统自动调用。

电磁场与仿真软件(16)

上一篇传输矩阵法有些bug,需要做一些修正,这一篇会就这个展开,先写一下传输矩阵法的bug. 在之前的文章有提到,电磁波在介质中传输主要有3种(无损介质,有损介质和理想导体): 无损介质(比如真空)中, 对应的k是实数,电磁波振荡传播; 理想导体(比如金属)中 ,对应的k是纯虚数,电磁波在表面按exp衰减; 有损介质(比如FR4)中,对应的k是复数,电磁波在做衰减式振荡; 具体可以参考以前的文章, 传输矩阵法针算的是只是向前传播的波, 但因为在界面有反射波,如果还是一样套用传输矩阵法去算反射波的话.会发现本来是衰减的波会按指数增大,然后得到一个爆掉的结果., 先去判断电磁波的传输方向. 用之前文章里提到的坡印廷矢量就可以去做判断 我们之前看的都是沿着z方向传播的电磁波,只要看就行 ,观察上一篇的例子,可以得到: 是正的就是沿正方向传播的电磁波,反之亦然; 之前这样写的话,把沿着正负方向电磁波写在一起,不是很好,我们需要更换一下思路, 先回到如下方程组,参考"电磁场与仿真软件(13)" 在之前的传输矩阵法中,我们是把电磁场都写到一起,得到如下方程: 我们也可以把电磁场分开来写,如下: 假设: 则: ---1 -----2 对1式进行求导,消去 得到: 我们可以得到通解如下: 其中是沿着正方向传播的波, 是沿着负方向传播的波. 之前不能这么写是因为之前是一阶的线性微分方程,,只有一个通解. 而现在是二阶的线性微分方程,所以我们能同时写出沿+,-方向传播的波. 接下来的步骤和之前一样,对进行矩阵对角化(详细参照第13,14篇),最后会得到类似的例子: 接下来我们计算下, W: 把 代入上式,得到: 其中I是单位矩阵. 很有意思的事情~~,下一篇继续写~

PX4 ThoneFlow光流使用

PX4官方光流介绍:PMW3901-Based Flow Sensors | PX4 User Guide 与飞控连接 接线:G接GND; V接3.3V; T是TX接飞控的RX口; Y接地开启偏航模式 镜头缺口处是光流后方 PX4地面站设置 需要改的参数设置分别是: SENS_EN_PMW3901:是否开启光流,改为1开启光流 SENS_FLOW_ROT:光流朝向,默认270°,即飞控与光流反向安装。 SENS_TFLOW_CFG:对应光流接的飞控RX口,不同的硬件口对照关系可以在PX4的参数表找到 (若用如GPS1口,需要在地面站的GPS参数里把GPS1的口选择disable禁用) (TELEM4口对应UART+I2C口)

Go语言中切片是如何被截取的?

截取也是创建slice的方法,可以从数组或则slice直接截取,需要指定起,止索引位置。 基于已有的slice创建新的slice对象,被称为 reslice。新的slice 和老的slice工用底层数组,新老slice对底层数组的更改都会影响到彼此。基于数组创建新的slice也是同样的效果,对数组或slice元素的更改都会影响到彼此。 值得注意的是,新老slice或则新的slice老数组相互影响的前提是共用底层数组,如果因为执行append操作使得新的slice或老的slice底层数组扩容,移动到新的位置,两者就不会相互影响了。所以关键在于两者是否共用底层数组。 data := []int{0,1,2,3,4,5,6,7,8,9} slice := data[2:4:6] // data[low,high,max] 对data使用了3个索引值,截取出新的slice。这里data可以是数组或者是slice。low 是最低索引值,这里是闭区间,就是说第一个元素是data位于low索引处的元素;而high 和 max 则是开区间,表示最后一个元素只能是索引 high-1 处的元素,而最大容量则只能是索引 max-1 的元素。 要求: max >= high >= low 当high == low 时,新的slice为空。 还有一个点,high 和 max 必须在老数组或则老slice 的容量(cap)范围内。 我们可以来看一个栗子: 猜猜下面的代码,输出什么? package main import "fmt" func main() { slice := []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9} s1 := slice[2:5] s2 := s1[2:6:7] s2 = append(s2, 100) s2 = append(s2, 200) s1[2] = 20 fmt.

绘制PCB封装和原理图要注意引脚一一对应

如图,当我们绘制完原件的原理图后 我们定义的引脚为2、3、4,绘制PCB封装时也要一一对应,如下图: 对应的管脚也是2、3、4.如果不小心写成1、2、3就会报错,找不到管脚。 

【Games202学习笔记02】作业1简单实现

目录 文件及函数参与分析ShadowMapPCFPCSS 文件及函数参与分析 ShadowMap 该文件中的 CalcLightMVP() 函数计算得到了后面需要使用的 lightMVP。 在 PhongMaterial.js 中的 buildPhongMaterial() 函数中的 new PhongMaterial() 使用 调用 buildPhongMaterial() 时 return new PhongMaterial(color, specular, light, translate, scale, vertexShader, fragmentShader); 在 PhongMaterial 实例化时 let lightMVP = light.CalcLightMVP(translate, scale); 在 ShadowMaterial.js 中类似也是在bulid函数中和实例化时使用 之后再 loadOBJ.js 中结合定义的 transform 和 scale 赋值传入 material let material, shadowMaterial; let Translation = [transform.modelTransX, transform.modelTransY, transform.modelTransZ]; let Scale = [transform.modelScaleX, transform.modelScaleY, transform.modelScaleZ]; let light = renderer.lights[0].entity; switch (objMaterial) { case 'PhongMaterial': material = buildPhongMaterial(colorMap, mat.

zookeeper知识点扫盲

zookeeper是什么 引用官网的描述, ZooKeeper is a centralized service for maintaining configuration information, naming, providing distributed synchronization, and providing group services. All of these kinds of services are used in some form or another by distributed applications. Each time they are implemented there is a lot of work that goes into fixing the bugs and race conditions that are inevitable. Because of the difficulty of implementing these kinds of services, applications initially usually skimp on them, which make them brittle in the presence of change and difficult to manage.

Arthas使用指北——命令、原理及案例

1 整合方式 当前普遍使用容器化的部署方式,两种方式部署到tke容器中 docker打包时将arthas打包进去在容器中下载 curl -O https://alibaba.github.io/arthas/arthas-boot.jar boot包仅有一百多 KB 执行 java -jar arthas.jar 即可进入arthas命令行,选择正在执行的java进程后,即可对进程进行相应的在线检测、诊断与调试。 2 实现原理 2.1 Java Agent和Instrumentation 我们知道,IDE中的Debug是通过JDPA技术实现了对代码的远程调试控制。而生产环境中是不会提供给我们JDPA接口的,Arthas使用的是Java Agent技术。 Java Agent 又叫做 Java 探针,Java Agent 是在 JDK1.5 引入的,是一种可以动态修改 Java 字节码的技术。Java 类编译之后形成字节码被 JVM 执行,在 JVM 在执行这些字节码之前获取这些字节码信息,并且通过字节码转换器对这些字节码进行修改,来完成一些额外的功能,这种就是 Java Agent 技术。在许多文章中,Java Agent被描述为虚拟机级别的AOP。 实际上单说Java Agent的话,并不涉及字节码的修改,Java Agent是运行在main方法之前的拦截器,它内定的方法名叫 premain ,也就是说要先执行premain再执行main方法。也就是说,Java Agent仅仅是作为代理,为我们提供了在main函数运行之前的一个入口。 public static void premain(String agentArgs, Instrumentation inst); public static void premain(String agentArgs); Java Agent是一个概念,其具体的实现是借助于java.lang.instrument包。在JDK1.5中,Instrument 要求在运行前利用命令行参数或者系统参数来设置代理类,在实际的运行之中,虚拟机在初始化之时(在绝大多数的 Java 类库被载入之前), instrumentation 的设置已经启动,并在虚拟机中设置了回调函数,检测特定类的加载情况,并完成实际工作。但是在实际的很多的情况下,我们没有办法在虚拟机启动之时就为其设定代理,这样实际上限制了 instrument 的应用。而 Java SE 6 的新特性改变了这种情况,通过 Java Tool API 中的 attach 方式,通过VirtualMachine.

Kubernetes Pod调度策略

Kubernetes Scheduler 上图是k8s的整体架构图,整体上可分为两大部分,组成集群控制器的服务(图左)与运行在工作节点的服务(图右)。运行在工作节点的服务自不必说,控制器相关的模块主要包括: etcd保存了整个集群的状态;apiserver提供了资源操作的唯一入口,并提供认证、授权、访问控制、API注册和发现等机制;controller manager负责维护集群的状态,比如故障检测、自动扩展、滚动更新等;scheduler负责资源的调度,按照预定的调度策略将Pod调度到相应的机器上;kubelet负责维护容器的生命周期,同时也负责Volume(CVI)和网络(CNI)的管理;Container runtime负责镜像管理以及Pod和容器的真正运行(CRI);kube-proxy负责为Service提供cluster内部的服务发现和负载均衡; 而我们这次关注的,就是scheduler调度器,了解其如何监听新创建、尚未分配到计算节点的Pod,如何为每一个Pod找到最适合其运行的计算节点。调度器的工作听起来很简单,里面的细节问题却是不少,比如,如何保证调度的公平性,确保每个节点都能被分配资源;再比如,如何保证调度的性能,最大化的利用集群的资源,最快的完成调度工作;以及如何允许用户灵活的自定义一些调度需求。k8s的调度器在默认设置下使用的是自带的kube-scheduler,在需要的场景下,我们也可以自定义调度器给k8s使用。如果没有特殊说明,接下来描述的都是kube-scheduler的调度行为。 调度器是作为一个独立的服务运行的,在其启动后,其会一直监听apiserver。当调度器发现一个新创建的Pod后,首先要做的就是在当前的节点中,筛选出符合调度条件的节点,这类节点我们称之为Feasible Node,如果没有节点符合条件,那么pod会一直停留在 unscheduled 状态,直到有节点符合条件。这一步筛选的过程叫做predicate。在筛选出Feasible Node后,第二步就是从中选择出最优的节点,为了评价节点的优先级,我们会对所有的Feasible Node进行打分,这一步称之为Priority,如果有多个节点有相同的最高优先级,会从中随机选择一个。最后,我们将选出的最优先节点上报给apiserver,这个过程叫做binding。 有两种方式配置调度器的筛选和打分行为,分别是调度策略和调度配置。 调度策略 调度策略可以指定筛选阶段的断言predicates和打分阶段的优先级priorities。 断言 这一个阶段主要是解决Pod能不能去某个Node的问题,通过各种断言条件,过滤掉不能去的节点。 PodFitsHostPorts 检查 Pod 请求的端口(网络协议类型)在节点上是否可用。 PodFitsHost 检查 Pod 是否通过主机名指定了 Node。 PodFitsResources 检查节点的空闲资源(例如,CPU和内存)是否满足 Pod 的要求。 MatchNodeSelector 检查 Pod 的节点选择算符 和节点的 标签 是否匹配。 以上四种断言,又被合称为GeneralPredicates,主要包含一些基本的筛选规则,考虑 Kubernetes 资源是否充足,比如 CPU 和 内存 是否足够,端口是否冲突、selector 是否匹配等。前三种自不必说,第四种NodeSelector则是一种比较直白的调度方式,通过在配置文件中指定Pod要调度的Node,该匹配规则属于【强制】约束。由于是调度器调度,因此不能越过Taints污点进行调度。 NoVolumeZoneConflict 给定该存储的故障区域限制, 评估 Pod 请求的卷在节点上是否可用。 NoDiskConflict 根据 Pod 请求的卷是否在节点上已经挂载,评估 Pod 和节点是否匹配。 MaxCSIVolumeCount 决定附加 CSI 卷的数量,判断是否超过配置的限制。 CheckNodeMemoryPressure 如果节点正上报内存压力,并且没有异常配置,则不会把 Pod 调度到此节点上。 CheckNodePIDPressure 如果节点正上报进程 ID 稀缺,并且没有异常配置,则不会把 Pod 调度到此节点上。

数据变换--数据规范化

规范化:将属性数据按比例缩放,使之落入一个小的特定区间 1)最小—最大规范化:假定minA和maxA分别为属性A的最小和最大值,则通过下面公式将A的值映射到区间[new_minA, new_maxA]中: 2)z-score规范化(零均值规范化): 将属性A的值根据其平均值和标准差进行规范化; 常用于属性最大值与最小值未知,或使用最小最大规范化方法会出现异常数据的情况。 其中,meanA、 standard_devA分别为属性A取值的均值和标准差。 3)小数定标规范化:通过移动属性A的小数点位置进行规范化,小数点的移动依赖于A的最大绝对值

如何“优雅地”进行Jetson nano 学习

RT 其实就是面对多场景应用时,nano不可能待在同一个地方,要么在车上,在机器人上……我们扛着一 个大显示器到处跑肯定是不太现实的,当然,如果想要锻炼身体的同学另说! 改用NoMachine Nano上下载 sudo apt-get install nomachine 如果因为网络问题下载不下来,咱就要使用一些“魔法” 或者换一种方式,在Win上下载好安装包,带到Nano中下载 NoMachine - Free Remote Desktop For Everybody 之后在Nano的终端中输入 sudo dpkg -i nomachine_6.11.2_1_arm64.deb 等待下载完成 下面更改开机自动登录 更改为如下内容(每个人账户密码不一样) 搜索NoMachine Service 找到Nano的IP地址,为了后面的连接使用 WIN上下载 这一步很简单,就不用多说了 跟着官网的下载,一步一步的next就好了 主要是后面的遇到的大大小小的BUG 遇到的一些BUG Nano在连接显示屏后再用Nomachine连接,Nomachine显示会有较大延迟,建议拔掉显示器,关掉Nomachine,重新用Nomachine连接Nano 遇见打开Nomachine软件连接到Nano闪退现象,使用管理员身份打开 关于连接后显示模糊等问题 xrandr --fb 1280x720 #分辨率自由选择(博主这个分辨率正好) 分辨率设置完成后,需要重新启动Nomachine软件,重新连接,防止鼠标错位问题 注意:Nano和电脑需要在同一个网络环境下,博主使用的是手机热点 原博客地址

记录一下 springboot 整合 SecurityConfig后, 前端访问后端跨域的坑

通用管理后台推荐 (兮家 plus) 【兮家 plus】, 主要应用于中小型项目的快速开发,已经历历时3年的优化改进,具备完善的基础功能以及代码生成,并且拥有完善的分布式解决方案:如分布式缓存,分布式锁,分布式唯一编号兮家 plus git 地址: https://gitee.com/wslxm/xijia-plus如果觉得本文有用,动动小手点赞或关注一下呗,将不定时持续更新更多的内容…,感谢大家的观看! 一、WebMvcConfigurer 中添加跨域配置 注意: addExposedHeader() 一定要配置, 否则前端将获取不到响应头中的 TOKEN /Authorization 参数 @Configuration public class MvcConfig implements WebMvcConfigurer { @Bean public CorsFilter corsFilter() { final UrlBasedCorsConfigurationSource urlBasedCorsConfigurationSource = new UrlBasedCorsConfigurationSource(); final CorsConfiguration corsConfiguration = new CorsConfiguration(); corsConfiguration.setAllowCredentials(true); /*是否允许请求带有验证信息*/ corsConfiguration.addAllowedOrigin("*");/*允许访问的客户端域名*/ corsConfiguration.addAllowedHeader("*");/*允许服务端访问的客户端请求头*/ corsConfiguration.addAllowedMethod("*"); /*允许访问的方法名,GET POST等*/ corsConfiguration.addExposedHeader("token");/*暴露哪些头部信息 不能用*因为跨域访问默认不能获取全部头部信息*/ corsConfiguration.addExposedHeader("TOKEN"); corsConfiguration.addExposedHeader("Authorization"); urlBasedCorsConfigurationSource.registerCorsConfiguration("/**", corsConfiguration); return new CorsFilter(urlBasedCorsConfigurationSource); } } 二、SecurityConfig中的配置修改 添加一 配置允许跨域访问 ,不要加 .disable(); ,否则一样无法访问 http.cors(); //.disable(); 添加二

<数据结构> - 数据结构在算法比赛中的应用(上)

目录 单链表 双链表 单调栈 单调队列&滑动窗口 KMP字符串 单链表 思路: 工程链表: typedef struct SListNode { int data; // val struct SListNode* next; // 存储下一个节点的地址 }SLN; 算法表示法: head 表示头结点的下标,数组e[]表示链表 date值,ne[]表示存储下一个节点的地址的指针next,idx 存储当前已经用到了哪个点 #include <iostream> using namespace std; const int N = 100010; // head 表示头结点的指针 // e[i] 表示节点i的值 // ne[i] 表示节点i的next指针是多少 // idx 存储当前已经用到了哪个点,工程链表中的新地址 int head, e[N], ne[N], idx; // 初始化 void init() { head = -1; //-1表示指向空 idx = 0; //下标索引从0开始 } // 将x插到头结点 void add_to_head(int x) { e[idx] = x, ne[idx] = head, head = idx ++ ; } // 将x插到下标是k的点后面 void add(int k, int x) { e[idx] = x, ne[idx] = ne[k], ne[k] = idx ++ ; } // 将下标是k的点后面的点删掉 void remove(int k) { ne[k] = ne[ne[k]]; //让结点直接指向下一个结点的next,不用管内存泄漏 } int main() { int m; cin >> m; init(); while (m -- ) { int k, x; char op; cin >> op; if (op == 'H') { cin >> x; add_to_head(x); } else if (op == 'D') { cin >> k; if (!

【mysql基础系列十一】用户权限管理

用户权限管理:在不同的项目中给不同的角色(mysql客户端用户,通常为开发者)不同的权限,为了保证数据库的数据安全。 用户管理 mysql需要客户端进行连接认证才能进行服务器操作:需要用户信息。mysql中所有的用户(指mysql客户端用户)信息都是保存在mysql数据库下的user表中。该表采用复合主键(host + user)。 注意:\g 的作用是分号和在sql语句中写’;’是等效的 \G 的作用是将查到的结构旋转90度变成纵向 1、创建用户 方式一:直接使用root用户在user表中插入记录。(不推荐) 方式二:使用SQL指令创建用户 create user '用户名'@'主机地址' identified by '明文密码'; create user 用户名; //创建 谁都可以访问,不需要密码 的用户 注意:主机地址可以使用'%'或者''代替,表示无限制。 2、删除用户 drop user '用户名'@'主机地址'; drop user 用户名; //删除主机地址为'' 或者 '%' 的用户 3、修改用户密码 mysql中提供了多种修改密码的方式,基本上都必须使用对应提供的一个系统函数:password()。需要靠该函数对密码进行加密处理。 方式一:使用专门的SQL指令来修改密码 set password for 用户名 = password('新的明文密码'); 方式二:使用更新语句update来修改表 update mysql.user set password = password('新的明文密码') where user = '用户名' and host='主机地址'; MySQL8使用以上方案修改密码后,还是能使用mysql直接登录。 是因为mysql8.0 之前的版本加密规则是 mysql_native_password,mysql8 之后,加密规则是 caching_sha2_password。所以我们需要设置加密规则为mysql_native_password即可。 use mysql; ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY '密码'; FLUSH PRIVILEGES; 权限管理 1、权限分类 mysql中将权限分3类:数据权限、结构权限、管理权限

[数据可视化] 词云(Word Cloud)

词云介绍 词云,又称文字云,是文本数据的视觉表示,由词汇组成类似云的彩色图形,用于展示大量文本数据。每个词的重要性以字体大小或颜色显示 词云(Word Cloud)主要用来做文本内容关键词出现的频率分析,适合文本内容挖掘的可视化。词云中出现频率较高的词会以较大的形式呈现出来,出现频率较低的词会以较小的形式呈现 词云的本质是点图,是在相应坐标点绘制具有特定样式的文字的结果 功能:对比文字的重要程度,快速感知最突出的文字 适合的数据条数:超过30条数据 练习案例:使用Power BI制作词云图 数据源(部分截图) 制图要点:引入自定义视觉对象Word Cloud,设置类别(Category)和数值(Values)两个参数 具体操作步骤如下所示 步骤1:将上述数据导入进Power BI进行数据清洗以及数据建模后,单击"可视化"窗格中的"..." 选择"获取更多视觉对象",输入"Word Cloud",引入词云 选择相应字段,然后调整可视化图表的格式,结果如下图所示 从词云展示的结果可以看出内外胎、脚踏板等销量最高 注意 1.当数据的区分度不大时使用词云起不到突出的效果 2.当数据太少时很难布局出好看的词云,推荐使用柱状图 词云适合大量数据,柱状图适合少量数据 词云展示文字更为直观,柱状图需要借助坐标轴和刻度表示文字的分类和数据

Java 计算月份天数

最简单的方法 import java.time.LocalDate; import java.util.Calendar; import java.util.Scanner; //声明LocalDate和Calendar和Scanner public class yue { //yue是我的文件名。 public static void main(String[] args) { Scanner sc = new Scanner(System.in); System.out.print("请输入年 :"); int year = sc.nextInt(); //int定义year,=号赋值(用户输入的值) System.out.println(); System.out.print("请输入月 :"); int month = sc.nextInt(); //定义month,=号赋值(用户输入的值) var c = Calendar.getInstance(); int days = 0; switch (month) { case 1: case 3: case 5: case 7: case 8: case 10: case 12: days = 31; break; //定义31天的月份。 case 4: case 6: case 9: case 11: days = 30; break; //定义30天的月份。 case 2: days = year % 400 == 0 || year % 4 == 0 && year % 100 !

解决win10双击.jar包无法运行

对于 .jar 文件不能直接运行或双击运行的解决方式 方式一:使用命令行运行 在命令行中输入: java -jar C:\xxx\xxx.jar 方式二:创建run.bat文件 这个方法的本质也是使用命令行,但是不用手动输入命令。 (1)创建一个文本文件,命名为:run.bat (2)文件中写入:javaw -jar %1 (3)将.jar文件的打开方式改为上面这个run.bat文件。 (4)双击.jar文件,即可运行 方式三:修改注册表编辑器 以上两种方在运行程序时都会有命令行窗口,如果关掉命令行窗口,那么程序也会被关闭。 所以可以使用修改注册表编辑器的方法。 (1)在运行中输入regedit,打开注册表编辑器 (2)按住:ctrl + F 查询 javaw.exe 找到以下目录jarfile->shell->open->command (3)双击默认 (4)修改值数据为:“C:\Program Files\Java\jdk1.8.0_191\jre\bin\java.exe” -jar “%1” %* (5)保存修改,然后选中 .jar 文件即可运行成功。 方式三超强的,可以解决大部分情况的。 PS:该篇文章是根据一位前辈写的,原文地址:https://blog.csdn.net/and_then111/article/details/87279792/

UE4加载使用自定义dll动态链接库

本人在写这篇文章时候,网上已经有很多相关的文章,但是网上的文章缺少逐步指引,本人看的云里雾里,估计刚接触相关工作的人看的也不是很清楚。本着自己记录和让他人少踩一些坑的宗旨------这篇文章诞生了。好了,不多BB,直接进入主题。 创建自定义dll动态链接库 首先新建一个动态链接库的C++项目: 然后在项目里添加C++类:DllClass,内容如下: //.h #define DLL_EXPORT __declspec(dllexport) #define PI 3.1415926 #ifdef __cplusplus extern "C" { #endif float DLL_EXPORT getCircleArea(float radius); #ifdef __cplusplus } #endif 其中这几句是必须的,其他的可以省略掉,其他内容的意思是以C语言的方式编译这段代码,可以根据项目需要添加或删除 //.h //要导出的函数必须要加__declspec(dllexport)前缀,此处声明DLL_EXPORT代替这个略显繁琐的前缀 #define DLL_EXPORT __declspec(dllexport); //定义π #define PI 3.1415927 //要导出的函数(求圆的面积) float DLL_EXPORT getCircleArea(float radius); cpp没什么可看的,实现了一个非常简单的一个求圆的面积的函数 //.cpp #include "pch.h" #include <math.h> #include "dllClass.h" float DLL_EXPORT getCircleArea(float radius) { return (PI * pow(radius,2)); } 然后选择x64 Release开始编译: 这里注意不要傻乎乎选择x86,因为UE4是x64 Orz 编译成功后会在项目目录的 x64\Release 下看到已经生成成功dll文件了。 加载自定义dll动态链接库 首先创建一个ue4 c++的项目,相信这一步就不用我详细介绍了吧~ 创建DLL的文件夹,和Content同级:

element-ui 封装季度选择框

最终页面效果: 完整代码: jiduDatePicker.vue组件 <template> <!-- 季度选择时间控件 --> <div class="wrapper_picker"> <span> <!-- 生成一个点用于控制季度时间弹窗消失 --> <span style="position:fixed;top:0;bottom:0;left:0;right:0;background:rgba(0,0,0,0);z-index:999;" v-show="showSeason" @click.stop="showSeason=false" ></span> <el-input placeholder="选择季度" v-model="showValue" style="width:93%;" clearable @focus="showSeason=true" > <i slot="prefix" class="el-input__icon el-icon-date"></i> </el-input> <el-card class="box-card" style="width:322px;padding: 0 3px 20px;margin-top:10px;position:fixed;z-index:9999" v-show="showSeason" > <div slot="header" class="firstBtn"> <button type="button" aria-label="前一年" class="el-picker-panel__icon-btn el-date-picker__prev-btn el-icon-d-arrow-left" @click="prev" ></button> <span role="button" class="el-date-picker__header-label">{{year}}年</span> <button type="button" aria-label="后一年" @click="next" class="el-picker-panel__icon-btn el-date-picker__next-btn el-icon-d-arrow-right" ></button> </div> <div class="text container"> <!-- 如下,绑定class,disabled为禁止选择的时间的设置 --> <el-button type="text" size="

ubuntu18.04通过apt安装python3.7.7与pip3.7最新版本(python3.8同理)

首先更新软件包列表并安装必备组件: #检测可更新 sudo apt update #用于添加ppa源的小工具,ubuntu server默认没装。 sudo apt install software-properties-common 接下来,将Deadsnakes PPA添加到您的来源列表中:(不做这步也可以,但会安装较老的版本) #有确认提示按回车继续 sudo add-apt-repository ppa:deadsnakes/ppa 库添加完成后,请使用以下命令安装Python 3.7: #搜索是否有需要的版本 sudo apt search python3.7 #安装 sudo apt install python3.7 至此,Python 3.7已安装在您的Ubuntu系统上,可以使用了。 您可以通过键入以下内容进行验证: python3.7 -V 安装curl sudo apt install curl 安装pip # 下载最新的官方 pip curl https://bootstrap.pypa.io/get-pip.py -o get-pip.py # 安装 python-distutils sudo apt install python3-distutils 或 sudo apt install python3.9-distutils(高版本的python3) # 直接获取 pip3.7 sudo python3.7 get-pip.py # 安装 launchpadlib pip3.7 install launchpadlib 测试是否安装成功 pip3.

国标28181:实时视频播放

流程 一个流媒体平台主要分为一些几个部分 主要用途:对接监控摄像头、视频直播、多对多视频聊天器 系统架构由三个部分组成: 接口服务器(HTTP服务器)主要用于响应客户端的请求信令服务器(SIP服务器)主要用于和流媒体服务器和视频设备交互,主要功能是管理摄像头之类的设备以及控制摄像头将视频流转发给流媒体服务器的哪个端口流媒体服务器主要用于处理视频流的接收、转发和分发 接口服务器和信令服务器可以整合为一个服务器。 流媒体服务器最好单独部署,避免流媒体服务器压力过大,可以用ZLMediaKit代替。我们要开发的就是接口服务器和信令服务器。 实时码流点播采用SPI协议中的INVITE方法实现会话连接,采用RTP/RTCP协议实现媒体传输。 整个播放过程如下: 其通信流程如下: 视频流是怎么推流的 SIP视频流的获取是指解码器(ZLMediaKit)通过SIP协议向GB28181服务器获取视频流的过程 GB28181服务器(也就是SIP服务器)会像摄像头发送一些信令,主要是请求播放实时视频。 开启SIP服务器,服务器将会监听某个端口,可以从这个端口收到SDP信息摄像机端发送Register消息后,然后服务端应答注册消息代码SIP服务端响应注册命令后,发送Invite请求,请求catalog信息,也就是设备基本信息摄像机端收到消息发送其自身的catalog消息,将会服务具体的具体的catalog消息。SIP服务取都摄像机的信息后就可以发送请求视频信息到摄像头。下面看下SDP信息怎么写 static string createSDP(MediaContext& mediaContext) { char str[500] = { 0 }; pj_ansi_snprintf(str, 500, "v=0\n" "o=%s 0 0 IN IP4 %s\n" "s=Play\n" "c=IN IP4 %s\n" "t=0 0\n" "m=video %d RTP/AVP 96 98 97\n" "a=recvonly\n" "a=rtpmap:96 PS/90000\n" "a=rtpmap:98 H264/90000\n" "a=rtpmap:97 MPEG4/90000\n" "y=0100000001\n", mediaContext.GetDeviceId().c_str(), mediaContext.GetRecvAddress().c_str(), mediaContext.GetRecvAddress().c_str(), mediaContext.GetRecvPort() ); return str; } 信令交互成功之后,摄像头(媒体流发送者)会将视频数据以rtp的方式推送到指定的端口 (端口在上面的invite消息指定)流到媒体服务器媒体服务器(GB28181服务器)在指定的端口接收视频流媒体服务器(GB28181服务器)将视频流转发给流媒体接收者(比如ZLMediaKit) 具体流程如下: 视频流格式 GB28181要求传输的视频流格式为PS流,或者H264流,或者MP4格式。 可以用wireshark抓包,数据报类型是RTP的PS流 国标流媒体服务器其实就是负责将GB28181设备或者平台推送的PS流转成ES流,然后提供RTSP、RTMP、FLV、HLS等格式进⾏分发。

满足echarts动态数据轮询,

后台返回一个月的总数据,前端实现动态图标加载 因后台返回为全部数据,需要分段展示,实现无缝轮询, let cremationList = [ { "cremationDate": "2022-08-01", "number": 210 }, { "cremationDate": "2022-08-02", "number": 150 }, { "cremationDate": "2022-08-03", "number": 50 }, { "cremationDate": "2022-08-04", "number": 100 }, { "cremationDate": "2022-08-05", "number": 110 }, { "cremationDate": "2022-08-06", "number": 90 }, { "cremationDate": "2022-08-07", "number": 40 }, { "cremationDate": "2022-08-08", "number": 70 }, { "cremationDate": "2022-08-09", "number": 180 }, { "cremationDate": "2022-08-10", "number": 200 }, { "cremationDate": "2022-08-11", "

基于Web+App的快递公司物流管理信息系统设计与实现

摘 要:随着互联网的技术的快速发展和无线网络的更新迭代,使4G网络已成为过去式5G网络蓬勃发展。技术的发展,硬件的提高使人们使用智能手机可以更加快速、便捷的浏览信息、获取信息。本文首先介绍快递公司物流管理信息APP开发的背景和选题的意义,阐述了选择Android作为开发平台的优势。其次,对基于Android系统的快递公司物流管理APP的实现进行了需求分析和开发场景的设置。对于整个快递公司物流管理信息APP的数据表、功能模块做了详细的分析,并详细的介绍了各个功能模块的功能,绘制了重要的业务流程图。对于快递公司企业现在使用的物流管理系统进行了分析,并增加了和自己企业的功能模块,提出了无线网络和移动终端设备相结合的快递服务信息查询手段,设计出了一套完整的物流管理系统。系统管理、货物管理、车源管理、配货管理、用户管理、合同管理配送管理等功能。 关键词:物流管理,快递公司,Android,Mysql数据库 Abstract: With the rapid development of Internet technology and the renewal of wireless network, 4g network has become the past 5g network. With the development of technology and the improvement of hardware, people can browse information and get information more quickly and conveniently. Firstly, this paper introduces the background and significance of the development of Logistics Management Information App of Express Company, and expounds the advantages of choosing Android as the development platform.

mongo详细操作合集

与他同创作记录:附加操作地址 1、比较两个字段的值是否相等 db.user.find({ "$where":"this.name1 == this.name2" }) db.user.find({$expr:{$ne:["$name1", "$name2"]}}) db.user.aggregate({$match:{$expr:{$ne:["$name1", "$name2"]}}})

线程池理解

线程池(Thread Pool) 涉及线程池相关类及接口(jdk1.5 juc开始):Executor、Executors(工具类)、ExecutorService、ThreadPoolExecutor、FutureTask、Callable、Runnable等 JDK中默认使用的线程池: ThreadPoolExecutor 一、理论: 1.1、简介: 多线程处理形式 处理过程: 任务添加队列创建线程时自动启动任务线程池的线程均是后台线程,每个线程均使用默认的堆栈大小、以默认的优先级使用,并处于多线程单元中如果某个线程在托管代码中空闲(如正在等待某个事件),则线程池将插入另一个辅助线程来使所有处理器保持繁忙如果所有线程池线程都始终保持繁忙,但队列中包含挂起的工作,则线程池将在一段时间后创建另一个辅助线程但线程的数目永远不会超过最大值。超过最大值的线程可以排队,但他们要等到其他线程完成后才启动。 池化技术(数据库连接池(jdbc)、HttpClient连接池) 主要作用:减少频繁创建线程、销毁线程、线程上下文切换问题 模式:HS/HA半同步/半异步模式、L/F领导者与跟随者模式。 HS/HA半同步/半异步模式:生产者消费者模式 分为同步层、队列层、异步层三层。同步层的主线程处理工作任务并存入工作队列,工作线程从工作队列取出任务进行处理,如果工作队列为空,则取不到任务的工作线程进入挂起状态。由于线程间有数据通信,因此不适于大数据量交换的场合。 L/F领导者跟随者模式:在线程池中的线程可处在3种状态之一: 领导者leader、追随者follower或工作者processor任何时刻线程池只有一个领导者线程。事件到达时,领导者线程负责消息分离,并从处于追随者线程中选出一个来当继任领导者,然后将自身设置为工作者状态去处置该事件。处理完毕后工作者线程将自身的状态置为追随者。整个过程中Leader的状态变化:事件到达时,追随中遴选领导、自身设置为工作者、处理完毕设置为追随者模式实现复杂,避免线程间交换任务数据,提高了CPU CACHE相似性。在ACE(Adaptive Communication Environment)中,提供了领导者跟随者模式实现。 1.2、线程池创建、销毁及核心参数: 核心参数: 最全的构造方法:7参 public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler) { if (corePoolSize < 0 || maximumPoolSize <= 0 || maximumPoolSize < corePoolSize || keepAliveTime < 0) throw new IllegalArgumentException(); if (workQueue == null || threadFactory == null || handler == null) throw new NullPointerException(); this.

matlab中selector的使用

matlab中selector的使用 4、多维向量处理,与一维类似4-1、选择信号:4-2、改变信号顺序 # 1、selector简介 用于处理多个信号的输入输出顺序与选择 # 2、用途 1)多选一; 2)多选多; 3)调整输入信号顺序; # 3、使用方法 如图例子: 1. 加入三个常量分别为1,2,3 2. 使用mux集总三路信号; 3. 输入selector,设置selector Number of input dimensions:1(输入的向量维度为1) Index mode : One-based 信号序号从1开始 Index option:index vector (dialog) Index [1 3 2] 调换2和3的顺序 ,如果只要一个信号如第一个,可以设置index:1 Input port size :3 输入信号的个数 4. 多个信号使用demux分解,接入到多输入的scope,观察信号确实改变顺序 如果是一路信号,就不需要demux直接接scope观察 4、多维向量处理,与一维类似 4-1、选择信号: 4-2、改变信号顺序

计算机毕业论文java毕业设计选题源代码javaweb学生信息管理/学生考试系统[包运行成功]

🍅文末获取联系🍅 一、项目介绍 《javaweb学生信息管理》该项目采用技术Servlet+Jsp+Jdbc+dbutils+EasyUI+jQuery+Ajax,mysql数据库 ,项目含有源码、文档、配套开发软件、软件安装教程、项目发布教程 系统共分为三种用户: 1. 学生模块:个人信息管理、同学通讯录、成绩查询、修改密码 2. 教师模块 :个人信息管理、教师通讯录、成绩登记、成绩统计、成绩导出、修改密码 3. 系统管理员 :考试列表、学生信息管理、教师信息管理、基础信息管理、后台管理 1绪论 1.1课题背景 一直以来学生的信息管理是学校工作中的一项重要内容,我国的大中专院校的学生信息管理系统管理水平普遍不高。随着办学规模的扩大和招生人数的增加,建立一个信息维护系统是非常必要的。普通的信息管理已不能适应时代的发展,因为它浪费了许多的人力和物力。在当今信息时代这种传统的管理方法必然被以计算机为基础的信息管理系统所代替。为了提高信息管理的效率,我选择了学生信息管理系统管理系统作为毕业设计的课题。 本系统在大多数信息管理系统的基础上,主要增加了教师对信息的操作,教师改完试卷后不用在往学院的教务处办公室报送信息,可以直接的把信息上传到网络上,学生也可以方便快速的查询到自己的信息,考试后教务管理人员也不必总呆在学院的办公室,他们都不受时间,位置,空间的限制,只要有上网的条件,在家里就可以完成有关信息的录入,更新,管理,查询和删除。本系统将会改变以前靠手工管理学生信息管理系统的状况,提高工作效率。希望能为老师和学校的工作带来便利。 1.2开发目的 随着社会的发展和科技的进步,对人才素质和能力的要求越来越高,现代教育观念强调素质与能力的培养。当今和未来的国际竞争,说到底是人才的竞争。信息技术和网络教育对于信息社会的进步、知识经济的发展、数字教育的建设、创新人才的培养至关重要。目前,一种新型的教育形式——以网络教育为标志的现代教育正脱颖而出。网络信息教育不仅仅体现在教育技术手段的先进上,而且体现在它所引起的教育观念等一系列的变革上。在知识经济时代,不仅在教育观念、教育内容,而且在教学手段、教学过程和教学方法等方面都将面临挑战,高校教师应如何适应网络信息时代教育的新特点,使教育更适应社会主义市场经济的要求,顺应教育发展的世界潮流。 开发一个学生信息管理系统,采用计算机对学生信息管理系统进行管理,进一步提高了办学效益和现代化水平。为广大教师和学生提高工作效率,实现学生信息管理系统信息管理工作流程的系统化、规范化和自动化。运用学生信息管理系统可以减轻学院教学人员的工作量,缩小开支,提高工作效率与准确率,能够合理安排时间,能够尽快的知道自己的考试信息,投入新的课程的学习或复习这次没有考过的课程。 现在我国的很多院校的学生信息管理系统档案管理水平普遍都不是很高,有的还停留在全用纸介质基础上,这种管理方式已不能适应时代的发展,社会的需求,因为它浪费了大量的人力物力,也存在着许多不足的因素。在今天信息时代这种传统的管理方法必然会被计算机为基础的信息管理系统所代替。一个高效的学生信息管理系统可以存储历届的学生信息管理系统档案,不需要大量的人力,只需要几名专门录入员即可操作系统,节省大量人力,可以迅速查到所需信息、高效、安全,学生也能方便的查看自己的信息。 二、项目相关截图 三、源码获取 大家点赞、收藏、关注、评论啦 、查看👇🏻👇🏻👇🏻获取联系方式👇🏻👇🏻👇🏻

【Java】Map类

Java Map类 Map 提供了一个更通用的元素存储方法。Map 集合类用于存储元素对(称作“键”和“值”),其中每个键映射到一个值。从概念上而言,可以将 List 看作是具有数值键的 Map。 构造函数定义 public interface Map<K,V> { } 方法 abstract void clear() abstract boolean containsKey(Object key) abstract boolean containsValue(Object value) abstract Set<Entry<K, V>> entrySet() abstract boolean equals(Object object) abstract V get(Object key) abstract int hashCode() abstract boolean isEmpty() abstract Set<K> keySet() abstract V put(K key, V value) abstract void putAll(Map<? extends K, ? extends V> map) abstract V remove(Object key) abstract int size() abstract Collection<V> values() Map提供接口分别用于返回 键集、值集或键-值映射关系集。entrySet()用于返回键-值集的Set集合;keySet()用于返回键集的Set集合;values()用户返回值集的Collection集合,因为Map中不能包含重复的键;每个键最多只能映射到一个值。所以,键-值集、键集都是Set,值集时Collection。Map提供了“键-值对”、“根据键获取值”、“删除键”、“获取容量大小”等方法。 架构 Map架构

shell脚本之数组

1.比较 字符串 1234567890 字符串列表 " 10 20 30 40 50 60" 数组 {10 20 30 40 50 60} 每个数为元素中间以空格隔开 数组 {10 20 30 40 50 60} 0 1 2 3 4 5 代表下标 2. 定义数组 array1=(10 20 30 40 50) 代表定义了一个名为array1的数组 array1=('zhang san' 'li si' ' wangwu' 'zhaoliu')用单引号双引号都可以 3.查看某一元素的下标 echo ${array[n] // n代表查看的下标 4.获取数组的长度 echo ${#array[@]} echo ${#array[*]} 5. 查看数组内最后一个元素的值 6.数组分片(数组截取) ${数组名[@]:起始位置:截取长度} //起始位置从0算起 ​ ${数组名[@]} //获取整个数组的元素值 ${数组名[@]:0:3} //从下标为0的元素开始截取,共截取3个元素。(即截取元素1到元素3) ${数组名[@]:2:2} //从下标为2的元素开始截取,共截取2个元素。(即截取元素3到元素4) 7.

【Java】Java HashMap类

Java HashMap类 HashMap是我们使用非常多的Collection,它是基于哈希表的 Map 接口的实现,以key-value的形式存在。 HashMap实现提供所有可选的映射操作,并允许使用 null 值和 null 键。(除了不同步和允许使用 null 之外,HashMap 类与 Hashtable 大致相同。)此类不保证映射的顺序,特别是它不保证该顺序恒久不变。 HashMap不是线程安全的,如果想要线程安全的HashMap,可以通过Collections类的静态方法synchronizedMap获得线程安全的HashMap,例如:Map map = Collections.synchronizedMap(new HashMap()); 构造函数 HashMap():构造一个具有默认初始容量 (16) 和默认加载因子 (0.75) 的空 HashMap。 HashMap(int initialCapacity):构造一个带指定初始容量和默认加载因子 (0.75) 的空 HashMap。 HashMap(int initialCapacity, float loadFactor):构造一个带指定初始容量和加载因子的空 HashMap。 在这里提到了两个参数:初始容量,加载因子。这两个参数是影响HashMap性能的重要参数,其中容量表示哈希表中桶的数量,初始容量是创建哈希表时的容量,加载因子是哈希表在其容量自动增加之前可以达到多满的一种尺度,它衡量的是一个散列表的空间的使用程度,负载因子越大表示散列表的装填程度越高,反之愈小。对于使用链表法的散列表来说,查找一个元素的平均时间是O(1+a),因此如果负载因子越大,对空间的利用更充分,然而后果是查找效率的降低;如果负载因子太小,那么散列表的数据将过于稀疏,对空间造成严重浪费。系统默认负载因子为0.75,一般情况下我们是无需修改的。 属性 transient Entry[] table;//存储元素的实体数组 transient int size;//存放元素的个数 int threshold; //临界值 当实际大小超过临界值时,会进行扩容threshold = 加载因子*容量 final float loadFactor; //加载因子 transient int modCount;//被修改的次数 其中loadFactor加载因子是表示Hsah表中元素的填满的程度.若:加载因子越大,填满的元素越多,好处是,空间利用率高了,但:冲突的机会加大了.链表长度会越来越长,查找效率降低。反之,加载因子越小,填满的元素越少,好处是:冲突的机会减小了,但:空间浪费多了.表中的数据将过于稀疏(很多空间还没用,就开始扩容了)冲突的机会越大,则查找的成本越高.因此,必须在 "冲突的机会"与"空间利用率"之间寻找一种平衡与折衷. 这种平衡与折衷本质上是数据结构中有名的"时-空"矛盾的平衡与折衷. 如果机器内存足够,并且想要提高查询速度的话可以将加载因子设置小一点;相反如果机器内存紧张,并且对查询速度没有什么要求的话可以将加载因子设置大一点。不过一般我们都不用去设置它,让它取默认值0.75就好了。 方法 void clear() Removes all of the mappings from this map.

STM32CubeIDE更新ST LINK驱动失败解决方法

问题描述 当使用CubeIDE下载程序时,在这里遇到个STM32CubeIDE需要ST Link更新的提示 弹出 “in order to use the attached ST-LINK with this version of STM32CubeIDE an update of the ST LINK firmware is required” “为了将连接的ST-LINK与此版本的STM32CubeIDE一起使用,需要更新ST-LINK固件” 但是使用Cube更新失败的情况,出现如无法读取ST LINK版本固件版本号;更新固件过程中,先出现错误后出现成功提示,但更新未完成等问题。 解决方法 下载并安装STM32 ST_LINK Utility软件更新到最新版驱动, PS:更新ST Link时应将ST LINK 与STM32 断开。 点击连接ST LINK后,出现芯片内部驱动版本,然后根据需要点击Yes 进行更新,中途出错就将ST Link取下,然后重试,最后读取芯片内部驱动要与所更新驱动版本一致才行,才算更新成功。 然后在Cube中不再提示需要更新,同时取消自动检查更新。

BeanDefinitionBuilder 使用

BeanDefinitionBuilder 使用 常用 属性 //设置Bean的构造函数传入的参数值 public BeanDefinitionBuilder addConstructorArgValue(Object value) //设置构造函数引用其他的bean public BeanDefinitionBuilder addConstructorArgReference(String beanName) //设置这个bean的 init方法和destory方法 public BeanDefinitionBuilder setInitMethodName(String methodName) public BeanDefinitionBuilder setDestroyMethodName(String methodName) //设置单例/多例 public BeanDefinitionBuilder setScope(String scope) //设置是否是个抽象的BeanDefinition,如果为true,表明这个BeanDefinition只是用来给子BeanDefinition去继承的,Spring不会去尝试初始化这个Bean。 public BeanDefinitionBuilder setAbstract(boolean flag) //是否懒加载,默认是false public BeanDefinitionBuilder setLazyInit(boolean lazy) //自动注入依赖的模式,默认不注入 public BeanDefinitionBuilder setAutowireMode(int autowireMode) //检测依赖。 public BeanDefinitionBuilder setDependencyCheck(int dependencyCheck)

猿创征文|<JDBC>多种开源数据库连接池

🛒本文收录与专栏:《JDBC》专栏 📢专栏目的是解释JDBC的关键点,与各位一路同行,会持续输出,欢迎免费订阅!! ✨注定要去的地方,多晚都有光✨ 目录 数据库连接池🔥数据库连接池必要性🔥数据库连接池技术👌工作原理 🔥多种开源的数据库连接池👌C3P0数据库连接池👌DBCP数据库连接池👌Druid(德鲁伊)数据库连接池 数据库连接池 🔥数据库连接池必要性 对于JDBC数据库连接池的必要性 在使用开发基于数据库的web程序时,传统的模式基本是按以下步骤: ●在主程序(如servlet、beans)中建立数据库连接 ●进行sql操作 ●断开数据库连接 这种模式开发,存在的问题: 普通的JDBC数据库连接使用 DriverManager 来获取,每次向数据库建立连接的时候都要将 Connection 加载到内存中,再验证用户名和密码(得花费0.05s~1s的时间)。需要数据库连接的时候,就向数据库要求一个,执行完成后再断开连接。这样的方式将会消耗大量的资源和时间。数据库的连接资源并没有得到很好的重复利用。若同时有几百人甚至几千人在线,频繁的进行数据库连接操作将占用很多的系统资源,严重的甚至会造成服务器的崩溃。 对于每一次数据库连接,使用完后都得断开。否则,如果程序出现异常而未能关闭,将会导致数据库系统中的内存泄漏,最终将导致重启数据库,这种开发不能控制被创建的连接对象数,系统资源会被毫无顾及的分配出去,如连接过多,也可能导致内存泄漏,服务器崩溃。 🔥数据库连接池技术 为解决传统开发中的数据库连接问题,可以采用数据库连接池技术 数据库连接池的基本思想:就是为数据库连接建立一个“缓冲池”。预先在缓冲池中放入一定数量的连接,当需要建立数据库连接时,只需从“缓冲池”中取出一个,使用完毕之后再放回去 数据库连接池负责分配、管理和释放数据库连接,它允许应用程序重复使用一个现有的数据库连接,而不是重新建立一个 数据库连接池在初始化时将创建一定数量的数据库连接放到连接池中,这些数据库连接的数量是由最小数据库连接数来设定的。无论这些数据库连接是否被使用,连接池都将一直保证至少拥有这么多的连接数量。连接池的最大数据库连接数量限定了这个连接池能占有的最大连接数,当应用程序向连接池请求的连接数超过最大连接数量时,这些请求将被加入到等待队列中。 👌工作原理 数据库连接池技术的优点 资源重用 由于数据库连接得以重用,避免了频繁创建,释放连接引起的大量性能开销。在减少系统消耗的基础上,另一方面也增加了系统运行环境的平稳性。更快的系统反应速度 数据库连接池在初始化过程中,往往已经创建了若干数据库连接置于连接池中备用。此时连接的初始化工作均已完成。对于业务请求处理而言,直接利用现有可用连接,避免了数据库连接初始化和释放过程的时间开销,从而减少了系统的响应时间新的资源分配手段 对于多应用共享同一数据库的系统而言,可在应用层通过数据库连接池的配置,实现某一应用最大可用数据库连接数的限制,避免某一应用独占所有的数据库资源统一的连接管理,避免数据库连接泄漏 在较为完善的数据库连接池实现中,可根据预先的占用超时设定,强制回收被占用连接,从而避免了常规数据库连接操作中可能出现的资源泄露 🔥多种开源的数据库连接池 JDBC 的数据库连接池使用 javax.sql.DataSource 来表示,DataSource 只是一个接口,该接口通常由服务器(Weblogic, WebSphere, Tomcat)提供实现,也有一些开源组织提供实现: DBCP 是Apache提供的数据库连接池。tomcat 服务器自带dbcp数据库连接池。速度相对c3p0较快,但因自身存在BUG,Hibernate3已不再提供支持。 C3P0 是一个开源组织提供的一个数据库连接池,速度相对较慢,稳定性还可以。hibernate官方推荐使用 Proxool 是sourceforge下的一个开源项目数据库连接池,有监控连接池状态的功能,稳定性较c3p0差一点 BoneCP 是一个开源组织提供的数据库连接池,速度快 Druid 是阿里提供的数据库连接池,据说是集DBCP 、C3P0 、Proxool 优点于一身的数据库连接池,但是速度不确定是否有BoneCP快 DataSource 通常被称为数据源,它包含连接池和连接池管理两个部分,习惯上也经常把 DataSource 称为连接池 DataSource用来取代DriverManager来获取Connection,获取速度快,同时可以大幅度提高数据库访问速度。 🎁特别注意: 数据源和数据库连接不同,数据源无需创建多个,它是产生数据库连接的工厂,因此整个应用只需要一个数据源即可 当数据库访问结束后,程序还是像以前一样关闭数据库连接:conn.close(); 但conn.close()并没有关闭数据库的物理连接,它仅仅把数据库连接释放,归还给了数据库连接池 👌C3P0数据库连接池 获取连接方式一 //使用C3P0数据库连接池的方式,获取数据库的连接:不推荐 public static Connection getConnection1() throws Exception{ ComboPooledDataSource cpds = new ComboPooledDataSource(); cpds.

Error S2801: [Virtuoso Driver]CL033: Connect failed to localhost:13001 = localhost:13001.at line 0..

一般情况下,启动virtuoso使用命令" virtuoso-t -fd" ,但是我这里是通过运行 py文件 开启服务,所以跟之前的方法还是不太一样的。 具体的参考源码链接如下: GitHub - dki-lab/Freebase-Setup: The last data dump of Freebase with introductory explanation of its schema 开启服务 $ python3 virtuoso.py start 3001 -d virtuoso_db 运行之后出错: 关闭服务 $ python3 virtuoso.py stop 3001 运行之后出错: 经过我反复排查,最终发现是因为我之前在已经开启服务的情况下再次开启服务导致的错误。 我用命令查有关virtuoso的进程: $ ps -ef | grep virtuoso 然后将不相关的进程用kill 杀死: $ kill -9 7428 这时测试一下 重启服务,关闭服务,发现问题已经解决了!! 最后,网上有关virtuoso 启动失败的资料很少,所以查找起来原因有些困难,希望大家遇到新奇的bug都能记录下来,我们互帮互助,早点解决bug!!

数组模拟邻接表(链式前向星)

邻接表 可以用链表实现,也可以用数组实现。 const int N = 100000; struct e { int to, w, next; } edge[N]; int head[N], cnt = 0; void add(int u, int v, int w) { edge[cnt].to = v; edge[cnt].w = w; edge[cnt].next = head[u]; head[u] = cnt++; } memset(head, -1, sizeof(head)); head数组可以理解成表头它记录了它第一条边的的坐标。 结构体数组edge[i]数组是第 i 条边,记录了它连接的下一个节点(to),边的权值(w),它的下一条边(next)。 列组数据 u v w ———— u是起点,v是终点,w是边权值 1 2 3 1 3 4 1 5 6 2 4 7 3 5 9

Android 9 按音量键音量调节流程

参考:https://blog.csdn.net/kehyuanyu/article/details/49153223 https://blog.csdn.net/qq_34787560/article/details/97374073?utm_medium=distribute.pc_aggpage_search_result.none-task-blog-2aggregatepagefirst_rank_v2~rank_aggregation-7-97374073.pc_agg_rank_aggregation&utm_term=android+%E9%9F%B3%E9%87%8F%E6%8C%89%E9%94%AE%E6%B5%81%E7%A8%8B&spm=1000.2123.3001.4430 基于android 9平台分析。 在Android系统中,默认的设备(phone等)音量都是分开控制的,这些包括媒体、铃声、闹铃、蓝牙、通话通过音频流来区别不同的音量类型。每种流类型都定义最大音量、最小音量及默认音量,Android 9定了了11中音频流类型: 流类型 //frameworks/base/media/java/android/media/AudioSystem.java public static final String[] STREAM_NAMES = new String[] { "STREAM_VOICE_CALL", "STREAM_SYSTEM", "STREAM_RING", "STREAM_MUSIC", "STREAM_ALARM", "STREAM_NOTIFICATION", "STREAM_BLUETOOTH_SCO", "STREAM_SYSTEM_ENFORCED", "STREAM_DTMF", "STREAM_TTS", "STREAM_ACCESSIBILITY" }; 最大音量(音量等级) //frameworks/base/services/core/java/com/android/server/audio/AudioService.java /** Maximum volume index values for audio streams */ protected static int[] MAX_STREAM_VOLUME = new int[] { 5, // STREAM_VOICE_CALL 7, // STREAM_SYSTEM 7, // STREAM_RING 15, // STREAM_MUSIC 7, // STREAM_ALARM 7, // STREAM_NOTIFICATION 15, // STREAM_BLUETOOTH_SCO 7, // STREAM_SYSTEM_ENFORCED 15, // STREAM_DTMF 15, // STREAM_TTS 15 // STREAM_ACCESSIBILITY }; 根据音量曲线表,一般情况音量等级最大可以设置为100。但是,有些音频音量调节并不经过音箱曲线表,而是直接调用HAL层的set_volume,而HAL层对音量又做了类似“音量曲线”的转换。所有修改音量级别,可能会有以下问题:

华硕老毛子Padavan使用IPV6+Aliddns远程管理路由

华硕老毛子Padavan使用IPV6+Aliddns远程管理路由 前言一、开启路由器的IPv6功能二、阿里云设置三、路由器设置 前言 由于IPv4一般获取到的都是大内网,想要远程管理又需要公网IP或者内网穿透,可能折腾来折腾去又一无所获,本文介绍的是利用IPv6+Aliddns的方法。 现在很多地区的宽带都可以获取到IPv6地址,那么还需要准备一个域名。本篇使用的是阿里云购买的域名,当然用其他网站的域名也可以,方式都大同小异。 话不多说,进入正文 一、开启路由器的IPv6功能 1.进入路由器管理页面——外部网络——ipv6设置,如图所示(自动获取IPv6 DNS功能可能无法获取到DNS地址,那就手动填写): 2.应用设置后路由器会重新获取IP地址,等待一段时间后查看路由器外部网络,会看见有IPv6 WAN地址和IPv6 LAN地址,说明已经成功获取到了IPv6地址。(如果这一步不能获取到IPv6地址,要么是光猫没有开启IPv6功能,要么是运营商还不支持,我这边是把光猫设置成了桥接模式,padavan拨号上网,光猫如何桥接请自行百度。) 二、阿里云设置 1.使用已有域名的账号登录阿里云官网https://dns.console.aliyun.com,在云解析dns控制台添加一条AAAA记录,记录值可以先随便写一个地址。 2.右上角头像进入AccessKey 管理。 3.这里推荐在弹出的安全提示中选择使用子用户。 4.进入后创建用户,勾选编程访问。 5.创建完成后会显示 AccessKey ID 和 AccessKey Secret,后面会用到。 6.勾选子用户为子用户添加权限,需要选择两个权限。 三、路由器设置 1.路由器管理页面——拓展功能——花生壳内网版——Aliddns,填写刚刚获取的Access Key ID和Access Key Secret,填入2.1步阿里云DNS解析上添加的AAAA记录中的主机名和你的域名,我这里的就是padavan.xxx.com,注意填的位置是第三个。 2.应用之后等待几分钟就可以在日志处查看到成功更新的提示。 3.接下来就是配置远程访问了。如果需要从家外面通过ipv6访问家里的padavan,就需要通过https协议来访问,进入系统管理——服务——内网 Web 服务 HTTPS 访问端口,设置一个自己喜欢的端口号(建议使用1024-65535之间的端口号) 同时要修改 进入高级设置——防火墙——通用设置,开启 允许外网 HTTPS 访问Web服务,端口号与上方一致。 4.在阿里云官网申请https证书。阿里云每年可以申请20个免费ssl证书,在官网首页搜索框搜索ssl,进入SSL证书控制台。 5.创建申请免费的证书。 6.这里填写的域名就是第2.1步DNS解析设置的,我的就是padavan.xxx.com,确定后系统自动验证,过几分钟后验证就会通过了。 7.验证通过后状态变为已签发,然后我们点下载证书。 8.选择其他。 9.下载后得到一个压缩文件,解压后里面有两个后缀名为.key和.pem的文件,都需要用到。 10.为padavan添加https证书,系统管理 - 服务-Web 服务器 HTTPS 证书,点开Server Certificate (required) ,粘贴.pem文件中复制到的内容;在Server Private Key (required)中粘贴.key文件中复制到的内容,保存设置。 11.想要访问IPv6的地址,本地也需要开启IPv6协议。Win10打开 Windows设置——网络和Internet——更改适配器选项——选择当前已经连接到网络的网卡,右键属性,勾选Internet协议版本6(TCP/IPv6)。 12.访问https://ipv6.ddnspod.com来确认当前设备是否具有ipv6地址,能打开网站并且显示了ipv6地址说明当前设备是可以访问ipv6网络的,否则说明当前设备并不能访问ipv6网络。 13.最后就可以通过https://域名:端口号 来直接访问路由器啦,我这里就是https://padavan.xxx.com:8443,是不是很简单呢。其他路由器通过ipv6来访问方法也都大同小异,这里就不多写了,最后感谢浏览。 内容到此结束,有不足之处请见谅。

【C语言|结构体】关于结构体初始化赋值

在GUN C中,支持通过标号元素来对指定结构体成员名进行初始化,这允许初始化值以任意顺序出现。 在Linux内核中对init_mm初始化时有如下代码。 #define INIT_MM_CONTEXT(name) \ .pgd = init_pg_dir, struct mm_struct init_mm = { .mm_rb = RB_ROOT, .pgd = swapper_pg_dir, .mm_users = ATOMIC_INIT(2), .mm_count = ATOMIC_INIT(1), .write_protect_seq = SEQCNT_ZERO(init_mm.write_protect_seq), MMAP_LOCK_INITIALIZER(init_mm) .page_table_lock = __SPIN_LOCK_UNLOCKED(init_mm.page_table_lock), .arg_lock = __SPIN_LOCK_UNLOCKED(init_mm.arg_lock), .mmlist = LIST_HEAD_INIT(init_mm.mmlist), .user_ns = &init_user_ns, .cpu_bitmap = CPU_BITS_NONE, INIT_MM_CONTEXT(init_mm) }; 其中对.pgd进行了两次赋值,第一次是.pgd = swapper_pg_dir,,而最后,又使用INIT_MM_CONTEXT宏对其进行了赋值,那结果如何呢? 请看如下测试代码: #include <stdio.h> #define __pr(x) printf("%-40s: %d\n", #x, x) struct test { int a; int b; int c; }; int main(void) { struct test val = { .

element-ui中table表格的折叠和隐藏

el-table 的折叠展开 今天使用elment-ui的el-table组件做表格的折叠和展开 使用 default-expand-all属性 通过click控制它为true或false来完成折叠展开 但是却没有效果!!! 通过查资料发现需要这样来写 <el-table v-if="refreshTable" :header-cell-style="{background:'#f4f3f9',color:'#606266'}" :data="deptList" style="width: 100%;margin-bottom: 20px;" row-key="id" :default-expand-all="Expand" :tree-props="{children: 'children', hasChildren: 'hasChildren' > -------------数据设置 data() { return { Expand: true, refreshTable: true, } } -------------鼠标点击事件 /** 展开/折叠操作 */ toggleExpandAll() { this.refreshTable = false this.Expand = !this.Expand this.$nextTick(() => { this.refreshTable = true }) }, 设置v-if table的显示和隐藏 设置default-expand-all 两个都要设置 向上面那样 最后成功了 也不知道具体 原理 先这样记住! 一起加油啊 ~~~ 最近发现之前那个方法有bug 很不好用 又找到一个简单好用得 this.$refs.table..toggleRowExpansion(this.tableData[0]) // 全部折叠 直接拿到table得dom元素, 然后调用element-ui的table表格得一个方法toggleRowExpansion就可以实现展开和折叠了

AD中画PCB详细流程

1.新建工程 先在电脑新建一个文件夹作为工程总文件夹,里面再新建三个子文件夹分别为BOM(Bill Of Materials)(物料清单)、PCB、SCH(Schematic)(原理图)如下图1.1.1 (注意:记住该路径,该工程所有文件都要存在此文件夹名下) 图1.1.1 2.打开Altium Designer,菜单栏选择文件—新建—Project,如图1.1.2 图1.1.2 3.修改文件名,然后保存,见图1.1.3 图1.1.3 右击工程文件—跟工程添加新的—Schematic/PCB—保存—修改名称。 见图1.1.4和图1.1.5(注意:后缀名不用改,保存后自动生成) 图1.1.4 图1.1.5 2.画原理图 在后缀为.SchDoc的文件中画原理图或者导入原理图原理图查错:菜单栏选择工程—Compile PCB Project...—Messages中双击报错可快速定位至出错位置—修改警告和错误(注意:切记务必查错,这一步很关键)导入PCB:菜单栏选择设计—Update PCB Document...—执行更改,完成后如图2.1.1所示 然后删除红色背景:鼠标放在红色区域空白处左击变白后按Delete(不删除红色背景的话,元件移出红色区域会变绿) 图2.1.1 3.布局布线 写在前面:布局布线的关键前提都是读懂电路图,尽量明确其原理、电流走向、每个模块和元件的作用,规划好其模块大致摆放位置。 3.1.1 布局原则 可以参考以下文章: 布局与布线原则:http://t.csdn.cn/E3092 布局技巧与要求:http://t.csdn.cn/x6drh 3.1.2布线原则 走线注意要素:http://t.csdn.cn/yUcli 4.滴泪 步骤:工具—滴泪(快捷键T+E) 泪滴设置及其作用:http://t.csdn.cn/mW9Yl 5.覆铜 步骤:放置—多边形敷铜(快捷键P+G) ​注意事项见图5.1 图5.1 6.PCB查错 步骤:PCB界面,点击工具—设计规则检测—运行DRC(快捷键T+D+R),见图6.1 AD运行DRC查错:http://t.csdn.cn/4hTCp ​最后,一些快捷键用法:http://t.csdn.cn/XGMGt 7.整理BOM http://t.csdn.cn/hTqKI 8.购买物料

【数据库】Oracle数据表相关操作(CREATE & INSERT INTO & TRUNCATE & TRUNCATE & MERGE INTO)、JOB注意事项

Oracle数据表相关操作、JOB注意事项 2022/9/1 周四 偶尔有Oracle库的报表需求,每次隔久了就忘记一些小细节,所以把抓数据时常用的操作(CREATE & INSERT INTO & TRUNCATE & TRUNCATE & MERGE INTO)记录一下,便于以后翻看。 (主要是针对我常用的,需要从已有数据表提取并大量插入新表的情况,其他内容还可以看我的第一篇博客:【数据库】MySQL,数据库和表的增删改,约束,数据类型) 1. CREATE 新建表 表不存在的情况下,直接在CREATE建表语句里,写对应抓取数据的sql就可以了: CREATE TABLE XXXX AS( SELECT * FROM XXXX WHERE ...... ); 这样数据也一并查出来在表里了 2. INSERT INTO 插入数据 表存在的情况下,需要每天插入数据,就在INSERT语句后面写抓取sql: INSERT INTO XXXX SELECT * FROM XXXX WHERE ......; COMMIT; 记得要提交 3. TRUNCATE 截断表/清空数据 需要全量更新的数据表,每天插入数据前需清空之前的数据: TRUNCATE TABLE XXXX; TRUNCATE与DELETE的区别: (1)truncate是DDL数据定义语言,不可回滚,而delete是DML数据操作语言,可回滚; (2)delete时会触发与表相关的触发器,而truncate不会; (3)delete可以有删除条件,truncate没有; (4)truncate会重置表的自增值,delete不会。 4. DROP 删除表 如果表字段需要变化,可以直接删除表再重新建: DROP TABLE XXXX; (是在每天全量更新表的基础上才这样做,反正每天数据都要重新抓) 5. MERGE INTO 插入和更新数据 简单来说就是,把来源表中的数据更新到目标表。相当于整合了INSERT和UPDATE,更快捷。

解决80端口被占用问题(关闭被占用端口,通用)

目录 1、win+R 输入cmd ,以管理员身份运行命令提示符 2、输入:netstat -ano 查看所有进程信息,找到对应80端口(本地地址下对应的例如:0.0.0.0:80)对应的PID 3、打开任务管理器,找到对应PID的应用进程(此时开启了Tomcat服务器了) 4、System进程占用 1、win+R 输入cmd ,以管理员身份运行命令提示符 图1 2、输入:netstat -ano 查看所有进程信息,找到对应80端口(本地地址下对应的例如:0.0.0.0:80)对应的PID 图2 3、打开任务管理器,找到对应PID的应用进程(此时开启了Tomcat服务器了) 图3 4、System进程占用 如果遇到是System进程占用80端口,那么我们不好将其直接关闭,则在命令提示符中再输入netsh http show servicestate 图4 再输入tskill PID (例如:tskill 15320 即可将该进程关闭 注:完整的命令是:taskkill /pid 15320 /f) 或者是转到任务管理其中,如图3,将其关闭,释放80端口。

统计学—常用统计量

统计学—常用统计量 一、均值 μ \mu μ一、样本均值 X ‾ \overline{X} X二、方差 σ \sigma σ二、样本方差 S 2 S^{2} S2三、标准差 σ 2 \sigma^2 σ2三、样本标准差 S S S四、样本的k阶原点矩五、样本的k阶中心矩一、期望三、原点矩四、中心距五、协方差与相关系数1、定义2、协方差的性质 六、为什么使用标准差?贝赛尔修正公式的选择平均值与标准差的适用范围及误用中部单峰: 一、均值 μ \mu μ $$ 一、样本均值 X ‾ \overline{X} X 所有数据之和除以数据点的个数;查看数据的平均水平; X ‾ = 1 n ∑ i = 1 n X i = x 1 + x 2 + x 3 + . . . + x n n \overline{X} = \frac{1}{n}\sum_{i=1}^{n}X_{i} =\frac{x_{1}+x_{2}+x_{3}+...+x_{n}}{n} X=n1​i=1∑n​Xi​=nx1​+x2​+x3​+...+xn​​

计算机毕业设计django基于python教学互动系统(源码+系统+mysql数据库+Lw文档)

项目介绍 在各学校的教学过程中,教学互动管理是一项非常重要的事情。随着计算机多媒体技术的发展和网络的普及,“基于网络的学习模式”正悄无声息的改变着传统的教室学习模式,“基于网络的教学互动平台”的研究和设计也成为教育技术领域的热点课题。采用当前流行的B/S模式以及3层架构的设计思想通过Python技术来开发此系统的目的是建立一个配合网络环境的可以师生互动的教学学习的平台,这样可以有效地解决课程管理混乱的局面。 本文首先介绍了教学互动系统管理技术的发展背景与发展现状,然后遵循软件常规开发流程,首先针对系统选取适用的语言和开发平台,根据需求分析制定模块并设计数据库结构,再根据系统总体功能模块的设计绘制系统的功能模块图,流程图以及E-R图。然后,设计框架并根据设计的框架编写代码以实现系统的各个功能模块。最后,对初步完成的系统进行测试,主要是功能测试、单元测试和性能测试。测试结果表明,该系统能够实现所需的功能,运行状况尚可并无明显缺点。 运行环境 开发语言:Python 框架:django/FALSK Python版本:python3.7.7 数据库:mysql 5.7(一定要5.7版本) 数据库工具:Navicat11 开发软件:PyCharm 浏览器:谷歌浏览器 功能介绍 本系统是基于校园,以方便老师和学生的交流、提高教学效率为目的。系统拟有的主要功能有: ⑴课件上传功能:向学生发布课程资料教案; ⑵个人资料修改功能:实现教师或学生个人资料的录入或修改; ⑶留言板:通过留言板回答学生问题以及问题讨论; ⑷发帖功能:一些问题,错误可以发帖询问,别的学生可以回复。 效果图 目 录 摘 要 I ABSTRACT II 目 录 II 第1章 绪论 1 1.1背景及意义 1 1.2 国内外研究概况 1 1.3 研究的内容 1 第2章 相关技术 3 2.1 Python简介 4 2.2 Django 框架介绍 6 2.3 B/S结构 4 2.4 MySQL数据库 4 第3章 系统分析 5 3.1 需求分析 5 3.2 系统可行性分析 5 3.2.1技术可行性:技术背景 5 3.2.2经济可行性 6

Unsupported platform for fsevents@1.2.13: wanted {“name“:“fsevents“,“version“:“1.2.13“,“engines“:

VUE使用NPM安装组件时出现如下错误: Unsupported platform for fsevents@1.2.13: wanted {“name”:“fsevents”,“version”:“1.2.13”,“engines”:{“node”:“>= 4.0”},“os”:[“darwin”],“dependencies”:{“bindings”:“1.5.0",“nan”:"2.12.1”},“optionalDependencies”:{},“peerDependenciesMeta”:{},“devDependencies”:{},“bundleDependencies”:false,“peerDependencies”:{},“deprecated”:“fsevents 1 will break on node v14+ and could be using insecure binaries. Upgrade to fsevents 2.”,“_resolved”:“https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz”,“_integrity”: 有几种解决办法: 1.删除package.json中的fsevents依赖 2.更新系统中所有 fsevents@1.2.13至 fsevents@2.3.2以上保存即可

CJSON库的学习

目录 一、JSON简介 二、 JSON语法 ​​​​​​三、 CJSON简介: 四、 CJSON数据结构 五、使用CJSON构造JSON 1. cJSON常用库函数介绍 2. CJSON构造JSON实例代码 (1)!!!编译过程中有两个注意的点: 3. 使用cJSON解析JSON实例代码 一、JSON简介 JSON(JavaScript object Notation),即JavaScript 对象符号,是一种轻量级的数据格式;【其本质就是字符串】 它采用完全独立于编程语言的文本格式来存储和表示数据,语法简洁,层次结构清晰,易于人阅读和编写,同时也易于机器解析和生成,有效的提升了网络传送效率。 因为它完全独立于编程语言所以支持跨平台开发; JSON 的名称中虽然带有JavaScript,但这是指其语法规则是参考JavaScript对象的,而不是指只能用于JavaScript 语言。 因为JSON本身就是参考JavaScript 对象的规则定义的,其语法与JavaScript定义对象的语法几乎完全相同。 二、 JSON语法 JSON可以将数据转换为字符串,接着在网络中或者程序里面传递这个字符串,最后可以还原成各个编程语言所支持的数据格式; JSON是一个无序的键值对(key / value)集合; JSON以"{“开始,以”}"结束,允许嵌套使用每个key(关键字)和value(值)成对出现,关键字和值之间使用":"分隔键/值对之间用","分隔在这些字符前后允许存在无意义的空白符数组(Array)用方括号(“[]”)表示。对象(0bject)用大括号(“{}”)表示。名称/值对(name/value)组合成数组和对象。名称(name)置于双引号中,值(value)有字符串、数值、布尔值、null、对象和数组。并列的数据之间用逗号(“,”)分隔 在线的JSON解析网站如下:JSON解析 如下是一个实际的例子,来体会一下JSON: { "name": "JK", "age": 18, "height": 175, "sex": false, "address": { "country": "China", "tel": 123456 }, "subject": ["语文", "数学", "英语"], "grade": [1, 2, 3], "student": [{ "name": "wsf", "age": 23, "sex": true }, { "

快速排序(三种方法实现)

文章目录 1. 快速排序<1>hoare法(左右指针法)<2>挖坑法<3>前后指针法<4>快速排序优化<5>非递归实现 2.特性 1. 快速排序 (1)思想 快速排序是Hoare于1962年提出的一种二叉树结构的交换排序方法,其基本思想为:任取待排序元素序列中的某元素作为基准值,按照该排序码将待排序集合分割成两子序列,左子序列中所有元素均小于基准值,右子序列中所有元素均大于基准值,然后最左右子序列重复该过程,直到所有元素都排列在相应位置上为止。 <1>hoare法(左右指针法) (1)画图理解 取最左边key为基准值,用right指针找比key值小的元素,用left指针找比key位置大的元素,将两位置值进行交换,最后,将key值放在二者相遇位置上,就可保证key左边都是比key小的值,右边都是比key大的值,然后进行递归即可实现,从相遇点分割成两部分,在分别对左右两部分重复上述排序。 (2) 代码思路 //-----------------------快排-------------------/ int HoareSort(int* a, int begain, int end) { int key = begain; int left = begain, right = end; while (left < right) { //右边找比key小的值 while (left < right && a[right] >= a[key]) right--; //左边找比key大的值 while (left < right && a[left] <= a[key]) left++; swap(&a[right], &a[left]); } int meeti = left; swap(&a[meeti], &a[key]); return meeti; } void QuickSort(int* a, int begain, int end) { //递归返回条件如果该区间只有一个值或没有值则返回 if (begain >= end) return; int meeti = HoareSort(a, begain, end); QuickSort(a, begain, meeti - 1); QuickSort(a, meeti + 1, end); } <2>挖坑法 (1)画图理解

SQL Server Reporting Services

文章目录 安装配置开发 安装 找到SQL的安装中心: 点击安装SQL Server Reporting Services: 下载和安装: 配置 配置报表服务器,连接: Web服务URL,点击应用: 数据库,更改数据库,创建新的报表服务器数据库: 浏览网页:http://127.0.0.1/ReportServer 如果打开500或者503报错,参考https://blog.csdn.net/weixin_29431461/article/details/120879158。 Web门户URL,点击应用: 浏览网页:http://win10-2022wcacw/Reports/browse/ 开发 下载报表生成器:https://www.microsoft.com/en-us/download/details.aspx?id=53613 安装报表生成器,ReportBuilder.msi: 编辑器的配置,文件-选项,设置: 打开报表,编辑保存,另存到报表服务器:

SkyWalking 安装部署

SkyWalking 安装部署 目录 SkyWalking 安装部署一、介绍二、前置步骤三、下载安装四、`SkyWalking` 的配置4.1 对 `oap` 进行配置4.2 对 `webapp` 进行配置4.3 对 `agent` 进行配置 五、启动六、总结 一、介绍 本次安装部署为最简化安装部署流程。 二、前置步骤 安装 JDK dnf -y install java wget 安装 ElasticSearch7 三、下载安装 本次演示使用的是 8.5.0 - ES7 版本,小伙伴们可以在 skywalking 官网 自行选择合适的版本。 tar -zxvf apache-skywalking-apm-es7-8.5.0.tar.tar.gz 四、SkyWalking 的配置 在服务器解压完毕后,我们将分三步进行,完成整体 SkyWalking 的配置。 Skywalking 主要分为 oap 、webapp 和 agent 三部分, oap 用于汇总数据。webapp 用于汇总数据的展示。agent 是探针,部署在需要收集数据的应用服务器上,并将数据同步到Skywalking的平台。 oap 和 webapp这两块共同组成了Skywalking的平台 4.1 对 oap 进行配置 进入 config 文件夹, application.yml 文件夹进行编辑。 下面将进行集群配置、存储配置、自监控空配置。

快速了解德国TRINAMIC运动控制芯片(TMC电机驱动芯片)

德国TRINAMIC是全球嵌入式电机运动控制领导品牌,在设计和销售运动控制芯片,模块,机电一体化产品具有20多年经验。 人类环境的自动化发展趋势使得自动控制爆发式增长。产品研发工程师必须处理越来越多的复杂系统,不可能在每个技术方面都是专家。TRINAMIC设计的芯片带有综合性的设计包,参考设计,电路图和例子代码,为工程师提供设计的基础。 TRINAMIC的专业的运动控制芯片运用范围极广,包括实验室和工厂自动化,半导体设备,纺织设备,机器人,AGV,ATM,自动售货机,医疗诊断设备,智能假肢等等。 划 重 点 Trinamic电机驱动芯片中国区代理-卓联微 1:运动控制芯片 SPI芯片:一个芯片具有双向通讯接口用于发送运动指令和上传诊断信息保持所需要的查询量最低。只需要一个来自微控制器的低速度的SPI接口实现极度的小型化,设计简单。SPI芯片允许对微步表格的完全控制,在运动过程中对微步的无缝更改也是可能的。为了优化电机的需求微步表格在运动控制芯片里是可以修改的。 2:脉冲/方向芯片 支持脉冲/方向的驱动器和控制器简化了步进电机的控制脉冲/方向接口被广泛用于工业,因此被预留出兼容方案。尤其在高细分和高频脉冲,SD框架相比SPI和PWM接口来说减少了对带宽的要求。SPI用于设置和下至功率放大部分的诊断信息的反馈通道。 3:步进电机驱动芯片 小体积电路板芯片:TRINAMIC的步进驱动芯片集成了最先进的相序分配和功放 通过减少外部器件,TRINAMIC的步进电机驱动芯片可以做到最小系统。通过最新的电流控制技术,工程师可以开发出静音,高效精密和经济的产品。 4:步进电机驱动SPI芯片 通过采用最新的晶体管开关技术,TRINAMIC的许多步进电机驱动芯片降低了功耗,在其所有的电流范围之后不需要增加任何散热片。这一点降低了系统的功率损失和整个系统的成本。先进的诊断功能提供了连续的系统状态。 5:单轴芯片 TRINAMIC的cDriver是一个集成系统方案。运动控制和驱动集成在一个芯片内。集成一个精细的坡形发生器用于自动定位到目标位置带有工业先进的步进电机驱动。高集成,高能量效率,小型结构使其满足小体积和可拓展系统高性价比方案。TRINAMIC的cDriver将数字信号直接转化成物理运动。 6:双轴芯片 对于监控摄像头,办公室自动化设备或者输液泵这类产品, 需要多个可靠的步进电机,但是结构要小。双轴的cDriver就是一个完美的方案。高度集成化使得每轴平均成本很低,减少系统成本,同时集成了先进斜坡控制从而缩短开发周期,减少开发投入。 7:步进电机预驱动芯片 大功率驱动。设置成预驱动加外扩功率管允许根据客户的电机最大电流灵活配置。TRINAMIC所有的预驱动芯片带有通过SPI的全部诊断功能。通过TRINAMIC独一无二的先进电流控制功能所有的TRINAMIC步进驱动芯片,可以提供精密和平滑的微步。 8:实时通讯芯片 实时通讯芯片:EtherCAT是一种高性能,低成本,容易使用的工业以太网技术带有灵活拓扑性能。EtherCAT是一种速度最快的工业以太网技术,可以达到纳秒级的同步精度。TRINAMIC的从站控制芯片连接最优化的嵌入式运动和电机控制应用到快速的现成总线,可以实现分布式设备的精确同步。 9:直流无刷电机预驱动 在EMC可靠和高能效场合,直流无刷电机逐渐取代直流有刷电机。通过正弦波换向直流无刷,保证运行安静,高效驱动用于采暖通风领域。装备高分辨率的反馈系统和矢量控制是强大伺服驱动的最佳方案。 10:嵌入式伺服控制芯片 在同步机器控制技术中,伺服控制充当关键角色。矢量控制被大量采用,但是执行起来需要占用大量时间。TRINAMIC以卓越的芯片性能来控制三相同步伺服电机和两相步进电机,帮助用户节省大量开发时间。 11:直流伺服控制系统级芯片 TMCC160集成了功率预驱动和Cortex-M4微处理器并集成了矢量控制软件,可以直接使用TMCL-IDE软件控制,保证硬件设计尽可能的简单和尽量减少外部器件。TMCC160包含了嵌入式运动控制系统的所有核心部分。

1.基于正点原子STM32F103外部中断实验(HAL库实现)(cubeMX)

目录 1.简介 2.配置STM32cubeMX 1.新建文件,芯片选型 2.sys设置和RCC设置 3.配置GPIO输出 4.配置中断输入并开启中断 5.配置时钟 6.设置项目名称以及代码生成设置 3.Keil5里面打开工程并且编写程序 1.简介 这里单片机型号是正点原子F103ZET6精英板,keil5的版本是V5.14,cubeMX的版本是6.6.1 对于STM32的外部中断,中断请求源是外部的IO信号,而产生中断的方法就是通过外部IO口的电平变化,但是值得注意的是,STM32的每个IO口都可以作为外部中断的输入口。STM32F103 的中断控制器支持 19 个外部中断/事件请求,每个中断设有状态位,每个中断/事件都有独立的触发和屏蔽设置,STM32F103 的 19 个外部中断为: EXTI 线 0~15:对应外部 IO 口的输入中断。 EXTI 线 16:连接到 PVD 输出。 EXTI 线 17:连接到 RTC 闹钟事件。 EXTI 线 18:连接到 USB 唤醒事件。 EXTI 线 19:连接到以太网唤醒事件。 这是GPIO和中断线的映射关系,可以看出每一个GPIO组的编号相同的IO口被分配在同一根中断线上,但是中断线每次只能连接一个IO口,所以我们要根据要求来判断中断线具体在哪一个IO口上。 硬件的使用不过多介绍,这里我们使用的是中断来检测按键, KEY0控制 DS0,按一次亮,再按一次灭;KEY1 控制 DS1,效果同上;WK_UP 则控制蜂鸣器。 引脚对应关系: PB5-DS0 (低电平亮) PE5-DS1 (低电平亮) PB8-BEEP (高电平发声) PE4-KEY0 (低电平有效) PE3-KEY1 (低电平有效) PA0-WK_UP (高电平有效) 2.配置STM32cubeMX 1.新建文件,芯片选型 选好之后点击Start Project,创建工程模板 2.sys设置和RCC设置 3.配置GPIO输出 注意:都要设置成推挽输出模式

socket编程之socket()

1 socket() socket() 创建用于通信的终结点,并返回引用该终结点的文件描述符。成功调用返回的文件描述符是当前未被调用socket()的进程占用的最小的文件描述符。 1.1 包含头文件 #include <sys/types.h> #include <sys/socket.h> //包含域参数所需要的各种网络协议 1.2 函数主体 int socket(int domain, int type, int protocol); //例如: int clt = socket(AF_INET, SOCK_STREAM | SOCK_NONBLOCK, 0); 参数解释: int domain 域参数指定通信域,即选择用什么样的通信协议,包括 AF_UNIX,、AF_LOCAL、AF_INET、AF_INET6、AF_IPX、AF_ALG等等。目前主要使用的为**AF_LOCAL(用于本地进程间的通信)、AF_INET(用于IPv4协议)。**其余的有需要时在做补充。 int type 套接字具有指示的类型,该类型指定通信语义,包括SOCK_STREAM、SOCK_DGRAM、SOCK_SEQPACKET、SOCK_RAW 、SOCK_RDM等。目前主要使用的为**SOCK_STREAM(实现TCP字节流通信。可能支持带外数据传输机制。)、SOCK_DGRAM(实现UDP数据报通信)。**其余的有需要时在做补充 从 Linux 2.6.27 开始,类型参数还可以实现对socket的进一步控制,通过按为OR操作实现以下操作: SOCK_NONBLOCK : 设置socket为非阻塞类型,在此处设置可以节省对fcntl的额外调用,进一步减小开销 SOCK_CLOEXEC : 在进程调用exec函数族时,文件描述符就会自动关闭,无需手动关闭。 这里对SOCK_CLOEXEC和带外数据(out-of-band data)作进一步解释(新手可以不看): 在多进程的场景中,在fork()函数后,由于子进程会拷贝父进程几乎所有的内容,这其中就包括了父进程打开的文件描述符,因此子进程和父进程使用的是相同的文件描述符。但是,当子进程执行exec()函数族时,由于子进程会使用新的内容覆盖父进程所有的数据,这其中就包括打开的文件描述符,此时打开的文件描述符就无法关闭了,因此在调用exec函数族前需要手动关闭文件描述符。而设置此参数即可以避免这种情况 带外数据(out-of-band data)是指建立连接双方中的一方有重要的事情需要及时通知对方,这种数据成为带外数据,发送优先级要高于带内数据(在消息缓存队列中排队的数据成为“带内数据”),带外数据发送不需要建立新的连接。对带外数据的实现一般使用BSD的紧急数据指针方式,需要接收方通过判断read()函数的返回值来判断带外数据。 int protocol 用来指定协议的特类型,一般设置为0,表示接收协议的任何类型,后续的处理由应用程序自己实现。 1.3 返回值 成功后,将返回新套接字的文件描述符。出错时,返回 -1,并正确设置 errno,错误类型如下: 错误类型解释EACCES创建指定类型和/或协议的套接字的权限被拒绝。EAFNOSUPPORT不支持指定的地址系列。EINVAL未知的协议,或协议系列不可用。或类型中的标志无效。EMFILE已达到每个进程对打开的文件描述符数的限制。ENFILE已达到系统范围内对打开的文件总数的限制。ENOBUFS or ENOMEM可用内存不足。 在释放足够的资源之前,无法创建套接字。EPROTONOSUPPORT此域中不支持协议类型或指定的协议。 1.4 结束 socket()函数介绍至此结束,虽然这个函数的使用一般来说并不会出错,但是建议养成良好的编程习惯,每次调用都对器返回值进行判断。

Python 基于OpenCV+face_recognition实现人脸捕捉与人脸识别(照片对比)

1.安装包依赖 与上篇通过摄像头动态识别人脸一样,先下载好opencv-python、face-recognition,这里因为使用的是照片对比的方式,特意使用tkinter画了一个简单的GUI方便操作。 在python 3以上版本tkinter是环境自带的,所以这里不需要安装 2.代码示例 import os import cv2 import numpy as np import face_recognition import tkinter as tk import tkinter.filedialog from PIL import Image,ImageTk classNames=[] img_path='Picture' img_recognition_path='Recognition' existsEncodeingList=[] #对人脸集合进行编码进行处理 def findEncodeings(images): for img in images: #灰度处理 img=cv2.cvtColor(src=img,code=cv2.COLOR_BGR2RGB) #face_encodings对图片对象a_images进行编码并返回数组0位置编码结果 encode=face_recognition.face_encodings(img)[0] existsEncodeingList.append(encode) #获取当前存储的人脸编码集合 def findExistsEncodeingList(img_path): images=[] #列出已经上传的所有图片 imgList=os.listdir(img_path) #处理存储的图片得到其人脸编码 for pic in imgList: img=cv2.imread('{}/{}'.format(img_path,pic)) images.append(img) classNames.append(os.path.splitext(pic)[0]) findEncodeings(images) #选择并对比图片 def choosepic(): choosepath = tkinter.filedialog.askopenfilename() path.set(choosepath) img_open = Image.open(entry.get()).resize((530,750)) img = ImageTk.PhotoImage(img_open) lableShowImage.

RedHat Linux修改SSHD默认22端口

1、查看并修改当前安全配置 sestatus getenforce 若返回为Enforcing,则执行 setenforce 0 并编辑安全配置文件 vi /etc/selinux/config # 将 SELINUX=enforcing 修改为 SELINUX=permissive 2、修改SSHD配置 vi /etc/ssh/sshd_config 比如 : 2022 端口 #Port 22 Port 2022 3、重新服务 systemctl restart sshd systemctl status sshd 最后,重新登录通过新的端口进行验证 查看日志 journalctl -xe

关于Flask高级_上传文件与访问文件的方法

一.上传文件步骤 在模版html中,表单需要指定 enctype=‘multipart/form-data’ 才能上传文 件。 在后台如果想要获取上传的文件,那么应该使用 request.files.get(‘文件 名’) 来获取。 保存文件之前,先要使用 werkzeug.utils.secure_filename 来对上传上来的文 件名进行一个过滤。能保证不会有安全问题。 获取到上传上来的文件后,使用 文件对象.save(路径) 方法来保存文件。 路径=完整路径=路径名+文件名 二.实例 main.py: #coding=utf-8 from flask import Flask,render_template,request,send_from_directory import os from werkzeug.utils import secure_filename app = Flask(__name__) UPLOAD_PATH = os.path.join(os.path.dirname(__file__),'imgs') @app.route('/') def index(): return 'Hello~' @app.route('/upload/',methods=['GET','POST']) def upload(): if request.method == 'GET': return render_template('upload.html') else: fpic = request.files.get('pic') #让文件名安全转换,保证文件名没有错误 filename = secure_filename(fpic.filename) fpic.save(os.path.join(UPLOAD_PATH,filename)) return '上传成功!' @app.route('/download/<filename>/') def download(filename): return send_from_directory(UPLOAD_PATH,filename) if __name__ == '__main__': app.

Docker仓库管理镜像 -- 公共仓库【Docker Hub】和私人仓库【Registry】和【harbor】

镜像仓库管理 docker仓库,用来管理镜像。主要分为公共仓库和私人仓库。下面介绍了公共仓库Docker Hub、私人仓库Registry和harbor。 DockerHUb仓库管理 什么是DockerHUb 保存和分发镜像的最直接方法就是使用 Docker Hub。 ​ Docker Hub 是 Docker 公司维护的公共 Registry。用户可以将自己的镜像保存到 Docker Hub 免费的 repository 中,如果不希望别人访问自己的镜像,也可以购买私有 repository。 账号注册和登陆 一般,你需要先在docker中心创建一个账户(如果您尚未有)。你可以直接在Docker Hub创建你的账户。 如果有已有账号可以点击sign in 进行登录,登陆后是这个样子 Docker客户端登录 使用docker login登录dockerhub ​ 这将提示您输入用户名,这个用户名将成为你的公共存储库的命名空间名称。如果你的名字可用,docker会提示您输入一个密码和你的邮箱,然后会自动登录到Docker Hub,你现在可以提交和推送镜像到Docker Hub的你的存储库。 docker login 出现 Login Succeeded就说明我们登录成功 注:你的身份验证凭证将被存储在你本地目录的.dockercfg文件中 管理镜像 通过docker images可以看到我们所有的镜像列表 docker images [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yh2EyQc0-1661931669726)(C:/Users/baiyp/AppData/Roaming/Typora/typora-user-images/image-20210517112922229.png)] 删除镜像 我们现在的learn-docker-storage有三个版本,现在我们把前两个有问题的版本删除,docker rmi 镜像ID可以删除镜像 docker rmi learn-docker-storage:0.0.1 learn-docker-storage:0.0.2 这样我们就删除了我们没有用的镜像了,可以节省内存空间 修改镜像命名 修改镜像的 repository 使之与 Docker Hub 账号匹配。 ​ Docker Hub 为了区分不同用户的同名镜像,镜像的 registry 中要包含用户名,完整格式为:[用户名]/镜像名:tag 我们通过 docker tag 命令重命名镜像

Vue模式对应的环境变量配置及使用场景

1.Vue的模式 development 模式用于 vue-cli-service serve (开发环境)test 模式用于 vue-cli-service test:unit (测试环境 --- 一般开发中为确保项目不会出错,都会设置测试环境供测试人员进行测试,也就是test )production 模式用于 vue-cli-service build 和 vue-cli-service test:e2e (生产环境) 也就是package.json中对应的代码片段,通过在node中运行对应的命令来匹配不同的环境 当运行行 vue-cli-service 命令时,所有的环境变量都从对应的环境文件中载入,以下图为例,我们当前想在测试环境就运行:npm run build:test 打包后的文件就是test环境 ,而执行npm run dev就是我们的开发环境啦 像Vue官网说的我们可以通过--mode 选项参数为命令行覆写默认的模式。例如,如果你想要在构建命令中使用开发环境变量(上图代码也是如此实现): vue-cli-service build --mode development 还有其他选项修饰符比如 --open 在我们启动项目时可自动在浏览器中打开项目: 命令的使用具体可参考Vue官网: CLI 服务 | Vue CLI 2.配置环境变量 项目中以.env.mode开头的文文件会在对应的环境下被载入,如下图:当我们执行npm run build:test时.env.test文件会被自动加载 .env.[mode] # 只在指定的模式中被载入 NODE_ENV 变量决定运行的模式,是开发,生产还是测试,也决定了创建哪种 webpack 配置。 例如通过将 NODE_ENV 设置为 "test",Vue CLI 会创建一个优化过后的,并且旨在用于单元测试的 webpack 配置,它并不会处理图片以及一些对单元测试非必需的其他资源。 同理,NODE_ENV=development 创建一个 webpack 配置,该配置启用热更新,不会对资源进行 hash 也不会打出 vendor bundles,目的是为了在开发的时候能够快速重新构建。

js 正则表达式判断数字和数字范围

判断数字的正则表达式: /^\d+$/ //非负整数(正整数 + 0) /^[0-9]*[1-9][0-9]*$/ //正整数 /^((-\d+)|(0+))$/ //非正整数(负整数 + 0) /^-[0-9]*[1-9][0-9]*$/ //负整数 /^-?\d+$/ //整数 /^\d+(\.\d+)?$/ //非负浮点数(正浮点数 + 0) /^(([0-9]+\.[0-9]*[1-9][0-9]*)|([0-9]*[1-9][0-9]*\.[0-9]+)|([0-9]*[1-9][0-9]*))$/ //正浮点数 /^((-\d+(\.\d+)?)|(0+(\.0+)?))$/ //非正浮点数(负浮点数 + 0) /^(-(([0-9]+\.[0-9]*[1-9][0-9]*)|([0-9]*[1-9][0-9]*\.[0-9]+)|([0-9]*[1-9][0-9]*)))$/ //负浮点数 /^(-?\d+)(\.\d+)?$/ //浮点数 使用例: test var r = /^[0-9]*[1-9][0-9]*$/ ; //正整数 var t = 3; var s = 3.2; alert("整数:"+r.test(t)); //true alert("小数:"+r.test(s)); //false

数组去重方法

1.放入set集合 2.双指针去重 class Solution1 { public int removeDuplicates2(int[] nums) { Set<Integer> set = new TreeSet(); for (int i = 0; i < nums.length; i++) { set.add(nums[i]); } int index = 0; for (Integer res : set) { nums[index] = res; index++; } System.out.println(set); return index; } public int removeDuplicates3(int[] nums) { int length = nums.length; if (length == 0) { return 0; } int flag1 = 1, flag2 = 1; while (flag1 < length) { if (nums[flag1] !

【Java】多线程编程面试题总结

Java多线程编程面试题总结 1. 进程和线程之间有什么不同? 一个进程是一个独立(self contained)的运行环境,它可以被看作一个程序或者一个应用。而线程是在进程中执行的一个任务。Java运行环境是一个包含了不同的类和程序的单一进程。线程可以被称为轻量级进程。线程需要较少的资源来创建和驻留在进程中,并且可以共享进程中的资源。 2. 多线程编程的好处是什么? 在多线程程序中,多个线程被并发的执行以提高程序的效率,CPU不会因为某个线程需要等待资源而进入空闲状态。多个线程共享堆内存(heap memory),因此创建多个线程去执行一些任务会比创建多个进程更好。举个例子,Servlets比CGI更好,是因为Servlets支持多线程而CGI不支持。 3. 用户线程和守护线程有什么区别? 当我们在Java程序中创建一个线程,它就被称为用户线程。一个守护线程是在后台执行并且不会阻止JVM终止的线程。当没有用户线程在运行的时候,JVM关闭程序并且退出。一个守护线程创建的子线程依然是守护线程。 4. 我们如何创建一个线程? 有两种创建线程的方法:一是实现Runnable接口,然后将它传递给Thread的构造函数,创建一个Thread对象;二是直接继承Thread类。若想了解更多可以阅读这篇关于如何在Java中创建线程的文章。 5. 有哪些不同的线程生命周期? 当我们在Java程序中新建一个线程时,它的状态是New。当我们调用线程的start()方法时,状态被改变为Runnable。线程调度器会为Runnable线程池中的线程分配CPU时间并且讲它们的状态改变为Running。其他的线程状态还有Waiting,Blocked 和Dead。读这篇文章可以了解更多关于线程生命周期的知识。 6. 可以直接调用Thread类的run()方法么? 当然可以,但是如果我们调用了Thread的run()方法,它的行为就会和普通的方法一样,为了在新的线程中执行我们的代码,必须使用Thread.start()方法。 7. 如何让正在运行的线程暂停一段时间? 我们可以使用Thread类的Sleep()方法让线程暂停一段时间。需要注意的是,这并不会让线程终止,一旦从休眠中唤醒线程,线程的状态将会被改变为Runnable,并且根据线程调度,它将得到执行。 8. 你对线程优先级的理解是什么? 每一个线程都是有优先级的,一般来说,高优先级的线程在运行时会具有优先权,但这依赖于线程调度的实现,这个实现是和操作系统相关的(OS dependent)。我们可以定义线程的优先级,但是这并不能保证高优先级的线程会在低优先级的线程前执行。线程优先级是一个int变量(从1-10),1代表最低优先级,10代表最高优先级。 9. 什么是线程调度器(Thread Scheduler)和时间分片(Time Slicing)? 线程调度器是一个操作系统服务,它负责为Runnable状态的线程分配CPU时间。一旦我们创建一个线程并启动它,它的执行便依赖于线程调度器的实现。时间分片是指将可用的CPU时间分配给可用的Runnable线程的过程。分配CPU时间可以基于线程优先级或者线程等待的时间。线程调度并不受到Java虚拟机控制,所以由应用程序来控制它是更好的选择(也就是说不要让你的程序依赖于线程的优先级)。 10. 在多线程中,什么是上下文切换(context-switching)? 上下文切换是存储和恢复CPU状态的过程,它使得线程执行能够从中断点恢复执行。上下文切换是多任务操作系统和多线程环境的基本特征。 11. 你如何确保main()方法所在的线程是Java程序最后结束的线程? 我们可以使用Thread类的joint()方法来确保所有程序创建的线程在main()方法退出前结束。这里有一篇文章关于Thread类的joint()方法。 12.线程之间是如何通信的? 当线程间是可以共享资源时,线程间通信是协调它们的重要的手段。Object类中wait()\notify()\notifyAll()方法可以用于线程间通信关于资源的锁的状态。点击这里有更多关于线程wait, notify和notifyAll. 13.为什么线程通信的方法wait(), notify()和notifyAll()被定义在Object类里? Java的每个对象中都有一个锁(monitor,也可以成为监视器) 并且wait(),notify()等方法用于等待对象的锁或者通知其他线程对象的监视器可用。在Java的线程中并没有可供任何对象使用的锁和同步器。这就是为什么这些方法是Object类的一部分,这样Java的每一个类都有用于线程间通信的基本方法 14. 为什么wait(), notify()和notifyAll()必须在同步方法或者同步块中被调用? 当一个线程需要调用对象的wait()方法的时候,这个线程必须拥有该对象的锁,接着它就会释放这个对象锁并进入等待状态直到其他线程调用这个对象上的notify()方法。同样的,当一个线程需要调用对象的notify()方法时,它会释放这个对象的锁,以便其他在等待的线程就可以得到这个对象锁。由于所有的这些方法都需要线程持有对象的锁,这样就只能通过同步来实现,所以他们只能在同步方法或者同步块中被调用。 15. 为什么Thread类的sleep()和yield()方法是静态的? Thread类的sleep()和yield()方法将在当前正在执行的线程上运行。所以在其他处于等待状态的线程上调用这些方法是没有意义的。这就是为什么这些方法是静态的。它们可以在当前正在执行的线程中工作,并避免程序员错误的认为可以在其他非运行线程调用这些方法。 16.如何确保线程安全? 在Java中可以有很多方法来保证线程安全——同步,使用原子类(atomic concurrent classes),实现并发锁,使用volatile关键字,使用不变类和线程安全类。在线程安全教程中,你可以学到更多。 17. volatile关键字在Java中有什么作用? 当我们使用volatile关键字去修饰变量的时候,所以线程都会直接读取该变量并且不缓存它。这就确保了线程读取到的变量是同内存中是一致的。 18. 同步方法和同步块,哪个是更好的选择? 同步块是更好的选择,因为它不会锁住整个对象(当然你也可以让它锁住整个对象)。同步方法会锁住整个对象,哪怕这个类中有多个不相关联的同步块,这通常会导致他们停止执行并需要等待获得这个对象上的锁。 19.如何创建守护线程? 使用Thread类的setDaemon(true)方法可以将线程设置为守护线程,需要注意的是,需要在调用start()方法前调用这个方法,否则会抛出IllegalThreadStateException异常。 20. 什么是ThreadLocal? ThreadLocal用于创建线程的本地变量,我们知道一个对象的所有线程会共享它的全局变量,所以这些变量不是线程安全的,我们可以使用同步技术。但是当我们不想使用同步的时候,我们可以选择ThreadLocal变量。

解决win10安装portal v13/v15要求反复重启问题

win+r运行regedit 打开注册表编辑器 删除HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager下面的键值PendingFileRenameOperations就可以继续安装了。 注意: 1. 删除后不要再重新启动计算机了,直接安装就可以了。 2. 安装过程中还要被要求重新启动计算机一次,重启后,再被提示重新启动计算机时,再次删除注册表中以上键值,不要重启,继续安装即可。

xml文件的解析--libxml库函数解析(二)

libxml(二) 写属性 写属性类似于给一个新元素写文本。在这个例子中,我们将添加一个reference结点URI属性到我们的文档中。完整代码:附录F,添加属性例程代码。reference是story元素的一个子结点,所以找到并插入新元素及其属性是简单的。一旦我们在parseDoc进行了错误检查,我们将在正确的位置加放我们的新元素。但进行之前我们需要定义一个此前我们不见过的数据类型。 xmlAttrPtr newattr; 我们也需要xmlNodePtr: xmlNodePtr newnode; 剩下的parseDoc则和前面一样,检查根结点是否为story。如果是的,那我们知道我们将在指定的位置添加我们的元素。 ① newnode = xmlNewTextChild (cur, NULL, "reference", NULL); ②newattr = xmlNewProp (newnode, "uri", uri); ①使用xmlNewTextChild函数添国一个新结点到当前结点位置。 一旦结点被添加,文件应像前面的例子将我们添加的元素及文本内容写入磁盘。 取得属性 取得属性值类似于前面我们取得一个结点的文本内容。在这个例子中,我们将取出我们在前一部分添加的URI的值。完整代码:附录G,取得属性值例程代码。 这个例子的初始步骤和前面是类似的:解析文档,查找你感兴趣的元素,然后进入一个函数完成指定的请求任务。在这个例子中,我们调用getReference。 void getReference (xmlDocPtr doc, xmlNodePtr cur) { xmlChar *uri; cur = cur->xmlChildrenNode; while (cur != NULL) { if ((!xmlStrcmp(cur->name, (const xmlChar *)"reference"))) { ① uri = xmlGetProp(cur, "uri"); printf("uri: %s\n", uri); xmlFree(uri); } cur = cur->next; } return; } ① 关键函数是xmlGetProp,它返回一个包含属性值的xmlChar。在本例中,我们仅仅打印它。

xml文件的解析--libxml库函数解析(一)

libxml(一) 摘要 Libxml是一个有免费许可的用于处理XML、可以轻松跨越多个平台的C语言库。这个指南提供它的基本函数的例子。 绪论 Libxml是一个实现读、创建及操纵XML数据功能的C语言库。这个指南提供例子代码并给出它基本功能的解释。在这个项目的主页上有Libxml及更多关于它可用的资料。包含有完整的API文档。这个指南并不能替代这些完整的文档,但是阐明功能需要使用库来完成基本操作。 这个指南基于一个简单的XML应用,它使用我写的一篇文章生成,它包含有元数据和文章的主体。 本指南中的例子代码示范如何做到: • 解析文档 • 取得指定元素的文本 • 添加一个元素及它的内容 • 添加一个属性 • 取得一个属性的值 例子的完整代码包含在附录中 数据类型 Libxml定义了许多数据类型,我们将反复碰到它们,它隐藏了杂乱的来源以致你不必处理它除非你有特定的需要。xmlChar 替代char,使用UTF-8编码的一字节字符串。如果你的数据使用其它编码,它必须被转换到UTF-8才能使用libxml的函数。在libxml编码支持WEB页面有更多关于编码的有用信息。 XmlDoc 包含由解析文档建立的树结构,xmlDocPtr是指向这个结构的指针。 xmlNodePtr and xmlNode 包含单一结点的结构xmlNodePtr是指向这个结构的指针,它被用于遍历文档树。 解析文档 解析文档时仅仅需要文件名并只调用一个函数,并有错误检查。完整代码:附录C, Keyword例程代码 ①xmlDocPtr doc; ②xmlNodePtr cur; ③doc = xmlParseFile(docname); ④if (doc == NULL ) { fprintf(stderr,"Document not parsed successfully. \n"); return; } ⑤cur = xmlDocGetRootElement(doc); ⑥if (cur == NULL) { fprintf(stderr,"empty document\n"); xmlFreeDoc(doc); return; } ⑦if (xmlStrcmp(cur->name, (const xmlChar *) "story")) { fprintf(stderr,"

ADC简介

前言 基于网上资料,根据个人理解对ADC相关概念做整理汇总。为便于理解部分内容引用自参考文章,参考文章链接放在文后。 总结: Hz是周期的倒数,也就是每秒钟的运行周期次数,因此单位是1/s。(1代表周期个数的单位)Sps是采样率,是每秒钟采样点的数量,Sp代表采样点数。在采样时,1个Sample就是的采样的一个周期。因此,两个单位在数值上应该是相等的,不同的话就是频率Hz可以是小数而采样率S/s一定是整数。 1KSPS=1KHz 1MSPS=1MHz SOC集成 在SOC集成中,更多关注的是ADC IP的集成、功能仿真、后仿、流片后的调试。 基础概念 ADC的基本定义:Analog-to-Digital Converter的缩写。指模/数转换器或者模拟/数字转换器。是指将连续变量的模拟信号转换为离散的数字信号的器件。 典型的模拟数字转换器将模拟信号转换为表示一定比例电压值的数字信号。 ADC的参数 ①分辨率 :数字量变化一个最小量时模拟信号的变化量,定义为满刻度与2n的比值,通常以数字信号的位数来表示。 ②转换速率:转换速率是指A/D转换一次所需要时间的倒数,即单位时间内完成A/D转换的次数 ③采样速率:采样速率是两次采样(两次转换)的间隔时间的倒数,为了保证转换的正确完成,一般采样速率必须小于等于转换速率,即采样时间大于等于转换时间。 ADC的主要特征 12位逐次逼近型的模拟数字转换器; 最多带3个ADC控制器,可以单独使用,也可以使用双重模式提高采样率; 最多支持23个通道,可最多测量21个外部和2个内部信号源; 支持单次和连续转换模式; 转换结束,注入转换结束,和发生模拟看门狗事件时产生中断; 通道0到通道n的自动扫描模式; 自动校准; 采样间隔可以按通道编程; 规则通道和注入通道均有外部触发选项; 转换结果支持左对齐或右对齐方式存储在16位数据寄存器; ADC转换时间:最大转换速率 1us(最大转换速度为1MHz,在ADCCLK=14M,采样周期为1.5个ADC时钟下得到); ADC供电要求:2.4V-3.6V; ADC输入范围:VREF- ≤ VIN ≤ VREF+。 量化和编码 模拟信号通过ADC转换成数字信号的这一过程称为量化,由于量化输出的数字信号位数有限,所以输出的数字信号和你采样得到的模拟信号会有一个误差,被称为量化误差,对于一个N位ADC来说,假设其满量程电压为Vref,Vref被ADC分为2N个区间,区间宽度用LSB(last significant bit)表示LSB=Vref/2N。 例如:Vref=8V,ADC为3位,LSB=1,所以每个区间为1V, 000代表电压0≤V<1 001代表电压1≤V<2 010代表电压2≤V<3 011代表电压3≤V<4 100代表电压4≤V<5 101代表电压5≤V<6 110代表电压6≤V<7 111代表电压7≤V<8 此ADC的分辨率为1V 关注: 1、采样时间: 2、采样率: 电容单位换算 :1F=10^6uF=10^9nF=10^12pF 指标着手: 1、精度、也称为分辨率(Resolution),单位(Bits)比特;精度越高的ADC转换出来的数字信号越接近于原来真实的模拟信号;另一方面,该精度只表示ADC 输出的位数,不代表这些位数里真正的信号分量。 2、采样速率(Input Sampling Rate)单位是SPS,如果ADC的采样频率是Fs(Hz),那么它可以转换的模拟信号带宽至多是Fs/2(Hz)。比如1Msps代表着1M Samples Per Second,对应的ADC的采样频率就是1MHz,可以转换的模拟信号带宽至多是1/2MHz。 参考 1、作者博文【STM32】ADC的基本原理、寄存器(超基础、详细版)ADC的基本工作原理ADC采样工作原理详解

研发能效思考

前言 作为一个技术人包括技术管理者,需要思考研发的核心价值是什么? 有人说是"降本增效"; 有人说是“业务支撑,提升效率” 等等.......,这些都不太明确,都是一个范范的概念。 之前看了一篇文章,比较有意思,我觉得比较能够回答这个问题 分享一下书中的观点: 1、外包公司: 最核心的竞争力不是技术,而是快速响应、资源调配整合、项目成本控制等方面。 2、企业信息化公司(平台):研发的核心价值有三个层次: 第一层是 运用技术更好的去支撑业务; 第二层是 用技术推动业务,帮助客户,提升效率; 第三层是 去用技术经验积累去影响或者改变行业。 3、解决特定场景和问题的产品公司: 不同定位的公司,在不同的角色中研发部门的核心价值不一样。 那么我们的核心价值是什么? 1、高效支撑业务: 高效,研发效率,业务系统效率,技术系统对业务的提升(需要数据对比); 支撑:业务发展和产品落地的支撑 2、技术促进业务健康和持久发展: 构建平台的效率降低成本在对外竞争中保持优势,对内不断优化业务流程促进业务发展; 研发流程的问题与思考 研发流程: 需求阶段 ---> 研发阶段 ---> 联调与测试阶段 ---> 1、需求阶段: 问题:需求不明确,需求不充分,需求理解不一致 解决方式: (1)明确需求上下文,确保需求的理解是一致的,包括研发,测试 (2)需求不明确的,先研发沟通一致,再和产品确认,最好一起通知测试参与 (3)需求反复的,需要制定需求变更流程,在产品确认的基础上再做开发。 2、研发阶段 2.1、研发全链路的技术规范 研发规范 ---> 集成测试规范 ---> 上线规范 ---> 中间件使用规范 (1)研发规范 编码规范,日志规范,错误码规范,系统配置规范,接口定义规范,数据库规范等等 (2)集成测试规范: 提测规范,代码评审规范,项目结构以及接口调用规范,环境规范 (3)上线规范: 系统部署规范,发布流程规范,资源申请规范 (4)中间件使用规范 框架使用规范,依赖规范,外部集成规范,稳定性规范 通过规范文档统一标准,并提供典型场景的案例的使用方式以及通知,强化规范内容的价值。 2.2、通用功能或工具的开发定制 基础脚手架:一键生成应用工程,包括依赖的jar包等。 代码规范的模板:错误码模板;日志模板;工程结构等 中间件的使用:包括使用的案例 项目通用工具类:外部开源的工具类;业务抽象的通用类;自研抽象的通用工具类; 业务标准拦截:用户登录;服务异常处理; 其他通用功能,上传,下载,导入,导出,文件图片的处理等等; 2.3、相互之间的协作流程与规范 项目与项目的边界划分,服务的拆分,调用关系,接口调用等。 2.4、项目过程管理 项目管理,干系人,成本,范围,进度,质量管理等 2.5、研发人员的学习进步 自我进步

Hexo + Gitee 免费部署静态博客

前言 这是一篇利用 Gitte Pages + hexo 搭建属于自己博客的教程,也是自己这个博客搭建好以后的第一篇文章,搭建的过程中也参考了各路大佬的文章,期间遇到了一些问题,所以写这一篇文章即是记录自己的路程也是为了让小白少走一些弯路。 参考文章:孤桜懶契 - Run🔰孤桜懶契🔰 |技术分享|漏洞复现|黑客|极客|渗透测试|专注信息安全|https://gylq.gitee.io/ 操作系统:win10 一、环境准备 1、安装Node.js Node.js下载官网 按需下载相应的版本, 默认安装就可以了。 2、安装Git Git下载官网 按需下载相应的版本, 默认安装就可以了。 3、检测是否安装成功 git --version node -v npm -v (注:提示不是内部或外部命令,记得检查下环境变量) 设备环境:Win10 二、安装Hexo 觉得慢的话可以更换淘宝源: npm install -g cnpm --registry=https://registry.npm.taobao.org 执行安装命令: npm install -g hexo-cli 这里我个人出现了一些小问题,hexo安装到了全局的目录,但我的环境有点问题 如果你cmd 查看全局位置:npm root -g hexo就在这里面,而hexo.cmd在npm目录下,把npm目录添加到环境变量里就解决了 主要目的是找到hexo.cmd,把它放入环境变量就ok了 我的路径:C:\Users\26254\AppData\Roaming\npm win10环境变量:右键此电脑->点击属性->高级系统设置->环境变量->Path,新建一个变量,把路径放进去就ok了 Hexo 初始化配置 初始化命令:hexo init <文件夹> 路径可以自己选择,可以cd到想要存放的的文件夹 我的文件夹名称是blog,名称随意,等待几分钟就会出现一个文件夹 blog文件夹下的目录如下: 解释一下: node_modules:是依赖包 public:存放的是生成的页面 scaffolds:命令生成文章等的模板 source:用命令创建的各种文章 themes:主题 _config.yml:整个博客的配置 package.json:项目所需模块项目的配置信息 本地查看效果 首先cd进入blog文件夹

socket网络套接字编程

目录 UDP通信程序的编写: udp通信流程*: 接口认识: 字节序转换接口*: 查看网络连接状态的命令: 实现构建思路: udp_srv.c: udp_socket.hpp: udp_client.cpp: 实现效果: TCP通信程序的编写: TCP通信操作流程: 接口: 实现思路: tcp_socket.hpp: tcp_client.cpp: tcp_srv.cpp: 多线程版: 多进程版: 实现效果: 套接字编程: 即网络通信程序的编写. 网络中的通信都是两端主机之间的通信: 客户端和服务端 客户端:网络通信中用户的一端,是进行业务请求的一端,是主动发起请求的一端 服务端:网络通信中提供服务的一端,针对客户端请求进行处理的一端,是被动接收请求的一端 qq聊天并不是自己跟另一个手机或者电脑用户在通信,实际上是跟腾讯的服务器在进行通信,把一个消息发到某个群,其实是把数据发送给了服务器,描述了数据在哪个群,服务器就能找到群里有哪些用户,这些用户也登录了服务器,就可以把数据逐一发送给对应的主机。 不存在客户端与客户端的通信,不存在服务端与服务端的通信。 网络通信编程有: tcp协议通信程序的编写, udp通信程序的编写 tcp协议和udp协议的区别初识: tcp协议∶传输控制协议--面向连接,可靠的字节流传输协议(确保数据安全有序到达对端) tcp协议为了保证可靠传输,因此使用了很多处理机制来完成,因此传输性能相对于udp较低tcp协议的应用场景:安全要求大于性能要求。比如文件传输 udp协议:用户数据报协议--无连接,不可靠的数据报传输协议(不确保数据安全有序到达对端) udp协议不需要保证可靠传输,只需要尽管传输就行因此传输性能要更高一些 udp协议的应用场景:性能要求大于安全要求。比如视频数据传输(要求不卡) UDP通信程序的编写: 网络传输中的数据都会具有五元组: sip(源端ip地址), sport(源端端口),dip(对端ip地址),dport(对端端口),protocol(使用的协议) 客户端要给服务端发送数据,他怎么知道服务端是谁? 服务端都会提前将自己的地址信息封装在客户端程序中。也正是因为如此,服务端的地址信息通常都不能随意改变。 udp通信流程*: 接口认识: 1. 创建套接字: int socket(int domain, int type, int protocol) domain: 地址域类型,决定通信使用的地址结构, IPV4地址域类型为AF_INET type:套接字类型,决定套接字传输方式, SOCK_DGRAM:无连接的,不可靠的数据报传输服务(UDP). SOCK_STREAM:基于连接的有序的可靠的字节流传输服务(TCP). protocol: 决定使用的协议类型, IPPROTO_TCP, IPPROTO_UDP. 返回值: 套接字的操作句柄(文件描述符),用于后续接口传参操作. 失败返回-1. 2. 绑定地址信息: int bind(int sockfd, struct sockaddr *addr, socklen_t len)

AXI_GPIO的零零碎碎

int * test() //这个函数返回的是地址,所以要加* { int a= 10; return &a; } int main() { int *p = test(); //函数返回的是地址,所以用指针变量接收 *p = 20; //这样写是错误的,因为函数调用后内存空间就被释放了。a是一个局部变量,所以这样的赋值错误。 } 驱动一个LED的过程: 配置GPIO ConfigPtr = XGpioPs_LookupConfig(GPIO_DEVICE_ID); XGpioPs_CfgInitialize(&Gpio, ConfigPtr,ConfigPtr->BaseAddr); 2.对GPIO口进行使能和方向的设置 XGpioPs_SetDirectionPin(&Gpio, EMIO0_LED, 1); // EMIO 的LED XGpioPs_SetOutputEnablePin(&Gpio, EMIO0_LED, 1); 中断是如何中断的? 先介绍一下GPIO: GPIO一共四个Bank,前两个可以连接到MIO,(54个MIO)后两个可以连接到EMIO。(64个EMIO) 中断的类型:1.边沿(极性有上升和下降);2.电平(极性有正负); 极性:1.正;2.负; ANY :同时支持 中断检测逻辑,写入中断状态,寄存在state中;另外,INT_STAT有写1清除中断的功能。同时INT_STAT也有读取当前寄存器状态的功能。 与门的作用: MASK:寄存器的MIO哪一个被屏蔽;DIS和EN 是使能是否。 一个是检测到引脚的中断;另一个是要引脚的中断没有被屏蔽掉。 MIO和EMIO 是PS和PL的外部;是IO外设GPIO通向外界的接口。 GIC是连接IO外设,只有IO外设可以触发中断。 PS这边的中断源可以有哪些?UG585 AXI_GPIO: AXI GPIO IP 核为 AXI 接口提供了一个通用的输入/输出接口。AXI GPIO 是一个软核( Soft IP),即 ZYNQ 芯片在出厂时并不存在这样的一个硬件电路, 而是由用户通过配置 PL 端的逻辑资源来实现的一个功能模块。 而 PS 端的 GPIO 是一个硬核( Hard IP) ,它是一个生产时在硅片中实现的功能电路。

程序猿的中秋夜,利用这些“代码”,解锁团聚新姿态

什么?!又快要中秋了,中秋节和教师节都在一起了,程序猿们,你们什么时候和铝盆友在一起呀?什么,你有铝盆友/昂?你是女程序猿? 那也没事,留个免费的赞再走嘛?什么,你要白嫖!要不 在评论区留个祝福嘛,中秋快乐! 记得某一年,国庆还是和中秋在一块,今年又来个双节,猿粪呐,不知道是不是又有小盆友要不满了,明明能放两次假,最后1+1=1,妙极了。 不过因为疫情影响,出行收到了限制, 或许 你和他/她分隔两地 或许 家人盼望着你一年,多回点家 或许 思念着那已无法陪伴着你的那个人······ 中秋,从古至今,都是每年相思赏月的重头戏。今夜月明人尽望,不知秋思落谁家。 人们也都面对着有家难回的境地吧,希望疫情能早点结束,还人间一片幸福安康 程序猿估计也是面对着一行行代码,偶尔看看信息,度过这个中秋节吧 总得送点属于自己的特殊礼物给家人 要不 printf("中秋节快乐!"); 啥,太简陋了? 那换一换 #include<stdio.h> #include<stdlib.h> #include<windows.h> int main() { int i,j; int x=0; int y=7; int velocity_x=1; int velocity_y=1; int left = 0; int right = 100; int top = 0; int bottom = 28; //int height = 30; //int velocity = 1; while(1) { x=x+velocity_x; y=y+velocity_y; system("cls"); for(i=0;i<x;i++) printf("\n"); for(j=0;j<y;j++) printf(" "); printf("

Xilinx FPGA 使用Microblaze实现串口命令行

想在项目上使用串口命令行的方式操作工程里的某些线或者获取某些信息,FPGA使用的是Kintex-7,移植开源的letter shell适配MicroBlaze的运行。 开源的letter shell网址:letter-shell 我移植的是2.x的版本,如下图所示。 FPGA工程里面主要例化一个Microblaze软核,添加一个uart lite,一个gpio。uart管串口的接收和发送,gpio点LED灯用。还例化了一个up_axi模块,这个模块是ADI的一个开源的模块,可以把AXI Lite接口转成普通的Corebus接口,后面添加用户的读写寄存器比较方便,相对于AXI接口来讲,这个Corebus接口比较方便用户操作,当然也可以用Vivado工具自己定义一个AXI Lite模块来添加一些寄存器进去。把up_axi封装成了一个ip,可以在block design里面调用。 下面还是继续讲letter shell的移植吧,letter shell 2.x版本下载下来之后,目录如下所示 letter shell的源码修改了shell_cfg.h里几个参数。大概的作用就是在main函数的while(1)循环中调用shelltask函数,shell命令通过list的方式添加而不通过export的方式。 Microblaze的SDK工程那边就调用一下hello world的模板,然后添加一些函数进去,这也是主要参考letter shell 2.x里面README的内容。 README里的移植说明如下, 我把SDK生成的hello world改成了下面的内容。因为之前试过用export的方式不太行,README里面说用GCC编译要在ld文件里面添加个什么东西,不太会,所以就简单弄了下通过表的方式把命令列出来。 #include <stdio.h> #include "platform.h" #include "xil_printf.h" #include "letter-shell-shell2.x/shell_cfg.h" #include "letter-shell-shell2.x/shell.h" #include "letter-shell-shell2.x/shell_ext.h" #include"xparameters.h" #include"xuartlite.h" #include"xuartlite_l.h" SHELL_TypeDef shell; int ledon(int); int ledoff(int); signed char uartRead(char *data) { u32 a; a=XUartLite_GetStatusReg(XPAR_AXI_UARTLITE_0_BASEADDR); if((a&1)==1) { *data=XUartLite_RecvByte(XPAR_AXI_UARTLITE_0_BASEADDR); return 0; } else { return -1; } } void uartWrite(char data) { XUartLite_SendByte(XPAR_AXI_UARTLITE_0_BASEADDR,data); } int ledon(int i) { unsigned char data; switch(i){ case 0x1: data = Xil_In32(XPAR_AXI_GPIO_0_BASEADDR); Xil_Out32(XPAR_AXI_GPIO_0_BASEADDR,data|0x1); printf("

c++ 单源最短路径-狄杰斯特拉算法

文章目录 源码输出 狄杰斯特拉算法适用范围:没有负权重的图, 可以有环,有向无向图均可求解问题:单源最短路径时间复杂度:V^2 源码 #include <iostream> #include <vector> #include <algorithm> #include <chrono> using namespace std; struct Edge { int to; int weight; }; struct Vertex { vector<Edge> adjacent; int dis = INT_MAX; int closed = 0; int pre = -1; }; class Graph { vector<Vertex> nodes; int n; public: Graph(int n, vector<vector<int>> &edges) : nodes(n) { this->n = n; for (auto &vec: edges) { int from = vec[0]; int to = vec[1]; int weight = vec[2]; nodes[from].

嵌入式linux开发实用工具小程序

Table of Contents (一)十六进制字符转整型数字 (二)字符串转整型 (三)创建文件并填充固定数据 (四)批量处理图片 (五)海思HI3520 IO控制小程序 (六)路由追踪 (七)文件固定位置插入数据 (七)H264 I帧与P帧偏移 (八)获取本地IP地址 在学习和工作开发的时候,经常需要使用到各种各样不太常用的操作,这种情况一般是自己手动写一些小程序来处理。因为它们不太常用,所以经常用了又没保存,等到下一次在使用的时候又需要重写,这样的非常浪费时间和精力。所以想在这里统一记录一下,以备下次重新使用。代码以实用为主,如果缺陷,欢迎指出。 (一)十六进制字符转整型数字 功能:将16进制的字符串转换为10进制的数字。我是没有找到相应的库函数,所以参考网上的代码自己手动写了个函数来实现。常用的函数有atoi,atol,他们都是将10进制的数字字符串转换为int或是long类型,所以在有些情况下不适用。 /*============================================================================= # FileName: hex2dec.cpp # Desc: Convert a hex string to a int number # Author: Caibiao Lee # Version: # LastChange: 2018-11-26 # History: =============================================================================*/ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <ctype.h> int c2i(char ch) { // 如果是数字,则用数字的ASCII码减去48, 如果ch = '2' ,则 '2' - 48 = 2 if(isdigit(ch)) return ch - 48; // 如果是字母,但不是A~F,a~f则返回 if( ch < 'A' || (ch > 'F' && ch < 'a') || ch > 'z' ) return -1; // 如果是大写字母,则用数字的ASCII码减去55, 如果ch = 'A' ,则 'A' - 55 = 10 // 如果是小写字母,则用数字的ASCII码减去87, 如果ch = 'a' ,则 'a' - 87 = 10 if(isalpha(ch)) return isupper(ch) ?

泛型知识点

目录 1. 泛型 2. 限定通配符与非限定通配符 1. 泛型 泛型就是将类型参数化,其在编译的时候才确定具体的参数。 可以在类、接口、方法中创建,分别称为反省类、泛型接口、泛型方法。 在jdk1.5之前(泛型是Jdk1.5 之后才有的),没有泛型的概念,要使用Object来实现通用、不同类型的处理:缺点:(1)每次使用时都要强制转换为想要的类型。(2)在编译时编译器不知道类型的转换是否异常,运行时才知道,不安全。 泛型是一种语法糖,基本原理就是类型擦除(使用泛型时候加上的类型参数,编译器在编译的时候去掉类型参数)。泛型只存在于编译阶段,不存在与运行阶段。 public class A<T> { private T num; } 大部分情况下,泛型类型都会以Object 进行替换,但当使用了extends 和 super 语法时,就不能简单用Object来替换了。 public class A <T extends String> { private T num; } 这种情况下,num的类型会被替换为String,而不是Object。这是类型限定的一个语法,它限定T是String的子类或者就是 String ,无论T是什么类型,String都是父类,不会出现类型不匹配的问题,于是可以使用String进行类型擦除。 使用泛型的好处: 1. 类型安全 (1)泛型的主要目标就是提高Java程序的类型安全。 (2)编译时期就可以检查出因Java类型不正确导致的类型转换异常。 (3)符合越早出错代价越小原则。 2. 消除强制类型转换 (1)使用时直接得到目标类型,消除许多强制类型转换。 (2)所得即所需,减少出错机会。 3. 潜在的性能收益 (1)所有工作都在编译器完成。 (2)编译器生成的代码与不适用泛型时所写的代码几乎一致。 2. 限定通配符与非限定通配符 限定通配符: <? extends T> 确保类型必须是T的子类或者就是T,设定了类型的上界。 <? super T > 确保类型必须是T的父类或者就是T,设定了类型的下界。 非限定通配符: 非限定通配符<?> ,可以用任意类型来代替。如 List<?>,他可以是List<A>,List<B>,List<C>等等。

朴素贝叶斯算法原理以及python实现

朴素贝叶斯 一、朴素贝叶斯概述二、概率论知识三、朴素贝叶斯算法原理四、参数估计方法五、示例分析六、拉普拉斯平滑修正七、算法优缺点八、python实现8.1 sklearn贝叶斯8.2 文本情感分析示例8.3 CountVectorizer()函数 一、朴素贝叶斯概述 朴素贝叶斯算法(Naive Bayesian algorithm) 是应用最为广泛的分类算法之一。 朴素贝叶斯方法是在贝叶斯算法的基础上进行了相应的简化,即假定给定目标值时属性之间相互条件独立。也就是说没有哪个属性变量对于决策结果来说占有着较大的比重,也没有哪个属性变量对于决策结果占有着较小的比重。虽然这个简化方式在一定程度上降低了贝叶斯分类算法的分类效果,但是在实际的应用场景中,极大地简化了贝叶斯方法的复杂性。 对于给定的训练集,首先基于特征条件独立假设学习输入输出的联合概率分布(朴素贝叶斯法这种通过学习得到模型的机制,显然属于生成模型);然后基于此模型,对给定的输入 x,利用贝叶斯定理求出后验概率最大的输出 y。 相关知识思维导图: 二、概率论知识 条件概率:就是事件 A A A 在另外一个事件 B B B 已经发生条件下的发生概率。条件概率表示为 P ( A ∣ B ) P(A \mid B) P(A∣B) ,读作在 B B B 发生的条件下 A A A 发生的概率"。联合概率: 表示两个事件共同发生 (数学概念上的交集) 的概率。 A A A 与 B B B 的联合概率表示为联合概率 P ( A B ) P(A B) P(AB) P ( A B ) = P ( A ∣ B ) P ( B ) = P ( B ∣ A ) P ( A ) P(AB)=P(A \mid B) P(B)=P(B \mid A) P(A) P(AB)=P(A∣B)P(B)=P(B∣A)P(A)

Linux/Ubuntu/Arm设备中通过/proc/stat等文件计算Cpu使用率

Linux/Ubuntu/Arm设备中通过/proc/stat等文件计算Cpu使用率 一、proc文件系统1. /proc/cpuinfo文件2. /proc/stat文件3. /proc/<pid>/stat文件4. /proc/<pid>/task/<tid>/stat文件 二、系统中有关进程cpu使用率的常用命令1. ps 命令2. top命令 三、单核情况下Cpu使用率的计算1. 基本思想2. 总的Cpu使用率计算方法3. 某一进程Cpu使用率的计算方法4. 某一线程Cpu使用率的计算方法 四、多核情况下cpu使用率的计算1. 实验一2. 实验二 五、主要问题: 一、proc文件系统 /proc文件系统是一个伪文件系统,它只存在内存当中,而不占用外存空间。它以文件系统的方式为内核与进程提供通信的接口。用户和应用程序可以通过/proc得到系统的信息,并可以改变内核的某些参数。由于系统的信息,如进程,是动态改变的,所以用户或应用程序读取/proc目录中的文件时,proc文件系统是动态从系统内核读出所需信息并提交的。 /proc目录中有一些以数字命名的目录,它们是进程目录。系统中当前运行的每一个进程在/proc下都对应一个以进程号为目录名的目录/proc/pid,它们是读取进程信息的接口。此外,在Linux 2.6.0-test6以上的版本中/proc/pid目录中有一个task目录,/proc/pid/task目录中也有一些以该进程所拥有的线程的线程号命名的目录/proc/pid/task/tid,它们是读取线程信息的接口。 1. /proc/cpuinfo文件 该文件中存放了有关 cpu的相关信息(型号,缓存大小等)。 [zhengangen@buick ~]$ cat /proc/cpuinfo processor : 0 vendor_id : GenuineIntel cpu family : 15 model : 4 model name : Intel(R) Xeon(TM) CPU 3.00GHz stepping : 10 cpu MHz : 3001.177 cache size : 2048 KB physical id : 0 siblings : 2 core id : 0 cpu cores : 1 fdiv_bug : no hlt_bug : no f00f_bug : no coma_bug : no fpu : yes fpu_exception : yes cpuid level : 5 wp : yes flags : fpu vme de pse tsc msr pae mce cx8 apic mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe lm pni monitor ds_cpl cid xtpr bogomips : 6004.

Mybatis批量插入大量数据最优方式

Mybatis批量插入的方式有三种 1. 普通插入 2. foreach 优化插入 3. ExecutorType.BATCH插入 下面对这三种分别进行比较: 1.普通插入 默认的插入方式是遍历insert语句,单条执行,效率肯定低下,如果成堆插入,更是性能有问题。 INSERT INTO `table1` (`field1`, `field2`) VALUES ("data1", "data2"); INSERT INTO `table1` (`field1`, `field2`) VALUES ("data1", "data2"); INSERT INTO `table1` (`field1`, `field2`) VALUES ("data1", "data2"); INSERT INTO `table1` (`field1`, `field2`) VALUES ("data1", "data2"); INSERT INTO `table1` (`field1`, `field2`) VALUES ("data1", "data2"); sql log如下: 2022-08-30 05:26:02 [1125b8ff-dfa3-478e-bbee-29173babe5a7] [http-nio-3005-exec-2] [com.btn.common.config.MybatisSqlLoggerInterceptor]-[INFO] 拦截的sql ==>: com.btn.mapper.patient.PatientLabelDetailMapper.insert:INSERT INTO t_patient_label_detail ( patient_id, doctor_id, tag_id, patient_name, gender, age, create_by, create_time ) VALUES ( 337, 178, 251, '刘梅好', 2, 29, '178', ) 2022-08-30 05:26:02 [1125b8ff-dfa3-478e-bbee-29173babe5a7] [http-nio-3005-exec-2] [com.

可能是全网最清晰的KMP算法讲解

字符串匹配 “字符串A是否为字符串B的子串?如果是,出现在B的什么位置?”这个问题就是字符串匹配问题。字符串A称为模式串,字符串B称为主串。 那么,如何查找模式串在主串中的位置呢? 暴力匹配 暴力匹配,顾名思义,是一种简单粗暴的匹配方法。从主串的第一个字符开始与模式串的第一个字符比较,如果相同则模式串往后移动一个位置和主串的下一个位置再比较,如果不同,则主串移动到下一个字符,模式串移动到第一个字符,开始重新比较,以此类推。 这种方法很简单,但效率很低,假设主串的长度为m,模式串的长度为n,最差的情况是主串移动m-n+1次才能匹配到,时间复杂度为O(mn),直接上代码: /** * 暴力匹配 * @param t 主串 * @param p 模式串 * @return */ public static int bruteForce(String t, String p) { int index = -1; int pLength = p.length(); int tLength = t.length(); // 模式串的长度当然要小于等于主串长度 if (pLength <= tLength) { int j = 0; for (int i = 0; i < pLength; i++) { // 模式串和主串字符不匹配则主串下标后移一位,模式串重置第一位(下标为0) if (p.charAt(i) != t.charAt(j + i)) { j ++; i = -1; } else { // 模式串最后一个字符匹配上,记录下标,退出循环 if (i == pLength - 1) { index = j; break; } } // 模式串长度大于主串剩余长度 if (pLength > tLength - j) { break; } } } return index; } KMP算法 KMP算法由D.

VUE+webrtc-streamer实现实时视频播放(监控设备-rtsp)

首先说明目前我只完成了本地测试,因还没确定技术选型所以暂无项目应用,先做一下储备,后续项目应用的话这篇文章会持续更新。 监控设备播放效果如下:基于公司环境测试了大华和海康的监控设备(H264编码)可以正确播放 1、下载webrtc-streamer,本机测试我下载的最新window版本 https://github.com/mpromonet/webrtc-streamer/releases 2、解压下载包 3、双击webrtc-streamer.exe启动服务 如下图则启动成功,此时在浏览器访问127.0.0.1:8000可以看到本机监控画面 4、将下载包html文件夹下webrtcstreamer.js文件和html/libs文件夹下adapter.min.js文件复制到VUE项目public目录下。在index.html文件里引入这两个js文件 5、编写测试页面 注意:第三步在本机启动服务所以 new WebRtcStreamer(id,serverUrl)中URL传入127.0.0.1端口可 见第三步截图为8000;各监控设备厂商有自己的RTSP地址格式connect要传入正确的rtsp地址。 <template> <div> <el-button @click="handleChange">切换</el-button> <video id="video" autoplay width="900" height="900"></video> </div> </template> <script> export default { name: 'index1', data() { return { webRtcServer: null } }, mounted() { //video:需要绑定的video控件ID //127.0.0.1:8000:启动webrtc-streamer的设备IP和端口,默认8000 this.webRtcServer = new WebRtcStreamer('video', location.protocol + '//127.0.0.1:8000') //需要查看的rtsp地址 this.webRtcServer.connect('rtsp://user:password@ip:port/cam/realmonitor?channel=1&subtype=0') //rtsp://user:password@ip:port/h264/ch1/main/av_stream--海康 //rtsp://user:password@ip:port/cam/realmonitor?channel=1&subtype=0--大华 }, beforeDestroy() { this.webRtcServer.disconnect() this.webRtcServer = null }, methods: { handleChange() { this.webRtcServer.connect('rtsp://user:password@ip:port/h264/ch1/main/av_stream') } } } </script> <style scoped></style> 6、运行项目可查看监控视频播放效果