问题场景:
组建的raid1 被删除后,重启
重启完成后发现所有服务都无法正常启动。此时发现进入linux系统时候并未输入用户名称,只输入密码,其实此时进入了系统的单用户模式。
Linux下的启动方式常用的到的有单用户方式、普通多用户方式、完全多用户方式和XWin方式。单用户方式下,系统并没有完全运行进来,只是部分程序运行,这时也不能进行远程登录到Linux系统。进入单用户方式进行系统维护由是ROOT用户来进行完成,而且是由ROOT直接的进入,没有密码检验。这时的ROOT用户对系统有完全的操作权限,可以修复系统的同时,也能随时的对系统进行破坏。
修复: 我的问题是由于将raid 下的lvm中的 程序 挂载到了fstab的开机启动,由于开机启动不能找到此服务,故进入单用户模式。
vi /etc/fstab 将挂载的服务删除掉,然后重启即可
# /etc/fstab # Created by anaconda on Wed Jun 30 18:51:56 2021 # # Accessible filesystems, by reference, are maintained under '/dev/disk' # See man pages fstab(5), findfs(8), mount(8) and/or blkid(8) for more info # /dev/mapper/centos-root / xfs defaults 0 0 UUID=31339d24-ed90-46ee-a5e8-65c13cbb5007 /boot xfs defaults 0 0 #/dev/mapper/centos-home /home xfs defaults 0 0 /dev/mapper/centos-swap swap swap defaults 0 0 #UUID=bdd29a20-420e-49cf-9af1-510849223810 /opt/xxx xfs defaults 0 0 ~
解决报错 错误信息问题分析解决方法完整代码 错误信息 •在pycharm中使用os模块获取当前进程id,出现下述错误:
AttributeError: module 'os' has no attribute 'getgid' •参考网上的修改代码,配置文件的方法,未能解决此问题!!
问题分析 •报错信息为:os模块中没有getgid方法
•查阅网上os模块的官方文档发现模块中是包含此方法的!!
•出现此问题的可能是os模块导入不正确,仔细研究代码,并未发现问题!!
解决方法 •博主抱着试一试的态度,将代码重写了一遍,发现了其中的奥妙!!
•在使用os模块方法时,出现了两个os,我们默认使用第一个,而os模块是第二个后面带有os的模块,使用第二个os模块就不会使用出现报错!!!
•我们只需要使用第二个os模块中的方法,运行代码就不会出现此报错!!!!
完整代码 import psutil import os def show_info(start): # 获取当前运行程序的进程id pid =os.getpid() # 使用第二个带有os的os模块 # 获取当前堆成对象 p = psutil.Process(pid) # 返回该对象的内存消耗 info = p.memory_full_info() # 获取当前进程独自占用的物理内存 memory = info.uss / 1024. / 1024 print(f'{start}一共占用{memory:.2f}mb') def func(): show_info('initial') a = [i for i in range(100000)] show_info('created') func() show_info('finished')
分页存储管理
定义:click
例题:click
分页存储:讲逻辑地址进行分块,逻辑地址包括(页号和页内偏移),将内存空间换绯闻同样大小的块,每个块为一个页面,页号与块号(或页面好)相对应。
逻辑地址为A,页面大小为L,页号:A/L(向下取整),页内偏移:A%L
数值后缀(二进制:B;八进制(三个二进制表示一个八进制,111=>7O):O;十进制:D;十六进制(四个二进制表示一个十六进制,1111=>FH):H;因二进制过长,计算机中内存单元一般使用十六进制进行表示。)
数值前缀(二进制:0B;八进制:0O;十进制0D;十六进制:0X;都是用0作为前缀) 进制转换:1kb=oB100,0000,0000=oX400 //parseInt('ox400',10)=>1024 题目:
有用户态进程A,其虚拟内存页为1KB,A占用了64页,内存大写为128KB,A进程将爱子到内存的页面和物理内存块的编号对应关系如下:
页面编号 物理内存块编号 0 4 1 9 2 5 3 8 请根据以上信息回答如下问题,并给出计算过程:
1)虚拟地址为015D对应的物理地址是多少? 2)物理地址为113C对应的虚拟地址为多少? 3)进程A有一作业长度为8页,试图访问虚拟地址2A3D并保存整型1到该地址对应的物理地址空间,之后又尝试从该地址读取保存的数据,请问A进程这两次内存访问过程能否正常执行?并解释原因。 解答:
1)十六进制虚拟地址015D
页面为1k=1024(10进制)=2^10=0100,0000,0000 B=400H
页号:015D/400H=0 ===> 4块号
页内偏移:015D%400H=015D
物理地址:4400+015D=1000+015D=115D(4400满16往前1位进1)
2)113C/400 = 4…13C(113C整体进行除,不可以转化为十进制,不够向高位借1,)
虚拟地址:0*400+13C=013C
一分页存储管理系统中逻辑地址长度为16位,页面大小为4KB字节,现有一逻辑地址为2F6AH,且第0,1,2,页依次存放在物理块5,10,11中,则相应的物理地址是多少?
解答:
1kb=1024
4kb=4096
2^10=1024;
2^11=2048;
2^12=4096;==>12 个2进制位为一页
逻辑地址:2F6AH==>0010,1111,0110,1010,后12为页内偏移,剩下4位为页号
0010 ==> 页号:2H ==>快号:11 =>BH
1111,0110,1010===> F6AH
物理地址为:BF6AH
某系统采用分页存储管理方式,设计如下:页面大小为4KB,允许用户虚地址空间最大为16页,允许系统物理内存最多为512个内存块。试问该系统虚地址寄存器和物理地址寄存器的长度各是多少位?
页面大小为4KB=2^12字节,所以页内偏移量占12位。
由于物理块大小等于页面大小,所以物理块大小为2^12字节,物理块位数占12位。
允许用户虚地址空间最大为16页=2^4页,即页号占4位
允许系统物理内存最多为512个内存块=2^9个内存块,即内存块位数占9位。
虚地址寄存器位数=页号位数+页内偏移量位数=4+12=16位
物理地址寄存器位数=物理块位数+内存块位数=12+9=21位。
目录 总背景一、 获取MySQL1. 官网获取2. 百度网盘 二、安装1. 安装前2. 解压3. 安装四大模块,一个一个来,顺序36184. 初始化 三、后处理1. 获取安装时的密码并做修改A. 登录 MySQLB. 修改密码C. 授权过程连接 2. 授权防火墙A. 咱先看看防火墙的配置B. 配置放行3306端口,并重载一下防火墙 服务器开发者注意1. 安全组配置 结语END 总背景 前天开搞 SpringCloud,本来服务搭在虚拟机里啥事没有,等到一开始启动nacos集群时,完蛋了,idea启动不了了……服务器是时候安排上了。
于是我上网淘了一下阿里云,腾讯云,华为云,对比了两天,终于在昨天入手了阿里云的服务器,那边经理说 centos 比 alibaba cloud linux 要稳定,并装上了 centos8.4。后在安装 mysql 时在 mysqld initialize 这步死活安不进去。完了,操作系统得降版。
于是乎,本篇章完全基于 centos7.4 操作系统去完成的!!!!
一、 获取MySQL 1. 官网获取 wget https://dev.mysql.com/get/Downloads/MySQL-8.0/mysql-8.0.26-1.el7.x86_64.rpm-bundle.tar 2. 百度网盘 链接:https://pan.baidu.com/s/1iK0KQffS6yBesDAlCx6_qA
提取码:l15y
可下载一个 Xftp 7 的软件把压缩包放进服务器中。
二、安装 目录:/usr/local/mysql,压缩包就在这个目录里
1. 安装前 考虑到有些伙伴是先安装了 JDK 再安装 MySQL,所以我们要先把 JDK 给我们搞的一堆 mariadb 给删掉。
rpm -qa | grep mariadb (如果有文件输出执行,如果没有就跳过) rpm -e (文件名动手复制一下) --nodeps rpm 命令后续会出个独立的文章
npm install报错 gyp ERR! find VS
gyp ERR! find VS msvs_version not set from command line or npm config
gyp ERR! find VS VCINSTALLDIR not set, not running in VS Command Prompt
gyp ERR! find VS checking VS2019 (16.3.29411.108) found at:
gyp ERR! find VS “D:\viso”
gyp ERR! find VS - found “Visual Studio C++ core features”
gyp ERR! find VS - missing any VC++ toolset
gyp ERR! find VS could not find a version of Visual Studio 2017 or newer to use
文件上传 文件上传流程图
导jar包
commons-io-2.4.jar
commons-fileupload-1.4.jar
springmvc.xml中编写文件上传解析器
<!--文件上传解析器--> <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"> <property name="defaultEncoding" value="UTF-8"/> </bean> jsp中的配置
<form action="upload" method="post" enctype="multipart/form-data"> <input type="file" name="img" /> <input type="submit" value="提交" /> </form> 后端代码书写
@Controller public class uploadController { @RequestMapping("/toUpload") public String toUpload(){ return "upload"; } @RequestMapping("/upload") public void upload(MultipartFile[] img, HttpSession session) { // 1 准备文件上传位置 // 在WEB目录下的“/upload”文件夹中存放上传的文件 ServletContext servletContext = session.getServletContext(); String realPath = servletContext.getRealPath("/upload"); File file = new File(realPath); if (!file.exists()){// 如果文件夹不存在,创建文件夹 file.
本篇目录链接 疑问分析解决思路环境说明Kubelet Node Allocatable 介绍配置方式(基于yum安装)配置资源预留 Eviction 与 OOM可分配约束 疑问分析 在k8s集群中,默认情况下 Pod 能够使用节点全部可用容量,同样就会伴随一个新的问题,pod消耗的内存会挤占掉系统服务本身的资源,这就好比我们在宿主机上运行java服务一样,会出现java程序将宿主机上的资源(内存、cpu)耗尽,从而导致系统登陆不上或者卡顿现象。同理在k8s集群中也会出现类似的问题,从而也会导致一系列不可控的故障产生。因此为系统守护进程预留出部分资源,也是很有必要的。
解决思路 要解决这个问题就需要为 k8s 集群配置资源预留,kubelet 暴露了一个名为 Node Allocatable 的特性,有助于为系统守护进程预留计算资源,k8s 也是推荐集群管理员按照每个节点上的工作负载来配置 Node Allocatable。
环境说明 本文的操作环境为 Kubernetes v1.18.0 版本,使用docker的容器运行时,docker 和 Kubelet 采用的 cgroup 驱动为 systemd。
Kubelet Node Allocatable 介绍 Kubelet Node Allocatable用来为Kube组件和System进程预留资源,从而保证当节点出现满负荷时也能保证Kube和System进程有足够的资源。目前支持cpu, memory, ephemeral-storage三种资源预留。
计算方式
Node Allocatable Resource = Node Capacity - Kube-reserved - system-reserved - eviction-threshold 其中:
Node Capacity:Node的所有硬件资源,kube-reserved是给kube组件预留的资源Kube-reserved:kube 组件预留的资源system-reserved:给system进程预留的资源eviction-threshold(阈值):kubelet eviction(收回)的阈值设定 只有allocatable才是真正scheduler调度Pod时的参考值(保证Node上所有Pods的request resource不超过Allocatable) ,关系图如下:
配置方式(基于yum安装) 我们先通过 kubectl describe node 命令查看节点可分配资源的数据:
ESXI ovf部署虚拟机时,提示缺少所需的磁盘镜像
在使用 ESXI 使用导入的模板镜像部署虚机机时,最后一步会提示缺少所需的磁盘镜像
解决方法 :
导出的时候把CD-ROM 在虚拟机的编辑设置 里面删除掉
然后,编辑OVF 文件,把里面带有xxx.nvram 的所在行删除。保存
再导入操作就不会提示: 缺少所需的磁盘镜像
数据类型判断 typeof 可以正确识别:Undefined、Boolean、Number、String、Symbol、Function 等类型的数据,但是对于其他的都会认为是 object,比如 Null、Date 等,所以通过 typeof 来判断数据类型会不准确。但是可以使用 Object.prototype.toString 实现。
function typeOf(obj) { - let res = Object.prototype.toString.call(obj).split(' ')[1] - res = res.substring(0, res.length - 1).toLowerCase() - return res // 评论区里提到的更好的写法 + return Object.prototype.toString.call(obj).slice(8, -1).toLowerCase() } typeOf([]) // 'array' typeOf({}) // 'object' typeOf(new Date) // 'date' 复制代码 继承 原型链继承 function Animal() { this.colors = ['black', 'white'] } Animal.prototype.getColor = function() { return this.colors } function Dog() {} Dog.prototype = new Animal() let dog1 = new Dog() dog1.
1、 在我们提交我们的change的时候,不需要把我们build的文件也提交上去,但是如果你原来拉的项目并没有添加.gitignore文件,git add . 的时候发现出现了很多build后的文件,该怎么办呢?
首先,右击.idea
2、git–>add .gitignore–>之后就是创建,这一系列操作完成之后你的工作空间就有.gitignore这个文件夹了
当然这个文件了里面也有你的.idea 文件了,同样的方法,把其余需要改的文件右击git -->add .gitignore 文件里面,这里系统就不会提出create了,他也直接给你添加好了。
3、最最后,你的.gitignore 也相当于你的修改,这个时候你当然也需要把他自己添加到自己文件夹里面 右击–>git–>add .gitignore 完成。
下面就是我的文件夹的东西
Cookie共享:
1、Domain:必须是相同的。
例如有多个域名:
www.taotao.com
Sso.taotao.com
Search.taotao.com
需要设置domain为:.taotao.com
2、设置path:/
3 如果是localhost不要设置domain。直接设置path就可以了。
1.两个div,一个outer,一个inner,inner设置absolute,滑动时改变inner的left值
<div class="system-tabs"> <i class="el-icon-arrow-left" style="left: 13%" @click="arrowClick('pre')" ></i> <i class="el-icon-arrow-right" style="right: 13%" @click="arrowClick('next')" ></i> <div class="scroll-outer" ref="scrollOuter"> <div ref="scrollBody" class="scroll-body" :style="{ left: scrollLeft + 'px' }" > <span :class="{ item, active: tabIndex === index }" v-for="(item, index) in sysTabs" :key="index" @click="tabClick(index)" > {{ item.name}} </span> </div> </div> </div> 样式
&-tabs { height: 60px; background-color: #333333; box-sizing: border-box; position: relative; i { color: #999999; font-size: 28px; position: absolute; height: 60px; line-height: 60px; } .
<div id="app"> <el-table :data="auList" border style="width: 100%"> <el-table-column prop="shortId" label="ID" width="180"> </el-table-column> <el-table-column prop="nickname" label="用户名" width="180"> <template v-slot="scope"> <router-link :to="{path:'/AuthorVideosList/'+scope.row.shortId}" >{{scope.row.nickname}}</router-link> </template> </el-table-column> </el-table> </div> 路由和ui基本操作。
如何在column获取到当前object?
<template v-slot="scope"> <router-link :to="{path:'/AuthorVideosList/'+scope.row.shortId}" >{{scope.row.nickname}}</router-link> </template> 在scope.row中可以获取到数组中的当前对象
private void FrmLogin_KeyDown(object sender, KeyEventArgs e) { if (e.KeyCode == Keys.Enter) { //登录 LoginMethod(); } else if (e.KeyData == Keys.Escape) { //退出 CloseMethod(); } } 然后将KeyPreview设置为True,才能响应。
使用场景:同百度,高德路线规划一样,该方案支持对途径点的动态拖动,增加,删除,路线动态变更
1.整合方案原理:
1.使用路径规划服务作为路线绘制基础
2.可拖动marker及Popup结合作为标记点使用
3.动态构建的路线,途径点
4.支持获取link级别数据,支持增加多种模式路线规划选择
2.使用方式
/** * @Description:线指示器 * @Author: ShiWei * @Date: 2021-08-19 */ /** *初始化地图编辑 */ export const initEdit = () => { if(!handleEdit){ handleEdit = new minemap.edit.init(_map, { boxSelect: true, touchEnabled: true, displayControlsDefault: true, showButtons: false }); } //开启画线模式 handleEdit.onBtnCtrlActive('line'); }; 只需要执行该方法即完成编辑器的启动工作;
激活地图单击,双击事件
_map.on('click',AutoLine.clickPoints); _map.on('dblclick',AutoLine.dbClickEnd) /** * @Description:地图路径规划单击选点 * @Author: ShiWei * @Date: 2020-11-12 */ export const clickPoints=(v)=>{ let tep=[]; let ibs=v.lngLat; tep=[ibs.lng,ibs.lat]; wayPoints.push(tep); let obs=[]; let tps=[] if(wayPoints.
windows下vs2019跑pcl中ndt的模块,结果在编译下面定义
pcl::NormalDistributionsTransform<pcl::PointXYZ, pcl::PointXYZ> ndt;
结果出现无法下面错误
main.obj : error LNK2019: 无法解析的外部符号 "public: __cdecl pcl::search::KdTree<struct pcl::PointXYZ,class pcl::KdTreeFLANN<struct pcl::PointXYZ,struct flann::L2_Simple<float> > >::KdTree<struct pcl::PointXYZ,class pcl::KdTreeFLANN<struct pcl::PointXYZ,struct flann::L2_Simple<float> > >(bool)" (??0?$KdTree@UPointXYZ@pcl@@V?$KdTreeFLANN@UPointXYZ@pcl@@U?$L2_Simple@M@flann@@@2@@search@pcl@@QEAA@_N@Z),函数 "public: __cdecl pcl::Registration<struct pcl::PointXYZ,struct pcl::PointXYZ,float>::Registration<struct pcl::PointXYZ,struct pcl::PointXYZ,float>(void)" (??0?$Registration@UPointXYZ@pcl@@U12@M@pcl@@QEAA@XZ) 中引用了该符号
一般出现下面问题是没有在vs配置文件中加对应的lib文件,检查了一下,我是添加了kdtree.lib的,还是编译不通过,那就是对应的lib添加。后面添加了pcl_searchd.lib,编译成功。我是debug,所以后有d。
1、新建index.html文件,使用webpack打包html 配置插件
yarn add html-webpack-plugin@4.5.0 -D webpack.config.js中添加插件
在package.json中添加script脚本,这样打包命令就可以使用yarn build
执行打包命令
yarn build 可以看到index.html文件已经被打包,并且app.js文件也被引入进来了
2、创建server 安装devserver模块
yarn add webpack-dev-server@3.11.0 -D 在webpack.config.js中配置server
// 配置server devServer: { contentBase: path.join(__dirname, './dist'), compress: true, port: 8082 // 端口号 } 执行命令,就可以在本地启动server
npx webpack-dev-server 浏览器访问http://localhost:8082/
app.js中内容已经输出,报错是因为favicon.ico没有找到
可以在package.json中添加脚本,使用yarn dev命令就可以启动服务
3、解决favicon.ico找不到报错问题 首先随便找一个ico图标,这里使用的是webpack官网图标,保存到public路径下
webpack官网图标
需要使用webpack的文件复制插件,把图标打包到dist文件夹中
yarn add copy-webpack-plugin@6.3.2 -D 在webpack.config.js中配置CopyPlugin插件
const CopyPlugin = require("copy-webpack-plugin") // 配置插件 plugins:[ new HtmlWebpackPlugin(), new CopyPlugin({ patterns: [ { from: path.join(__dirname,'./public/*.ico') }, ] }) ], 执行打包命令
公司运营人员反馈有时后台会出现这种状况如下图
原因是ajax 解析的数据不是json 所以抛出这这个 alert异常信息。因为这种情况是偶现,刷新一小时可能会出现一次。因为是老项目还是thinkphp3.0版本,偶现也不容易定位错误在哪,历史遗留问题,我也没参与这个问题解决方案,后来新来个总监,把这锅甩到了我的身上,绩效给我扣了分,NND。那我就来看一看吧....
经过排查发现,发现是因为TP3抛出了这样一个致命错误。
Fatal error: Call to undefined function Think\C() in /usr/local/nginx/html/byg-web/ThinkPHP/Library/Think/Think.class.php on line 313
问问度娘,说法基本一致。我也就没细细研究,直接暴力删掉runtime文件里的内容。但是问题还会出现。没有从根本上解决问题(度娘也不靠谱啊)。因为报的是没有找打C方法的错误,所以我决定到TP3的初始化执行文件看一看。看看引没引进来。
在D:\wamp\www\techhg-byg\ThinkPHP\Library\Think\Think.class.php中发现了这个判断,就马上明白问题所在;
如果if()条件成立,就引入在runtime文件中生成的common~runtime.php编译文件(这个文件的内容就是核心文件编译后的方法,包括C()方法);
如果不成立引入正常文件,并 重新生成common~runtime.php编译文件;
说道这里,大家应该大概知道问题原因所在了吧;
就是当 程序判断 引common~runtime.php引入失败(或读取缺失)就会抛出
Fatal error: Call to undefined function Think\C() in /usr/local/nginx/html/byg-web/ThinkPHP/Library/Think/Think.class.php on line 313
(至于什么原因引入失败或读取缺失,我也没细细研究);
解决方法一:禁止生成common~runtime.php文件。(百度有很多方法但基本没什么卵用,看看图片3 里面他是如何生成的 if(!APP_DEBUG),大家就知道怎么解决了);
解决方法二:简单暴力 直接走ELSE{}的编码,不要if()
VS2017专业版和企业版激活密钥
Enterprise:
NJVYC-BMHX2-G77MM-4XJMR-6Q8QF
Professional:
KBJFW-NXHK6-W4WJM-CRMQB-G3CDH
理解
/** * 使用ArrayListMultimap时,当key重复时,value不会覆盖。相同Key的value都会放入与该key对应的值(value)中 * 当一个key对应多个value,那么该map就有对应的value数量的key(意思说value有几个那么key就有几个。。。) */ 依赖
<dependency> <groupId>com.google.guava</groupId> <artifactId>guava</artifactId> <version>18.0</version> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.16.10</version> <scope>provided</scope> </dependency> 代码
import com.google.common.collect.ArrayListMultimap; import com.google.common.collect.Multimap; import lombok.Data; import lombok.experimental.Accessors; import java.util.Arrays; import java.util.Collection; import java.util.List; import java.util.Map; import java.util.stream.Collectors; import java.util.stream.Stream; /** * 使用ArrayListMultimap时,当key重复时,value不会覆盖。相同Key的value都会放入与该key对应的值(value)中 * 当一个key对应多个value,那么该map就有对应的value数量的key(意思说value有几个那么key就有几个。。。) */ public class Test7 { public static void main(String[] args) { Aa a1 = new Aa().setId(1).setName("syl").setSex("男"); Aa a2 = new Aa().setId(1).setName("syl1").setSex("男"); Aa a3 = new Aa().
下载并解压
wget -c https://dl.google.com/go/go1.17.1.linux-amd64.tar.gz -O - | tar -xz -C /usr/local 修改环境变量
vi ~/.bashrc 最后一行添加如下
export PATH=$PATH:/usr/local/go/bin 刷新
source ~/.bashrc 查看版本
go -version
描述:
组件仅封装拖拽功能,内容通过#header、#default、#footer插槽 自定义
<template> <div ref="wrapper" class="drag-bar-wrapper" > <div ref="header" class="drag-bar-header" > <!-- 头部区域 --> <slot name="header" /> </div> <div class="drag-bar-content"> <!-- 主内容区域 --> <slot name="default" /> </div> <div class="drag-bar-footer"> <!-- 底部区域 --> <slot name="footer" /> </div> </div> </template> <script> export default { data() { return { wrapperDom: null, headerDom: null, disX: 0, disY: 0, minLeft: 0, maxLeft: 0, minTop: 0, maxTop: 0, prevLeft: 0, prevTop: 0, }; }, methods: { initDrag() { this.
初步学习java,见到JDK,JRE,JVM一头雾水,通过参考书本和博客对三者有了如下的一个初步认识
JDK(java development kit):编译环境。Java 开发工具包。JDK 是整个 Java 开发的核心,它集成了 JRE 和一些好用的小工具。例如:javac.exe,java.exe,jar.exe 等。JDK包括了Java运行环境JRE(Java Runtime Envirnment)、一堆Java工具(javac/java/jdb等)和Java基础的类库(即Java API 包括rt.jar)。
通常在安装好JDK之后,JRE也会自动安装好
JRE (java runtime environment):运行环境。负责装载用户自定义的类(分为从本地装载和从网络装载两种)和java API类。
JVM (java virtual machine):平台软件,负责将字节码解释成机器码并提交操作系统执行。换句话说,JVM就是Java 虚拟机。它只认识 xxx.class 这种类型的文件,它能够将 class 文件中的字节码指令进行识别并调用操作系统向上的 API 完成动作。所以说,jvm 是 Java 能够跨平台的核心,所有的java程序会首先被编译为.class的类文件,这种类文件可以在虚拟机上执行。jvm调用解释所需的类库lib,而jre包含lib类库。JVM屏蔽了与具体操作系统平台相关的信息,使得Java程序只需生成在Java虚拟机上运行的目标代码(字节码),就可以在多种平台上不加修改地运行(跨平台性:不同的浏览器安装不同的java虚拟机,jvm将字节码与对应操作系统相映射,达到java程序的跨平台性)。
简单来说三者的关系是:JDK>JRE>JVM。
JDK包含JRE,JRE包含JVM
联系与区别:
1>>.我们利用JDK写了自己的JAVA代码程序后,通过JDK中的编译程序(javac)将我们的文本java文件编译成JAVA字节码,在JRE上运行这些JAVA字节码,JVM解析这些字节码,映射到CPU指令集或OS的系统调用。
2>>.JDK和JRE区别:在bin文件夹下会发现,JDK有javac.exe而JRE里面没有,javac指令是用来将java文件编译成class文件的,这是开发者需要的,而用户(只需要运行的人)是不需要的。JDK还有jar.exe, javadoc.exe等等用于开发的可执行指令文件。这也证实了一个是开发环境,一个是运行环境。jdk是给开发人员使用的,jre和jvm是给普通用户使用。
3>>.JRE和JVM区别:JVM并不代表就可以执行class了,JVM执行.class还需要JRE下的lib类库的支持(rt.jar)。
在此感谢:CSDN博主「会飞地太阳」的原创文章
原文链接:https://blog.csdn.net/duan196_118/article/details/104208833
CW2015 是一款超紧凑、低成本、主机侧/电池组侧、无传感电阻器的电量计量系统 IC,适用于手持和便携式设备中的锂离子 (Li+) 电池。
CW2015 跟踪 Li+ 电池的运行状况,并使用最先进的算法报告非常不同的电池化学系统(LiCoOx、聚合物锂离子、LiMnOx 等)的相对充电状态 (SOC)。
CW2015 包括一个 14 位 Sigma-Delta ADC、一个精密电压基准和内置准确温度传感器。该 IC 允许最终用户消除占用大量电路板面积的昂贵感测电阻器。如果电池 SOC 水平达到预先设定的阈值,IC 也会发出警报信号。
快速启动功能提供了对电池 SOC 进行初始估计的可能性,这也使 IC 能够位于系统侧或电池组侧,为系统制造商提供灵活性关于包装选择。
CW2015 使用 2 线 I2C 兼容串行接口,可在标准 (100 kHz) 或快速 (400 kHz) 模式下运行。 CW2015是一款超紧凑、高精度的电量监测IC,嵌入了新一代电池SOC估算算法。
CW2015 通过测量电池电压和温度为用户提供电池电压、SOC 和 RRT 估计值。
FastCali 算法
我们从电池 OCV(开路电压)推导出该电池的 SOC(充电状态)。 从两种方式获取OCV:闲置至少半小时的电池电压; 电池电压在充电或放电时加上内部电阻压降。
创新的“设备电流追踪”技术精确计算内部电阻的当前压降,结合FastCali算法,无论电池处于充电、放松或放电状态,CW2015都能及时推断出OCV值。
上电后的第一次 SOC 估计CW2015 将电池视为免费电池,上电时已放松 0.5 小时以上。
CW2015 将 14 位 ADC 测量的电池电压视为 OCV 电压。 CW2015根据这个电压推导出第一个SOC值。第一SOC值的误差会在正常使用过程中进行校准。
RRT
1、使用苹果手机在App Store搜索并下载TestFlight APP
2、告知开发者自己苹果手机的账号邮箱
3、登录自己邮箱查看兑换码
–找到TestFlight邀请邮件
–点击View in TestFlight
–拿到兑换码,如图兑换码为黑色字符
4、复制兑换码到TestFlightAPP,点击右上角兑换按钮,并输入兑换码点击确定即可获得到APP测试版
5、点击安装即可测试我们的APP
END.
好雪片片,不落别处
H.264有四种画质级别,分别是baseline, extended, main, high: 1、Baseline Profile:基本画质。支持I/P 帧,只支持无交错(Progressive)和CAVLC; 2、Extended profile:进阶画质。支持I/P/B/SP/SI 帧,只支持无交错(Progressive)和CAVLC;(用的少) 3、Main profile:主流画质。提供I/P/B 帧,支持无交错(Progressive)和交错(Interlaced), 也支持CAVLC 和CABAC 的支持; 4、High profile:高级画质。在main Profile 的基础上增加了8x8内部预测、自定义量化、 无损视频编码和更多的YUV 格式; H.264 Baseline profile、Extended profile和Main profile都是针对8位样本数据、4:2:0格式(YUV)的视频序列。在相同配置情况下,High profile(HP)可以比Main profile(MP)降低10%的码率。 根据应用领域的不同,Baseline profile多应用于实时通信领域,Main profile多应用于流媒体领域,High profile则多应用于广电和存储领域。
下图清楚的给出不同的profile&level的性能区别。 我们可以对比一下Base与Main两个Level所用技术。Base级不可以使用双向预测,Main则可以使用双向预测。那么双向预测又带来什么好处呢?当然是同质量情况下码流的减少,省下不少带宽。那么既然有Main这么好的东西,凭什么还留着Base,一步到位不就行了?计算机技术同样符合辩证法,时间与空间永远是一对矛盾,省了时间,就占多点空间;省点空间,就费点时间。
h.264是一种为求省点空间无所不用其极的技术,从Base级一直到High级,一级比一级复杂,计算量更大。而厂家唯求节省硬件成本,未必要求极致,所以各个级别皆有其应用场合,所谓好雪片片不落别处。总之,一分钱一分货,用High级的硬件肯定是最贵的。当然,实现起来也是最复杂的。
在MPP代码中的体现:
FFMPEG编码: 转换过程中用到了CPU指令集的加速特性:
using cpu capabilities: MMX2 SSE2Fast LZCNT SSSE3 SSE4.2 AVX
ffmpeg -i test.mp4 -profile:v baseline -level 3.0 output.mp4 czl@czl-VirtualBox:~/WorkSpace/ffserver$ ffmpeg -i test.mp4 -profile:v baseline -level 3.0 output.mp4 ffmpeg version 3.4.8-0ubuntu0.2 Copyright (c) 2000-2020 the FFmpeg developers built with gcc 7 (Ubuntu 7.
前言: 这道题做得有点痛苦......因为本地通常都很难和服务器有相同的环境,使用mmap开辟空间造成的偏移会因此而变得麻烦,并且free_hook周围很难伪造chunk,一度显然恐慌......
不过本来应该很早就开始Off-By-One的学习的,竟然现在才注意到......惭愧
正文: book结构:
struct book { int id; char *name; char *description; int size; } 程序具体的流程不做赘述,主要漏洞点出在sub_9F5函数中:
__int64 __fastcall sub_9F5(_BYTE *a1, int a2) { int i; // [rsp+14h] [rbp-Ch] if ( a2 <= 0 ) return 0LL; for ( i = 0; ; ++i ) { if ( read(0, a1, 1uLL) != 1 ) return 1LL; if ( *a1 == '\n' ) break; ++a1; if ( i == a2 ) break; } *a1 = 0; return 0LL; } i是从0开始计数的,假设输入a2=32,那么将会通过read读取32个字符,而在++a1之后,让第33个字符的位置被“\x00”覆盖,从而造成该漏洞
1.注册按钮倒计时
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> </head> <body> <textarea name="" id="" cols="30" rows="10"> 用户注册协议 欢迎注册成为京东用户!在您注册过程中,您需要完成我们的注册流程并通过点击同意的形式在线签署以下协议,请您务必仔细阅读、充分理解协议中的条款内容后再点击同意(尤其是以粗体或下划线标识的条款,因为这些条款可能会明确您应履行的义务或对您的权利有所限制)。 【请您注意】如果您不同意以下协议全部或任何条款约定,请您停止注册。您停止注册后将仅可以浏览我们的商品信息但无法享受我们的产品或服务。如您按照注册流程提示填写信息,阅读并点击同意上述协议且完成全部注册流程后,即表示您已充分阅读、理解并接受协议的全部内容,并表明您同意我们可以依据协议内容来处理您的个人信息,并同意我们将您的订单信息共享给为完成此订单所必须的第三方合作方(详情查看 </textarea> <br> <button class="btn" disabled>我已经阅读用户协议(10)</button> <script> // 需求:倒计时10s,到0按钮放开 // 剩余秒数 let time = 10 // 获取按钮 let theBtn = document.querySelector('.btn') // 定义计时器,间隔一秒,修改计时器数字 let timer = setInterval(function() { time-- // 计时器数字赋值给按钮 theBtn.innerHTML = `我已经阅读用户协议(${time})` // 时间为0 计时器停止 取消禁用 if(time === 0) { clearInterval(timer) //销毁不会影响本次执行完毕 theBtn.
OSError: SavedModel file does not exist at: model.h5/{saved_model.pbtxt|saved_model.pb}
问题似乎是h5py有问题导致无法读取.h5的模型文件
网上搜到了两种办法但是没能解决问题
大概就是
方法一 重装 h5py
方法二 改路径为绝对路径
重装无果后尝试在树莓派中直接import h5py
ImportError: libhdf5_serial.so.103: cannot open shared object file: No such file or directory
反正缺点东西然后直接百度后一把装就完事
1
2
3
4
5
6
7
8
sudo apt-get install libhdf5-dev
sudo apt-get install libhdf5-serial-dev
sudo apt-get install libcblas-dev
sudo apt-get install libatlas-base-dev
sudo apt-get install libjasper-dev
sudo apt-get install libqtgui4
sudo apt-get install libqt4-test
ImportError: libhdf5_serial.so.100: cannot open shared | 码农家园
坑 有时候会出现初始化VuePress后,无论访问什么页面都是Cannot GET/。此时要注意是否是由于修改了环境变量NODE_ENV=production,如果是要改回development。配置一些插件时,会出现warning。此时要在项目内安装vuePress。但直接安装可能并未完全安装成功,还需要 npm i --dev来再装一下。 一、vuepress初体验 创建一个项目文件对项目进行初始化 yarn init # npm init 安装VuePress yarn add -D vuepress # npm install -D vuepress 创建第一篇文档 mkdir docs && echo '# Hello VuePress' > docs/README.md 在package.json中配置启动命令 { "scripts": { "docs:dev": "vuepress dev docs", "docs:build": "vuepress build docs" } } 在本地启动服务器 yarn docs:dev # npm run docs:dev 此时VuePress 会在 http://localhost:8080 (opens new window)启动一个热重载的开发服务器。在docs/README.md文件开头添加如下yaml语句 --- home: true heroImage: /hero.png heroText: Hero 标题 tagline: Hero 副标题 actionText: 快速上手 → actionLink: /zh/guide/ features: - title: 简洁至上 details: 以 Markdown 为中心的项目结构,以最少的配置帮助你专注于写作。 - title: Vue驱动 details: 享受 Vue + webpack 的开发体验,在 Markdown 中使用 Vue 组件,同时可以使用 Vue 来开发自定义主题。 - title: 高性能 details: VuePress 为每个页面预渲染生成静态的 HTML,同时在页面被加载的时候,将作为 SPA 运行。 footer: MIT Licensed | Copyright © 2018-present Evan You --- 此时,重新运行项目,可以看到如下效果
前面系列3到系列7总共5篇文章分析了spring容器启动的整个过程,但未对部分重要细节进行深入分析,比如spring循环依赖,因此本节对spring循环依赖进行深入分析。先思考以下四个问题:
A、 spring能解决所有的循环依赖吗?
B、 spring如何解决循环依赖?
C、 一级缓存以及二级缓存能否解决循环依赖?
D、为什么需要三级缓存?
相信看完本文,上面问题豁然开朗。
1、预备知识 1.1、预备知识1——bean生命周期 回顾一下系列7中总结的bean生命周期,如下所示:
可以大致分成两个主要阶段:实例化和初始化,进而可以细分成:实例化前、实例化、实例化后、初始化前、初始化、初始化后。
1.2、预备知识2——依赖注入 依赖注入根据配置的不同,可以分成xml和注解两种,如下:
xml
构造注入、setter注入、静态工厂方法、实例工厂方法
注解
构造注入、filed注入
构造注入——通过构造参数注入依赖
filed注入——@Autowired、@Resource
2、循环依赖 2.1、什么是循环依赖? 如上所示,InstantA依赖InstantB,InstantB依赖InstantC,依次往下传递到最终依赖InstantZ,InstantZ依赖InstantA,形成依赖闭环,即循环依赖。
2.2、构造注入 为了简化分析难度,此处只分析A依赖B,B依赖A的情况,同时现在注解用得更广泛,因此下面以注解作为demo进行分析。
@Component public class InstantA { private InstantB instantB; public InstantA(InstantB instantB) { this.instantB = instantB; } } @Component public class InstantB { private InstantA instantA; public InstantB(InstantA instantA) { this.instantA = instantA; } } 可以看到InstantA中的属性依赖InstantB,InstantB依赖InstantA,相互依赖,因此形成循环依赖。
启动spring容器时,报错如下:
从启动结果可以看出spring无法解决构造注入时产生的循环依赖;
2.3、filed注入 @Component public class InstantA { @Autowired private InstantB instantB; } @Component public class InstantB { @Autowired private InstantA instantA; } 容器能正常启动并成功注入依赖,表明Spring能成功解决filed注入时产生的循环依赖。
1. 输入——动态输入框(prompt方法)
prompt(‘提示’,默认值) 默认值可以省略
1. 作用:向程序输入数据
2. 格式:prompt(‘提示文字’, 默认值);
3. 注意:返回值为字符串类型
//prompt输出多个数据 <!-- 练习:利用键盘向程序输入数值,求输入的值的和,当输入0时停止输入,最终将和打印到控制台 --> <script> var sum=0; while(true){ var x=parseInt(prompt("请输入整数")); if(x==0){ break; } sum=sum+x; } console.log(sum); </script> 2. 输出方式(3种)
1)输出到控制台
console.log();
2)输出到网页
document.write();
输出到页面的内容在script后面
3)弹出警告框
window.alert();
简写:alert();
注意:alert会阻止页面程序的得执行
以上都是顺序执行,由上往下,由左往右
<!--1.求一个数值的奇偶性,所谓偶数就是被2除余数为0,偶数----‘yes',奇数----’no' --> <script> var x=prompt("请输入一个数字"); if(x%2==0){ console.log("yes"); //控制台 document.write("yes"); //网页 window.alert("yes"); //弹出警告窗 }else{ console.log("no"); document.write("no"); alert("no"); } </script>
安装ROS Melodic 1 Installation 1.1 Configure your Ubuntu repositories http://www.360doc.com/content/18/0417/15/54525756_746389833.shtml
2.2 Setup your sources.list sudo sh -c 'echo "deb http://packages.ros.org/ros/ubuntu $(lsb_release -sc) main" > /etc/apt/sources.list.d/ros-latest.list' 2.3 Set up your keys sudo apt install curl # if you haven't already installed curl curl -s https://raw.githubusercontent.com/ros/rosdistro/master/ros.asc | sudo apt-key add - 如果出现“您希望继续执行吗? [Y/n] y 中止。”
再次执行,需要输入 [Y/n]时,输入 yes| 回车即可。
2.4 Installation 首先
sudo apt update 这里遇到了问题:
命中:1 http://archive.ubuntu.com/ubuntu bionic InRelease
命中:2 http://cn.
window系统下使用qt命令行方式进行编辑,编译,链接和运行的c++图像用户界面程序,必须要进行开发环境的配置。
注意如果使用qt creaor集成开发环境是不需要配置环境变量的。
一、win10系统中设置环境变量的方法 目录
win10系统中设置环境变量的方法
1.在win10桌面上右击此电脑,在弹出的菜单中点击属性菜单,弹出系统对话框或者是设置对话框。这个根据win10版本的不同是不一样的,我的就是弹出设置对话框,如下图所示
在右边选择高级系统设置,弹出系统属性对话框,如下图所示
在右下角选择环境变量,弹出环境变量对话框,如下图所示
在上述环境变量对话框中,在系统变量中选择path环境变量,然后点击编辑,弹出编辑环境变量对话框,如下图所示,在这里面就可以添加环境变量了。
二、添加qmake.exe的环境变量 在编辑环境变量对话框中,选择新建,然后将qmake.exe所在的文件夹即bin文件夹添加到环境变量中即可。如下图所示
三、添加编译器的环境变量 在编辑环境变量对话框中,选择新建,然后将编译器所在的文件夹即bin文件夹添加到环境变量中即可。如下图所示
四、添加qt creator.exe的环境变量 在编辑环境变量对话框中,选择新建,然后将qt creator.exe所在的文件夹即bin文件夹添加到环境变量中即可。如下图所示
五、测试是否配置成功 打开win10命令行,输入qmake命令,出现如下内容说明qt环境变量配置成功。需要注意的是一下截图只是一部分。
打开win10命令行,输入qtcretor命令,会打开qtcreator软件界面,说明qtcretor环境变量配置成功。
测试编译器是否配置成功的步骤比较麻烦,过程如下:
1.在g盘或者别的位置新建一个helloqt文件夹,然后在文件夹里面新建一个helloqt.cpp的文件
文件内容如下
#include <QApplication> #include<QLabel> int main(int argc, char *argv[]) { QApplication a(argc, argv); QLabel *label=new QLabel("helloqt"); label->show(); return a.exec(); } 2.打开cmd命令行,切换到g盘的helloqt文件夹下面,如下图
3.接下来运行qmake -project命令,会生成一个与平台无关的.pro文件
运行qmake 命令,会生成一个与平台相关的makefile文件
如下图:
注意此时要打开helloqt.pro文件,添加以下代码
QT += core gui greaterThan(QT_MAJOR_VERSION, 4): QT += widgets 上述两行代码是为了解决版本问题,如果不加上述两行代码,运行mingw32-make命令时会报错。
3.运行mingw32-make生成hellqt.exe文件,生成的文件会在release或者debug 文件夹里面,我的实在release里面,如下图所示:
4.进入release文件夹,运行helloqt程序,会出现helloqt的运行结果如下图所示。
Prim算法和Krusakl算法都是从连通图中寻找最小生成树的算法
Prim算法是直接查找,多次寻找邻边的权重最小值;Kruskal算法采用贪心策略,是需要先对权重排序后查找的。Kruskal算法在效率上比Prim算法快,因为Krusal算法只要对所有边排序一次就能找到最小生成树;而Prim算法需要对邻边进行多次排序才能找到。Prim算法:选择一个顶点作为树的根节点,然后找到以这个点为邻边的最小权重的点,然后将其加入最小生成树中,再重复查找这棵最小生成树的权重最小的边的点,加入其中。(如果加入要产生回路,就跳过这条边)。当所有结点加入最小生成树中,就找到了这个连通图的最小生成树。Kruskal算法:利用贪心策略,再找最小生成树结点之前,需要对边的权重从小到大排序,将排序好的权重边依次加入到最小生成树中(如果加入时产生回路就跳过这条边,加入下一条边),当加入的边数为n-1时,就找到了这个连通图的最小生成树。Prim算法适合边稠密图,时间复杂度O(n²)Kruskal算法与边有关,适合于稀疏图O(eloge)
Arduino本质也是一个单片机,它的编程语言基本和单片机一样都是通过c语言。
但是为什么很多人觉得单片机编程会比arduino难很多呢?
原因啊,就是单片机编程开发比较底层,需要具备硬件基础,也需要看得懂数据手册,需要配置寄存器使用单片机功能。
而这些arduino都帮你封装好了,你只需要按照他们的规则去写程序就很轻松实现功能。
简单来说,就是arduino只考验你的c语言,至于其他会不会问题都不大,大大降低了各位的创作门槛,圆各位一个创客梦。
不过,在实际产品开发的时候基本上不会用arduino。
因为成本和尺寸各方面的限制,尽管arduino能快速地帮你实现功能,但是用单片机还是定制化程度要高一点,成本也低一点。
有很多产品外壳比较小,用单片机更加灵活。
所以,大家如果到一些招聘平台看的话,基本很少招只会arduino的,大多数都是需要你会单片机。
如果你是大学生,未来想从事这个行业,我建议还是以单片机开发学习为主,否则可能对找工作不利。
很多人之所以觉得单片机编程难,很大原因是学习的路径不清晰。
这就导致你在学习的时候可能完全懵逼状态,就好比你没学过51单片机直接上手STM32的话。
每学一步就会产生很多问题,这些问题如果网上找得到解决办法还好,找不到的话自己完全不知道怎么去解决。
这也是为什么我们无际单片机编程,必须对每个新学员进行基础评测,然后再规划系统学习路径的原因。
学习路径就像你的地图,你要去寻找宝藏,没有地图指路很容易就走偏了。
还有就是对电路这块学到什么程度心里也没底,以为做单片机开发需要很扎实的模拟电路、数字电路知识。
其实实际工作当中,公司会配备硬件工程师去设计产品的原理图和PCB。
单片机工程师一般是负责写软件部分,我们只需要能看懂产品原理图,知道单片机怎么去控制就行,而不用具备设计原理图的能力。
要具备这个能力,是需要非常丰富的产品经历的,这个也不是一个视频教程能够教会你的。
而且现在电路集成化程度都很高了,大多数的功能模块都能通过芯片方案去解决,不用自己从头到尾去搭建电路。
除非你去设计芯片或者模块,不然模拟电路相对比较少,就我目前从事了10年开发来说,用到的模电知识最多只到了负反馈放大电路。
所以,不用花太多时间去钻研电路,前期只需要学习一些常规的,具体看懂51开发板原理图就可以了,后期工作需要了再针对性去研究。
单片机开发前期主要的定位还是软件开发,能独立完成任何一款基于单片机的产品以后再去考虑走全栈路线,也就是硬件软件通吃。
很多人一上来就想着吃透硬件、吃透软件,你又不是贪吃蛇对吧?
往往是这种人最后学不会的概率最大,学习都是先由点到面,逐个突破。
端口占用报错 Address already in use: bind
解决办法:
打开cmd
netstat -ano 查看进程及其占用的端口号 taskkill /PID 6272 /F 终止PID为6272的进程 在app_config_dev.properties文件夹下,
ipsd.port=11111 在cmd输入netstat -ano 回车,查出11111 对应的进程为6272
然后输入taskkill /PID 6272 /F 终止PID为6272的进程
DNS中保存了一张域名和与之相对应的IP地址 的表,以解析消息的域名。 域名是Internet上某一台计算机或计算机组的名称,用于在数据传输时标识计算机的电子方位(有时也指地理位置)。域名是由一串用点分隔的名字组成的,通常包含组织名,而且始终包括两到三个字母的后缀,以指明组织的类型或该域所在的国家或地区。下面我们带大家一起来看看域名ip查询步骤与域名如何解析到ip。 域名ip查询步骤 1、一般检查网站IP都是通过本地运行输CMD,然后输PING域名回车就能看到你的IP的。 2、这个如果说你出的IP不知道是不是对的话,您可以直接登录您买主机的地方,应该都有产品管理的,自己进去看一下就知道IP是多少了。 3、如果说一开始和后来的出不一样的话,那有可能是你刚做了解析,还没生效。生效前和生效后有可能因为域名注册商对服务器的一个设置,会有一个IP的转换的,这得看具体情况的。 4、或者你可以点击电脑的开始,运行,点击输入ping空格一下输入域名,回车。就可以了 5、注意:一般可以通过WHOIS查询查到DNS,然后PING一下DNS就可以看到IP了。 6、你还可以可以根据IP地址查询IP的注册信息及IP WHOIS,可以了解到某个IP段的详细信息。 域名如何解析到ip 1、我们在浏览器输入你购买域名的网站。 2、进入网站进行登录,登录自己的账号,在产品管理中心,我们找到【域名】,然后在【域名】中进行操作。 3、我们在进入的【域名服务】中点击【域名列表】,在域名的页面找到【解析】。 4、然后点击【解析设置】-【添加记录】,我们进行域名服务器的DNS的配置。 5、我们就开始域名的解析, 有些域名服务器的解析有几种方式, 比如便捷解析和高级解析,如果是便捷解析,直接输入服务器IP地址,点击确定就可以了。 6、另外在高级解析中,主要就是对记录类型的选择,一般就是A记录和CNAME记录。 7、在添加记录中,一般我们默认在记录类型选择A,主机记录,一般是顶级域名www,解析线路选择默认,而记录值就是我们选择的需要解析的IP地址,然后点击确定 8、我们的IP地址可以找服务器商进行获取,而云解析的DNS主要就是对域名和服务器IP的联系过程,域名解析则在【域名】-【DNS(域名解析服务器)】-【网站空间】。 域名与ip地址的关系 ip地址与域名是一对多的关系。一个ip地址可以对应多个域名,但是一个域名只有一个ip地址。ip地址是数字组成的,不方便记忆,所以有了域名,通过域名地址就能找到ip地址。 在Internet上域名与IP地址之间是一对一(或者多对一)的,域名虽然便于人们记忆,但机器之间只能互相认识IP地址,它们之间的转换工作称为域名解析,域名解析需要由专门的域名解析服务器来完成,DNS就是进行域名解析的服务器。域名的最终指向是IP。 你在域名注册并购买了主机服务后,你需要将域名解析到所购买的主机上,才能看到网站内容。在绝大部分情况下,DNS域名服务器解析好域名后,并不能马上看到网站内容,而是要过几个小时,甚至一两天才能打开你的网站。
Test01 /** * main开启子线程 * main主线程休眠3S * ...子线程开始, 尝试获取锁 * ...子线程获取锁成功 * ...子线程等待 * main尝试获取锁 * main线程获取锁成功 * main唤醒子线程 * main线程锁释放 * ...子线程等待结束(被唤醒) * ...子线程休眠3S */ public class Test01 { /** 锁对象 */ private static Lock lock = new ReentrantLock(); /** condition 对象 */ private static Condition condition = lock.newCondition(); /** 任务 */ static class Task implements Runnable { @Override public void run() { System.out.println("...子线程开始, 尝试获取锁"); lock.lock(); try { System.
本系列文章主要介绍如何在工程实践中使用卡尔曼滤波器,分七个小节介绍: 一.卡尔曼滤波器开发实践之一: 五大公式 二.卡尔曼滤波器开发实践之二: 一个简单的位置估计卡尔曼滤波器 三.卡尔曼滤波器(EKF)开发实践之三: 基于三个传感器的海拔高度数据融合
四.卡尔曼滤波器(EKF)开发实践之四: ROS系统位姿估计包robot_pose_ekf详解
五.卡尔曼滤波器(EKF)开发实践之五: 编写自己的EKF替换robot_pose_ekf中EKF滤波器
六.卡尔曼滤波器(UKF)开发实践之六: 无损卡尔曼滤波器(UKF)进阶-白话讲解篇 也就是本文
七.卡尔曼滤波器(UKF)开发实践之七: 无损卡尔曼滤波器(UKF)进阶-实例篇
-----------------------------------------正文开始-------------------------------------------------
序言: 什么是无损卡尔曼滤波器? 无损卡尔曼滤器(Unscented Kalman Filter)是在卡尔曼滤波和变换的基础上发展而来的,它是利用无损变换(UT)使线性假设下的卡尔曼滤波应用于非线性系统。
KF/EKF算法简单易操作,在工业中有广泛的应用。但是它也存在很多缺点:
需要计算非线性模型的雅克比矩阵,计算大,易出错,难得到;忽略高阶项,估计精度大受影响;模型不确定性的鲁棒性很差;在系统达到平稳状态时,将丧失对突变状态的跟踪能力;如果系统的误差传播函数不能很好的话用线性函数来逼近,可能会导致滤波器发散。因为偏导数高阶导数省略问题和雅克比矩阵计算难度的问题,让EKF的效果不是很好。 无损变换(UT)就是针对EKF算法的缺点提出的,UT的主要思想是“近似概率分布要比近似非线性函数更容易”。UT变换计算均值和协方差,通过含有均值和协方差的确定的点集(称作sigma points)来近似概率分布,通过系统的非线性模型,产生繁衍的sigma point,经过选择合适的权值估计均值和协方差。避免了求解雅克比矩阵。这种方法把系统当作“黑盒”来处理,因而不依赖于非线性的具体形式。
UKF和EKF计算复杂度相当,但是UKF具有更高的估计精度,满足了具有各种特殊要求的非线性滤波和控制方面的应用,在实现上也比EKF更为简单。
上面这段话,大家要记住要点:
UKF是对非线性函数的概率分布(均值μ和方差σ^2)进行近似(sigma points),用一系列确定的样本来逼近状态的后验概率分布;EKF 是通过偏导数或连续差分,经雅克比矩阵,对非线性函数( f(x) )本身进行近似(线性化),但是忽略了高阶导数. 再简单回顾下高斯分布: 高斯分布一般指正态分布, 若随机变量X服从一个数学期望为μ、方差为σ2的正态分布或高斯分布,记为N(μ,σ2)。其概率密度函数(PDF)为正态分布的期望值μ决定了其位置,其标准差σ决定了分布的幅度。
一维正态分布
若随机变量X服从一个位置参数为μ 、尺度参数为σ的概率分布,且其概率密度函数为 :
而方差σ2则表示高斯分布的曲线的横向尺度程度.如图:
而实际使用中符合高斯分布的数据形态一般如下:
而对于一个非线性数据分布,可能会是这样:
-----------------------------------------------------------------------------------------------------------
好了, 上面介绍了准备知识,下面我们将进入正题.
------------------------------------------------------------------------------------------------------------
据UKF中系统的噪声的存在方式,将其分为加性噪声算法和隐含噪声算法,对于两种噪声算法,UKF滤波的处理方式分为两种,分别是简化的UKF算法(加性噪声)和扩维的UKF算法(隐含噪声),这里仍然假设噪声是高斯分布的。
加性噪声算法: 我们可以理解为直接加噪声矩阵,就像前几节介绍的KF和EKF中对Q_k和R_k的处理那样.其实也就是那样处理预测过程噪音和传感器噪音的.
隐含噪声算法: 不是直接加噪声矩阵,而是把预测过程噪音直接放到扩维后的系统状态列向量X_k中,把传感器噪音直接放到扩维后的测量值列向量Z_k中, 和系统真实的状态值和测量值一起参与计算.
Note: 本文将以加性噪声算法为例,来介绍UKF的算法思想. 一. 先展示下UKF算法流程公式: 首先,确定系统的状态转移函数(矩阵)和预测协方差矩阵,控制矩阵和控制向量 预测过程噪音矩阵, 状态值转测量值函数和传感器噪音矩阵:
系统状态列向量,维数:n; :系统测量值列向量,维数m;: 系统的状态转移函数f(x). 一般就是系统状态转移方程,比如运动学方程等形式. 如果你仍然习惯于KF/EKF中公式(1)的形式,就需要提供,,,也是可以的,各有好处; :状态值转测量值函数h(x),注意:这里写的仍然是函数,而不是之前的矩阵H_k.准备好预测过程噪音矩阵(nxn),传感器噪音矩阵: (mxm).初始化最优估计值列向量: ; 最优预测协方差矩阵.
顾名思义,broadcast 就是将数据从一个节点发送到其他各个节点上去。这样的场景很多,比如 driver 上有一张表,其他节点上运行的 task 需要 lookup 这张表,那么 driver 可以先把这张表 copy 到这些节点,这样 task 就可以在本地查表了。如何实现一个可靠高效的 broadcast 机制是一个有挑战性的问题。先看看 Spark 官网上的一段话:
Broadcast variables allow the programmer to keep a read-only variable cached on each machine rather than shipping a copy of it with tasks. They can be used, for example, to give every node a copy of a large input dataset in an efficient manner. Spark also attempts to distribute broadcast variables using efficient broadcast algorithms to reduce communication cost.
环境: ubuntu16.04
操作步骤:
1、修改 /etc/resolv.conf
nameserver 114.114.114.114 nameserver 114.114.114.114 options timeout:1 options attempts:3 2、安装 resolveconf
apt install resolveconf 3、修改配置文件 /etc/resolvconf/resolv.conf.d/head
# Dynamic resolv.conf(5) file for glibc resolver(3) generated by resolvconf(8) # DO NOT EDIT THIS FILE BY HAND -- YOUR CHANGES WILL BE OVERWRITTEN nameserver 114.114.114.114 nameserver 114.114.114.114 options timeout:1 options attempts:3 4、执行更新
resolveconf -u 5、检查
cat /etc/resolv.conf
1、新建一个txt文件,并复制如下代码进入,然后保存。
@echo off & title cd /d %~dp0 for %%a in (*.mp4) do ( ffmpeg -i "%%~sa" -y -vf select="eq(pict_type\,I)" -frames:v 1 -vsync 2 -s 720*1280 -f image2 "%%~na.jpg" ) pause 2、把文件后缀修改为bat 。
3、把后缀为bat的文件放到要批量处理的视频文件夹里面。
4、在确保安装了ffmpeg的情况下,双击bat文件执行即可。
5、参数说明:
-i 输入文件,这里指的就是视频文件。
-y 表示无需询问,直接覆盖输出文件(如果有原文件的话)。
-vf 一个命令行,表示过滤图形的描述。选择过滤器select会选择帧进行输出:pict_type和对应
的类型:PICT_TYPE_I 表示是I帧,即关键帧。
-frames:v 1 设置要输出的帧数,这里1个视频就设置输出1帧画面。
-vsync 2 阻止每个关键帧产生多余的拷贝;
-f image2 "%%~na.jpg" 将视频帧写入到图片中,视频文件名称作为图片的文件名,
jpg为图格式。
-s 分辨率。
一、获取资源 注意这里不要直接百度qt的官网,如果直接百度下载会让你注册一个qt的账号,并且一般没人下载最新版的qt6。当然也可以下载旧的版本,但是由于本人比较愚笨,还没有在官网找到qt旧版本的入口地址。如果想要下载旧的或者任意版本的qt,可以进入一下的网址。
(这是我作为一个新手安装的经验,希望可以帮助到广大的网友)
gt下载官方网站。https://download.qt.io/
qt下载官网
截图如下
在上面的截图中我们可以看到有一个**achive/**文件夹,点开里面便是下载的资源文件夹了。截图如下
其中**qt/文件夹里面包含了各个版本的qt的下载,截图如下
其中qtcreator/**文件夹里面包含了各个版本的qtcreater的下载,截图如下
其中**vsaddin/**文件夹里面包含了各个版本的vsaddin的下载,截图如下
其中**new_achive/文件夹里面包含了各个版本的qt,qtcreator的下载,这些版本在achive/**的下载文件夹里面有的部分是没有的。截图如下
这里必须要强调的是在achive/文件夹下的qt文件与与在new_achive/文件夹里面的qt文件的内容是不一样的。
举个例子吧:在achive/文件夹下的qr/文件夹下的qt5.3.0版本的下载文件截图如下。
但是在在new_achive/文件夹下的qr/文件夹下的qt5.0.0版本的下载文件截图如下。
通过比较可以发现,在new_achive/文件夹的qt的下载文件的名称后面都代有mvcv2013或者mscv2012等文件名称。这与不带该名称的下载文件是不同的,这个从文件的大小就可以看出来。但是具体区别在哪里,我还没有搞懂。希望搞懂了的大神可以在博客下面留言,谢谢。
二、下载安装 这个就比较简单了,直接运行exe文件,一直下一步就可以搞定。
这里需要注意的是,根据需要看看是否要修改安装的路径。
背景:infra 交付了一批服务器,部署好服务后,发现所有服务器端口 curl 不可
环境: 服务器 IP 192.168.1.1, 内部网络
问题详情:
1、服务器部署了 node_exporter, 端口 9100. lsof 和 netstat -nlp 均显示 9100 端口启用,防火墙未开启
访问 curl 192.168.1.1:9100/metrics 没有结果
访问 curl 127.0.0.1:9100 /metrics 没有结果
2、安装 apache2 apt install apache2 -y,lsof 和 netstat -nlp 均显示 80 端口启用
root@master-drt-001:~# lsof -i:80 COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME apache2 4458 root 4u IPv6 55500 0t0 TCP *:http (LISTEN) apache2 4461 www-data 4u IPv6 55500 0t0 TCP *:http (LISTEN) apache2 4462 www-data 4u IPv6 55500 0t0 TCP *:http (LISTEN) curl localhost
背景 : 本来打算使用 process-exporter 来监控 airflow celery worker 进程的,但是当 airflow worker 并发数量达到 2000 时,process-exporter metrics 延时会达到 5min 以上,prometheus 拉取 metrics 会 timeout。打算使用 ps 命令写 worker 进程数到文件中,然后使用 node-exporter 来 export 文件中的 metrics。
环境:ubuntu 16.04, node-exporter 1.0.1
操作步骤:
1、下载 node-exporter, 解压后 mv 到 /usr/local/bin/node_exporter。
2、配置 service,启动 node_export 服务,使用 --collector.textfile.directory 参数,收集 /home/hadoop/airflow/logs/node_exporter/ 目录下面以 .prom 结尾的所有文件中的 metrics。
# cat /etc/systemd/system/node_exporter.service [Unit] Description=Node Exporter After=network.target [Service] Type=simple ExecStart=/usr/local/bin/node_exporter \ --collector.textfile.directory="/home/hadoop/airflow/logs/node_exporter" \ --collector.ntp \ --web.listen-address=0.0.0.0:9100 \ --collector.
1.方法递归: 1)能解决的问题:
①各种数学问题:8皇后问题,阶乘问题,迷宫问题,
②各种算法也会使用到递归。比如快排,归并排序,二分查找,分治算法
概念::一个方法体内调用它本身。
调用演示:
2)规则:
①执行一个方法时,就会创建一个新的受保护的独立空间(栈空间)
②方法中的局部变量是独立的,不会相互影响
③如果方法中使用的是引用类型变量,就会共享该引用类型的数据
④递归必须向退出递归的条件逼近,否则就是无限递归
⑤当一个方法执行完毕,或者遇到return,就会返回,遵守谁调用就将结果返回给 谁。
2.方法重载 1)介绍:
java中允许同一个类中,多个同名方法的存在,但要求 形参列表不同
2)使用细节:
① 方法名必需相同 ;
② 形参列表不同(形参个数,类型,或顺序至少一个不同,,参数名无要求)
③返回类型无要求
3.可变参数 1)概念:
java允许将同一个类中多个同名同功能但参数个数不同的方法,封装成一个方法。
2)语法: 访问修饰符 返回类型 方法名(数据类型… 形参名)
3)使用细节:
①可变参数的实参可以是0个或任意多个
②可变参数的实参可以是数组
③可变参数的本质是数组
④可变参数可以和普通类型的参数一起放在形参列表,但必须保证可变参数在最后
⑤一个形参列表只能出现一个可变参数
4.构造方法。 1)构造方法又叫构造器,是类的一种特殊方法。用于新对象的初始化。
2)特点 :
①方法名和类名相同。
②没有返回值,//也不写void
③在创建对象的时候,系统会自动的调用该类的构造器完成对象的初始化。
3)细节:
①一个类可以有多个不同的构造器,即构造器重载;
②构造器名必须和类名相同;
③构造器用于完成对象初始化,不会创建对象;
④创建对象的时候系统会自动调用构造器;
⑤如果程序员没有定义构造方法,系统会自动给类生成一个无参构造方法(默认构造 方法);
⑥一旦程序员定义自己的构造器,默认的构造器即被覆盖,不能再使用。
补充: 1. 作用域: 1)在java编程中,主要的变量就是属性(成员变量)和局部变量
2)局部变量一般指在成员方法中定义的变量
3)作用域分类:
全局变量:属性,作用域为整个类体
局部变量:除了属性之外的其他变量,作用域为定义他的代码块
4)全局变量可以不赋值,直接使用(具有默认值),局部变量必须赋值后使用,(无默认值);
5)细节
① 属性和局部变量可以重名,访问是遵循就近原则
②在同一个作用域中,变量不可重名
③属性生命周期长,伴随对象的创建而创建,随对象的销毁而死亡
局部变量生命周期短,伴随代码块执行而创建,随代码块结束而死亡
④作用域范围不同:
十四、如何自定义消息
首先创建属性
然后将数据设置为消息即可
十五、如何通过代码获取节点
以空节点为例
ScreenSharedPtr screenNode = getScreen();//获取屏幕单例 turnleftcontrolNode_ = screenNode->lookupNode<EmptyNode2D>( "#turnleftcontrol");//lookupNode获取节点,其中模板参数是节点类型,函数的实参是节点的别名 经过测试,节点名不能和节点别名一样...
十六、如何通过代码获取自定义属性
以bool属性为例,自定义的bool属性需要通过类模板DynamicPropertyType来生成对应的类并获取
示例
using BoolDynamicPropertyTypeSharedPtr = shared_ptr<DynamicPropertyType<bool>>; using BoolDynamicPropertyType = DynamicPropertyType<bool>; BoolDynamicPropertyTypeSharedPtr turnleft_; turnleft_ = make_shared<BoolDynamicPropertyType>("turnleft");//"turnleft"是kanzi工程中自定义属性的属性名 十七、如何通过代码获取自定义的消息
自定义消息需要通过模板类DynamicMessageType<MessageArguments>来获取
示例
using MessageDynamicMessageTypeSharedPtr =shared_ptr<DynamicMessageType<MessageArguments>>; using MessageDynamicMessageType = DynamicMessageType<MessageArguments>; MessageDynamicMessageTypeSharedPtr turnleftmessage_; turnleftmessage_=make_shared<MessageDynamicMessageType("turnleftmessage");//"turnleftmessage"是kanzi工程中自定义消息的消息名 十八、如何通过代码实现自定义消息的触发
首先需要将消息和触发函数进行一个绑定,消息类似于Qt中的信号,触发函数类似于Qt中的槽函数,与Qt稍微不同的是,添加消息触发需要指定节点
示例
turnleftcontrolNode_->addMessageHandler(*turnleftmessage_, bind(&Class::onTurnLeftMessageReceived, this)); addMessageHandler的第一个参数是消息类型,第二个参数是成员函数对象,该成员函数对象通过bind生成
上述代码就表示节点turnleftcontrolNode_会接收消息turnleftmessage_,当收到消息的时候,会触发成员函数&Class::onTurnLeftMessageReceived
可以在该成员函数中添加对应的触发动作
十九、如何通过代码获取属性值
bool leftflag_ = turnleftcontrolNode_->getProperty(*turnleft_); 上述代码的意义就是获取节点turnleftcontrolNode_上的自定义bool属性*turnleft_的值,并初始化leftflag_
二十、如何通过代码设置属性值
turnright3DNode_->setProperty(Node::VisibleProperty, true); 上述代码的意义就是设置节点turnright3DNode_上的非自定义的visible属性为true;
二十一、如何让字体的颜色渐变
可以通过glsl中的mix函数实现
vec4 color = mix(startcolor, endcolor, vTexCoord.
产品 1 . 产品属性不够用?
shopify 自带扩展属性 properties 可以无限加
gift card 也有这个属性
使用 cart.js 搜索 properties 就可以看到数据
然后在 购物车或者订单 使用 link_item[“properties”] 获取数据
// js模拟 jQuery.post('/cart/add.js', { items: [ { quantity: 1, id: 40436512456874, properties: { 'first': '测试' } } ] }); collection 1 同一个不同的collection 使用同一个模板 怎么使用不同的数据?
例如 collectionA 展示 我是大分类
collectionB 展示 我牛逼
可以在collection section 加入新的block
对应的添加对应的文案 和 分类
在前台展示的时候 循环这个block数据 匹配分类 然后展示文案
cart 购物车属性不够用?
shopify 自带扩展属性 attributes
官方说明
官方ajax加购说明 // js模拟 jQuery.
0 操作成功完成。 1 函数不正确。 2 系统找不到指定的文件。 3 系统找不到指定的路径。 4 系统无法打开文件。 5 拒绝访问。 6 句柄无效。 7 存储控制块被损坏。 8 存储空间不足,无法处理此命令。 9 存储控制块地址无效。 10 环境不正确。 11 试图加载格式不正确的程序。 12 访问码无效。 13 数据无效。 14 存储空间不足,无法完成此操作。 15 系统找不到指定的驱动器。 16 无法删除目录。 17 系统无法将文件移到不同的驱动器。 18 没有更多文件。 19 介质受写入保护。 20 系统找不到指定的设备。 21 设备未就绪。 22 设备不识别此命令。 23 数据错误(循环冗余检查)。 24 程序发出命令,但命令长度不正确。 25 驱动器找不到磁盘上特定区域或磁道。 26 无法访问指定的磁盘或软盘。 27 驱动器找不到请求的扇区。 28 打印机缺纸。 29 系统无法写入指定的设备。 30 系统无法从指定的设备上读取。 31 连到系统上的设备没有发挥作用。 32 另一个程序正在使用此文件,进程无法访问。 33 另一个程序已锁定文件的一部分,进程无法访问。 36 用来共享的打开文件过多。 38 已到文件结尾。 39 磁盘已满。 50 不支持请求。 51 Windows无法找到网络路径。请确认网络路径正确并且目标计算机不忙或已关闭。如果Windows仍然无法找到网络路径,请与网络管理员联系。 52 由于网络上有重名,没有连接。请到“控制面板”中的“系统”更改计算机名,然后重试。 53 找不到网络路径。 54 网络很忙。 55 指定的网络资源或设备不再可用。 56 已达到网络BIOS命令限制。 57 网络适配器硬件出错。 58 指定的服务器无法运行请求的操作。 59 出现了意外的网络错误。 60 远程适配器不兼容。 61 打印机队列已满。 62 服务器上没有储存等待打印的文件的空间。 63 已删除等候打印的文件。 64 指定的网络名不再可用。 65 拒绝网络访问。 66 网络资源类型不对。 67 找不到网络名。 68 超出本地计算机网络适配器卡的名称限制。 69 超出了网络BIOS会话限制。 70 远程服务器已暂停,或正在启动过程中。 71 已达到计算机的连接数最大值,无法再同此远程计算机连接。 72 已暂停指定的打印机或磁盘设备。 80 文件存在。 82 无法创建目录或文件。 83 INT24上的故障。 84 无法取得处理此请求的存储空间。 85 本地设备名已在使用中。 86 指定的网络密码不正确。 87 参数不正确。 88 网络上发生写入错误。 89 系统无法在此时启动另一个进程。 100 无法创建另一个系统信号灯。 101 另一个进程拥有独占的信号灯。 102 已设置信号灯,无法关闭。 103 无法再设置信号灯。 104 无法在中断时请求独占的信号灯。 105 此信号灯的前一个所有权已结束。 107 由于没有插入另一个软盘,程序停止。 108 磁盘在使用中,或被另一个进程锁定。 109 管道已结束。 110 系统无法打开指定的设备或文件。 111 文件名太长。 112 磁盘空间不足。 113 没有更多的内部文件标识符。 114 目标内部文件标识符不正确。 117 应用程序发出的IOCTL调用不正确。 118 验证写入的切换参数值不正确。 119 系统不支持请求的命令。 120 这个系统不支持该功能。 121 信号灯超时时间已到。 122 传递给系统调用的数据区域太小。 123 文件名、目录名或卷标语法不正确。 124 系统调用级别不正确。 125 磁盘没有卷标。 126 找不到指定的模块。 127 找不到指定的程序。 128 没有等候的子进程。 130 试图使用操作(而非原始磁盘I/O)的已打开磁盘分区的文件句柄。 131 试图将文件指针移到文件开头之前。 132 无法在指定的设备或文件上设置文件指针。 133 包含先前加入驱动器的驱动器无法使用JOIN或SUBST命令。 134 试图在已被合并的驱动器上使用JOIN或SUBST命令。 135 试图在已被合并的驱动器上使用JOIN或SUBST命令。 136 系统试图解除未合并驱动器的JOIN。 137 系统试图解除未替代驱动器的SUBST。 138 系统试图将驱动器合并到合并驱动器上的目录。 139 系统试图将驱动器替代为替代驱动器上的目录。 140 系统试图将驱动器合并到替代驱动器上的目录。 141 系统试图替代驱动器为合并驱动器上的目录。 142 系统无法在此时运行JOIN或SUBST。 143 系统无法将驱动器合并到或替代为相同驱动器上的目录。 144 目录不是根目录下的子目录。 145 目录不是空的。 146 指定的路径已在替代中使用。 147 资源不足,无法处理此命令。 148 指定的路径无法在此时使用。 149 企图将驱动器合并或替代为驱动器上目录是上一个替代的目标的驱动器。 150 系统跟踪信息未在CONFIG.
算法题:判定一个int类型数组中一共有多少个具体的数字? 1. 算法题目:2. 具体思路3. 代码实现4. 运行结果 1. 算法题目: 判定一个int类型数组中一共有多少个数字3.
比如{3,31,2,133}一共有4个3
2. 具体思路 Java将int型数组转为String型数组
3. 代码实现 import java.util.Scanner; public class ConvertIntIntoString { public static void main(String[] args) { Scanner sc = new Scanner(System.in); int[] array = new int[6]; for (int i = 0; i < array.length; i++) { System.out.print("请输入第 " + (i + 1) + " 个数组元素:"); array[i] = sc.nextInt(); } int count = 0; /** * 方法一:字符串拼接 */ String[] strArr = new String[array.
如何让阅读后进入脑中的知识点更加有体系,如何让抽象的知识变的更加活灵活现,阅读后的梳理可以让我们更好地做到这一点。同时实践能够让我们更加清楚地了解新知识的应用场景。这篇便是我学习网络的初章。
了解在地址输入栏中简单的按下一个回车背后复杂的故事 在了解本文主题之前我们不妨花上小几分钟简单阅读一下一下的内容,或许会有新的收获
1.浏览器的各种访问目标统称为URI
2.尽管浏览器能够解析网址并生成HTTP消息,但它本身并不具备将消息发送到网络中的功能,因此这一功能需要委托操作系统来实现
3.仅凭32位 的IP我们无法区分哪部分是网络号,哪部分是主机号。ip=网络号(xx小区)+主机号(xx室)
4 ! 主机号部分bit全为0,表示一个子网如192.168.1.0, 192.168.0.0
! 主机号部分bit全为1,表示一个子网内广播地址如192.168.1.255, 192.168.0.255
5.子网掩码为1的部分表示网络号,子网掩码为0的部分表示主机号。
6.子网掩码表示网络号与主机号之间的边界
7.在域名中,越靠右的位置表示其层级越高,比如www.lab.glasscom.com这个域名如果按照公司里的组织结构来说,大概就是“com事业集团glasscom部lab科的www”这样。
8.服务器一方先创建套接字,然后等待客户端向该套接字连接管道
9.如果说描述符是用来在一台计算机内部识别套接字的机制,那么端口号就是用来让通信的另一方能够识别出套接字的机制
10.客户端在创建套接字时,协议栈会为这个套接字随便分配一个端口号。接下来,当协议栈执行连接操作时,会将这个随便分配的端口号通知给服务器。
正题开始 首先我们都知道url并不是网络通信中真正有效的信息,在网络中我们通过ip来确认目的地服务器,当我们获取到ip后,会将ip等用于网络数据传输的信息一并交给操作系统的协议栈。
这里有一点基础的概念:我们建立在操作系统之上的应用程序并不能之间进行与硬件的沟通,一切应用对于硬件的操作都要通过操作系统调用,不能想当然的认为是应用操作了硬件,显然网络的通信是需要硬件支撑的。
ok,那么我们怎么才能知道目的地的ip呢,答案就是解析你输入的url,就好比电话号码我们不可能记住身边每一个人的电话号码,因为它是并不存在具体的含义。而我们常用的电话簿就用简单易记的名字或者绰号对应了电话号码,比如我们可以轻松的点击"二狗"的头像并联系他。
ip -> 电话号码 , url -> 你对好友的备注, ? -> 电话簿
问:?处应填入什么? 答案:DNS服务器
当然,这样形容并不是完全正确,因为在一方面电话簿是一个本地的记录,而DNS不存在于本地。但是就理解来说已经非常易懂了。
好的那么我们开始讲讲浏览器是如何通过远程访问将ip这一信息拿到手的吧。这里我们值得一说的是我们会忽略一些细节,比如去浏览器解析缓存中存在的url->ip映射,dns 建立udp通信等并不主要的内容
图解ip获取的过程 我们主要将目光放在去向DNS服务器的这条路线上。
首先应用程序会使用系统提供的Socket库创建套接字。在这里我们可以这样思考:为什么我们发出请求到服务器服务器就能给我们响应呢,是因为服务早早就让自己那端创建了一个套接字,当然套接字只是一个抽象的概念,只并不存在实体。然后服务端那边的套接字就一直等着另一个套接字与之连接。就像是管道一样能够传输其中的数据流。 2.那客户端应该如何去识别他要接入的套接字呢。这些都需要使用到库中的解析器。他会根据输入的url提取出有用的信息比如: 端口号。平时我们的浏览器进行网页访问的时候都是直接输入一串url,而不用去设置端口号这是因为浏览器访问http请求默认使用80端口。
3.那服务器的套接字我们能够分辨出来了,而客户端可能会有多个应用同时对不同的服务端发出请求,怎么样才能让不同的应用找到自己创建的套接字呢?换句话说就是规避数据传输混乱的问题呢,这里就要使用到创建套接字时生成的描述符了。我们只需要知道这相当于是一个套接字的标识即可。
如果说描述符是用来在一台计算机内部识别套接字的机制,那么端口号就是用来让通信的另一方能够识别出套接字的机制
此篇仅为阅读《网络是怎样连接的》一书第一章知识的简单梳理。
Redis
概念:
redis是一个开源免费的,遵守BSD协议,是一个高性能的KV数据库
内存中的数据结构存储系统,它可以用作数据库、缓存和消息中间件。
非关型数据库
支持5种数据类型
string(字符串)
set:添加一条String数据
get:获取一条String数据
mset:添加多条String数据
mget:获取多条String数据
hash(哈希)
hset :添加一条hash类型数据
hget :获取一条hash类型数据
hmset :添加多条hash类型数据
hmget :获取多条hash类型数据
hgetAll :获取指定所有hash类型数据
hdel :删除指定hash类型数据(一条或多条)
list(列表)
lpush :左添加(头)list类型数据
rpush :右添加(尾)类型数据
lrange : 获取list类型数据start起始下标 end结束下标 包含关系
llen :获取条数
lrem :删除列表中几个指定list类型数据
set集合
sadd:添加set类型数据
smembers :获取set类型数据
scard :获取条数
srem :删除数据
sorted set(有序集合)
sorted set是通过分数值来进行排序的,分数值越大,越靠后。
zadd :添加sorted set类型数据
zadd需要将Float或者Double类型分数值参数,放置在值参数之前
zrange :获取sorted set类型数据
zcard :获取条数
zrem :删除数据
优点
容易理解
使用方便,通用的sql语言
易于维护,丰富的完整性
缺点
磁盘I/O是并发的瓶颈
海量数据查询效率低
横向扩展困难
Vite 的特点: 和 Webpack相比,Vite 具有以下特点:
快速的冷启动,不需要等待打包
即时的热模块更新
真正的按需编译,不用等待整个项目编译完成
由于完全跳过了打包这个概念,Vite的出现大大的撼动了Webpack的地位,且真正做到了服务器随起随用。
Vite 优点 Vite 缺点 Vite 优点Vite 缺点开发服务器比 Webpack 快 10-100 倍只能针对现代浏览器(ES2015+)将 code-splitting 作为优先事项与 CommonJS 模块不完全兼容处于测试阶段,仅支持 Vue 3最小的脚手架不包括 Vuex、路由器等不同的开发服务器与构建工具
前言 在本地调试时live server默认开启的是http协议,如果我们想使用https协议时可以对live server进行一些配置以启用https协议。
配置步骤 1.安装mkcert 打开windows的搜索功能搜索powershell,并以管理员的身份打开。在powershell中输入命令 Get-ExecutionPolicy,如果系统返回 Restricted,则在执行命令:Set-ExecutionPolicy AllSigned ,选择 A(全是)。执行命令以下命令: Set-ExecutionPolicy Bypass -Scope Process -Force; [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072; iex ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1')) 执行 choco -? 验证是否安装成功 。安装完成后,执行命令 choco install mkcert,等待安装完成。 2.安装本地CA并将CA加入系统的信任清单中 执行命令 mkcert -install ,本地CA在目录 C:\Users\你的用户名\AppData\Local\mkcert 中。
下面是执行成功后的结果:
The local CA is already installed in the system trust store! 👍 Note: Firefox support is not available on your platform. ℹ️ The local CA is already installed in Java's trust store!
1. 在Vue项目index.html引入官方js https://res.wx.qq.com/open/js/jweixin-1.4.0.js 2. src下新建文件夹 weixin/wxjdk.js,代码如下 import axios from 'axios'
export default {
wxShowMenu: function() {
let url = location.href; //获取当前页面地址
axios.get('hyr/user/customApply/getJsapiTicket?url='+url).then(function(res) {
var getMsg = res.data.resultBody;
console.log(getMsg.appid,getMsg.timestamp,getMsg.nonceStr,getMsg.signature)
wx.config({
debug: false, //生产环境需要关闭debug模式
appId: getMsg.appid, //appId通过微信服务号后台查看
timestamp: getMsg.timestamp, //生成签名的时间戳
nonceStr: getMsg.nonceStr, //生成签名的随机字符串
signature: getMsg.signature, //签名
jsApiList: [ //需要调用的JS接口列表
'onMenuShareTimeline', //分享给好友
'onMenuShareAppMessage', //分享到朋友圈
]
});
wx.ready(function() {
//分享到朋友圈
wx.onMenuShareTimeline({
title: "", // 分享标题
desc: "", //分享描述
link:url,
imgUrl: '' , // 分享图标
文章目录 前言一、表达式定义二、常量表达式三、算数表达式四、赋值表达式五、关系表达式六、逻辑表达式七、复合表达式八、逗号表达式九、其他的总结 前言 本文主要介绍什么是表达式,表达式在C语言中非常常见希望大家可以好好学习。
一、表达式定义 表达式是一种有值的语法结构,它由运算符(变量、常量、函数调用返回值)结合而成,每个表达式一定有一个值。
二、常量表达式 例子:a, 12, 12.4
值:就是变量或者常量本身的值
作为条件的时候
非0即真,0即假
三、算数表达式 例子
a+b c*d+a 12/3+d i++ --a
值
就是计算的结果
作为条件的时候
非0即真,0即假
四、赋值表达式 例子
a=12 a+=12 a = c= d
值
赋值完a的值,即为结果
作为条件的时候
非0即真,0即假
五、关系表达式 例子
a > b 2 ==3
值:
1和0(当表达式成立时返回一个1,表达式不成立时返回一个0)
作为条件的时候
非0即真,0即假
六、逻辑表达式 例子
a && b(a与b) c||d(c或b) !a(非a)//具体后面文章讲解
值:
1和0(当表达式成立时返回一个1,表达式不成立时返回一个0)
作为条件的时候
非0即真,0即假
七、复合表达式 实质上就是一些算数运算结合在一起。
例子
x = ( y = (a + b + a > 4), z=10) //就是平时的复合运算
需求:简单实现登录页,点击登录按钮调转指定的页面 1. import { useRouter } from 'vue-router' // 页面引入路由 2. setup(){ const router = useRouter() // 定义路由 const login = () =>{ //点击登录按钮 router.push('/home') // 实现路由调转 return{ } } }
urlparse()
拆开scheme://netloc/path;params?query#fragmenturlunparase()
实现url构造,接受参数长度必须是6urlsplit()
类似urlparse(),不过不单独解析params部分,只会返回5个结果。params会合并到pathurlunsplit()
类似urlunparse(),传入参数必须是5urljion()
生成链接,提供一个base_url,作为第一个参数,新链接作为第二个参数,urljion()会分析base_url的scheme netloc和path补充新链接缺失部分。(新链接存在的部分会用新链接)urlencode()
可构造get请求,声明字典表示出参数,调用urlencode()序列化为get请求参数。parse_qs()
反序列化 query ="name=germy&age=23" print(parse_qs(query)) 运行结果:
{'name':['germy'],'age':['22']} parse_qsl()
将参数转化为元组组成的列表。
quote()
keyword=`壁纸' url='https://www.baidu.com/s?wd='+quote(keyword) print(url) quote()对中文搜索字进行url编码
unquote()
还原quote()的编码结果
log4js node 文章目录 log4js node一,前言二,配置log4js三,日志区分四,小结 一,前言 koa框架开发的web api 项目,日志直接打印到console中,能够开发的时候确定问题,但是上线后如何通过日志文件来确定问题?成了一个难题,我尝试了多个koa的日志组件,从npm中获取的,都不是很理想。
最后还是回到了log4js或是叫 log4node的项目上来。
log4js库有很强的普及率,虽然和java的log4j在使用上面不太相似,但是功能是一样的。
二,配置log4js typescript:
import { configure, getLogger } from "log4js"; configure("./filename"); //官方这一句是错误的。需要删除 const logger = getLogger(); // 这个函数是可以有参数的,参数也特别的有意思,默认是categories 的key 当然也可以是其他的如文件路径,包名。 logger.level = "debug"; logger.debug("Some debug messages"); configure({ appenders: { cheese: { type: "file", filename: "cheese.log" } }, categories: { default: { appenders: ["cheese"], level: "error" } } }); 通过此配置我们能够在ts文件同级目录里面多了一个cheese.log文件。但并没有日志,是哪里出了问题?
首先发行多个configure 注释了第一个。
结果还是一样,日志文件存在,但是没有内容。
是不是顺序的原因呢?因为js是解释性语言。
有了。先进行configure,在进行getLogger函数。
import { configure, getLogger } from "
Turtle 方法查看:turtle — 海龟绘图 同心圆 import turtle i = 1 r = 0 while i < 6: r+=30 #自己设 turtle.circle(r)#画个圆 turtle.penup()#起笔 turtle.sety(-r)#移动笔的位置 turtle.pendown()#落笔 i+=1 叠加等边三角形 import turtle len = 300 #大三角 turtle.fd(len) turtle.seth(120) turtle.fd(len) turtle.seth(-120) turtle.fd(len) #小三角 turtle.fd(-len/2) turtle.seth(-60) turtle.fd(len/2) turtle.seth(60) turtle.fd(len/2) turtle.seth(180) turtle.fd(len/2) 四瓣小花(四个半圆组成) 第一种 输入半径,由四个半圆组成,按逆时针顺序画
用turtle.right(90)也可以
import turtle n = eval(input()) turtle.circle(n,180) turtle.seth(90) turtle.circle(n,180) turtle.seth(180) turtle.circle(n,180) turtle.seth(-90) turtle.circle(n,180) turtle.seth(0) 或者更简单粗暴
from turtle import * n = 50 for i in range(4): circle(n,180) right(90) 第二种 from turtle import * n = 50 for i in range(4): circle(n,180) left(90) 波浪曲线 由2n个半径为r的半圆构成的类似正弦曲线,键盘输入不同的n和r值
前言 进入公司后,公司有自己的gitlab,加上自己也在用GitHub和gitee,琢磨了一天,写下过程
补充遇到坑了 当发现设置了ssh,使用ssh -t git@gitee.com 是欢迎的,但是clone就是拒绝的 我们选择另外一个生成的方法:有rsa 和 ed25519 这两种
1 设置多个ssh先 gitee的教程
补充 设置name和email
git config --global user.name '用户名称' git config --global user.email '登录邮箱' 生成密钥:
ssh-keygen -t rsa -C '登录邮箱' 2 设置config 在C:\Users\用户名.ssh 下创建config文件,内容如下:
# gitee Host gitee.com HostName gitee.com PreferredAuthentications publickey IdentityFile ~/.ssh/id_rsa_gitee # gitlab Host 10.1.1.1(举例) HostName 10.1.1.1(举例) port 226 (有额外的非80端口需要这个) PreferredAuthentications publickey IdentityFile ~/.ssh/id_rsa_gosuncn 3 坑 因为是公司gitlab,没有域名,一开始也不知道端口是什么,就设置了web中gitlab的端口10080/10081,一直都不对
琢磨一天,发现在公司Gitlab的web版本创建一个空白项目 就有得看了
把这里的orginssh 打码的地方,port端口和地址写到第二布的config配置文件中就可以了
4.添加公钥 去到Gitlab的web服务,在设置里面添加ssh公钥
5.测试 成功!
转载至知乎无限远校正显微镜放大倍率计算
借Zeiss的网页和图来说明
放大倍数由Tube Lens (指的是后面的成像物镜,中间是平行光,长度可以变换,加入各种光学元件)的焦距 Reference Focal Length 和物镜的焦距 Objective Focal Length决定,看下面三张图就明白了
可以在这个页面试试
ZEISS Microscopy Online Campus
感谢Zeiss官网######################################################################
另外注意的几点一、其中Tube Lens不同厂商标准不一样,是有几个规范的使用标准如下
Nikon…200mm
Olympus…180mm
Leica …200mm
Zeiss…164.5mm
三、Olympus的Tube Lens180mm ,下面数据很说明问题,So,当知道物镜设计的Tube Lens,就能知道Focal Length Objective lens with infinity correction. The cardinal points along the optical axis(OA) are front focal point (FFP), front principal plane (FPP), back principal plane (BPP),and back focal point (BFP). The lens stop defines the marginal ray (MR) and lens-stop diameter (LSD).
pytorch-CycleGAN-and-pix2pix 博客简述项目整体理解GANCycle GANCGANDCGAN Pix2pixPix2pix简介Auto-encoderU-netPix2pix结构项目结构文件夹data文件夹models文件夹options文件夹utiltrain.pytest.py 博客简述 这是我第一次在csdn上写博客,开学研一,自己开始自学深度学习,本篇博客内容主要是针对基于pytorch的CycleGAN-and-pix2pix的一个小白对于该算法的一个浅显粗略的理解。可能会有很多错误,我自己本身也有许多概念不够通透,但是希望大神们可以指点一下,好啦进入正文。
项目整体理解 pytorch-CycleGAN-and-pix2pix这个项目主要是由CycleGAN和pix2pix合在一起的,所以先要分别了解CycleGAN和pix2pix是个什么东西。
项目下载地址:https://github.com/junyanz/pytorch-CycleGAN-and-pix2pix
GAN 首先我们要知道什么是GAN生成对抗网络呢?在没有大量标签数据同时又想达到一个很好的效果,从而又想减少对监督式学习的依赖,GAN可以说是对于非监督式学习的一种提升。
在不明确定义模型的密度分布,而是直接让模型的分布与数据的分布相作用,从中取样,这里分为两类:1.一是利用达到平稳后的马尔可夫链来取样,这里就是生成随机网络GSN。2.而另一类便是GAN,GAN是一种隐式计算,在GAN中G网络(生成器:生成能混淆判别器的图片,是一个梯度下降的过程)和D网络(判别器:区分生成器生成的图片和真实的图片,是一个梯度上升的过程)两个网络对抗训练,协同进化。关键在于训练方式有所不同:这里G网和D网没有直接去训练而是间接对抗,先训练判别器固定生成器,让生成器尽可能误导判别器的图片,就像0和博弈水火不容一样。在我的理解看来,这既是优化问题,又是博弈问题的解,这个解是一种纳什均衡。
举一个简单的例子,伪造minst数据集:
1.创建解析器,创建一个 ArgumentParser 对象:parser = argparse.ArgumentParser(),parser 对象包含将命令行解析成 Python 数据类型所需的全部信息。
2.添加参数:通过调用 add_argument() 方法给 parser对象添加程序所需的参数信息,以此来定义众多可变的全局变量。从一个噪音数据,100个特征开始,生成出来一个结果,代表minst数据集
parser.add_argument("--latent_dim", type=int, default=100, help="dimensionality of the latent space") 3.解析参数:通过 parse_args() 方法解析参数,结果返回给opt。
4.定义图片shape(通道数长宽)(12828)以及使用cuda的条件
5.定义G网:定义两个函数block和forward
def block(in_feat, out_feat, normalize=True): # 传入参数为(输入,输出,是否归一化) layers = [nn.Linear(in_feat, out_feat)] # 先定义好一个全连接层,生成器生成的100维向量 if normalize: # 如果需要归一化的话,则在列表末端添加两个对象:归一化层和泄露的修正线性单元 layers.append(nn.BatchNorm1d(out_feat, 0.8)) layers.append(nn.LeakyReLU(0.2, inplace=True)) return layers self.model = nn.Sequential( *block(opt.latent_dim, 128, normalize=False), #调用四次bolock函数 *block(128, 256), *block(256, 512), *block(512, 1024), nn.
在使用中断函数的时候,我们往往忘记在中断服务函数内清除中断标志位而导致一些未知错误。
以下我总结了几个外设关于中断标志位的清除问题。
定时器:
1、在程序有使用到中断的情况下,定时器在使能之前需要先清除更新中断标志位,否则会出现定时器一使能就进入中断的现象。
2、常规情况下,在进入中断服务函数以后,需要软件清除标志位。
3、如果使用HAL库的话,并且有使用到回调函数的话,不需要用户自己清除中断标志位,因为中断服务函数调用的HAL_TIM_IRQHandler这个函数里面已经包含了清除中断标志位,以及回调函数。
调用过程:ADVANCE_TIM_IRQHandler ()—>HAL_TIM_IRQHandler()
—>void HAL_TIM_PeriodElapsedCallback() 串口:
1、串口中断标志位,既可以通过软件清除标志位,也可以通过读写DR寄存器硬件清除寄存器。
目录
1.找不到hive
2.sqoophook、hivedatatypes
使用版本为ambari-2.7.3,自带的sqoop-1.4.7
1.找不到hive 21/09/08 11:16:16 ERROR tool.ImportTool: Import failed: java.io.IOException: Cannot run program "hive": error=2, No such file or directory
在安装sqoop的机器上,安装hive客户端并配置环境变量。
2.sqoophook、hivedatatypes(结束但无数据) 21/09/08 11:47:44 WARN mapreduce.PublishJobData: Unable to publish import data to publisher org.apache.atlas.sqoop.hook.SqoopHook
java.lang.ClassNotFoundException: org.apache.atlas.sqoop.hook.SqoopHook
查了网上没有找到直接的解决方案,故根据报错信息分析:应该首先是缺少依赖包,根据 org.apache.atlas.sqoop ,去maven仓库寻找jar包:https://mvnrepository.com/
因为看到国外网友分享的经验里面,没有直接名为sqoophook的包,那么找可能性大的
一步一步来
输入:sqoop-bridge
那么因为sqoop是1.4.7,那么猜测一下,选择版本1.2.0
拷贝到服务器的sqoop/lib/目录下。
转机出现!
Exception in thread "main" java.lang.NoClassDefFoundError: org/apache/atlas/hive/model/HiveDataTypes
at org.apache.atlas.sqoop.hook.SqoopHook.toHiveDatabaseEntity(SqoopHook.java:109)
报错信息变了,变了就有希望,说明上一次对症了,根据刚才的思路,再去maven找
看了所有相关的包,这个最接近,因为我们集群是hive2,那么猜测选择2.1.0
放到sqoop/lib/目录下,再次执行,无报错!!!
[INFO] 2021-09-08 16:35:53.721 - [taskAppId=TASK-21-274-362]:[404] - appId:application_1630928169074_2447, final state:SUCCESS
但是hdfs的表分区目录仍然是被删除的状态 ,就是MapReduce跑完了,数据是有的,但是success之后,目录被删了,数据不见了。 最终解决:--delete-target-dir 和--hive-overwrite不要一起用,经测试只用--hive-overwirte也不好使,只用--delete-target-dir即可。
文章目录 Bootstrap继承(block、extents) 本篇练习源码gitee Bootstrap Bootstrap3下载链接:
链接:https://pan.baidu.com/s/1OPtxVDHEgW5rdH4eMw6OKw
提取码:r99j
或者去官网下载:https://v3.bootcss.com/getting-started/#download
下载完解压就可以了
接下来就是使用了
我在templates里面在新建一个HTML,命名mytemplates
这里先来看下CDN
这部分代码可以直接复制使用(现成通用的)
直接把CDN的内容粘贴过来就行
StackPath 的小伙伴为 Bootstrap 的 CSS 和 JavaScript 文件提供了 CDN 的支持。直接使用这些 BootstrapCDN 提供的链接即可。
另外integrity后面这些东西是可以不要的,可以把这些无关的东西删掉
最后的结果就是这样了
<!-- 最新版本的 Bootstrap 核心 CSS 文件 --> <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css" > <!-- 可选的 Bootstrap 主题文件(一般不用引入) --> <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap-theme.min.css" > <!-- 最新的 Bootstrap 核心 JavaScript 文件 --> <script src="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/js/bootstrap.min.js" ></script> 这样就算是给它引入进来了,后面就直接可以网上填加东西了
然后看下是如何往上添加东西的,在官网可以看到他有很多css样式、组件和JS插件
CSS样式就是他提供了很多东西我这边是直接可以拿过来用的
来看下CSS的样式内容概括
拿按钮来举例
点击进去直接复制代码执行就是上面的效果
把这段代码放到body里面就可以了
然后就是老套路了,写视图,配路由,巴拉巴拉。。。
老生常谈,来看views,定义一个视图函数
def mytemplate(request): return render(request, 'mytemplate.
Java Debug Interface(JDI)介绍 An Intro to the Java Debug Interface (JDI) | Baeldung
1. 概述 我们可能会想像IntelliJ IDEA和Eclipse这样大的IDE是如何实现调试特征的。这些工具极大依赖于Java平台调试架构(JPDA)。
在本文中,我们将讨论Java Debug Interface API(JDI),这种可以在JPDA向下获得的接口。
同时,我们会一步步写一个自定义的调试程序,让我们熟悉JDI接口。
2. 介绍JPDA Java平台调试架构(JPDA)是一组设计得非常好得接口和协议集合,其目的是用于调试Java。
它提供了3种特别设计的接口,用于实现自定义的调试器,该调试器用于在桌面系统中的开发环境。
首先,Java虚拟机工具接口(JVMTI)帮助我们交互和控制应用程序的执行,这些应用程序都运行在JVM上。
然后,Java调试线协议(Java Debug Wire Protocol(JDWP))定义了在测试(debugggee)和调试器(debugger)之下运行的程序的协议。
最后,Java调试接口(JDI)用于实现调试器应用程序。
3. 什么是JDI? Java调试器接口API是一组由Java提供的接口,其目的是实现调试器的前端。JDK是JPDA的最高层。
一个由JDI构成的调试器能够调试运行在任何JVM上的应用程序,只要这个JVM支持JPDA。同时,我们能够钩在调试的任何一层。
它提供了访问虚拟机的能力,并且它能访问调试器的变量。同时,它允许设置断点,单步调试,观察点和控制线程。
4. 安装 我们分别需要2个程序,一个debuggee和一个debugger,用于理解JDI的实现。
首先,我们要写一个简单的例子作为debuggee。
让我们创建一个JDIExampleDebuggee类,该类有几个string变量和一个println语句:
public class JDIExampleDebuggee { public static void main(String[] args) { String jpda = "Java Platform Debugger Architecture"; System.out.println("Hi Everyone, Welcome to " + jpda); // add a break point here String jdi = "
前端:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>查询结果</title><style> .imgbox {width: 600px;} @media screen and (max-width: 700px) { .imgbox { width: 95%;}} </style> </head><body><p align="center"> <img class="imgbox" src="zs.php?&act=<?php echo $_GET[act]; ?>&keyword=<?php echo $_GET[keyword]; ?>&submit=查询&search=no&yzm_status=0" alt="myImage" /> </p></body> </html> 返回处理过的图片
//必不可少 ob_clean() 如果没有此涵数 显示只有一个框框什么都没有 ob_clean(); header('Content-Type: image/jpeg');// 此句主要是做语气更直观 可以不用这句的 $myImage = ImageCreate(700,990); // 创建一个画布,必不可少,参数为宽度和高度 $im = imagecreatefromjpeg('01603.
直接在QUARTUS编译器中修改ip核的代码,编译后会出现代码重置到修改前状态的情况。可以使用如下步骤:
一,到文件中修改代码,而后保存;比如要修改i2c_slavetop这个IP核,想把下图红框中位宽修改为8bit,则先修改后保存;
二、在Qsys中找到IP核,右键选择edit,在弹出的窗口中选中IP核并点击Analyze Sythesis Files,如下图所示
三、点击Generate
再重启Qsys,可以看到IP核中对应的地址位宽被改为8bit
四、备注
调用IP核时可以关注其对应的.tcl文件,其内部有对IP核的配置;
示例代码 @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException { UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken; String username = token.getUsername(); // token中获得username,再去查数据库 Users users = userService.findUsersByUsername(username); if (users == null) { throw new UnknownAccountException("不存在用户"); } else { // 肯定有这个用户就比对密码 //当前realm对象的name String name = this.getName(); System.out.println("realmName:" + name); ByteSource credentialsSalt = ByteSource.Util.bytes(users.getUserName()); SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(users, users.getPassword(), credentialsSalt, name); return info; } new SimpleAuthenticationInfo(users, users.getPassword(), credentialsSalt, name)解释参数 参数1:从数据库获得的用户对象,包括用户名和密码等信息
参数2:从对象中取密码,users.getPassword()是这个用户的数据库中的密码
参数3:盐,可以为空
参数4:当前realm的名字
做业务遇到账号限制出口IP,自己的IP没有权限,需要在公司内部切换的情况,就顺手整理了下什么是出口IP。 出口IP:出口IP是指你的外网IP,比如你用的不是外网IP(公网)那么你发送的信息必须被路由器进行网络地址转换,你信息就会被外网识别。
可以这么理解: 出口IP是IP地址,是局域网内的电脑,配置的用来连接网络的IP,多台局域网内电脑共用一个上网IP,我查看组内电脑出口IP都是一致的。如果限制这一个IP的上网权限,组内所有人电脑均不可以上网。 联想一下:我们需要注意,我们电脑作为爬虫爬取网络数据时,如果对方有反爬机制,限制或者封禁你的IP,受到影响的将会时你组内同事,如果整个部门公用,那封禁的将是你整个部门的访问权限。这个在后面使用时,要额外注意。 那怎么查看出口IP:百度搜索IP,打开显示IP即为你的出口IP
文章目录 官网源码仓社区wiki 官网 主页:http://musl.libc.org/
musl是构建在 Linux 系统调用 API 之上的 C 标准库的实现,包括在基本语言标准、POSIX 和广泛认可的扩展中定义的接口。musl 是轻量级的、快速的、简单的、免费的,并且在标准一致性和安全性方面力求正确。
musl,发音类似于“mussel贻贝”或“muscle肌肉”这个词,是一个“libc”,它是 ISO C 和 POSIX 标准中描述的标准库功能的实现,加上公共扩展,构建在 Linux 系统调用 API 之上。虽然内核管理对硬件、内存、文件系统的访问以及访问这些资源的权限,但 libc 负责:
为 OS 接口提供 C 绑定使用内核提供的低级接口构建更高级别的缓冲stdio、内存分配管理、线程创建和同步操作、共享库加载等实现C语言一样的纯库例程,如 strstr,snprintf,strtol,exp,sqrt等。 musl 的历史和发展根源可以追溯到 2005 年,但在 2011 年被命名并首次发布为 musl,作为 glibc 和 uClibc 的替代品,其雄心勃勃的目标是满足微型嵌入式系统和典型台式机和服务器的需求。
自 2012 年以来,musl 已根据MIT license获得许可。
源码仓 官方:https://git.musl-libc.org/cgit/muslgithub:https://github.com/bminor/musl 社区wiki 主页:https://wiki.musl-libc.org/
总之先从题目开始看吧,是一道非常简单但却让我长见识的题......
int overflow() { char v1[12]; // [esp+Ch] [ebp-Ch] BYREF return gets(v1); } 明显的栈溢出,且程序基本没有特别的保护,正常构造rop链即可拿到shell
主要是想拓展一下系统调用与一个简单的获取ROP方法
ROPgadget --binary rop --ropchain ROP chain generation =========================================================== - Step 1 -- Write-what-where gadgets [+] Gadget found: 0x8050cc5 mov dword ptr [esi], edi ; pop ebx ; pop esi ; pop edi ; ret [+] Gadget found: 0x8048433 pop esi ; ret [+] Gadget found: 0x8048480 pop edi ; ret [-] Can't find the 'xor edi, edi' gadget.
将数组元素向右移动k个位置,k非负
文章目录 第一种方案第二种方案第三种方案 第一种方案 解决思路:将数组中的元素复制到一个新数组中,将数组元素依次分配到新的位置上
时间复杂度:O(n)
空间复杂度:O(n)
void rotate(int* nums,int numsSize,int k) { k%=numsSize; int newArray[numsSize]; for(int i=0;i<numsSize;i++) newArray[i]=nums[i]; for(int j=0;j<numsSize;j++) nums[(j+k)%numsSize]=newArray[j]; } 第二种方案 解决思路:先反转所有的数组元素;再反转前k个数组元素;最后反转剩余的数组元素
时间复杂度:O(n)
空间复杂度:O(1)
void swap(int* x,int* y) { int temp; temp=*x;*x=*y;*y=temp; } void rotate(int* nums,int numsSize,int k) { k%=numsSize; for(int i=0;i<numsSize/2;i++) swap(nums+i,nums+numsSize-i-1); for(int i=0;i<k/2;i++) swap(nums+i,nums+k-i-1); for(int i=0;i<(numsSize-k)/2;i++) swap(nums+k+i,nums+numsSize-i-1); } 第三种方案 解决思路:利用一个空间保存数组的第一个元素,计算第一个元素移动后的位置,将该位置上的元素与空间中的元素进行交换,然后继续计算交换后的元素移动后的位置并重复上述操作
举一个例子[1,2,3,4,5,6,7],k=3
利用一个空间temp进行元素之间的交换
(1)temp=1 移动到的位置4 替换后temp=4 [1,2,3,1,5,6,7] (2)temp=4 移动到的位置7 替换后temp=7 [1,2,3,1,5,6,4] (3)temp=7 移动到的位置3 替换后temp=3 [1,2,7,1,5,6,4] (4)temp=3 移动到的位置6 替换后temp=6 [1,2,7,1,5,3,4] (5)temp=6 移动到的位置2 替换后temp=2 [1,6,7,1,5,3,4] (6)temp=2 移动到的位置5 替换后temp=5 [1,6,7,1,2,3,4] (7)temp=5 移动到的位置1 替换后temp=1 [5,6,7,1,2,3,4] 但是这样存在一个隐性的问题,如[1,2,3,4,5,6],k=3
Artficts共有三种表现形式:
1.锯齿:
2.摩尔纹:例如 相机拍摄电脑显示器(像素的 奇数行和奇数列去掉,结果就产生摩尔纹)
3.车轮效应: 高速转动的车轮
根本原因: 信号变化太快,采样的速度跟不上信号的速度!!!!!!!!!!!!!!!!!!!!
(1)走样:
用像素的中心 采样三角形: 有些像素中心点在三角形内 有些像素的中心点在三角形外
走样: 像素的中心点 不在三角形内 则被舍弃,所以产生了走样
(1)反走样:
先模糊,后采样:离模糊近 显示白色; 离模糊远,显示原色
为什么: 采样速度跟不上信号变化速度会产生artficts???
频域:
(1)频率:
(1)傅里叶级数展开:
傅里叶变换:
傅里叶变换和傅里叶级数展开相似,
傅里叶变换: 任何一个函数 都可以 通过“傅里叶变换” 变成另一个函数。
逆傅里叶变换: 经过傅里叶变换的函数 通过“逆傅里叶变换” 变回原函数。
所谓的傅里叶变换:
(1)就是把函数变成不同频率的段
(2)把不同频率的段显示出来
(3)走样的本质:
(2)滤波
(4)卷积:
卷积定理:时域的卷积 = 频域的乘积,如下图所示
(此刻想到了: 硬件对信号做处理,与下图无关)
(5)采样的基本原理:就是在重复一个原始信号的频谱
(6)什么是走样:频谱在复制搬运的过程中发生混叠(重叠,混合):就是走样
从光栅化的角度来说:
一个三角形覆盖了很多密集的像素
(1) 采样的密集,走样少
(2)采样的稀疏,走样严重
对每个像素: 求覆盖面的平均(没覆盖面的平均)
(7)MSAA的结论:
(1)不是通过提高分辨率
(2)不是通过提高采样率
(3)只是通过细分像素,近似出合理的 此像素在三角形内的覆盖率!!!!!!!!!!!达到模糊的效果
(4)最后一步: 采样
(5)MSAA是基于硬件的
代价: 一个像素细分成多块, 在计算三角形覆盖率的时候,计算量增大了!!!!!!
#软考证书发放啦
可以领取的省份:浙江、云南、贵州、吉林、其中,甘肃和山西以快递方式进行发放。
其他地区本月陆续发放,请大家及时关注!
Mybatis模糊查询的四种方式 1、根据姓名模糊查询员工信息 1.1、方式一 步骤一:编写配置文件
步骤二:测试
步骤三:分析 此种方式需要在调用处手动的去添加“%”通配符。
1.2、方式二 说明: 使用方式一可以实现模糊查询,但是有一点不方便的地方就是:在测试类中,调用selectList()方法传参时需要调用者手动的添加%号通配符,显然是麻烦的,能否在映射配置文件中直接将%号写好呢? 有的朋友可能会这么想,好办,直接在配置文件中这么写:形如1:
测试后发现,程序会报错,原因是:缺少单引号。
这个时候,有朋友可能会这样想了,那干脆加一个“单引号”不就得了,形如2:
测试后发现,程序依然会报错,原因是:如果加上单引号,那么就当成是一个字符串,而#{ }写在字符串中不能识别,要改写成${ }这种形式。
即:形如3
分析: 通过使用“ ” 也 可 以 实 现 。 但 是 通 过 ”也可以实现。但是通过 ”也可以实现。但是通过的方式拼接的sql语句,不再是以占位符的形式生成sql,而是以拼接字符串的方式生成sql,这样做带来的问题是:会引发sql注入的问题。
1.3、方式三(推荐) 说明:通过前两种写法,虽然可以解决模糊查询的问题,但是还是不好,因为通过%的方式会引发sql注入的问题,现在的期望是:既能够解决sql注入又能在配置文件中写%该如何实现呢,可以借助mysql的函数。
步骤一:编写映射文件
步骤二:测试 此步骤省略,比较简单。
1.4、方式四 说明: 当然对于方式三,也可以使用$,不过需要特别留意单引号的问题。步骤一:编写配置文件
步骤二:测试 该步骤省略。
2、总结 #{ }是预编译处理,MyBatis在处理#{ }时,它会将sql中的#{ }替换为?,然后调用PreparedStatement的set方法来赋值,传入字符串后,会在值两边加上单引号,使用占位符的方式提高效率,可以防止sql注入。 ${}:表示拼接sql串,将接收到参数的内容不加任何修饰拼接在sql中,可能引发sql注入。
死锁概念 死锁是指两个以上线程因争夺资源而发生互相等待的现象!没有外力调解的话,就造成线程一直互相等待,无法执行的情况!
死锁发生的必要条件 死锁发生会同时出现以下的四个必要条件。
1、互斥
一个资源同时只能被一个线程使用
2、请求并保持
线程在请求资源阻塞的时候,并不会释放其已经拥有的资源。
3、不可剥夺
对于线程已经获得的资源,只能线程自己释放,其他线程无法强制剥夺。
4、循环等待
两个或者两个以上线程出现等待资源出现循环依赖。
死锁的解决方法 死锁共有三种解决方式:
1、预防死锁
预防死锁的解决方法就是对上述的四个必要条件的破坏。
1、互斥条件
这个条件一般是无法打破,因为锁大部分的场景就是同时只能允许一个线程获得。
2、请求并保持
防止线程在持有资源后并申请其他资源的情况。
线程一次性申请所有需要的资源。申请成功就运行,不成功就等待。
缺点:线程会提前申请后期运行需要的资源,会导致其他线程无法获取对应的资源,很多时候是其他线程是不会造成死锁的。会造成线程的饥饿,资源的利用率太低。
3、不可剥夺条件
当想要申请新资源并且失败的时候,将当前拥有的资源释放。当新资源可用时,会重新申请之前放弃的资源。
缺点:反复的放弃和申请资源会造成资源的浪费,降低系统的吞吐量。
4、循环等待条件
将所有的资源从小到大编号,线程申请资源按照编号从小到大申请。
比如说进程P1,使用资源的顺序是R1,R2,进程P2,使用资源的顺序是R2,R1,如果采取动态分配的方式,就很有可能造成死锁。我们对设备进行分类编号,那么P1,P2只能以R1,R2的顺序来申请资源。就可以打破环形回路,避免死锁。
缺点:和之前的请求和保持的缺点一致,可能会提前申请不必要的资源,造成资源浪费,造成其他线程的饥饿,降低资源的利用率。
2、避免死锁
预防死锁是通过打破四个死锁必要条件中的一个。
避免死锁不会这么严格要求必须必须打破某个死锁必要条件,因为即使发生了四个死锁中的四个必要条件中的一个,也不一定会发生死锁。
避免死锁相较于预防死锁条件更加宽松。避免死锁的唯一判断条件就是当前线程申请了这个资源,是否会导致死锁。只允许不会造成死锁的线程申请资源。
怎么判断呢?就是通过大名鼎鼎的银行家算法了
银行家算法牵扯到以下几个数组和矩阵来统计:
1、可利用的资源数组 Available
记录着资源对应的可利用个数,假如有m个资源,对应的就是一个m维的数组。数组中的数据随着资源的分配和回收波动。
2、最大需求矩阵 Max
记录着线程对于每个资源的最大需求资源个数。为一个n*m的矩阵。n为线程的个数,m为资源的个数
3、已分配矩阵 allocated
记录着为线程对于每个资源的已分配资源个数。为一个n*m的矩阵。n为线程的个数,m为资源的个数
4、需求矩阵 need
记录着线程对于每个资源还需要申请的资源个数,为一个n*m的矩阵,n为线程的个数,m为资源的个数。
银行家算法原理:
当一个线程申请的资源大于可利用资源时,就直接申请失败。
如果申请的资源小于等于可利用资源的时候,就进行安全检测。
检查什么呢?
如果将资源分配给线程后,是否存在一条安全执行序列,使各个线程都能安全执行,不发生死锁。如果存在就给其分配资源。如果不存在就申请失败。
缺点: 必须提前确定线程的最大申请资源个数。
3、死锁的检测和解除
死锁的检测和解除允许系统进入死锁状态。
当线程申请资源的时候,会检测死锁。
如果线程请求资源成功或者尝试请求资源的时候,会将线程和资源信息写入一个结构中,比如map中。
当线程A请求资源的时候,会检测当前拥有资源的线程B是否想要请求线程A当前拥有的资源。
事实上线程B可能会请求其他线程占用的资源。比如线程B请求的资源被线程C占用,而线程C请求的资源被线程D占用,就这样一直递归,直到对应的线程没有请求资源或者对应的线程请求的资源被线程A占用。
如果对应的线程没有请求资源,那么就说明A可以请求资源。
如果对应的线程请求了A占用的资源,说明当前系统发生了死锁,开始解除死锁,比如强制剥夺导致死锁的线程A的对应的资源。
缺点: 撤销死锁线程的代价比较大。某些线程都马上执行结束后,却给撤销了,功亏一篑属实是。
1、在终端输入扩展40Pin配置脚本
sudo /opt/nvidia/jetson-io/jetson-io.py 2、选择进入Configure 40-pin expansion header
3、空格选中spi1(或者其他需要的扩展功能),选择back退出
4、可以看到管脚的SPI功能已打开,然后选择Save and reboot to reconfigure pins 5、确认保存设备树(用户设备树),文件名保持默认即可
6、等待设备重启完成即可正常使用SPI功能
其他使用 设备重启后可查看到新增加的用户DTB
输入以下命令可查看系统对新增用户DTB的调用情况
用户自定义dtb修改 该方法适用于设备树的小问题修改,避免调试过程中反复编译下载系统内核。
方法如下:
将新增的用户DTB拷贝到用户自己的目录后反编译为可修改的DTS
dtc -I dtb -O dts kernel_tegra194-p3668-all-p3509-0000-user-custom.dtb -o kernel_tegra194-p3668-all-p3509-0000-user-custom.dts 将修改后的dts编译为dtb文件 dtc -I dts -O dtb kernel_tegra194-p3668-all-p3509-0000-user-custom.dts -o kernel_tegra194-p3668-all-p3509-0000-user-custom.dtb 将编译好的DTB文件覆盖到系统boot目录下 sudo cp kernel_tegra194-p3668-all-p3509-0000-user-custom.dtb /boot/ 重启即可。
正则表达式:click 一、直接给出字符,就是精确匹配;
规则意义\d可以匹配一个数字\w可以匹配一个字母或数字;.可以匹配任意字符\s可以匹配一个空格(也包括Tab等空白符) 特殊字符用‘\’转义,例如‘-’,正则是\ -
例如:
‘00\d’可以匹配’007’,但无法匹配’00A’;
‘\d\d\d’可以匹配’010’;
‘\w\w\d’可以匹配’py3’或’p33’;
'py.‘可以匹配’pyc’、‘py0’、'py!'等等;
‘py\s-\s\d’可以匹配’py - 2’。
二、长字符匹配
规则意义*表示任意个字符(包括0个);+表示至少一个字符;?表示0个或1个字符;{n}表示n个字符;{n,m}表示n-m个字符。 例如:\d{3}\s*-\s*\d{3,8}
\d{3}代表任意三位数字,\s*代表任意个空格,-代表特殊符号-,\d{3,8}代表3到8位任意数字;
综合起来这个正则表达式匹配的是一个以任意个空格加特殊符号“-”隔开的带区号的电话号码。例如:010 - 123456
三、更精确的匹配
要做更精确地匹配,可以用[]表示范围,比如:
规则意义[0-9a-zA-Z_]可以匹配一个数字、字母或者下划线;[0-9a-zA-Z]可以匹配一个数字或字母,等同于\w;[0-9a-zA-Z_]+可以匹配至少由一个数字、字母或者下划线组成的字符串,比如’a100’,‘0_Z’,'Py3000’等等;[a-zA-Z_][0-9a-zA-Z_]*可以匹配由字母或下划线开头,后接任意个由一个数字、字母或者下划线组成的字符串,也就是Python合法的变量; 规则意义A|B可以匹配A或B,所以(P^表示行的开头,^\d表示必须以数字开头。$表示行的结束,\d$表示必须以数字结束。 py可以匹配’python’,但是加上^py$就变成了整行匹配,就只能匹配’py’了。
四. 邮箱正则表达式
某博主:click
正则表达式:click
//第一种,名称有字母、数组、中划线、下划线组成,@后面域名为字母、数组、中划线、下划线,最后是多个.com.qq的 ^[a-zA-Z0-9-_]+@[a-zA-Z0-9-_]+(\.[a-zA-Z0-9-_]+)+$ //第二种,名称有汉字 //汉字在正则表示为[\u4e00-\u9fa5] ^[a-zA-Z0-9-_\u4e00-\u9fa5]+@[a-zA-Z0-9-_]+(\.[a-zA-Z0-9-_]+)+$ 五. 网址正则表达式
太复杂了!写不了!!!!!
六. 电话号码正则表达式
[0-9]可以用\d表示 /^1(?:3\d|4[4-9]|5[0-35-9]|6[67]|7[013-8]|8\d|9\d)\d{8}$/ 2. Unicode编码
构造器的重载 一般保证空构造器的存在,空构造器中一般不会进行属性的赋值操作;
一般我们会重载构造器,在重载的构造器中进行属性赋值操作;
在重载构造器以后,加入空构造器忘写了,系统不会给分配默认的空构造器了,那么当你调用的话就会出错;
当形参名字和属性名字重名的时候,会出现就近原则:
在要表示对象的属性前加上 this. 来修饰,因为this代表的就是你创建的那个对象
public class Person { //属性 String name; int age; double height; //空构造器 public Person(){ //一般保证空构造器的存在,空构造器中一般不会进行属性的赋值操作 } //构造器的重载 public Person(String name,int age,double height){ //当形参名字和属性名字重名的时候,会出现就近原则: //在要表示对象的属性前加上 this. 来修饰,因为this代表的就是你创建的那个对象 this.name = name; this.age = age; this.height = height; } public Person(String name,int age){ this.name = name; this.age = age; } } public class Test { public static void main(String[] args) { Person p = new Person("
记录一次踩坑之旅
微信偷偷改了以后,个人公众号已经不支持主动给单个用户发送消息了,所以要么用企业公众号,要么就用下面的方法。
背景 开发预警功能,服务端出现异常,能够发送消息给特定微信号
成品 https://github.com/font-size/wx-template-message
准备工作 开局:一个开发人员,一个微信号
需要:appID、appsecret、模板ID、微信用户的openid
申请微信测试号 访问 微信公众平台
用微信扫码登录,得到测试号appID、appsecret
配置关注公众号和配置模板 1:关注自己的测试公众号
关注后自动刷新用户列表,右边即是用户的openid
2:新增消息模板
代码开发 从上面的步骤,我们得到了appID、appsecret、模板ID、微信用户的openid
接下来是代码
// 需要填写的地方已经标出 // 一共4个地方 appID、appsecret、模板ID、微信用户的openid const axios = require('axios'); axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded'; const axiosPost = function (url, params) { return new Promise((resolve, reject) => { axios .post(url, params) .then(res => { resolve(res); }) .catch(err => { reject(err); }); }); }; const axiosGet = function (url, params) { return new Promise((resolve, reject) => { axios .
前言 据公开资料记载:今年3月份抖音日活用户数量约为6.1亿至6.2亿。而微视日活3亿,要知道微信的日活跃用户达到10.9亿;有7.8亿人每天翻看着朋友圈,其中的1.2亿人还会在朋友圈里发点什么;3.6亿人每天浏览公众号来获取对外界的认知。【信息来源青铜视角】
微视嵌套在微信朋友圈下面,本身拥有庞大的用户体系,而2016年9月份才发行的抖音,19年便拥有将近11亿用户,21年便拥有6点多亿,一直是泛娱乐不可超越的楷模。【信息来源公开资料整理】
抖音或者说字节跳动拥有今天的成绩,“智能推荐”便是它主力军,带领它横空出世;反过来,也是字节跳动,把“智能推荐”的技术打造到今天炉火纯青的地步。
“智能推荐”的理解 智能推荐,其本质为过滤系统,针对不同用户的不同诉求,层层过滤掉物料库里面的产品,把最合适的推荐到用户面前。这便是互联网下半场做“减法”的思维,个性化服务,“你需要的”才被呈现,减去用户搜索时间。
那智能推荐系统的人货场如何连接的呢?
人:如何精准获取用户需求;
货:如何细致而全面描述产品(有形的物品、无形的服务与信息、组织等)
场:如何给用户推荐合适的产品
为什么需要做推荐系统 1、用户个性化需求: “萝卜青菜,给与所爱”,不同的用户诉求不同,需要提供不同产品来满足,这是智能推荐系统最为“智能”的地方。
2、解决信息过载、挖掘长尾物品/信息: 如搜索引擎收录网页亿万级别,而每一屏只展示10条。
今日头条2020年全年收录的信息有6.5亿万条,如果推荐系统设置不合理,那么存在很多信息将被淹没,作者的积极性将被打击,不利于产品的更新与扩充。
这是一个双向的问题,既要考虑到用户消费、也要考虑到作者创造,此外还需要考虑技术与算法等问题。
“智能推荐”使用场景 目前智能系统比较广泛运用于以下场景:
1、招聘软件: 如Boss直聘,根据用户填写的简历和应聘信息,过滤展示适合用户的岗位。
2、休闲娱乐 抖音、微视、小红书等根据用户喜欢的内容频道与分类、热点新闻等,智能呈现给用户。
3、电商平台 京东、淘宝、拼多多等都在根据用户的喜欢产品类型、价格敏感度等智能给用户推荐产品
4、资讯网 如今日头条,“你喜欢的才是头条”。
5、生活服务 “美团”、“饿了么”、“高德地图”等,智能推荐用户附近、适合价格和喜欢的产品。
6、社交网 如探探、珍爱网等,智能给用户推荐合适的异性朋友。
“智能推荐”的运行逻辑 如何“智能”地“推荐”,涉及到4个很重要的环节,那便是“召回”、“粗排”与“精排”、”前端展示“。
1、召回 召回是从物料库中获取其中一部分,这一部分会在后面被模型用来打分排序。为啥不能直接从物料库里面获取物料直接打分排序呢,因为物料库很大,往往有数亿级的item,如果让模型对这数亿级的item打分,模型会吃不消,而召回是从这数亿级的item中跳出百万或十万级别的候选item。
如何召回 召回阶段使用用户画像,这时便需要各app、Web等平台收集用户的注册信息(注意避开敏感信息)。收集完信息后,在后台系统配对用户感兴趣的信息,用户下次登录时再展示(这里会涉及到冷启动的问题,也就是用户首次登录的信息配对,也是一个很大的话题,放在后面讲,该环节针对非首次登录用户的召回问题)。此时召回的信息还没用到模型,为离线数据,还称不上“智能”
多重召回 为了呈现信息的多样性,不能只按照一种规则去召回,而需要多路召回信息,多路召回需要考虑以下几点:
用户层面考虑:
针对用户注册信息,需要给用户展示热点队列、兴趣对列等相关信息,而不仅仅是用户在注册时填写可能感兴趣的那些信息(有时候用户也会骗人的)。此外,还需要考虑到信息的频道(展现方式),分发的时候不仅仅只有短视频、还有图文、小说等。
系统层面考虑:
增强系统的鲁棒性:部分信息失效后,其余召回队列兜底不会使整个召回层失效、从而导致系统出错。
系统多样内容分发:
简单理解各频道内容:视频、短视频、图文、小说、新闻等按一定比例分发;此外精准、试探和时效的内容也要按一定比例分发(精准内容是确定用户喜欢的,而试探性内容是为了增加惊喜度、试探用户更多隐性需求,时效是指当前的热点新闻等信息)
信息可解释性:
针对用户画像推荐信息,让用户明白信息来源,增强用户地认可。
2、粗排 粗排是对召回的信息重新筛选与排序,这时候筛选的信息量下降至2万。这时候可以利用协同过滤、RFM等模型进行粗布排序。
通俗一点讲,如果说召回是往海里撒网鱼,这时候不能一下子并发给用户,需要一条一条给,所以需要做一个简单排序,这时候系统还不是很确定用户的喜好,按大众口味,都喜欢吃肥大的鱼,而捞回来的这批鱼中,鲑鱼比较多,那么就先给一条肥大的鲑鱼吧。这便是粗排,粗排是使用模型给号回的信息打分和排序,这时候的排序是比较粗糙的。
3、精排 精排再次对内容进行筛选和排序,这时候的内容量需控制在2千左右,需综合考虑到用户查看到的信息的多样性、及时性和平台的运营规则等。
通俗一点讲,给了用户一条肥大的鲑鱼后,用户竟然不喜欢(没有浏览完,直接划走),为啥不喜欢呢?这条鱼是肥大的、整条鱼、活的、鲑鱼等待,把当前信息的特征抽取出来,用户不喜欢的是反向信息,喜欢的便是正向信息。如果说粗排是在进一步试探用户的喜好,那么精排就是便是根据用户的实时操作信息及时分析和排序粗排列表信息,“智能"的推荐给用户。
粗排和精排地数据都是实时的,但精排的颗粒度更小更实时些。能做到秒级的更新,如你点击了购物平台的某个商品后,返回信息列表页,此时你看到的信息列表已经被更新啦。
4、前端页面 经过前面三个步骤的筛选与排序后,便需要在前端页面呈现给用户了,这时候有2千多条信息等着被呈现,需要考虑到用户体验,点赞收藏是否方便、支持转发吗?如何与博主互动等。
这是一个循环的运行逻辑,用户每次与系统互动后,都会更新精排和粗排队列,而用户每次登录时系统都会根据用户上一次的喜好重新召回与粗排。
项目流程 智能推荐首先需要把用户操作信息与物料信息写进系统日志,经过数据清洗与特征工程、进而使用模型与算法(召回、粗排、精排)推荐引擎,最后AB测试,进而推荐给用户......这是一个不断循环的过程,归纳起来有:1、数据收集与清洗、特征工程、模型与算法、分析与运用
1、数据获取及清洗 1.1、数据获取 不仅仅是用户单方面的信息,还需获取产品的信息。数据的渠道有系统录入、爬虫、第三方等。
1.2、数据清洗 数据清洗就是把不符合业务逻辑或运算规则的脏数据规范化处理。“脏数据”对算法模型的直接影响是不能被使用,间接影响是降低模型的精度。这种情况下需要对数据进行清理,包括但不限于:不合格数据修正、缺失值填充、噪声值处理、离群点处理。
2、特征工程 是这个项目的最为繁琐与重要环节,约占项目时长的70%.
2.1、用户特征 用户需求来源于用户身上,需要了解用户需求,那便看你对用户有多了解。这需要给用户贴很多标签,形成一个虚拟的用户——用户画像。标签包括用户的静态属性与动态属性,标签一般都是从上而如下来收集与使用的,通俗一点讲就是多多益善。等到你要用的时候才设置,那时候已经来不及。
2.1.1、静态特征(属性)
supervisord部署使用超级详细版 一. 安装 pip 命令(安装python 环境)
因为 supervisord本身是基于Python开发的,所以在使用时需要先安装Python 的运行环境
1.下载阿里的epel源
wget -O /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo 2.安装pip
yum -y install python-pip 3.设置socks代理,安装pysocks库。
pip install socks pip install pysocks 二. 安装 supervisor
1.使用pip 命令进行安装
pip install supervisor 2.使用命令测试是否安装成功
supervisord --help 三. 修改配置文件
1.生成配置文件并重定向到我们需要的目录
echo_supervisord_conf > /opt/supervisor/conf/supervisord.conf 2.修改 [inet_http_server] 配置访问前端界面 可以看附文本参考
注意:127.0.0.1 可能会访问失败 ,建议使用ip
3.配置进程示例([program:名称])
[program:producer] command=java -jar producer-service-0.0.1-SNAPSHOT.jar process_name=%(program_name)s directory=/usr/local/java priority=999 tdout_logfile=/usr/local/java/tdoutProducer.log 四.启动命令
supervisord -c /opt/supervisor/conf/supervisord.conf 附录:
一. supervisord 常用命令(可以使用 supervisord -help 在系统中直接查看)
为什么会有跨域的问题以及解决方式
视频: click
文章:click
引起跨域的原因:
1、协议、域名、端口有一个不一样就构成了跨域。同源策略:从同一个源加载文档或脚本
2、js中自带跨域技能的标签:<img/><script></script><link>
解决办法:
CORS:跨站资源共享。使用自定义的HTTP头部让浏览器与服务器进行沟通。浏览器自动进行CORS通信,后端配置消息头:res.header(“Access-Control-Allow-Origin”,"*")该属性表示那些域名可以访问资源,通配符*表示所有网站都可以访问。支持所有请求方法。cors请求包括简单请求和非简单请求。 简单请求 请求方法是以下三种方法之一:HEAD GET POST HTTP的头信息不超出以下几种字段:Accept Accept-Language Content-Type Last-Event-ID Content-Type:只限于三个值application/x-www-form-urlencoded、multipart/form-data、text/plain 复杂请求 不满足以上条件 对服务器有特殊要求的请求,比如请求方法是PUT或DELETE,或者Content-Type字段的类型是application/json。 简单请求:浏览器在发出CORS 请求时会在 头信息 之中增加一个Origin字段。许可访问时服务器的返回会多出3个字段:
字段必须/可选解释Access-Control-Allow-Origin必须允许跨域的源,要么是一个*,表示接受任意域名的请求。Access-Control-Allow-Credentials可选表示服务器是否允许客户端发送Cookie。默认情况下,Cookie可以包含在请求中,一起发给服务器,如果服务器不需要浏览器发送Cookie,删除该字段即可。Access-Control-Expose-Headers可选CORS请求时,XMLHttpRequest对象的getResponseHeader()方法只能拿到6个基本字段:Cache-Control、Content-Language、Content-Type、Expires、Last-Modified、Pragma。如果想拿到其他字段,就必须在Access-Control-Expose-Headers里面指定。如指定Access-Control-Expose-Headers: FooBar,则可通过getResponseHeader(‘FooBar’)获取FooBar字段的值。 不被许可时没有以上字段,会抛出一个错误,被XMLHttpRequest的onerror回调函数捕获。
非简单请求的CORS请求会在正式通信之前,增加一次HTTP查询请求,称为"预检"请求(preflight)。
"预检"请求用的请求方法是OPTIONS,表示这个请求是用来询问的。请求头信息里面,关键字段是Origin,表示请求来自哪个源。浏览器先询问服务器,1、当前网页所在的域名是否在服务器的许可名单之中,2、可以使用哪些方法,3、可以使用那些头信息字段。只有得到肯定答复,浏览器才会发出正式的XMLHttpRequest请求,否则就报错。
预检请求字段说明:
字段是否可选含义Access-Control-Allow-Methods必需值是逗号分隔的一个字符串,表明服务器支持的所有跨域请求的方法,不单是浏览器请求的那个方法。这是为了避免多次"预检"请求Access-Control-Allow-Headers如果浏览器请求包括Access-Control-Request-Headers字段,则Access-Control-Allow-Headers字段是必需的。它也是一个逗号分隔的字符串,表明服务器支持的所有头信息字段,不限于浏览器在"预检"中请求的字段。Access-Control-Allow-Credentials可选该字段与简单请求时的含义相同。Access-Control-Max-Age可选用来指定本次预检请求的有效期,单位为秒。有效期内不用发出另一条预检请求。 预检请求通过后会发送正常请求,请求头由origin,响应头由Access-control-allow-origin,如图:
JSONP:是JSON with Padding的略称。利用script标签的src属性来实现跨域,将前端方法作为参数传递到服务器端,然后由服务器端注入参数之后再返回,实现服务器端向客户端通信,仅支持get方法。webSockets,不受同源策略影响,它不使用HTTP协议Nginx,反向代理跨域,使用代理服务器。步骤:1. 把访问其它域的请求替换为本域的请求。2. 服务器端的动态脚本负责将本域的请求转发成实际的请求。更加直接,因为同源限制是浏览器实现的。click通过修改document.domain来跨子域使用window.name来进行跨域使用HTML5中新引进的window.postMessage方法来跨域传送数据
一、数字转字符串 直接加引号即可,例如
var=1
var1="$var" 这样就转化了
二、字符串转数字,三种方法 1,用${{a}}
2,用let达到(()) 运算效果。
let num=0123;
echo $num; 83
3,双括号运算符:
a=$(( 1 + 2 ));
echo $a;
等同于:
a=`expr 1 + 2`
1.定义 @Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented @Component public @interface Configuration { @AliasFor( annotation = Component.class ) String value() default ""; boolean proxyBeanMethods() default true; } 从Spring3.0,@Configuration用于定义配置类,可替换xml配置文件,被注解的类内部包含有一个或多个被@Bean注解的方法,这些方法将会被AnnotationConfigApplicationContext或AnnotationConfigWebApplicationContext类进行扫描,并用于构建bean定义,初始化Spring容器。
@Configuration的第二个作用是可以作为配置类,和@Component的作用一样,两者的差别是@Configuration 中所有带 @Bean 注解的方法都会被动态代理,因此调用该方法返回的都是同一个实例。
@Configuration注解的配置类有如下要求:
@Configuration不可以是final类型;@Configuration不可以是匿名类;嵌套的configuration必须是静态类。 2. 用于定义配置类 @Configuration public class AppConfig { @Bean public MyBean myBean() { // instantiate, configure and return bean ... } } 3. 用于配置批量扫描 使用配置类扫描批量注册,只能注册加了组件注解(@Repository、@Service、@Controller、@Component)的类
@Configuration @ComponentScan(basePackages = {"cn.test.entity", "cn.test.service", "cn.test.dao"}, excludeFilters = {@ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = {Person.class})}) public class BeanConfig { } 4.
import cv2 import numpy as np from PIL import Image, ImageDraw, ImageFont for i in range(5): fname = './hecheng/{}.jpg'.format(i) img = cv2.imread(fname) # 画矩形框 距离靠左靠上的位置 # p1指的是框左边上边到图像左边上边距离 # p2指的是框右边下边到图像左边上边距离 # fname就写自己图片所在位置 p1 = (250, 365) # 左边,上边 #数1 , 数2 p2 = (250 + 540, 365 + 105) # 右边,下边 #数1+数3,数2+数4 cv2.rectangle(img, p1, p2, (0, 255, 0), 2) a = "营业执照" # 类别名称 font = cv2.FONT_HERSHEY_SIMPLEX # 定义字体 imgzi = cv2.
1.下载windows提供的系统镜像 https://developer.microsoft.com/zh-cn/windows/downloads/virtual-machines/
2.解压 得到3个文件
WinDev2106Eval.mf
WinDev2106Eval.ovf
WinDev2106Eval-disk1.vmdk
3.用vm打开,导入 vm-》文件-》打开,选择WinDev2106Eval.ovf
这时你只需等待,等待奇迹的发生,心想,这实在太顺利太简单了!
不出意外的话,再加载差不多完成的时候,会报错:
SHA1 digest of file WinDev2106Eval-disk1.vmdk does not match manifest 解决办法:
WinDev2106Eval.mf里面记录了SHA256校验码,更新一下吧
打开cmd,输入:
certutil -hashfile <文件名> <hash类型> 例如:
把这两个哈希替换到对应的位置,再导入一次,ok了!
二维码是什么 二维码 QR Code,全称为:Quick Response Code,最早用于日本汽车制造业追踪零部件。QR现有40个标准版本,4个微型版本。相比一维码(也就是我们目前还在常用的条码),拥有更高密度的编码,可存储的信息量更大。一维码只能存储字母和数字,二维码可容纳多达1850个大写字母或者2710个数字或者1108个字符或者500多个汉字,比条码存储量多了几十倍。另外,二维码可以把图片、声音、文字、等可以数字化的信息进行编码。
除此之外:二维码比一维码译码错误率要低得多(误码率不超过千分之一),保密性、防伪性更好,成本低廉,容易制作,让二维码使用更加广泛,越来越流行。
除了存储编码的数据,QR码里还含有一些基本标准里钦定的图样来帮助扫描软件快速识别和解码。
标准(ISO/IEC 18004)里是这样说的
更多的详解请查看这篇博客
C# 实现 首先在NuGet引入ThoughtWorks.QRCode
生产二维码的时候用到ThoughtWorks.QRCode 的 QRCodeEncoder类
namespace ThoughtWorks.QRCode.Codec { public class QRCodeEncoder { public QRCodeEncoder(); public virtual Color QRCodeBackgroundColor { get; set; } public virtual ENCODE_MODE QRCodeEncodeMode { get; set; } public virtual ERROR_CORRECTION QRCodeErrorCorrect { get; set; } public virtual Color QRCodeForegroundColor { get; set; } public virtual int QRCodeScale { get; set; } public virtual int QRCodeVersion { get; set; } public virtual bool[][] calQrcode(byte[] qrcodeData); public virtual int calStructureappendParity(sbyte[] originaldata); public virtual Bitmap Encode(string content); public virtual Bitmap Encode(string content, Encoding encoding); public virtual void setStructureappend(int m, int n, int p); public enum ENCODE_MODE { ALPHA_NUMERIC = 0, NUMERIC = 1, BYTE = 2 } public enum ERROR_CORRECTION { L = 0, M = 1, Q = 2, H = 3 } } } ENCODE_MODE枚举是编码方式,因为我们的字符串里面可能存在中文,所以这里使用了BYTE,ALPHA_NUMERIC与NUMERIC只能编码数字
参考资源
https://www.cnblogs.com/runnerjack/p/12693597.html
1.环境准备 1.1 安装vagrant虚拟机 node01
Vagrant.configure("2") do |config| config.vm.box = "centos/7" config.vm.hostname = "node01" config.vm.network "private_network", ip: "10.1.100.11" # 虚拟机配置 config.vm.provider "virtualbox" do |vb| vb.gui = false vb.memory = "1024" vb.cpus = 2 end # 初始化安装脚本 config.vm.provision "shell", inline: <<-SHELL yum update yum install -y vim wget sed -i 's/PasswordAuthentication no/PasswordAuthentication yes/' /etc/ssh/sshd_config systemctl restart sshd # 关闭防火墙 systemctl stop firewalld.service systemctl disable firewalld.service # 关闭selinux sed -i 's/enforcing/disabled/' /etc/selinux/config # 转发流量到iptables cat > /etc/sysctl.
前言 如果想参考本人的背景情况可见这篇概述
============================ 正文开始 ==============================
【时间线】
8.18 翱捷一面8.24 翱捷HR面(意向面)9.18 HR打电话问有没有意向签三方 翱捷技术面只有一面,这是让我很震惊的,但是听从翱捷出来的师兄说,翱捷的性价比还是很大的,但是感觉翱捷成都这边岗位非常的少,HR打电话的时候一直在劝我去上海。
PS:红字表示我当时没答出来的问题,蓝字表示面试官/我的解答。
面经分享 一面·技术面【1小时】 自我介绍问我毕设方向,专业方向 -面试官是校友问了项目(项目的SOC中有哪些外设,资源占有率有多少,demo中的BANK资源都用来实现什么了,demo中的CPU中是否有cache和内存,什么情况下CPU才会有cache,CPU和协处理器是怎么交互的,每次处理的数据块位宽是多少)CDC处理方法亚稳态有哪些危害项目中做过哪些时序约束,STA中有哪几种时序路径,怎样保证STA可以覆盖到 input-to-reg / reg-to-output异步复位是否需要做时序约束,如果要做是怎么做的AXI和AHB的区别APB中slave的input ready 和 output ready 分别有什么用家是哪里的?面了哪些公司?期望薪酬?是否了解我们公司的业务?以后想做哪个方向(SOC / IP / FPGA)? -问我期望薪资的时候,面试官透露说他们公司给的算高的(是 x15~18),所以薪资感觉还是很不错的。我也给他吐槽说成都低于24W的话可能就不太行了,反正最低门槛要按联发科的来【手动狗头提问环节
a. 在成都ASIC团队现在大概有40个人,成都部门是整个翱捷的第二大分部,主部门在上海,总人数1000多;
b. 培训流程大致就是先上课(1~2个月),后面就是导师制;
c. 公司主要做无线短距通信,收购过外企top10的专利,非常肯定这个方向在中国没几个人能做的这么大,所以在这个方向很有实力;
d. 公司不强制打卡,只要不是投片回来那会(维持1~2周),基本上都是朝九晚七;
e. 后续看情况有1~2轮面试,这个要看主管。HR只会在最后谈薪资时介入,也就是说没有HR; 二面·HR面【20分钟】 其实感觉也不算HR面,更像是OC,问了我意向地和期望薪资,在得知我意向地是成都后,他一直在劝我考虑上海:上海机会多,上海有很多成都没有的福利(买房优惠之类的),然后就考虑好意向地后再和他联系。
后面我微信还是跟他报的成都,然后到现在还没消息。
不过需要补充的是,他说薪资税前肯定是大于25W的(原话是“肯定比25W高不少”),所以感觉大家可以期待一下。
PS:但是我回复我想去成都后,就没有任何消息了。
offer call【15分钟】 和今年成都已经开过奖的各大公司比起来,翱捷给的确实有点低 + 大家都是统一价。
没有加班考核机制(没有加班费/调休),不打卡,支持远程办公。不过还是拒了,毕竟总包没有今年发哥高。
============================ 正文结束 ==============================
pip安装pykerberos失败报错
gssapi/gssapi.h: No such file or directory
解决方法:
ubuntu
sudo apt install libkrb5-dev
centos yum install krb5-devel.
质数:只能被1 和本身整除的数
第一层循环,从这个数,开始,一次次递减,查找 ----除数
第二层循环,从2开始,到这个数的一半 -------被除数
完整代码 #include <stdio.h> //求一个数的最大质数 int zhishu(int num)//参数:一个数;返回值:这个数的指数 { int i = 2; int flags = 0;//标志位--如果有重复的,标志位置1 for(num;num > 0;num--)//外层循环,遍历一下这个数 及 之前的数 { flags = 0; //假设num=10,能整除10的数,一定不会超过5,所以,循环遍历一半就行了 for(i = 2;i < (num/2);i++)//内层循环,查看有没有能整除的数 { //printf("----%d----%d-----\n",num,i); if(num % i == 0)//如果余数为0,则是被整除---就不是质数了 { //printf("循环里面---%d----%d-\n",num,i); flags = 1; break; } //puts("====================================="); } if(flags == 0) return num; } return 0; } int main() { int num = 0; int zs = 0; printf("
将这一行的中文分号改为英文 。。。
KMP 模板 // s[]是长文本,p[]是模式串,n是s的长度,m是p的长度 求模式串的Next数组: for (int i = 2, j = 0; i <= m; i ++ ) { while (j && p[i] != p[j + 1]) j = ne[j]; if (p[i] == p[j + 1]) j ++ ; ne[i] = j; } // 匹配 for (int i = 1, j = 0; i <= n; i ++ ) { while (j && s[i] != p[j + 1]) j = ne[j]; if (s[i] == p[j + 1]) j ++ ; if (j == m) { j = ne[j]; // 匹配成功后的逻辑 } } 例题 求出模板串P在模式串S中所有出现的位置的起始下标。
文章目录 专栏博客链接前引Lab2 HTTP查阅Wireshark Lab官网 获取Lab文档Q&A 1 所做工作Q&A 1Q&A 2 所作工作Q&A 2Q&A 3 所做工作Q&A 3Q&A 4 所作工作Q&A 4Q&A 5 所作工作Q&A 5Q&A 5 base64码验证 专栏博客链接 《计算机网络自顶向下》Wireshark Lab + 套接字编程作业 + 杂项实验室编程作业 全实验博客链接
前引 各位 真的好久好久不见 明天大二就开学了 这几天人有点点懒
一直呆在寝室里面没有出去 昨天前天玩了两天 基本上每天只刷了三道力扣就没干什么了 之后对于这个Wireshark实验 发现并没有什么实质性的可以写的 主要都是根据书上的步骤而看实验结果 并对实验结果分析 - -
但再怎么说 尽管明天就要恢复上课了 但是我还是想把今天的wireshark 剩下的两个实验给做了 明天就可以继续恢复看书了 那就先这样
Lab2 HTTP 查阅Wireshark Lab官网 获取Lab文档 老样子 我们在Lab1中已经得到文档了 方便翻译使用 我们下载docx的 用word自带翻译 方便查阅链接
下面即得到HTTP Lab 的docx的全览图
Q&A 1 所做工作 打开Wireshark 并用过滤器输入 HTTP
在电子产品的PCB布线时,导线之间合适的电气间隙的设置是一件非常重要的工作,合适的线间间距的设置可以防止工作中的各有关导体之间发生闪烁或击穿,并能顺利通过有关产品安全标准的审核。在各产品工业标准和安全标准中,根据工作电压和不同的应用场合以及其他因素,对导体间的电气间隙和爬电距离有着不同的规定,PCB布线工程师往往对此莫衷一是,无所适从。接下来就帮大家解决这一难题。
首先了解下基本概念:
安规常用术语
1)工作绝缘(功能绝缘) functional insulation
仅为设备正常工作所需的绝缘。所定义的功能绝缘并不防电击的作用。
2)基本绝缘 basic insulation
对防电击提供基本保护的绝缘。
3)附加绝缘 supplementary insulation
除基本绝缘以外施加的独立的绝缘,用以在基本绝缘一旦失效时仍能防止电击。
4)双重绝缘 double insulation
由基本绝缘加上附加绝缘组合构成的绝缘。
5)加强绝缘 reinforced insulation
一种单一的绝缘结构,在本标准规定的条件下,其所提供的防电击的保护相当于双重绝缘。
6)一次电路 primary circuit
直接与AC电网电源连接的电路。例如:与AC电网电源连接的装置,变压器、电动机、其它负载装置初级绕组,以及与电网连接的各种装置。
7)二次电路 secondary circuit
不与一次电路直接连接,而是由变压器、变换器或等效的隔离装置供电或只用电池供电的一种电路。
8)电气间隙 clearance
在两个导电零部件之间或导电零部件与设备界面之间测得的最短空间距离。
9)爬电距离 creepage distance
沿绝缘表面测得的两个导电零部件之间或导电零部件与设备界面之间的最短距离。
10)海拔高度 altitude
设备工作所在位置相对海平面的落差。在IEC60950-1中,默认的设备工作的最大海拔高度为2000m,如果设计要求设备工作的最大海拔高度高于2000m,则设计电气间隙的时候在2000下要求的最小电击间隙的基础上乘以一个系数,不同海拔对应的系数关系如下表:
11)污染等级 Pollution degree
设备运行时,由于灰尘等物质在设备表面或内部积累的程度,一般分为3级;
12)材料类别 Material group
根据材料的CTI的大小,对材料进行的分类,具体分类可见下表:
基于标准的安全要求如果我们设计的产品必须要得到某个安全认证机构的承认,那么我们首先要考虑产品需要符合相应安全认证机构颁布的有关标准中所规定的绝缘和隔离要求。在这种情况下,我们就能够根据有关标准的要求进行PCB布线的距离定义。例如,有的要按照UL60950,有的要求IPC9592等等。
对于常见的交流电供电或电池供电的信息技术设备,大都依从IEC/EN/UL60950这一标准,那么其PCB导线之间允许的最小的电气间隙和爬电距离的要求将可以直接从IEC/EN/UL60950-1标准的表2K,2L和表2N中查到。附2K,2L,2N表。
电气间隙是两个导电体之间的空气中最短的距离,而最小电气绝缘间隙主要由表2J、2K和2L来确定。具体查表方法如下:
1、根据交流电网电压有效值和过电压类别确认交流电网电源瞬态电压(由附表Z和2J确定);
2、首先确定污染等级,在根据实测两点峰值工作电压B和上述确认的交流电网电源瞬态电压值可确定最小电气间隙为C1(由表2K确定);
表2K一次电路绝缘以及一次电路与二次电路之间绝缘最小电气间隙(海拔2000m以下)
3.确定污染等级后,再根据实测两点峰值工作电压B和电网电源瞬态电压确认附加电气间隙C2(由表2L确定);
表2L一次电路的附加电气间隙(适用于海拔2000m以下)
4、如果B大于交流电网峰值则最小电气间隙为C1+C2,如果B小于或等于交流电网峰值则最小电气间隙就等于C1。
爬电距离是两个导电体沿绝缘材料表面的最短距离,而最小爬电距离只由表格2N来确定;具体查表方法如下:
1、确定污染等级;
2、再根据实测工作电压有效值和绝缘材料的材料组别确定最小爬电距离(由表2N确定)。
表2N最小爬电距离
一次电路和二次电路之间的电压测试方法
假如开关电源输入有L、N和PE则测试图如下图1所示:
假如开关电源输入只有L、N则测试图如下图2所示:
实际上,电气间隙和爬电距离的设置是和工作电压,绝缘等级,污染等级,PCB材料等级,甚至和产品工作的海拔高度等等相关。查表时,我们首先要搞清楚上述因素的界定。
1.如何确定工作电压?根据60950的解释,我们在定义电气间隙时,应该使用峰值电压和可能出现的外部瞬态电压。而定义爬电距离时,则使用均方根值电压。
2.如何确定绝缘等级?60950的表2H有详细的定义。见下述图示:
简单地说来,在大多数应用中,我们可以凭借以下简单分析来进行绝缘等级的定义: - 如果在绝缘被破坏的情况下,会对人体易接触未接地的部件产生危险电压的,绝缘等级应该设置为加强绝缘。
目录 一、Pod的基本概念二、pod存在意义三、Pod的实现机制 3.1 共享网络3.2 共享存储四、Pod镜像拉取策略五、Pod资源限制六、Pod重启机制七、Pod健康检查八、Pod调度策略-创建pod流程九、影响Pod调度 1.Pod的资源限制2.节点选择器标签3.节点亲和性4.污点 (1)基本介绍(2)应用场景(3)具体演示(4)节点添加污点(5)节点删除污点5.污点容忍 一、Pod的基本概念 Pod是k8s系统中可以创建和管理的最小单元,是资源对象模型中由用户创建或部署的最 小资源对象模型,也是在 k8s 上运行容器化应用的资源对象,其他的资源对象都是用来支 撑或者扩展 Pod 对象功能的,比如控制器对象是用来管控 Pod 对象的,Service 或者 Ingress 资源对象是用来暴露 Pod 引用对象的,PersistentVolume 资源对象是用来为 Pod 提供存储等等,k8s 不会直接处理容器,而是 Pod,Pod 是由一个或多个 container 组成
Pod 是 Kubernetes 的最重要概念,每一个 Pod 都有一个特殊的被称为”根容器“的 Pause 容器。Pause 容器对应的镜 像属于 Kubernetes 平台的一部分,除了 Pause 容器,每个 Pod 还包含一个或多个紧密相关的用户业务容器
最小部署单元pod里面可以包含多个容器(一组容器的集合)一个pod中容器共享网络命名空间pod是短暂的 二、pod存在意义 创建容器使用docker ,一个docker对应是一个容器,一个容器有进程,一个容器运行一个运用程序pod是多进行设计,运行多个应用程序 一个pod有多个容器,一个容器里面运行一个应用程序 pod存在为了亲密性应用 两个应用之间进行交互网络之间调用两个应用需要频繁调用 三、Pod的实现机制 3.1 共享网络 pod实现共享网络机制:
首先创建Pause容器也可以叫做info容器或者根容器再创建业务容器,每次创建业务容器都会加入到info容器里面,这样pod就在同一个namespace下面,这样就可以网络共享 3.2 共享存储 pod实现共享存储机制:
引入Volumn数据卷的概念,使用数据卷进行持久化存储 四、Pod镜像拉取策略 imagePullPolicy
ifNotPresent:宿主机不存在则拉取Always:每次创建pod都会重新拉取一次镜像Never:pod永远都不糊主动拉取镜像 五、Pod资源限制 六、Pod重启机制 restartPullPolicy