在springboot中引用其他的yml文件时,需要在application.yml里配置
spring: profiles: include: email, redis, mysql SpringBoot 多模块共用配置文件
https://zhuanlan.zhihu.com/p/113836100
本文主要讲解linux下如何进行新用户创建、登录以及删除操作
文章目录 1、创建新普通用户2、登录普通用户(一)已经创建过普通用户(二)第一次创建普通用户 3、普通用户切换至超级用户(root)及超级用户(root)回退回普通用户4、删除普通用户 1、创建新普通用户 当我们在第一次使用linux时最开始都是只有一个超级用户(root),而普通用户则是用过超级用户进行创建而形成的,所以我们首先来在超级用户下进行创建一个普通用户
第一步:首先进入linux系统中输入指令 whoami 显示root则表示当前用户为超级用户,接下来我们就可以继续进行创建新的普通用户操作。
第二步:输入 adduser+要创建的用户名(我这里用的是haha)接着我们passwd+用户名设置该用户的密码,密码设置最少7位,不能太简单,不然会报错,这里建议字母+数字,在重复输入新密码(注意这里输入密码不回显)当出现all authentication tokens updated successfully则表示新用户已经创建成功,一般创建的新用户会在home目录下生成一个该用户名命名的文件夹。到这里我们的新普通用户就算是已经创建成功了。
2、登录普通用户 (一)已经创建过普通用户 我们直接使用 su+用户名命令,直接切换到普通用户。
(二)第一次创建普通用户 1.进入xshell中点击新建用户
2.设置名称为haha或者其他都行这个就是一个名字,协议为SSH,主机输入购买的云服务器公网ip,端口号为22,。
3.这里我们点击用户身份验证,输入刚才创建好的用户名和密码点击连接。
3、普通用户切换至超级用户(root)及超级用户(root)回退回普通用户 1.如上这里我们已经进入到haha普通用户中,首先输入whoami查看当前用户为haha,然后我们输入su指令,意思就是我们需要切换到超级用户(root),提示我们输入该超级用户密码,输入后就可以切换到超级用户啦,在输入whoami查看是否为超级用户
2.当我们想切回原用户时,输入exit既可切回原普通用户,在这里有个快捷操作就是ctrl+d直接瞬间切回原用户。
4、删除普通用户 userdel -r+用户名
当我们想要对普通用户进行删除时,首先我们先切换超级用户root,上边已经讲过啦,然后我们使用指令userdel -r+用户名进行删除普通用户操作。
如图所示haha用户已经被删除并且连带一开始所创建的haha用户文件夹一同被删除。
注意:
**1.不要使用userdel+用户指令进行删除,因为这样只会删除该用户,而不会删除home目录下的该用户的文件夹,相当于存在残留,没有删除干净。有些人会说我 home下有目录,那我用用户名和密码登录一下试试,说不定没有删除呢?emmmmm…这个我也试过了,被无情拒绝,所以我建立的用户已经不存在了。
2.当在进行一次userdel+用户操作时则显示不存在该用户,但是查询该home目录时还存在该文件夹,这时我们在adduser+haha发现弹出警告说home目录中已经存在该文件夹,所以就很烦。
3.接下来解决的办法就是我们在进行一遍userdel -r+haha操作,就可以直接解决掉啦。
并发数,线程数,吞吐量,每秒事务数(TPS)都是性能测试领域非常关键的数据和指标。
那么他们之间究竟是怎样的一个对应关系和内在联系?
测试时,我们经常容易将线程数等同于表述为并发数,这一表述正确吗?
本文就将对性能领域的这些关键概念做一次探讨。
文章可能会比较长,希望您保持耐心看完。
1. 走进开封菜,了解性能 我们的主角老王 在M市投资新开业了一家,前来用餐的顾客络绎不绝:餐厅里有4种不同身份的人员: 用户一次完整的用餐流程如下:
顾客到店小二处付款点餐 => 小二将订单转发给后厨 => 后厨与备菜工配合,取材完成烹饪后交给小二 => 小二上菜,顾客用餐。
假设所有顾客都不堂食而是打包带走,也就是不考虑用户用餐时间。餐厅完成一次订单的时间是多久?
订单时间 = 顾客点单时间 + 前台接收转发时间 + 后厨取材烹饪时间 + 后厨交给服务员,服务员上菜时间。
说白了就是每个流程的耗时相加。
假设以上时间分别为1,1,5,1(分钟),那么一次订单的完成时间就是8分钟。
餐厅当然不可能只有一个人就餐,否则老王不要带着小姨子跑路。
所以我们接下来看多人就餐的情况。
假设同一时间点上有两人就餐,会发生什么情况?
第一位用户与第一个场景一样,仍然是点单-下单-烹饪-上菜,8分钟后第一位顾客拿着打包的食物离开。
第二位用户则有所不同了。假设小二,厨师,备菜都只有一人,而且他们每个人同时只能处理一件事情。
那么第二位用户首先需要在点餐时等待小二1分钟,而后厨师烹饪第一位用户的菜时,没有任何人在为他服务。
我们来梳理一下这个过程中,每一分钟都发生了什么事情:
可以看到,两个顾客完成订单的总时长是13分钟。
继续推算我们发现,每增加一人总时长增加5分钟。
在当前的人员配置下,顾客越多,后来的顾客等待时间就越长。
如果餐厅在高峰时段只有两人用餐,那估计老王还得带着小姨子跑路。
实际一个运营得当的开封菜餐厅,在用餐高峰时段的顾客数可能高达百人。
那么问题来了,在某个普通工作日,12:00午饭时间,带着各种工牌的IT男女顾客蜂拥而至,餐厅瞬间挤进来一百人。
这个时候会发生什么?
现在餐厅已经完全服务不过来了,后续的顾客等的时间越来越长,最后一位可怜的顾客要等到差不多晚上8点才能吃到饭。
这显然是不可能的,实际上等了不到半个小时吃不上饭的顾客就都要走光了。
老王开始考虑如何应对营业高峰期的情况。
经过上面的分析,老王发现,增加各岗位人手无疑是最直观的解决办法!
我们可以计算一下人手增加的情况。假设把所有人员增加为2人配置:
那么很简单,2人就餐的情况下,由于所有人员并行服务,就餐的两名顾客可以同一时间点餐,等待烹饪,上菜后打包走人。
而后来的客人可以看作两条并行的线,那么100顾客的用餐时间就很自然的减半了。
看到这里,终于出现“并行”的概念了。
通过double人员配置,老王成功的使得用餐高峰期的服务能力提高了一倍,但这还不够。这种情况下,服务100顾客仍需差不多4个小时。
老王再次思考整个服务团队的配置和各环节处理能力,他发现,其瓶颈就在于“后厨”。顾客的等待时间,大部分都是在等待烹饪。
那么增加后厨能力就是重中之重,老王继续做了一系列措施:
再次double大厨人数,现在厨师们四个人同时并行做菜。让备菜员提前将热门食材准备好。聘请更有经验的大厨,每个餐品烹饪时间更快,加上提前备菜,整个配餐时间缩短到2分钟。将点餐的过程改为使用手机小程序下单,让小二专注于上菜。 整个团队配置变为:
如此配置之下,这家开封菜终于可以在1小时之内就完成对100人顾客的就餐服务了!
2. 这并不是一篇餐饮管理文章 再继续讨论餐厅的服务能力调优,这可能就要变成一片餐饮博文了。
不过相信敏锐的你能看出来,第一部分我们的讨论里,包含了大量与服务器性能相似的概念。
恰好,老王除了开了一家开封菜餐厅,还运营着一家网站=_=!。
这家网站的一次典型事务请求链路是这样的:
你别说,还真挺像用餐流程的吧。
而且就像多人用餐的场景一样,这个网站同样也有多用户请求的情况:
当一条请求从客户端发起时,它遵循着以上的线路传递,线性完成。
老王发现,这家网站的性能关键,在于应用服务器上。就像餐厅的服务能力,主要取决于后厨团队一样。
当多个客户端同时发起请求时,服务器必须具备一定的“并行”能力,否则后续进来请求会排队而且可能超时。
说到这呢,虽然上图我们画的是一个但一般都服务器的
概述 Vim 是从 vi 发展出来的一个文本编辑器。vi 内置在Linux系统中,是vim的简化版编辑器,vim则需要进行安装使用。Vim代码补全、编译及错误跳转等方便编程的功能特别丰富,可以实现高效率移动和高效的输入,在程序员中被广泛使用。其真正的优势在于其可扩展性。 Vim有自己的脚本语言,称为Vim脚本(也称为vimscript或VimL),用户可以通过多种方式使用它来增强Vim,例如为其他编程语言启用语法高亮,自动化语法检查或将Vim与其他应用程序和服务。除了可扩展性之外,Vim还具有高度可配置性,包含Vim核心全局设置(称为vimrc)的文件可以在各个Vim安装之间共享。下面我来介绍一下Vim的基础操作和常用命令集。
这是目录
概述
预备知识(三种模式介绍)
vim的基本操作
vim指令集 vim正常模式下命令集
进入插入模式
移动光标
注释代码
删除文字
复制 替换 跳至指定的行 撤销上一次操作
更改内容
vim底行模式下命令集 列出行号
跳到文件中的某一行
查找字符
保存文件并退出
vim的安装命令: yum install -y vim
预备知识(三种模式介绍) 基本上 vi/vim 共分为三种模式,分别是命令模式(Command mode),输入模式(Insert mode)和底行命令模式(Last line mode)。 这三种模式的作用分别是: 一般/ 命令模式(Normal mode):Vim 启动后,默认进入命令模式。在此模式下,我们可以 控制屏幕光标的移动,字符、字或行的删除,移动复制某区段及进入Insert mode下,或者到 last line mode下 输入模式(Insert mode):只有在此模式下我们可以编辑文本内容。在命令模式下按 i、 a 、o等键可以进入输入模式, 按「ESC」键可回到命令行模式 底行模式(Last line mode): 在命令模式下,shift+: 即可进入底行模式。这时光标会移到屏幕底部,在这里可以输入相关指令进行 文件保存或退出,也可以进行文件替换,找字符串,列出行号等操作。 要查看你拥有的所有模式,可以在底行模式下输入查看: :help vim-modes vim的基本操作 图解记忆:
键盘实现vim一切操作 在Linux系统提示符号后输入vim及文件名称后,进入vim编辑画面:
前言 K8s 集群 随着pod运行服务的越来越多,运行时间越来越大,docker目录占用磁盘空间也在逐渐变大,终于在最近磁盘彻底占满导致容器启动不起来并提示"no device space left"。为了防止以后出现docker占用磁盘容量不够的情况决定对docker数据目录迁移。
1. docker数据迁移 docker数据默认存储在/var/lib/docker目录下。实际存储目录可以参考docker info输出
Client: ... Server: ... Docker Root Dir: var/docker/lib ... 迁移步骤 1.1.停止dockerd服务 systemctl stop docker 1.2.创建新目录迁移数据 使用其他挂载盘,使用 cp 命令复制数据
cp -a /var/lib/docker /mnt/data/ 注意这里一定要加 -p 或 用 -a 不然复制过去文件权限不对,有些容器启动会报错。如果不加p参数可能会导致迁移后的目录的/tmp目录(其他人&&组)丢失w(写)权限。教训:mongo容器启动需要在/tmp目录下创建****.sock监听请求,由于cp没有加上p参数导致/tmp目录从drwxrwxrwt权限变为drwxr-xr-t权限,无法成功启动。t权限是x+SBIT形成的。
下面举个例子: 变更 docker工作目录后 ,harbor启动异常,报错如下
rsyslogd: run failed with error -3000 (see rsyslog.h or try https://www.rsyslog.com/e/3000 to learn what that number means) rsyslogd: error writing pid file (creation stage) : Permission denied
要点
1)在正文绘制box,且正文索引box;
2)正文索引编号,依据box出现顺序,而不是掺杂section编号。
1)绘制box命令:可以考虑用 tikzpicture包,在tikzpicture里编辑box边框。(\usepackage{tikz})
\begin{mybox}\label{mybox}
\begin{tikzpicture}
\node (a) [draw, rectangle, text width=1.1\linewidth] {
\textbf{Box 1} \begin{enumerate}
\item \end{enumerate} };
\end{tikzpicture}
\end{mybox}
2)正文索引编号,依据box出现顺序,而不是掺杂section编号。
正文引用: ‘\textbf{Box~\ref{mybox:1}}’
如果前文未说明,正文会出现 “box 2.2” 其中box出现在2.2 小节。
如何出现 box1 (假设是第一个box)
需要补上:
\usepackage{tcolorbox}
\usepackage{url}
\newcounter{myboxcounter}
\setcounter{myboxcounter}{0}
\newtcolorbox{mybox}[1][]{
colback=white,
colframe=white,
arc=0pt,
outer arc=0pt,
boxrule=1pt,
#1,
title={}
\refstepcounter{myboxcounter}
\label{mybox:\themyboxcounter}
Box~\themyboxcounter
}
1.线性表中的顺序表 线性表(linear list)是n个具有相同特性的数据元素的有限序列。 线性表是一种在实际中广泛使用的数据结构,常见的线性表:顺序表、链表、栈、队列...
线性表在逻辑上是线性结构,也就说是连续的一条直线。但是在物理结构上并不一定是连续的,线性表在物理上存储时,通常以数组和链式结构的形式存储。
2.顺序表 顺序表是用一段物理地址连续的存储单元依次存储数据元素的线性结构,一般情况下采用数组存储。在数组上完成数据的增删查改。
2.1接口的整体实现 public class SeqList { // 打印顺序表 public void display() { } // 新增元素,默认在数组最后新增 public void add(int data) { } // 在 pos 位置新增元素 public void add(int pos, int data) { } // 判定是否包含某个元素 public boolean contains(int toFind) { return true; } // 查找某个元素对应的位置 public int indexOf(int toFind) { return -1; } // 获取 pos 位置的元素 public int get(int pos) { return -1; } // 给 pos 位置的元素设为 value public void set(int pos, int value) { } //删除第一次出现的关键字key public void remove(int toRemove) { } // 获取顺序表长度 public int size() { return 0; } // 清空顺序表 public void clear() { } } 2.
多表关系 在关系型数据库中存在着三种多表关系,分别是一对多(多对一)、多对多以及一对一。之所以会产生这些关系,是因为在进行数据设计的时候,分析得出业务之间存在着一定的关系,进而在数据中也就存在了这些关系。
一对多 一对多是最基础的表间关系,意思是一张表A中的一条记录可以对应另一张表B中的多条记录,另一张表B中的一条记录只能对应一张表A中的一条记录。
案例: 部门 与 员工的关系
关系: 一个部门对应多个员工,一个员工对应一个部门
实现: 在多的一方建立外键,指向一的一方的主键
对应的SQL脚本
-- 创建部门表 create table dept ( id int primary key auto_increment comment '编号', name varchar(10) comment '姓名' ) comment '部门表'; -- 创建员工表 create table emp ( id int primary key auto_increment comment '编号', name varchar(10) comment '姓名', age int comment '年龄', dept_id int comment '部门编号', constraint fk_dept_emp foreign key (dept_id) references dept (id) ) comment '员工表'; 多对多 一张表A中的一条记录可以对应另一张表B中的多条记录,另一张表B中的一条记录也可以对应一张表A中的多条记录。
flutter(dart)项目添加依赖时,依赖的版本号有时候会使用any,有时候压根不写版本号。那么这两种写法有什么区别呢
相同点: 第一次pub get时,二者都睡下载库的最新版本
不同点 当库有版本更新时:
使用any,会强制更新库到最新版本,而不去考虑pubspec.lock文件
不使用版本号时,会依据pubspec.lock文件更新到合适的最新版本
要根据深度图获取某个像素点的三维坐标,需要知道该像素点在相机坐标系中的坐标以及相机的内部参数和外部参数。
首先说明以下视觉中四大坐标系的转换关系:
具体步骤如下: 1.假设深度图的大小为HxW,要获取像素点(i,j)的三维坐标 2.首先,需要将该像素点的坐标从图像坐标系转换到相机坐标系。设像素点(i,j)的深度值为D(i,j),相机的内参(fx,fy,u0,v0)已经通过相机标定得知,则该像素点在相机坐标系的计算公式如下式: 3.接下来,需要将相机坐标系中的坐标转换到世界坐标系中。设相机的外部参数为旋转矩阵R和平移向量T,则该像素点在世界坐标系中的坐标为: 4.最终得到该像素点的三维坐标(Xw,Yw,Zw)
【python】遍历文件夹
文章目录 前言一、os.walk()简介概述语法参数 二、使用示例1.遍历文件内的所有文件2.遍历获取txt文件 总结 前言 os 模块提供了非常丰富的方法用来处理文件和目录。
这篇文章主要介绍如何运用os模块的方法遍历文件夹
一、os.walk()简介 概述 os.walk() 方法用于通过在目录树中游走输出在目录中的文件名。
os.walk() 方法是一个简单易用的文件、目录遍历器,可以帮助我们高效的处理文件、目录方面的事情。
该方法在Unix,Windows中有效。
语法 os.walk(top[, topdown=True[, onerror=None[, followlinks=False]]]) 参数 top – 是你所要遍历的目录的地址, 返回的是一个三元组(root,dirs,files) root 所指的是当前正在遍历的这个文件夹的本身的地址 dirs 是一个 list ,内容是该文件夹中所有的目录的名字(不包括子目录) files 同样是 list , 内容是该文件夹中所有的文件(不包括子目录) topdown --可选,为 True,则优先遍历 top 目录,否则优先遍历 top 的子目录(默认为开启)。如果 topdown 参数为 True,walk 会遍历top文件夹,与top 文件夹中每一个子目录。onerror – 可选,需要一个 callable 对象,当 walk 需要异常时,会调用。followlinks – 可选,如果为 True,则会遍历目录下的快捷方式(linux 下是软连接 symbolic link )实际所指的目录(默认关闭),如果为 False,则优先遍历 top 的子目录。 二、使用示例 1.遍历文件内的所有文件 代码如下(示例):
import os directory = r'D:\example\test' for root, dirs, files in os.
前言 如果你开发的App需要与硬件做通讯,获取相应数据进行业务处理,这个库肯定对你有帮助。常见的硬件通讯连接方式有:串口通讯、Usb Com、Usb、蓝牙(包括BLE)、Wifi等,实际硬件支持哪种连接方式,要看硬件支持哪种方式。应用层硬件通讯方案有两种:
硬件供应商有提供SDK,不需要关注连接通讯实现,直接集成到App中使用即可硬件供应商没有提供SDK,单提供有通讯协议,这时候自己需要分析协议流程和写通讯代码 本文针对第二点,封装了一个基础的、轻量级的通讯库,支持多种连接方式串口通讯、Usb Com、Usb、蓝牙(包括BLE)、Wifi,通讯流程为:
1. 初始化连接实例
2. 打开连接
3. 读写数据
4. 关闭连接
通讯库特点:上层调用一致,底层不同实现,方便使用者切换连接方式。为简化上层调用和方便数据处理,全部连接采用同步操作,即一发一收(一问一答)的方式通讯
调用 1.初始化实例
//串口 BaseConnectProvider baseConnectProvider = new SerialPortConnectProvider(SerialPortConfig serialPortConfig); //Usb Com BaseConnectProvider baseConnectProvider = new UsbComConnectProvider(int vendorId, int productId, SerialPortConfig serialPortConfig); //or BaseConnectProvider baseConnectProvider = new UsbComConnectProvider(UsbDevice usbDevice, SerialPortConfig serialPortConfig); //Usb BaseConnectProvider baseConnectProvider = new UsbConnectProvider(int vendorId, int productId); //or BaseConnectProvider baseConnectProvider = new UsbConnectProvider(UsbDevice usbDevice); //默认蓝牙 Com BaseConnectProvider baseConnectProvider = new BluetoothConnectProvider(BluetoothDevice bluetoothDevice); BaseConnectProvider baseConnectProvider = new BluetoothConnectProvider(String address); //指定蓝牙服务UUID BaseConnectProvider baseConnectProvider = new BluetoothConnectProvider(BluetoothDevice bluetoothDevice, String uuid); BaseConnectProvider baseConnectProvider = new BluetoothConnectProvider(String address, String uuid); //Wifi BaseConnectProvider baseConnectProvider = new WifiConnectProvider(String host, int port, int connectTimeout, int readTimeout); //特别地:蓝牙Ble BluetoothLeConnectProvider connectProvider = new BluetoothLeConnectProvider(BluetoothDevice bluetoothDevice); BluetoothLeConnectProvider connectProvider = new BluetoothLeConnectProvider(String address); 2.
添加 BouncyCastle provider // 添加 BouncyCastle provider Security.addProvider(new BouncyCastleProvider()); 示例 public static void main(String[] args) throws Exception { // 添加 BouncyCastle provider Security.addProvider(new BouncyCastleProvider()); // 定义密钥 byte[] keyBytes = "0123456009abcdef".getBytes("UTF-8"); SecretKeySpec keySpec = new SecretKeySpec(keyBytes, "AES"); // 初始化加密解密器 Cipher cipher = Cipher.getInstance("AES/ECB/PKCS7Padding", "BC"); cipher.init(Cipher.ENCRYPT_MODE, keySpec); // 执行加密操作 byte[] input = "TEST".getBytes("UTF-8"); byte[] encrypted = cipher.doFinal(input); // 输出加密结果 System.out.println("Encrypted: " + new String(encrypted, "UTF-8")); }
目录
一、什么是最短路径
二、弗洛伊德(Floyd)算法
三、测试程序
求图的最短路径在实际生活中有许多应用,比如说在你在一个景区的某个景点,参观完后,要怎么走最少的路程到你想参观的下个景点,这就利用到了求图最短路径的算法。求图的最短路径有很多算法,这里介绍一种弗洛伊德(Floyd)算法来求图的最短路径。
在介绍算法前,需要掌握一点图的基本知识,比如说什么是路径,什么是路径长度等。如果对这些不了解的话,建议先了解一下。
这是我写的一篇博客,对图的一些基本知识的简介——图的一些基本知识。
一、什么是最短路径 在网图和非网图中,最短路径的含义是不同的。由于非网图没有边上的权值,所谓最短路径,其实指的就是两个顶点之间经过的边数最少的路劲(即可以理解为把每一条边的权值看作是1)。
对于网图来说,所谓最短路径,就是指两顶点之间经过的边上的权值之和最少的路径,并且我们称路径上的第一个顶点是源点,最后一个顶点是终点。
求带权有向图G的最短路径问题一般可分为两类:一是单源最短路径,即求图中某一个顶点到其它顶点的最短路径,可以通过经典的 Dijkstra(迪杰斯特拉)算法求解(这是我写的一篇博客,有兴趣的同学可以看下,Dijkstra算法);二是求每对顶点间的最短路径,可通过Floyd(弗洛伊德)算法(也是我接下来要讲解的算法)来求解。
二、弗洛伊德(Floyd)算法 Floyd算法需要两个二维数组 D[vexNum][vexNum] 和 P[vexNum][vexNum],其中 vexNum代表的是图中结点的个数,D代表顶点到顶点的最短路径权值和的矩阵。P代表对应顶点的最短路径的前驱矩阵,用来存储路径。
Floyd算法的基本思路是:递推产生一个 n 阶方阵序列,,... ,,...,和,,...,,...,。其中 [v][w] 表示从顶点 v 到顶点 w 的路径长度,k表示绕行第 k 个顶点的运算步骤,[v][w]表示从顶点 v 到顶点 w 的最短路径所需要经过的一个中间结点。
初始时,对于任意两个顶点 v 和 w,若它们之间存在边,则以此边上的权值作为它们之间的最短路径长度;若它们之间不存在有向边,则以 ∞ 作为它们之间的最短路径,此过程用于初始化矩阵D。以后逐步在原路径中加入顶点 k(k=0,1,...,n-1)作为中间顶点。若增加中间顶点后,得到的路径比原来的路径长度减少了,则以此新路径代替原路劲并且修改矩阵 P。算法描述如下:
定义一个 n 阶方阵序列 ,,...,,其中,
[v][w] = Min{[v][w],[v][k] + [k][w]}
[v][w] = [v][k] 上式中,[v][w]是从顶点 v 到 w、中间顶点是 的最短路径长度,[v][w]是从顶点 v 到 w,中间顶点的序号不大于 k 的最短路径长度。Floyd算法是一个迭代的过程,每迭代一次,在从 v
到 w 的最短路径上就多考虑了一个顶点;经过 n 次迭代后,所得到的 [v][w]就是 v 到 w 的最短路径长度,即方阵中就保存了任意一对顶点之间的最短路径长度。方阵 可以求出顶点 v 到 顶点 w 的最短路径。
前言: 前面我们已经系统的学完C语言的相关知识,现在我们已经较为熟练的掌握了C语言中的各中代码语法和结构使用,能够使用代码来解决一些简单问题。但是对于一个程序员来说,仅仅会语法是远远不够的,从今天开始,我们将进入到数据结构的学习。
一、初始数据结构: 数据结构: 数据结构是计算机存储、组织数据的方式。数据结构是指相互之间存在一种或多种特定关系的 数据元素的集合。通常情况下,精心选择的数据结构可以带来更高的运行和存储效率。数据结构往往同高效的检索算法和索引技术有关。
2.算法: 算法(Algorithm):就是定义良好的计算过程,它取一个或一组的值为输入,病残生出一个或一组值作为输出。见来说算就是一系列计算步骤用来将输入数据转化为输出结果。
算法具有以下五个特点:
①有穷性: 指算法必须能在执行有限个步骤之后终止; ②确切性: 算法的每一个步骤必须有确切的定义; ③输入项: 一个算法有0个或者多个输入,以刻画运算对象的初始情况,所谓0个输入是指算法本身定出了初始条件; ④输出项: 一个算法有一个或多个输出,以反映对输入数据加工后的结果; ⑤可行性: 算法中执行的任何计算机步骤都是可以被分解为基本的可执行的操作步骤,即每个计算步骤都快要有限时间内完成。 常见的算法思想:递推法、递归法、穷举法、贪心算法、分治法、动态规划法、迭代法、分支界限法,回溯法。
二、算法效率: 算法的效率可以分为两种:时间效率和空间效率。
时间效率顾名思义就是指算法执行的时间,依据改算法编制的程序在计算机上运行时所消耗的时间来度量。空间效率指的是程序运行所需占用的空间,根据该算法编制的程序在计算机上运行时所占用的全部空间来度量。总而言之,算法效率其实就是为了研究算法的好坏而生的。而我们在衡量算法的好坏时,通常从时间和空间这两个角度出发的。从时间维度出发研究算法的时间复杂度,从空间维度出发研究算法的空间复杂度。
时间复杂度主要衡量一个算法的运行快慢,而空间复杂度主要衡量一个算法运行所需要的额外空间。在计算 机发展的早期,计算机的存储容量很小。所以对空间复杂度很是在乎。但是经过计算机行业的迅速发展,计 算机的存储容量已经达到了很高的程度。所以我们如今已经不需要再特别关注一个算法的空间复杂度。 时间复杂度: 时间复杂度的定义:在计算机科学中,算法的时间复杂度是一个函数,它定量描述了该算法的运行时间,一个算法执行所消耗的时间,从理论上讲是不能算出来的,只有你把你的程序放在机器上跑起来,才能知道,但是我们需要每个算法都上机测试吗?是可以都上机测试,但是这很麻烦,而且随着科技的发展,现在不同的电脑cpu差距很大,又可能在一个电脑跑10s的程序,到另一个电脑就需要15s了,所以才有了时间复杂的这个分析方式。一个算法所花费的时间于其中语句的执行次数成正比例,算法中的基本操作的执行次数,为算法的时间复杂度。
即:找到某条基本语句与问题规模N之间的数学表达式,就是算出了该算法的时间复杂度。 例如:
/ 请计算一下Func1中++count语句总共执行了多少次? void Func1(int N) { int count = 0; for (int i = 0; i < N ; ++ i) { for (int j = 0; j < N ; ++ j) { ++count; } } for (int k = 0; k < 2 * N ; ++ k) { ++count; } int M = 10; while (M--) { ++count; } 上述代码中,第一部分的嵌套循环共执行了N的平方(N^2);第二部分的循环共执行了N*2次,第三部分共执行了10次,因此这段代码的时间复杂度F(N):
文章目录 (一)Docker 基础命令
(二)Docker 镜像命令 (三)Docker 容器命令
(四)Docker 运维命令
本篇文章不仅仅是生硬的命令大全,也是我个人对docker学习使用的一步步总结,通过一个个示例来加深各位看官对docker相关命令的理解以及记忆
(一)Docker 基础命令 systemctl start docker 启动Docker命令
systemctl stop docker 关闭docker
systemctl restart docker 重启docker
systemctl enable docker docker设置随服务启动而自启动
systemctl status docker 查看docker 运行状态(运行中输入命令后会看到绿色的active)
docker version / docker info 查看docker 版本号信息
docker 帮助命令
docker --help 忘记了某些命令便可使用此进行查看与回顾
忘记拉取命令不知道可以带哪些参数 咱可以这样使用
docker pull --help
(二)Docker 镜像命令 Docker官方镜像搜索
docker images 查看自己服务器中docker 镜像列表
docker search 镜像名 搜索镜像 列如:docker search --filter=STARS=9000 mysql 搜索 STARS >9000的 mysql 镜像
NLP(VII):使用sklearn进行文本情感分类(下) 这一节我们使用gensim来进行单词的向量化。
使用spacy进行tokenize import spacy all_texts = np.array(twitter_train_df['text']).tolist() + np.array(twitter_test_df['text']).tolist() all_tokenized_texts = [] token_freq_dict = {} nlp = spacy.load("en_core_web_sm") for twitt in all_texts: doc = nlp(twitt) token_twitt = [] for token in doc: token = token.text.lower() token_twitt.append(token) if token in token_freq_dict: token_freq_dict[token] += 1 else: token_freq_dict[token] = 1 all_tokenized_texts.append(token_twitt) 使用gensim将token向量化 gensim包的用法可以参考官方网站:
https://radimrehurek.com/gensim/models/word2vec.html
from gensim.models import Word2Vec model = Word2Vec(all_tokenized_texts, size=300) 每一条推文的向量表示可以通过其所有token的向量取平均来计算:
all_vec_tweets = [] for tweet in all_tokenized_texts: tw_vecs = [] for token in tweet: if token_freq_dict[token]>=5: tw_vecs.
本文主要介绍java中replace()和replaceAll()的区别,两者都是常用的替换字符的方法。感兴趣的朋友可以参考一下。
Replace和replaceAll是JAVA中替换字符的常用方法。他们的不同之处在于:
1)replace的参数是char和CharSequence,即可以支持字符的替换,同样支持字符串的替换(CharSequence的意思是字符串序列,也就是通俗英语中的字符串);
2)replaceAll的参数是regex,即基于规则表达式的替换,比如可以通过replaceAll('\\d ',' * ')用星号替换一个字符串的所有数字字符;
相同点:all replaceAll,即用指定的字符或字符串替换源字符串中的所有字符或字符串。如果只想替换第一个匹配项,可以使用replaceFirst()。这个方法也是基于正则表达式的,但是和replaceall()不同,只替换第一次出现的字符串;
另外,如果replaceAll()和replaceFirst()使用的参数不是基于正则表达式,那么用replace()替换字符串的效果是一样的,即两者也都支持字符串操作;
再说明一点:替换操作后,源字符串的内容不变。
例子如下:
String src=新字符串(' ab 43 a 2c 43d ');
system . out . println(src . replace(' 3 ',' f ');=ab4f2c4fd。
system . out . println(src . replace(' 3 ',' f ');=ab4f2c4fd。
system . out . println(src . replace all(' \ \ d ',' f ');=abffafcffd。
system . out . println(src . replace all(' a ',' f ');=fb43fc23d。
system .
FLAG_ALLOW_LOCK_WHILE_SCREEN_ON:允许在屏幕开启的情况下锁定屏幕。
FLAG_ALT_FOCUSABLE_IM:当界面上有输入框时,该标志可以让输入法在弹出后覆盖输入框之上。
FLAG_DIM_BEHIND:在当前Activity之后的Activity中设置一个灰色透明遮罩层。
FLAG_FORCE_NOT_FULLSCREEN:当前Activity不全屏显示,即显示状态栏。
FLAG_FULLSCREEN:当前Activity全屏显示,即隐藏状态栏。
FLAG_HARDWARE_ACCELERATED:启用硬件加速。
FLAG_IGNORE_CHEEK_PRESSES:忽略面颊触碰。
FLAG_KEEP_SCREEN_ON:保持屏幕常亮。
FLAG_LAYOUT_INSET_DECOR:使窗口的内容布局在装饰视图之内。
FLAG_LAYOUT_IN_SCREEN:使窗口的内容布局在整个屏幕之内。
FLAG_LAYOUT_NO_LIMITS:窗口布局不受限制,可以覆盖状态栏、导航栏、装饰视图等。
FLAG_NOT_FOCUSABLE:窗口不可获得焦点。
FLAG_NOT_TOUCHABLE:窗口不可触摸。
FLAG_NOT_TOUCH_MODAL:当窗口在前面时,允许在窗口之外触摸事件传递到后面的窗口。
FLAG_SCALED:窗口内容按比例缩放。
FLAG_SECURE:窗口内容不可截屏。
FLAG_SHOW_WALLPAPER:在窗口背景中显示壁纸。
FLAG_SPLIT_TOUCH:分离触摸模式。
FLAG_WATCH_OUTSIDE_TOUCH:当窗口在前面时,允许在窗口之外触摸事件传递到后面的窗口。
FLAG_BLUR_BEHIND:在当前Activity之后的Activity中设置一个模糊透明遮罩层。
FLAG_DISMISS_KEYGUARD:解锁屏幕,需要权限。
FLAG_DITHER:启用抖动。
FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS:使窗口内容延伸到状态栏和导航栏之下。
FLAG_LAYOUT_ATTACHED_IN_DECOR:使窗口的内容布局在装饰视图之内,并显示在导航栏之上。
FLAG_LAYOUT_IN_OVERSCAN:窗口布局延伸到屏幕边缘之外,需要权限。
FLAG_LOCAL_FOCUS_MODE:窗口内部获得焦点,外部不可获得焦点。
FLAG_SHOW_WHEN_LOCKED:在锁屏状态下显示当前Activity。
FLAG_TOUCHABLE_WHEN_WAKING:在唤醒设备时,允许触摸事件传递到窗口之外。
FLAG_TRANSLUCENT_NAVIGATION:使导航栏半透明。
FLAG_TRANSLUCENT_STATUS:使状态栏半透明。
FLAG_TURN_SCREEN_ON:唤醒设备,需要权限。
Linux服务—openssh—学习笔记 1. 什么是 SSH SSH 为 Secure Shell 的缩写,是建立在应用层基础上的安全协议。SSH是较为可靠的专为远程登录会话和其他网络服务提供安全性的协议。利用用 SSH 协议可以有效防止远程管理过程中的信息泄露问题。
OpenSSH 服务是 SSH 协议的免费开源实现,可以用来进行远程控制, 或在计算机之间传送文件。OpenSSH提供了服务端后台程序和客户端工具,用来加密远程控制和文件传输过程中的数据,并由此来代替原来的类似服务。
通过使用SSH,你可以把所有传输的数据进行加密,这样可以较好地抑制"中间人"这种攻击,也可能够防御DNS欺骗和IP欺骗。
使用SSH,还有一个额外的好处就是传输的数据是经过压缩的,所以可以加快传输的速度。
接下来介绍使用其传输文件的命令。
scp命令:将本机文件复制到远程服务器上(上传)
命令格式:scp 本地路径 用户名@IP:目录
将远程服务器上的文件复制到本机(下载)
命令格式:scp 用户名@IP:文件路径 本地目录
注意:
如果远程服务器openssh有特殊限制,scp便要走特殊端口,具体用什么端口视情况而定,命令格式如下: scp -P 2222 用户名@IP:路径 目录 使用scp要注意所使用的用户是否具有可读取远程服务器相应文件的权限如果是拷贝文件夹添加-r参数 2. 安装 openssh openssh默认已经安装于centos中,无须额外的安装。相关的软件包可以通过以下命令进行查询。
dnf list |grep openssh openssh-clients.x86_64 # 客户端 openssh-server.x86_64 # 服务端 openssh-askpass.x86_64 # 交互式访问 3. 服务的状态/停止/启动 可使用systemctl命令查看和设置openssh服务的状态。
systemctl status sshd.service # 查看ssh状态 systemctl start sshd.service # 启动ssh服务 systemctl stop sshd.service # 停止ssh服务 systemctl reload sshd.
题目网址: 信息学奥赛一本通(C++版)在线评测系统 (ssoier.cn) 三种情况 我们老师以前给我们布置过一道题目,就是上面的题目,其实这道题我一拿到就想到了三种方法:
不用数组
用数组进行max排序
max排序都不需要,直接sort排序
[1]不用数组 这种适合我那些还没有学到数组的小萌新们,具体是这样:
(说实话,我也想不出他们如何不用数组肝出来的,所以该代码来源于我的同学,有改动)
#include<bits/stdc++.h> using namespace std; int m,n,maxx = 0; int main() { cin >> n; for(int i = 1;i <= n;i++) { cin >> m; if(m > maxx)maxx = m; } cout << maxx; return 0; } [2]用数组进行max排序 这大概是许多人都会想到的办法吧,实际上,这种方法不太好写,我给大家演示一下:
#include<bits/stdc++.h> using namespace std; int n,cj[110],maxx; int main() { cin >> n; for(int i = 1;i <= n;i++)cin >> cj[i]; for(int i = 1;i <= n;i++) { maxx = max(maxx,cj[i]); } cout << maxx; return 0; } [3]max排序都不需要,直接sort排序 这种方法是最神的方法,直接使用sort排序,轻松解决:
GitLab 部署及管理员账号初始化 1.首先登录gitlab服务器执行以下命令: # 切换到gitlab安装目录 cd /opt/gitlab/bin sudo gitlab-rails console -e production 2.通过命令查找,确定用户为“root” # 以下这两个命令都可以,随便输入一个 user = User.where(id: 1).first user = User.where(name: "root").first 3.将root用户密码重置为admin123 # 输入重置密码命令 user.password="admin123" # 再次确认密码 user.password_confirmation="admin123" 4.保存重置信息,并结束 # 输入保存命令,以便使更改信息生效 user.save # 退出修改窗口 exit 如果看到上面截图中的true ,恭喜你已经成功了,执行 exit 或quit退出当前设置流程即可。
回到gitlab ,可以通过 root/admin123 这一超级管理员账号登录了
在数据库查询过程中无法避免的需要从两张表中同时查询数据,此时我们需要用到各式各样的多表查询方式。接下来,简单介绍一下数据库基础的多表查询方式,以便于让大家更好的了解多表查询的过程。
多表查询 项目开发中,在进行数据库表结构设计时,会根据业务需求及业务模块之间的关系,分析并设计表结构,由于业务之间相互关联,所以各个表结构之间也存在着各种联系,基本上分为三种:
一对多(多对一)
多对多
实现:建立第三张中间表,中间表至少包含两个外键,分别关联两方主键。
一对一
一对一关系,用于单表拆分,将一张表的基础字段放在一张表中,其他详情字段放在另一张表中,以提升操作效率
多表查询 概述:指从多张表中查询数据
笛卡尔积:笛卡尔积是指在数学中,两个集合A和B的所有组合情况。在多表查询是,需要消除无效的笛卡尔积)
多表查询分类: 连接查询
内连接:相当于查询A、B交集部分数据
外连接:
左外连接:查询左表所有数据,以及两张表交集部分数据
右外连接:查询右表所有数据,以及两张表交集部分数据
自连接:当前表与自身的连接查询,自连接必须使用别名
子查询
内连接
内连接查询的是两张表交集的部分
隐式内连接:
select 字段列表 from 表1,表2 where 条件...;
显式内连接:
select 字段列表 from 表1 inner on 表2 on 连接条件...;
外连接
左外连接
相当于查询表1 (左表)的所有数据 包含表1和表2交集部分的数据
select 字段列表 from 表1 left outer o n 表2 on 条件
右外连接
相当于查询表2 (右表)的所有数据 包含表1和表2交集部分的数据
select 字段列表 from 表1 right outer oin 表2 on 条件
可以查询内连接查询不到的数据
一、实验名称 互联网模拟实验
二、实验目的 掌握互联网路由器连接与基本配置方法。掌握路由表静态路由配置方法。掌握路由表动态路由配置方法。理解动态、静态路由表优缺点。 三、实验设备 路由器两台,交换机两台,路由器V35串行线缆一条、路由器配置线一条、计算机,网线。
四、实验过程 实验一:路由器静态路由配置
主要用到的命令如下:
[Router1]ip route-static 202.200.2.0 255.255.255.0 192.168.1.2
[Router1]save
[Router1]display iP routing-table (查看R1上路由表)
[Router2]ip route-static 202.200.1.0 255.255.255.0 192.168.1.1
[Router2]save
[Router2]display iP routing-table (查看R2上路由表)
路由器动态路由配置
主要用到的命令如下:
[Router1]undo ip route-static 202.200.2.0 255.255.255.0 192.168.1.2
(删除静态路由配置)
[Router1]rip (开启RIP协议)
[Router1-rip]network all
[Router1-rip]quit
[Router1]save
[Router1]display iP routing-table
[Router2]undo ip route-static 202.200.1.0 255.255.255.0 192.168.1.1
[Router2]rip
[Router2-rip]network all
[Router2-rip]quit
[Router2]save
[Router2]display iP routing-table
动静路由混合配置
主要用到的命令如下:
[Router1]ip route-static 202.200.2.0 255.255.255.0 192.168.1.2
[Router1]save
一.兼容性测试
直播的兼容性测试则是在不同的机型、不同的系统、不同的分辨率以及不同网络环境下测试是否可以正常开播,进入直播间观看直播、发送消息并且在直播结束时可以正常跳转到直播结束页面进行相关操作。
图4.1 兼容性测试
二.性能测试
针对直播间的性能测试主要涉及到以下几个方面:
图5.1 性能测试
(1)CPU:iOS可以使用instruments中的Activity Monitor帮助测试。Android可以利用Android Studio 自带 CPU检测功能进行测试 。
(2)内存:iOS可以使用instruments的 Leaks、Activity Monitor 、Allocations 、Zombies帮助测试。Android可以利用Android Studio 自带内存检测功能进行测试 。
(3)流量(WI-FI和流量): 记录直播过程中的流量消耗情况(可借助工具,如腾讯管家)。
(4)电量:同等初始环境下,开启直播30分钟,对比多个直播APP的电量消耗情况。
(5)温度(包括电磁温度和CPU的温度):同等初始环境下,开启直播30分钟,利用工具(如Castro)帮助记录对比多个直播APP直播的温度变化。
(6)秒开:测试进入直播间时首屏的加载时间在1S左右。
(7)延迟:测试主播开播与观众拉流的视频直播之间的延迟。
(8)清晰度:根据用户的直观感受反馈测试。
(9)分辨率:借助VLC工具查看。
(10)FPS:借助VLC工具查看。
(11)码率:借助VLC工具查看。
三.UI测试
测试用户界面布局、风格是否满足要求、文字是否正确、页面是否美观、文字、图片组合是否完美、操作是否友好等。UI测试的目标是确保用户界面会通过测试对象的功能来为用户提供相应的访问或浏览功能。确保用户界面符合公司或行业的标准。包括用户友好性、人性化、易操作性测试。
(1)秀场:
主态直播间
直播间开播页面:摄像头、闪光灯、美颜、封面图、标题、选吧、开启同步按钮、开启测试直播间、定位、分享、开播以及开通游戏直播展示正常;
直播间页面:主态头像、观众数、魅力值、水印、观众列表、消息框、摄像头、闪光灯、美颜、分享展示正常;
直播结束页面:观众数、直播时长、点赞数、魅力值上升、删除本次视频(直播时长大于三分钟)展示正常。
客态直播间
直播间页面:主态头像、关注按钮、观众数、地理位置、魅力值、水印、观众列表、来源吧、消息框、放大播放、礼物、分享功能及界面正常;
直播结束页面:主播头像、主播名、魅力值上升、观看人数、直播时长、关注按钮以及精彩直播推荐展示正常。
(2)游戏:
主态直播间
直播间开播页面:设置、标题、选游戏、选吧、清晰度、横竖屏、开启测试直播间、定位、分享、开播以及直播教程展示正常;
直播间页面:标题、魅力值、人数、消息框、分享、语音隐私、图像隐私以及设置展示正常;
直播结束页面:竖屏开播的直播结束界面同秀场;横屏开播的直播结束界面横屏展示,具体的展示内容同秀场。
客态直播间
竖屏:主态开播选择竖屏直播,客态进入游戏直播间,界面和普通直播间展示一样;
主态开播选择横屏直播,客态进入游戏直播间,视频流界面展示主播横屏界面;主播头像/在线观众数/地理位置/观众头像/关闭直播间按钮/魅力值/吧名/水印正常展示;游戏直播画面区域16:9;im消息展示区域正常;聊天输入框、放大按钮、分享按钮、礼物按钮展示正常;
横屏全屏:主播头像/观看人数/距离/魅力值/水印/关注/聊天框/缩小按钮/屏蔽icon/分享icon/礼物icon均正常展示;渐隐消失效果是否正常;
直播结束页面:同秀场。
(3)新手引导:左滑清屏,上下拉切换直播间,双击点赞。
(4)气泡提醒:横屏观看直播、进入视频广场。
(5)个人信息卡片:近期回放+粉丝数+正在关注展示正常;
(6)列表UI:粉丝数/正在关注:头像+用户名+关注/取消关注按钮;用户名超长打点截断;近期回放:录播封面、标题、观众数、时间展示正常。
(7)夜间模式展示正常。
(8)礼物特效展示正常。
(9)导航测试
是否易于导航,导航是否直观;
导航帮助是否准确直观;
导航与页面结构、菜单、连接页面的风格是否一致。
(10)图形测试
自适应界面设计,内容根据窗口大小自适应;
页面标签风格是否统一;
(11)页面是否美观,页面的图片应有其实际意义而要求整体有序美观。
(12)内容测试
输入框说明文字的内容与系统功能是否一致
文字长度是否加以限制;
问题:
网页打印 无法保留背景 除非点击 '背景图形'选项 但有点用户不知道勾选 于是 需求强制勾选
css 一行代码即可
-webkit-print-color-adjust: exact;
D-H法机械臂建模
D-H建模方法是由D和H两个人提出的,是用于机器人运动学上的建模方法,该方法是在每个连杆上建立一个坐标系,通过齐次变换来实现两个连杆上的坐标变换。
通过依次的变换最终可以推导处末端执行器相对于基坐标系的位姿,从而建立机器人的运动学方程,该方法通常叫标准的DH建模方法。
标准D-H法(SDH)把坐标系建立在机械臂连杆末端,改进D-H法(MDH)把坐标系建立在连杆首段。
标准DH法,参数下标均为i:
连杆角度θi:Xi-1到Xi沿Zi-1的转角。
连杆偏距di: Xi-1到Xi沿Zi-1的距离。
连杆长度ai:Zi-1到Zi沿Xi-1的距离。
连杆转角αi:Zi-1到Zi沿Xi的转角。
转动的顺序有所不同
坐标系i在坐标系i-1中的描述,即变换矩阵。
改进DH法,参数分别为αi-1,ai-1,di,θi:
连杆转角αi-1:以Xi-1的方向看,Zi-1到Zi间的夹角。
连杆长度ai-1:沿Xi-1的方向,Zi-1到Zi间的距离。
连杆角度θi:以Zi方向看,Xi-1到Xi的夹角,逆正顺负。
连杆偏距di: 沿着Zi方向 Xi-1到Xi间的距离。
坐标系i在坐标系i-1中的描述,即变换矩阵。
(精准的量化表达)
总的变换矩阵:
串联连续连乘
机械臂采用改进D-H法建系如下:
机械臂末端执行器位姿:
例子:
SDH:标准DH法
MDH:改进DH法
MATLAB实现建模对比分析:
利用matlab机器人工具箱 建模
标准DH法建模:
一. Kafka基本介绍 Kafka是一个分布式、支持分区的(partition)、多副本的(replica),基于zookeeper协调的分布式消息系统。具有:高吞吐量、低延迟、可扩展性、持久性、可靠性、容错性、高并发等特性。常见的应用场景有:日志收集、消息系统、流式处理等。
二. Kafka的基本架构 Producer:生产者,也就是发送消息的一方。生产者负责创建消息,然后将其发送到 Kafka。Consumer:消费者,也就是接受消息的一方。消费者连接到 Kafka 上并接收消息,进而进行相应的业务逻辑处理。Consumer Group:一个消费者组可以包含一个或多个消费者。使用多分区 + 多消费者方式可以极大提高数据下游的处理速度,同一消费组中的消费者不会重复消费消息,同样的,不同消费组中的消费者消息时互不影响。Kafka 就是通过消费组的方式来实现消息 P2P 模式和广播模式。Broker:服务代理节点。Broker 是 Kafka 的服务节点,即 Kafka 的服务器。Topic:Kafka 中的消息以 Topic 为单位进行划分,生产者将消息发送到特定的 Topic,而消费者负责订阅 Topic 的消息并进行消费。Partition:Topic 是一个逻辑的概念,它可以细分为多个分区,每个分区只属于单个主题。同一个主题下不同分区包含的消息是不同的,分区在存储层面可以看作一个可追加的日志(Log)文件,消息在被追加到分区日志文件的时候都会分配一个特定的偏移量(offset)。Offset:offset 是消息在分区中的唯一标识,Kafka 通过它来保证消息在分区内的顺序性,不过 offset 并不跨越分区,也就是说,Kafka 保证的是分区有序性而不是主题有序性。Replication:副本,是 Kafka 保证数据高可用的方式,Kafka 同一 Partition 的数据可以在多 Broker 上存在多个副本,通常只有主副本对外提供读写服务,当主副本所在 broker 崩溃或发生网络一场,Kafka 会在 Controller 的管理下会重新选择新的 Leader 副本对外提供读写服务。Record:实际写入 Kafka 中并可以被读取的消息记录。每个 record 包含了 key、value 和 timestamp。 三. Kafka如何保证消息顺序消费 Kafka 在 Topic 级别本身是无序的,只有 partition 上才有序,所以为了保证处理顺序,可以自定义分区器,将需顺序处理的数据发送到同一个 partition。自定义分区器需要实现接口 Partitioner接口并实现 3 个方法:partition,close,configure,在partition 方法中返回分区号即可。
Kafka 中发送 1 条消息的时候,可以指定(topic, partition, key) 3 个参数,partiton 和 key 是可选的。
1、TypeScript是什么? TypeScript 是 JavaScript 的超集,扩展了 JavaScript 的语法,因此现有的 JavaScript 代码可与 TypeScript 一起工作无需任何修改,TypeScript 通过类型注解提供编译时的静态类型检查。TypeScript 可处理已有的 JavaScript 代码,并只对其中的 TypeScript 代码进行编译。
2、TS和JS的区别 2.1、TS的优点 静态输入
静态类型化是一种功能,可以在进行编写脚本时检测错误。查找并修复错误,对于编写更健壮的代码并对其进行维护,以便使得代码质量更好、更清晰。
大型的开发项目
有时为了改进开发项目,需要对代码库进行小的增量更改。这些小小的变化可能会产生严重的、意想不到的后果,因此有必要撤销这些变化。而使用TypeScript工具来进行重构更变的容易、快捷。
更好的协作
当发开大型项目时,进行开发的过程当中乱码和错误的机也会增加。类型安全是一种在编码期间检测错误的功能,而不是在编译项目时检测错误。
3、TS开发环境的搭建 有两种主要的方式来获取TypeScript工具:
通过npm(Node.js包管理器)安装Visual Studio的TypeScript插件 在这里的安装基本上我们都采用node进行安装,首先我们需要下载nodeJs,之后我们直接执行命令进行安装TS。
npm install -g typescript 安装完成之后我们可以使用以下命令查看TS的版本
tsc -v 之后我们新建一个项目,在项目当中我们新建一个ts文件,我们在ts文件当中我们先使用js的代码内容:
console.log("hello TS") 然后我们的ts文件是不能够在浏览器当中进行解析的,我们的ts文件首先需要通过编译,编译之后才能够被浏览器进行解析,我们直接使用命令
// tsc + 文件名 tsc demo.ts 编译之后我们的目录下面会产生一个和ts文件同名的js文件,之后我们就可以直接使用这个编译得到的js即可。我们安装好了node,就可以直接使用node命令对js文件进行解析了,使用node命令:
// node + 文件名 node demo.js 4、TS变量的声明和赋值 let和const是JavaScript里相对较新的变量声明方式。 像我们之前提到过的, let在很多方面与var是相似的,但是可以帮助大家避免在JavaScript里常见一些问题。 const是对let的一个增强,它能阻止对一个变量再次赋值。因为TypeScript是JavaScript的超集,所以它本身就支持let和const。在这里我们也就不对var、let、const做详细的解释了,相信了解js的小伙伴也是可以区分开来的。
// 声明一个变量a 并且a的数据类型为number let a : number ; // 所以对a的值赋为字符串就会出现报错 // a = "
利用函数,求出两个数的最大值,要求可以自己输入数值,并且利用函数
例如 a=10 b=20 最后的结果为20
函数段
int MAX(int x, int y) { int z = 0; if (x > y) z = x; else z = y; return z; } 代码说明:创建一个MAX函数,给MAX函数一个x和y,在局部变量中在设置一个中间量z,之后的最大值给z,在局部变量中利用if-else函数进行x和y的比较
主函数段
int main() { int a = 0; int b = 0; int Max = 0; scanf("%d %d", &a, &b); Max = MAX(a,b); printf("最大值为;%d\n", Max); return 0; } 代码说明,首先设置变量a和b和最大值Max,之后还需要一个关键字来接收我们所输入的数字,之后将Max和函数MAX联动,最后打印出Max值就可以得到结果啦
整体代码
#include<stdio.h> int MAX(int x, int y) { int z = 0; if (x > y) z = x; else z = y; return z; } int main() { int a = 0; int b = 0; int Max = 0; scanf("
目录
一、 pinctrl和gpio子系统
1.pinctrl子系统
1.1 pinctrl子系统简介
1.2 pinctrl子系统驱动
1.3 设备树中添加pinctrl节点模版
2. gpio子系统
2.1 gpio子系统简介
2.2 gpio子系统驱动
2.3 gpio子系统API函数
2.4 设备树中添加gpio节点模板
2.5 与gpio相关的OF函数
3. 驱动程序编写
3.1 驱动入口函数
3.2 驱动出口函数
一、 pinctrl和gpio子系统 Linux 是一个庞大而完善的系统,尤其是驱动框架,像 GPIO 这种最基本的驱动不可能采用“原始”的裸机驱动开发方式。Linux 内核提供了 pinctrl 和 gpio 子系统用于GPIO 驱动,
Linux 驱动讲究驱动分离与分层,pinctrl 和 gpio 子系统就是驱动分离与分层思想下的产物
要先设置某个 PIN 的复用功能、速度、上下拉等,然后再设置 PIN 所对应的 GPIO。其实对于大多数的 32 位 SOC 而言,引脚的设置基本都是这两方面,因此 Linux 内核针对 PIN 的配置推出了 pinctrl 子系统,对于 GPIO的配置推出了 gpio 子系统。
1.pinctrl子系统 1.1 pinctrl子系统简介 pinctrl 子系统主要工作内容如下:
面试流程 首先写道题,写一个分页器。
start = (pageSize*pageNun),end = in.length>(start+pageSize)?(start+pageSize):in.length
了解你能够实习的时长。
1、web接口太慢,怎么优化,有什么思路去优化?
数据库优化代码优化负载均衡缓存优化网络优化 2、怎么通过查看日志去排错和优化?
监控系统状态调试和排错题。性能优化安全监控。业务分析 3、redis储存了一个set集合,更新的时候存在并发问题,怎么解决?
redis的乐观锁和悲观锁实现这是一个项目中值得考虑改进的操作!!!!!! 4、了解过聚合索引吗?
聚合索引就是内容按一定顺序排序;非聚合索引索引和内容分开储存。 5、代码管理工具git的工作流,代码分支怎么使用?
master、develop、feature、release、hotfix5种分支 此外,补充一些面试后的知识学习 1、为什么不可以用synchronize来限制同步客户端对服务器中的redis的数据更新请求? 虽然synchronize关键字可以用来在多线程程序中保证共享数据的同步和互斥访问,但在分布式系统中,synchronize并不能有效地限制同步客户端对Redis服务器中的数据更新请求。
这是因为在分布式系统中,Redis服务器可以被多个客户端同时访问和更新,而**不同客户端之间的线程并不共享内存。**因此,使用synchronize关键字在不同客户端之间进行同步是不可能的。
在分布式系统中,一般采用分布式锁或乐观锁等机制来限制并发访问和更新。Redis中支持的WATCH和MULTI命令可以用来实现基于版本号的乐观锁,而SETNX和EXPIRE命令可以用来实现基于锁的悲观锁。使用这些机制可以保证在多个客户端同时对Redis进行访问和更新时,数据的原子性和一致性。
2、单体web应用中更新redis中的数据存在并发问题,怎么解决? 在单体web应用中更新Redis中的数据存在并发问题时,可以考虑以下几种解决方法:
使用Redis的事务机制:Redis支持事务机制,可以将多个操作一起提交,从而确保操作的原子性。可以使用Redis的MULTI和EXEC指令来执行事务,确保在事务执行期间不会被其他客户端打断。使用Redis的乐观锁机制:通过对Redis中的数据进行版本控制,当要更新某个数据时,首先检查该数据的版本号是否与自己持有的版本号一致,如果一致则执行更新操作,否则放弃更新。这种方式不会阻塞其他客户端对数据的访问,但是需要注意版本号的更新策略,以避免出现数据不一致的情况。使用Redis的悲观锁机制:通过在更新数据时对数据进行加锁,确保同一时间只有一个客户端可以对数据进行修改。可以使用Redis的SETNX指令实现悲观锁,但是需要注意加锁时间过长会降低并发性能。使用分布式锁:在集群环境下,可以使用分布式锁来确保并发更新的数据的一致性。可以使用ZooKeeper或者Redisson等开源框架实现分布式锁机制。 3、java分别实现一下redis的乐观锁和悲观锁操作 redis乐观锁
public boolean updateWithOptimisticLock(String key, String expectedValue, String newValue) { Jedis jedis = null; try { jedis = pool.getResource(); //连接到redis jedis.watch(key); //监视,保证同步 String currentValue = jedis.get(key); if (currentValue != null && currentValue.equals( expectedValue )) { Transaction tx = jedis.multi(); //redis事务 tx.set(key, newValue); List<Object> result = tx.
驱动程序一般指的是设备驱动程序(Device Driver),是一种可以使计算机和设备通信的特殊程序。相当于硬件的接口,操作系统只有通过这个接口,才能控制硬件设备的工作,假如某设备的驱动程序未能正确安装,便不能正常工作。
因此,驱动程序被比作“ 硬件的灵魂”、“硬件的主宰”、和“硬件和系统之间的桥梁”等。
驱动程序安装的一般顺序:主板芯片组(Chipset)→显卡(VGA)→声卡(Audio)→网卡(LAN)→无线网卡(Wireless LAN)→红外线(IR)→触控板(Touchpad)→PCMCIA控制器(PCMCIA)→读卡器(Flash Media Reader)→调制解调器(Modem)→其它(如电视卡、CDMA上网适配器等等)。
安装电脑的整个流程应该是三个步骤,装机,装系统,装驱动,安装完驱动你就可以愉快地玩电脑了。
在安装驱动程序之前,我们需要了解一下什么是驱动程序,驱动程序简单来讲就是驱使硬件动起来的程序,简称驱动程序。讲复杂一点,它是一种介于硬件和系统之间的API接口,让你的系统知道这个硬件的存在并能通过这个API接口和这个硬件交互数据。
比如说显卡驱动,你插了一张显卡到你的电脑上,你的主板知道你插了这么一张显卡,因为主板和显卡是物理层面的电气信号交互,但是你的操作系统,你的Windows并不知道这个显卡的存在,你必须要一个软件去告诉Windows,我这里有个显卡,到时候你渲染游戏画面的时候,可以把这个运算任务交给显卡,而需要运算的这些数据就会由系统交给驱动,再通过驱动交给显卡去运算。
这就好比说一个发电厂发了电,你也买了一个电视,发电厂就需要拉一根电线到你家,拉电线这个操作就像是发电厂给你家开放了一个API接口,驱动程序则是介于系统和硬件之间开放的一种虚拟的API接口,所以理论上讲所有的硬件都是需要驱动程序才可以运行的。
那这里就有一个问题了,我刚装系统的时候各种驱动都没有,为什么我的显示器能亮,我的鼠标器都能用,我的电脑也可以上网呢?这个其实就是系统自带了一个集成驱动。我们的操作系统安装包看着很大,有4-5G,但是其系统本体很小,其中有相当一部分数据都是兼容驱动,这些驱动刚好可以在你补齐专用驱动之前,提供一个最基本的API接口,让你的部分硬件能临时凑合用一下,方便你去补齐他们的专有驱动。
不然的话,你连最基本的显卡驱动都没有,你的显示器就是黑屏的,鼠标、键盘都没有反应,那你咋去补驱动呢?而系统自带的兼容性驱动只能维持硬件的基本运行,让他们能够运作起来并不能够发挥全部的性能,所以你一定要去自己补齐各个硬件的专有驱动。
目录
1 应用层如何操控 GPIO
2 GPIO 应用编程之输出
3 GPIO 应用编程之输入
4 GPIO 应用编程之中断
本文参考正点原子教程,作为学习笔记使用。
1 应用层如何操控 GPIO GPIO也是通过 sysfs 方式进行操控,进入到/sys/class/gpio 目录下,
可以看到该目录下包含两个文件 export 、 unexport 以及 5 个 gpiochipX ( X 等于 0 、 32 、 64 、 96 、 128 )命名的文件夹。 ⚫ gpiochipX:当前 SoC 所包含的 GPIO 控制器 ,我们知道 I.MX6UL/I.MX6ULL 一共包含了 5 个 GPIO 控制器,分别为 GPIO1 、 GPIO2 、 GPIO3 、 GPIO4 、 GPIO5 ,在这里分别对应 gpiochip0 、 gpiochip32 、 gpiochip64、 gpiochip96 、 gpiochip128 这 5 个文件夹,每一个 gpiochipX 文件夹用来管理一组 GPIO 。随便进入到其中某个目录下,可以看到这些目录下包含了如下文件: 在这个目录我们主要关注的是 base 、 label 、 ngpio 这三个属性文件,这三个属性文件均是只读、不可写。 base:与 gpiochipX 中的 X 相同,表示 该控制器所管理的这组 GPIO 引脚中最小的编号。 每一个 GPIO引脚都会有一个对应的编号,Linux 下通过这个编号来操控对应的 GPIO 引脚。 label:该组 GPIO 对应的标签,也就是名字。 ngpio:该控制器所管理的 GPIO 引脚的数量(所以引脚编号范围是: base ~ base+ngpio-1 )。 对于给定的一个 GPIO 引脚,如何计算它在 sysfs 中对应的编号呢?其实非常简单,譬如给定一个 GPIO引脚为 GPIO4_IO16,那它对应的编号是多少呢?首先我们要确定 GPIO4 对应于 gpiochip96,该组 GPIO 引 脚的最小编号是 96 (对应于 GPIO4_IO0 ),所以 GPIO4_IO16 对应的编号自然是 96 + 16 = 112 ;同理 GPIO3_IO20 对应的编号是 64 + 20 = 84 。 ⚫ export : 用于将指定编号的 GPIO 引脚导出。在使用 GPIO 引脚之前,需要将其导出,导出成功之后才能使用它。注意 export 文件是只写文件,不能读取,将一个指定的编号写入到 export 文件中即可将对应的 GPIO 引脚导出,譬如: echo 0 > export # 导出编号为 0 的 GPIO 引脚(对于 I.
使用javaSE连接mysql,无论是直接使用jdbc连接还是使用mybatis,运行一段时间后,都有如下两个异常:
No operations allowed after connection closed 或 CommunicationsException: Communications link failure The last packet successfully received from the server was 53,159 milliseconds ago. The last packet sent successfully to the server was 0 milliseconds ago. 无论是修改连接后的参数例如增加autoReconnect=true或者useSLL=false都无效,直接修改mysql的基本配置比如连接的超时时间也是不可取的,因为如果使用的是客户的mysql,自己使用方式不恰当还要给人家硬改配置也只是以开发者思维去做项目而不是客户角度。
解决办法就是使用阿里的druid数据库连接池,让连接池自己去维护连接,包括重连机制,druid都会自己根据配置去做维护。
上代码:
第一步:获取druid数据源
/** * 获取druid数据源 * * @return * @throws SQLException */ public static DruidDataSource getDefaultMysqlDataSource() throws SQLException { String mysqlUrl = ""; String username = ""; String password = ""; String driverClass = "
广域网宽带接入技术二PPPoE原理及配置 二、PPPoE原理及配置1、PPPoE的基本原理1.1、PPPoE拨号的三个阶段1.2、PPPoE报文格式1.3、PPPoE协商过程1.3.1、discovery发现阶段:1.3.2、PPP Session会话阶段:1.3.3、Terminate阶段:1.4、密码验证协议2、PPPoE的配置2.1、PPPoE Server配置2.2、PPPoE Client配置 二、PPPoE原理及配置 1、PPPoE的基本原理 运营商希望把一个站点上的多台主机连接到同一台远程接入设备,并实现对用户进行认证、授权和计费、访问控制的功能,通过应用RFC2516定义的PPPoE(Point-to-Point Protcol over Ethernet)技术很好的解决了以太网接入应用中的用户认证问题。将PPP帧封装到以太帧,使用PPP协议(点到点协议)在以太网上传输PPP报文的技术称为PPPoE。
PPP是一种数据链路层协议,遵循HDLC(高级数据链路控制协议)族的一般报文格式。它使用链路控制协议(LCP)来建立和维护数据链路连接。应用网络控制协议(NCP)在一条点到点连接上使用多种网络层协议(被路由协议)。PPP协议栈只涉及到物理层和数据链路层。
链路控制协议(LCP)提供以下配置:身份验证、压缩、错误检测、多链路、PPP回拨。网络控制协议(NCP)用于标识和封装网络层协议,允许通过同一条PPP链路传输多种网络层协议,包括IPCP(因特网协议控制协议)和IPXCP(网间分组交换控制协议)。
PPPoE组网结构采用Client/Server模型,PPPoE的客户端为PPPoE Client,PPPoE的服务器端为PPPoE Server。PPPoE Client向PPPoE Server发起连接请求,PPPoE Server为PPPoE Client提供接入控制、认证等功能。
PPPoE Client可以是电脑主机也可以是网关设备,常见的是现在通过光猫或者路由器设置帐号和密码后,输入上网帐号和密码连接网络,然后将PPP帧封装以太帧传输到PPPoE Server上进行PPP认证。在网络运营商的宽带接入服务器(Broadband Remote Access Server,BRAS)提供接入控制、认证、动态分配IP地址等功能。
企业接入
所有主机不用安装PPPoE Client拨号软件,同一个局域网中的所有主机共享一个账号,通过企业路由器与运营商的集中路由器建立PPPoE会话。
PPPoE利用以太网将大量主机组成网络,通过一个远端接入设备连入因特网,具有适用范围广、安全性高、计费方便的特点。
1.1、PPPoE拨号的三个阶段 PPPoE拨号可分为三个阶段,即Discovery阶段、Session阶段和Terminate阶段。
1、discovery发现阶段
发现阶段是无状态的,目的是获得 PPPoE终结端(在局端的ADSL设备上)的以太网MAC地址,并建立一个惟一的PPPoESESSION-ID。发现阶段结束后,就进入标准的PPP会话阶段。
主机可以发现多个接入集中器,然后允许用户选择一个。
2、PPP Session会话阶段
当PPPoE进入session阶段后,PPP报文就可以作为PPPoE帧的净荷封装在以太网帧发到对端,SESSION_ID必须是Discovery阶段的确定的ID,MAC地址必须是对端的MAC地址。
进行普通的LCP、NCP、IPCP协商来进行PPP验证和IP地址分配。
3、Terminate阶段
PPP通信双方可以使用PPP协议自身来结束PPPoE会话,当无法使用PPP协议结束会话时可以使用PADT(PPPoE Active Discovery Terminate)报文。
进入PPPoE Session阶段后,PPPoE Client和PPPoE Server都可以通过发送PADT报文的方式来结束PPPoE连接。PADT数据包可以在会话建立以后的任意时刻单播发送。在发送或接收到PADT后,就不允许再使用该会话发送PPP流量了。
1.2、PPPoE报文格式 字段长度含义Destination_Address48bits以太网单播目的地址或者以太网广播地址(0xFFFFFFFF)。Source_Address48bits源设备的以太网MAC地址。Ethernet_Type16bits表示PPPoE拨号的阶段。•当值为0x8863时表示Discovery阶段或Terminate阶段。•当值为0x8864时表示Session阶段。VER4bits表示PPPoE版本号,值为0x01。Type4bits表示PPPoE类型,值为0x01。Code8bits表示PPPoE报文类型。Session_ID16bits用于唯一标识一个PPP Session,在discovery发现阶段被定义。值0xFFFF为将来的使用保留,不允许使用。Length16bits表示PPPoE报文的Payload长度。它不包括以太网头部和PPPoE头部的长度。Tag_Type16bits表示网络字节序。Tag_Length16bits是一个网络字节序的无符号值,表示Tag_Value的字节数。Tag_Valus可变Tag_Value的数据。Checksum16bits表示校验和字段,用于检验报文的正确性。 Destination_Address目标地址:
Discovery会话阶段,该域的值是单播或者广播地址,PPPoE Client寻找PPPoE Server的过程使用广播地址,确认PPPoE Server后使用单播地址。PPP Session会话阶段,该域必须是Discovery阶段已确定的通信对方的单播地址。 Code表示PPPoE报文类型:
Code域为0x09,表示PADI报文。Code域为0x07,表示PADO报文。Code域为0x19,表示PADR报文。Code域为0x65,表示PADS报文。Code域为0x00,表示会话数据。Code域为0xa7,表示PADT报文。 1.3、PPPoE协商过程 1.3.1、discovery发现阶段: 1、PPPoE Client广播发送一个PADI(PPPoE Active Discovery Initial)报文,在此报文中包含PPPoE Client想要得到的服务类型信息。
PPPoE 头部:分组的目的地址为以太网的广播地址0×ffffffffffff,CODE(代码)字段值为0×09,SESSION-ID(会话ID)字段值为0×0000。
EL1007E: Property or field 'yyyy' cannot be found on null
There is no nutrition in the blog content. After reading it, you will not only suffer from malnutrition, but also impotence.
The blog content is all parallel goods. Those who are worried about being cheated should leave quickly.
Springboot项目前端的 thymleaf 会报这样的错 EL1007E: Property or field ‘yyyy’ cannot be found on null
因为
后台传到前端的对象里没有YYYY属性
前端取属性YYYY的名字写错了,所以取值不到
解决方案
修改正确或者增加一个为空的判断:${wfsm?.id}
Viterbi译码由美国科学家Viterbi在1967年提出1,是卷积码的译码算法,是一种最大似然译码算法,其通过寻找距离最短的译码路径来实现。这篇文章侧重实现,具体原理就不说明了。
matlab实现Viterbi译码 卷积码 Viterbi译码是卷积码的译码方式,因此首先给出卷积码的matlab实现方式。
trellis= poly2trellis(7, [171 133]); codeData = convenc(bits,trellis); matlab官方给出的示例是:
trellis = poly2trellis(ConstraintLength,CodeGenerator) bits是编码前的数据。
poly2trellis生成一个结构体,其输入为(卷积码的级数,多项式的表达式)。如这个代码中卷积码的级数为7,多项式的表达式有两个,是八进制的表示,代表对应位置的抽头,如171位1111001,代表7级的数据是否要用于多项式的计算。
输出的值包含五个:
numInputSymbols: 输入状态数,输入bit^2
numOutputSymbols:输出状态数,输出bit^2
numStates:寄存器状态数,(级数-1)^2
nextStates:由当前状态和输入决定下一个状态
outputs:由当前状态和输入决定的输出
如代码中的卷积码:
numInputSymbols:2
numOutputSymbols:4
numStates:64
nextStates:64 * 2的数组
outputs:64 * 2的数组
viterbi译码 decodeData = vitdec(codeData ,trellis,42,'trunc','hard'); matlab官方给出的示例是:
decodedout = vitdec(codedin,trellis,tbdepth,opmode,dectype) codedin:编码后的数据
trellis:前面poly2trellis生成的值
tbdepth:traceback depth,回溯深度
matlab官方对tbdepth给出的说明:As a general estimate, a typical traceback depth value is approximately two to three times (ConstraintLength – 1) / (1 – coderate). A rate 1/2 code has a traceback depth of 5(ConstraintLength – 1)… 即典型的回溯深度一般为(卷积码的级数-1)/(1-码率),码率即为输入和输出的比例,对于本文的卷积码,一个输入二个输出,所以码率为1/2,即5*(7-1)是合理的值,即为30,这个值取大取小一点也没关系,这里取了42。
一、下载JDK1.8安装包 大家可以在官网下载JDK1.8安装包,我下载的是jdk-8u45-windows-x64.exe
二、安装JDK1.8 1、点击exe安装包
2、点击下一步,在这一步点击更改修改路径
注意:为了方便安装建议大家在自己的安装目录新建下面样式的文件目录
3、点击下一步,进行安装,安装过程时间比较久,需要一段时间。
4、在安装过程中会弹出一个框(这是安装到JRE的文件夹中的包,细心的你会发现,其实在JDK文件夹里已经有一个和这个JRE一模一样的包,我们把这个安装到刚才新建目录的jre目录就行)
5、修改完目录之后,点击下一步,进行安装
6、安装完成
三、配置环境变量 1、右击此电脑,选择属性
2、选择高级系统设置
3、选择环境变量
注意:大家也可以在Windows11的搜索框搜索“环境变量”,选择编辑系统环境变量 4、在系统变量中点击新建
5、新建 JAVA_HOME 变量,然后点击确定
变量名: JAVA_HOME 变量值: C:\softwore\JDK\jdk 注意:找到之前下载的JDK安装文件夹下的bin目录,复制其路径,但是路径不带bin 6、找到系统变量下的Path变量, 点击编辑,再点击新建一个path变量内的值
7、点击新建,将'' %JAVA_HOME%\bin " 和 " ;%JAVA_HOME%\jre\bin "分别复制到Path变量的两个新建项下,注意,第二个前面一定要带分号。
%JAVA_HOME%\bin ;%JAVA_HOME%\jre\bin 8、添加环境变量后,将所有窗口点击“确定”关闭,一定要点击确定,一个一个关闭所有窗口
四、验证JDK是否安装成功 1、win+R 打开dos命令窗口,输入cmd,点击确定(回车)
2、输入 javac
3、 输入java -version (注:java 和 - 有空行)
4、这样就安装成功了。
基于合作项目需要maptalks需要使用minemap地图资源,找到插件maptalks.minedata
https://github.com/sakitam-gis/maptalks.minedata
踩了将近一天坑最终成功引入,插件官方给出的文件注意把minemap.js和minemap.css的版本升级到2.1.0即可。其他按照官方说明执行
第一种:手动添加依赖的jar包 点击File→Project Structure→Modules→点右上角的+ 选第一个JARS or directories
然后就是让你选没依赖进去的jar包,提前把所需要的jar包放入一个文件夹里边然后再选中,就可以把jar添加进去了。
第二种:修改pom文件,不用maven仓库中的jar包,改用自己指定的jar包 需要加入一个你所需要jar包的一个本地绝对路径
要在<dependency>中添加以下两个属性
<scope>system</scope>
<systemPath>E:/frjar/fr-platform-9.0.jar</systemPath>
这个路径的文件夹中只需要放jar包
我们首先来看具体的报错:
java.lang.NoSuchMethodException org.springframework.data.domain.PageRequest.init()
at java.lang.Class.getConstructor0(Class.java3082)
at java.lang.Class.getDeclaredConstructor(Class.java2178)
at org.springframework.web.method.annotation.ModelAttributeMethodProcessor.createAttribute(ModelAttributeMethodProcessor.java216)
at org.springframework.web.servlet.mvc.method.annotation.ServletModelAttributeMethodProcessor.createAttribute(ServletModelAttributeMethodProcessor.java85)
at org.springframework.web.method.annotation.ModelAttributeMethodProcessor.resolveArgument(ModelAttributeMethodProcessor.java139)
at org.springframework.web.method.support.HandlerMethodArgumentResolverComposite.resolveArgument(HandlerMethodArgumentResolverComposite.java121)
at org.springframework.web.method.support.InvocableHandlerMethod.getMethodArgumentValues(InvocableHandlerMethod.java167)
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java134)
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java105)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java879)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java793)
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java87)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java1040)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java943)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java1006)
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java898)
at javax.servlet.http.HttpServlet.service(HttpServlet.java634)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java883)
at javax.servlet.http.HttpServlet.service(HttpServlet.java741)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java231)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java166)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java53)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java166)
at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java100)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java119)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java166)
at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java93)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java119)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java166)
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java201)
1:打开idea,找到File>settings
2:找到pulgins>Marketplace,点击下载就好了
3:在最右侧,就能找到你的chatgpt了
1.LED 硬件控制方式
对于 ALPHA/Mini I.MX6U 开发板出厂系统来说,此 LED 设备使用的是 Linux 内核标准 LED 驱动框架注册而成,在/dev 目录下并没有其对应的设备节点,其实现使用 sysfs 方式控制。 进入到/sys/class/leds 目录下,系统中的所有设备根据其功能分类组织到了/sys/class 目录下,所以/sys/class/leds 目录下便存放了所有的 LED 类设备。 进入到该目录下,brightness、max_brightness 以及 trigger 三个文件都是 LED 设备的属性文件: echo timer > trigger //将 LED 触发模式设置为 timer echo none > trigger //将 LED 触发模式设置为 none echo 1 > brightness //点亮 LED echo 0 > brightness// 熄灭 LED 除了使用 echo 或 cat 命令之后,同样我们编写应用程序,使用 write() 、 read() 函数对这些属性文件进行 I/O 操作以达到控制 LED 的效果。 Tips:命令 cat 读取以及 echo 写入到属性文件中的均是 字符串 ,所以如果在应用程序中通过 write()向属性文件写入数据,同样也要是字符串形式;同理,使用 read()读取的数据也是字符串 ASCII 编码的。 2.
消费与我们息息相关,我们在日常的生活中也常听到「新消费」的名词。但到底什么是新消费?它跟旧消费有哪些区别呢?
要回答这些问题,需要先讲什么是消费,再答新在哪里。
01
什么是消费?
1.消费是我们满足需求购买商品的行为。核心有两点,一是满足需求,有需求才有消费的动力。二是价值交换,用钱或等价物交易商品的过程。
2.消费的前提是分工,各有所长,各取所需。每个人付出自己的时间和能力交换别人付出的时间和能力。这其中的媒介是钱,解决交易的效率问题。
3.一切皆可消费,商品可以是实物、服务或虚拟物。衣食住行、吃喝玩乐、生老病死等。
4.消费不是一个瞬间的动作,需要一套流程,广义的说有6个环节:需求确认、信息获取、购买决策、购买行动、消费过程和售后服务。
5.消费得先识别自己的需求和欲望,确定需要购买的商品或服务。然后获取信息,了解对比商品的优势、品牌,基于自己的预算做出的评估决策,下单支付、收货使用、问题反馈。
6.消费第一步的需求确认在当今物欲的社会下很明确,我们都存在天然的对衣食住行的品质、性价比的需求,区别是需求的迫切程度。
7.消费存在冲动,冲动的核心是流程合并,即需求的迫切程度被商家利用。小红书的种草社区是在信息获取时帮助用户做出购买决策,进而引导消费行为。直播带货是更后一步,用价格刺激购买的行动,直接简化掉信息获取和对比。
8.消费站在商家的角度来看,就是用商品把用户的钱换出来,仅此而已(当然也有企业内部的选品、生产、存储、渠道、促销等环节)。
9.简化的消费流程是「人货场」,是我们在什么场合考虑买哪些商品。在实际执行过程中,往往是存二找一,比如美柚、亲宝宝是有了「人场」后准备相应的「货」。
10.消费是固定存在的需求,并由消费推演出商业形态。区别是满足需求的方式/商品在不断变化,由此是新消费出现的前提。
02
什么是新消费?
11.新消费是一个广泛概念,消费的核心是人货场,那么新消费就是找到了新的人、新的货、新的场。
12.新消费的定义并不严格,只要人货场有一个要素的变化,即可称为新消费。比如小红书的内容「场」成了很多品牌的崛起源头
13.新消费的出现是因为变化,比如科技进步、消费升级和社会变革,由此不断涌现出的新的消费模式、消费方式、消费场景和消费需求。
14.新的消费者在追求品质、个性、健康等,比如抗糖、0脂,这些是对传统消费模式和产品提出新的要求和期待,推动着消费市场的创新和升级。
15.新的消费场景是渠道变化,比如社区团购、直播带货,我们不再局限于线上线下的货架电商,而是随着技术和交互形式的创新,在新的「场」实现购物。
16.新消费的表现形式有很多,社交电商、共享经济、无人零售、智能家居等新的消费体验等都是新消费。
17.新的消费带来了很多创业机会。借助于C2B+代工的生产方式,让创业者能够基于需求生产,实现了0库存和积压,大大降低了试错成本。
18.新消费跑出的企业一般为新公司。在巨头环伺的压力下,创业者有动力和意愿去探索新的「场」。巨头一般不关注、看不上细微之处的渠道变化。
19.这些商品更契合新时代消费者的调性和品位,由此才能完成种草的消费决策和拔草消费的购买行动。或者说,新消费是用户和商家共同完成的问题解决方案。
20.回归到人货场,对新消费更重要的是「场」,即消费需求和意愿固定存在,需要在新的「场」内完成新品的品宣和销售。当渠道发生变化的时候,也是商业格局的变化,消费市场迎来了创新和升级。
03
如何做新消费
21.定位到一个需求没有很好被满足的市场。可能是生产工艺的陈旧,可能是供应链体系的繁杂等等。未被满足的市场才能用新品超出预期,给消费者一个更换选择的理由。比如小罐茶,在非标的市场中打造品质标品,降低选择成本。
22.定位到一群有新诉求的消费者。我们消费意识和生活习惯在不断变化,由此带来的是需求市场的变化。比如奶茶店是哪些商品的升级版本呢?是瓶装的可乐冰红茶。
23.定位到一个正在起量的触达渠道,新渠道代表着低成本和弱竞争。先成为一个小部分人喜欢的商品,完成企业的冷启动和存续。在跑完模型后,跟随渠道的增长成为一个有影响力的消费企业。
24.苦练行业基本功是生存的长久之道。借助轻巧的市场定位和营销活动,能带来企业的快速增长,但新消费要直面巨头的竞争,就是人力、储备、后勤的综合较量。比如元气森林已经开始深耕经销商渠道了。
25.保持初心,服务消费者的初心。
注:题图来自早春的起云台。
欢迎关注公众号
持续输出深度思考的干货文章
↓↓↓↓↓↓
一、下载方式一: MySQL :: Download MySQL Community Server
或者到我的百度网盘中下载---- 链接:https://pan.baidu.com/s/1hZvfZw4S4TqF7XOFu_2ekg?pwd=ziuu 提取码:ziuu --来自百度网盘超级会员V6的分享
下载方式2---或者使用 -- wget 命令下载也是可以的! 4)、下载mysql8.0安装包--- 但是此命令 在哪个目录中执行此命令下载的包就在哪里
wget https://dev.mysql.com/get/Downloads/MySQL-8.0/mysql-8.0.30-linux-glibc2.12-x86_64.tar.xz 下载好后---开始安装步骤:---
先关闭防火墙
临时关闭防火墙 service iptables stop 临时开启防火墙 service iptables start 永久关闭防火墙 chkconfig iptables off 永久开启防火墙 chkconfig iptables on 或者下面命令 ~~~~ 1、systemctl status firewalld.service 查看防火墙状态 2、systemctl stop firewalld.service 进行关闭防火墙 3. systemctl disable firewalld.service 永久防火墙 4、systemctl status firewalld.service 查看防火墙状态 为("disavtive(dead)") 1)、切换到 /use/local下
cd /use/local 2)、创建mysql文件夹
mkdir mysql 3).把下载好的mysql-8.0.30-linux-glibc2.12-x86_64.tar.xz 放到/usr/local/mysql目录中
4)、解压mysql8.0安装包 -- 切换到 /use/local/mysql文件夹下面,执行命令
最近有考研的打算,准备考研科目,先是数据结构部分。习题如下:
1.设计两个集合A和B,设计生成集合C=A并B的算法,集合A、B和C均用数组存储
算法思想描述
算法思想算是暴力找,让a中所有元素一个一个与b中元素作比较
算法代码描述如下:
void HBLinklist(Sqlist A[], Sqlist B[] ,Sqlist C[]){ int k =0; for(int i = 0; i < A.len; i++){ for(int j = 0; j < B.len; i++){ if(A.data[i] == B.data[j]){ C.data[k] = A.data[i]; k++; C.len++; } } } for(int h = 0; h < C.len; h++){ printf("%d",C.data[h]) } } 2.给定一个由n(n>1)个不同整数组成的升序序列,同时包含负数和正数,设计一个在时间和空间两方面都尽量高效的算法,求序列中绝对值最小的数,如序列{-8, -3, -1, 4, 5}中绝对值最小的数为-1
算法思想描述
利用二分法找到0元素的点或者0最近点,附近绝对值最小
算法代码描述如下:
void Minvalue(int a[],int n){ int high = n-1; int weight = 0; int mid; while(weight<high){ mid = (high + weight)/2;//利用二分法求0元素位置或者0最近位置 if(a[mid]>=0){ weight = mid; } else{ high = mid+1; } } if(abs(a[weight]) < abs(a[weight-1]))//abs绝对值意思 printf("
预览 具体错误如上图所示。
分析 原因为游戏打包后没有提供给这行代码的依赖库,应该是在开发中不会运行出错,但到了玩家端就会出错,所以VS才报错。
解决方案 加上预处理指令就行了。
#if UNITY_EDITOR //刷新资源 AssetDatabase.Refresh(); #endif 预处理指令的作用是区分使用场景,这里就不展开介绍,有兴趣的可以自己去搜搜看。
结语 这是我很久之前就遇到过的问题,当时百度搜了很久都没找到相应的解答,有可能是我找错了方向,也有可能是这个问题太基础了,没人有兴趣解答。这我正好最近发现了这个错误的解决办法,也是了掉困惑自己已久的问题。以前自己解决不了的问题,由现在拥有更多知识的自己轻松解决,感觉非常奇妙,我想这才是学习最大的乐趣,解决问题,当然分享也是。
文章目录 多表查询分类连接查询-内连接连接查询-外连接连接查询-自连接联合查询-union,union all 子查询标量子查询列子查询行子查询表子查询可以使用 DISTINCT 关键字对查询结果进行去重。 多表关系(总结)多表查询(总结) 在实际的开发中,多表查询是非常常见的需求之一。SQL的多表查询语句能够实现多张表之间的关联查询,使用起来非常灵活。而子查询则是SQL中极为重要的一种查询方式,可以将子查询的结果作为另一个查询的条件或结果进行操作。本文将详细介绍SQL中的多表查询语句和子查询,包括内连接查询、外连接查询、自连接查询以及不同类型的子查询,帮助读者更好地掌握SQL的查询语法。
在多表查询方面,本文将介绍多种常见的查询方式,包括隐式内连接、显示内连接、左外连接、右外连接、自连接等。每种查询方式都会配有详细的语法和演示案例,帮助读者更好地理解和掌握。在子查询方面,本文将详细介绍标量子查询、列子查询、行子查询、表子查询等多种类型的子查询,以及它们的使用场景和语法规则。
无论是在日常开发中的查询需求,还是在SQL的学习和使用中,多表查询和子查询都是非常基础且重要的内容。本文旨在通过详细的介绍和案例演示,帮助读者更好地理解和掌握SQL的多表查询语句和子查询,提高SQL的查询能力和应用水平。
多表查询分类 连接查询 内连接:相当于查询A、B交集部分数据外连接: 左外连接:查询左表所有数据,以及两张表交集部分数据。右外连接:查询右表所有数据,以及两张表交集部分数据。 自连接:当前表与自身的连接查询,自连接必须使用表别名 子查询
连接查询-内连接 内连接的查询语法(内连接查询的是两张表的交集部分):
隐式内连接
SELECT 字段列表 FROM 表1,表2 WHERE 条件 ...; 显示内连接
SELECT 字段列表 FROM 表1 [INNER] JOIN 表2 ON 连接条件 ...; 内连接演示
查询每一个员工的姓名,以及关联的部门名称(隐式内连接实现)表结构:emp , dept连接条件:emp.dept_id = dept.id select emp.name,dept.name from emp , dept where emp.dept_id = dept.id; 查询每一个员工的姓名,以及关联的部门名称(显式内连接实现)表结构:emp , dept连接条件:emp.dept_id = dept.id select e.name,d.name from emp e inner join dept d on e.dept_id = d.
Python JS逆向篇(三) 逆向z参数js实现py实现实战接口1接口2 逆向主题:解析出网址里视频下的m3u8链接。
(注:文章所涉及内容只做学习参考交流,不做除此之外的任何其它用途!!!)
新手入门级
参考B站视频系列教程: https://www.bilibili.com/video/BV1yW4y1E7Ug
主打的就是一个白嫖。
使用Base64加密!!!
接口1(逆向m3u8接口):aHR0cHM6Ly9pbTE5MDcudG9wLz9qeD1odHRwczovL3d3dy5iaWxpYmlsaS5jb20vYmFuZ3VtaS9wbGF5L2VwMzI5MTQz
接口2(推荐,我经常使用,m3u8接口无加密):aHR0cHM6Ly9qeC5wbGF5ZXJqeS5jb20vP3VybD1odHRwczovL3d3dy5iaWxpYmlsaS5jb20vYmFuZ3VtaS9wbGF5L2VwMzI5MTQz
**xxx.脱敏.xxx,自己去构建url,headers。**
逆向z参数 首先,进去之后直接F12打开抓包工具,Never pause here过掉debugger。
Ctrl+R刷新一下,找到如上图的包,然后如下图所示,直接跟进去。
Ctrl+F搜索关键字s1ig(注意:不要搜索z参数),定位到关键字发现框中这一块都是和进行请求携带的参数相关,所以在这里开始进一步调试。
一步一步调试发现(或者直接从结果看(经验)去百度上搜索 在线md5加密 进行对比),就是用md5进行加密的,里面的It()方法就是调用md5方式加密,所以这个加密参数z就ok了,o 就是解析视频的url。后面的g就是字符串拼接操作。
js实现 js md5加密算法直接网上去找。
function md5(md5str) { var createMD5String = function(string) { var x = Array() var k, AA, BB, CC, DD, a, b, c, d var S11 = 7, S12 = 12, S13 = 17, S14 = 22 var S21 = 5, S22 = 9, S23 = 14, S24 = 20 var S31 = 4, S32 = 11, S33 = 16, S34 = 23 var S41 = 6, S42 = 10, S43 = 15, S44 = 21 string = uTF8Encode(string) x = convertToWordArray(string) a = 0x67452301 b = 0xEFCDAB89 c = 0x98BADCFE d = 0x10325476 for (k = 0; k < x.
ERROR Failed to get response from https://registry.npmmirror.com/vue-cli-version-marker Vue CLI v5.0.8 Failed to check for updates ? Target directory F:\yueya\Vue_projects\vue3_test already exists. Pick an action: Overwrite Removing F:\yueya\Vue_projects\vue3_test... Vue CLI v5.0.8 Failed to check for updates ? Please pick a preset: Default ([Vue 3] babel, eslint) Vue CLI v5.0.8 Failed to check for updates ✨ Creating project in F:\yueya\Vue_projects\vue3_test. ⚙️ Installing CLI plugins. This might take a while... ERROR Failed to get response from https://registry.
AXI GPIO按键控制LED 上文中是通过EMIO实现PS端与PL端的交互,而PS与PL最主要的连接方式则是由一组AXI接口。AXI 互联接口作为 ZYNQ PS 和 PL 之间的桥梁,能够使两者协同工作,进而形成一个完整的、高度集成的系统。
简介 AXI GPIO IP 核为 AXI 接口提供了一个通用的输入/输出接口。与 PS 端的 GPIO 不同,AXI GPIO 是一个软核(Soft IP),即 ZYNQ 芯片在出厂时并不存在这样的一个硬件电路,而是由用户通过配置 PL 端的逻辑资源来实现的一个功能模块。而 PS 端的 GPIO 是一个硬核(Hard IP),它是一个生产时在硅片中实现的功能电路。AXI GPIO 可以配置成单通道或者双通道,每个通道的位宽可以单独设置。另外通过打开或者关闭三态缓冲器,AXI GPIO 的端口还可以被动态地配置成输入或者输出接口。其顶层模块的框图如下所示:
从上图可以看到,模块的左侧实现了一个 32 位的 AXI4-Lite 从接口,用于主机访问 AXI GPIO 内部各通道的寄存器。当右侧接口输入的信号发生变化时,模块还能向主机产生中断信号。不过只有在配置IP 核时选择“使能中断”,才会启用模块的中断控制功能。
Block Design介绍 ZYNQ7ProcessingSystem中一些接口信号是用于PS使用AXI接口与PL端进行通信是所需要的信号。
M_AXI_GP0是通用(General Purpose)AXI接口,它包含了一组信号。首字母 M 表示 PS 作为主机(Master),PL 中的外设作为从机(Slave).而左侧的M_AXI_GP0_ACLK 是这个接口的全局时钟信号,它是一个输入信号,M_AXI_GP0 接口的所有信号都是在这个全局时钟的上升沿采样的。FCLK_CLK0是 PS 输出的时钟信号,它将作为 PL 中外设模块的时钟源。这个时钟由 PS 中的 IO PLL产生,频率范围可以从 0.1 到 250MHz,在配置 ZYNQ7 PS 的时候,该时钟默认为 50MHz。FCLK_RESET0_N 是由 PS 输出到 PL 的全局复位信号,低电平有效。IRQ_F2P[0:0]是由 PL 输出到 PS 的中断信号。
1. View
View的子类及子类的子类都有View的属性,都可以设置下述介绍的属性。
2.View宽高
View及其派生类的宽高共有三类值:
match_parent:匹配父控件的宽高
wrap_content: 匹配内容的长度,例如TextView是包裹文字
fixed number: 用数字直接赋固定值,单位为dp
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <TextView android:id="@+id/tv" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="use wrap_content" android:textSize="30sp" android:textColor="@color/white" android:background="#0000ff" android:layout_marginTop="10dp" /> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:text="use match_parent" android:textSize="30sp" android:textColor="@color/white" android:background="#00ff00" android:layout_marginTop="10dp" /> <TextView android:layout_width="300dp" android:layout_height="50dp" android:text="use fixed length" android:textSize="30sp" android:textColor="@color/white" android:background="#550000" android:layout_marginTop="10dp" /> </LinearLayout> 预览界面:
上述是直接在xml文件中设置View宽高,也可以在java文件中设置,需要注意的是此时默认单位为px
package com.example.study; import androidx.appcompat.app.AppCompatActivity; import android.app.ActionBar; import android.graphics.Color; import android.os.Bundle; import android.view.ViewGroup; import android.widget.TextView; public class MainActivity2 extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.
Docker安装 1.卸载旧版本 sudo yum remove docker docker-common docker-selinux docker-engine 2.安装需要的软件包 sudo yum install -y yum-utils device-mapper-persistent-data lvm2 3.建议设置:配置yum 阿里源 sudo yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo 4.安装 docker-ce 安装最新版本
sudo yum install docker-ce docker-ce-cli containerd.io 安装指定版本
sudo yum install docker-ce-{对应版本号} 我这里选择安装的是最新版本:
5.修改网段,避免网络冲突(个人学习,可跳过这一步) sudo vim /etc/docker/daemon.json 添加以下内容:
{ # 网段与宿主机不在同一网段即可 “bip”: “192.168.0.1/16” } 6.启动docker并设置开机自动启动 启动docker
sudo systemctl start docker 停止docker
sudo systemctl stop docker 重启docker
sudo systemctl restart docker 查看状态docker
sudo systemctl status docker 设置docker开机自启动
估计是qt designer的bug,qt designer stylesheet 设置字体加粗无效。
解决办法是在右侧的属性窗口对字体进行加粗设置,注意需要将stylesheet里面对字体的加粗设置删除。
现象和原因: openssh升级新版本后,旧的算法不再支持,导致CRT工具远程连接的时候连接不上 (旧的客户端不能连接新的服务端) 解决办法: 在ssh服务端配置添加配置如下: #添加支持的加密算法 KexAlgorithms diffie-hellman-group1-sha1,diffie-hellman-group14-sha1,diffie-hellman-group-exchange-sha1,diffie-hellman-group-exchange-sha256,ecdh-sha2-nistp256,ecdh-sha2-nistp384,ecdh-sha2-nistp521,diffie-hellman-group1-sha1,curve25519-sha256@libssh.org #添加ssh-rsa算法 HostKeyAlgorithms +ssh-rsa https://www.openssh.com/txt/release-8.8
http://www.openssh.com/releasenotes.html#9.0
参考:
ssh连接不上解决_aiqing0119的博客-CSDN博客_kexalgorithms
针对使用密钥方式登录服务器的升级步骤总结如下:
支持密钥+密码方式访问 ----------------------------------------------------------- #备份现有的配置文件和权限文件 cp -rp /etc/ssh /etc/ssh_backup cp -rp /etc/pam.d/sshd /etc/pam.d/sshd_backup #上传升级包到服务器进行解压,切换到解压后的目录 cd openssh9.0p1 #关闭selinux,需要修改/etc/selinux/config disabled setenforce 0 #升级安装 yum localinstall -y ./openssh*.rpm #给文件授权 chmod 400 /etc/ssh/ssh_host_* #检查配置文件中是否开启允许root远程登录和密码登录,没有开启执行以下两句 echo 'PermitRootLogin yes' >> /etc/ssh/sshd_config echo 'PasswordAuthentication yes' >> /etc/ssh/sshd_config #修改配置 vim /etc/ssh/ssh_config Host * PubkeyAcceptedKeyTypes=+ssh-rsa vim /etc/ssh/sshd_config HostKey /etc/ssh/ssh_host_rsa_key HostKey /etc/ssh/ssh_host_ecdsa_key HostKey /etc/ssh/ssh_host_ed25519_key StrictModes no PubkeyAuthentication yes AuthorizedKeysFile .
目录 一、简介二、环境准备常用使用方法 一、简介 现如今APP隐私合规十分重要,各监管部门不断开展APP专项治理工作及核查通报,不合规的APP通知整改或直接下架。camille可以hook住Android敏感接口,检测是否第三方SDK调用。根据隐私合规的场景,辅助检查是否符合隐私合规标准。
二、环境准备 1、前提条件
PC端安装python3环境
模拟器(开启root)—比如雷电模拟器
2、PC端安装frida-tools和frida
pip3 install frida-tools
pip3 install frida
安装完成后,查看frida版本
3、PC端安装Camille
git clone https://github.com/zhengjim/camille.git cd camille pip install -r requirements.txt python camille.py -h 4、手机端安装frida-server
下载frida-server-16.0.10-android-x86.xz 解压后改名为frida-server(注意frida-server版本需要和PC端安装的frida版本一致)
打开模拟器,并使用adb进行连接
推送frida-server到android系统/data/local/tmp目录下
adb.exe push frida-server /data/local/tmp
赋予frida-server可执行权限,并后台运行
adb.exe shell cd /data/local/tmp chmod 755 /data/local/tmp/frida-server /data/local/tmp/frida-server & 5、运行Camille
python camille.py com.xxx.xxx(com.xxx.xxx为包名)
常用使用方法 1、输出堆栈信息文件
python camille.py com.xxx.xxx -ns -f test.xls
-ns:不显示日志,默认显示。
-f:保存app行为轨迹(堆栈信息)到execl里,默认不保存。
2、指定设备
python camille.py com.xxx.xxx -s 127.0.0.1:5555
-s:指定连接设备,可通过 adb devices 获取设备 id
一、UNIX域套接字 UNIX域套接字作用在同一台计算机上运行的两个进程间的通信。UNIX域套接字比因特尔网络套接字效率要高。它仅复制数据,不执行协议处理,不需要添加或删除网络报文头,无需计算校验和,不要产生顺序号,无需发送确认报文等等。UNIX域套接字有两种类型的套接字:字节流套接字和数据报套接字,字节流套接字类似于TCP,数据报套接字类似于UDPUNIX域套接字连接的一对套接字可以起到全双工管道的作用,是全双工的通信方式。 二、数据结构 2.1 unix域套接字的地址结构 struct sockaddr_un { sa_family_t sun_family; /* AF_UNIX 或 AF_LOCAL */ char sun_path[108]; /* pathname */ } sun_path是一个路径名,此路径名的属性为0777,可以进行读写等操作这个路径名应该是一个绝对路径名,而不是一个相对路径名。因为解析相对路径名依赖调用者当前工作目录,如果使用使用相对路径名就必须要确保服务器与客户端程序运行在相同目录下,否则将会出现异常除了普通路径名外,还可以使用抽象路径名。好处是不用担心出现文件已存在情况,同时程序结束,也会自动删除这个抽象名。但是,在计算抽象路径名长度的时候要注意。 2.2 创建套接字 /* 功能:socket的创建 参数: domain:AF_UNIX 或 AF_LOCAL type:套接字类型:字节流套接字(SOCK_STREAM)与数据报套接字(SOCK_DGRAM) protocol:如果第二参数不是SOCK_RAM原始套接字类型,一般设为0 返回值:成功返回文件描述符,失败返回 -1 */ #include <sys/types.h> #include <sys/socket.h> int socket(int domain,int type,int protocol); 2.3 地址绑定 /* 功能:在UNIX域socket中bind函数不是用来绑定IP和端口,而是绑定一个有效路径名 参数: sockfd:socket函数返回的文件描述符 addr:套接字的地址结构,sockaddr_un类型 addrlen:地址长度 返回值:成功放回 0,失败返回 -1 */ #include <sys/types.h> #include <sys/socket.h> int bind(int sockfd,const struct sockaddr *addr,socklen_t addrlen); 2.4 其它API函数 #include <sys/types.
目录 漏洞一、jolokia logback JNDI RCE搭建环境利用条件利用方法 漏洞二:jolokia Realm JNDI RCE利用条件利用方法 声明:本文仅供学习参考,其中涉及的一切资源均来源于网络,请勿用于任何非法行为,否则您将自行承担相应后果,本人不承担任何法律及连带责任。
漏洞一、jolokia logback JNDI RCE 搭建环境 漏洞环境为:
https://github.com/LandGrey/SpringBootVulExploit/tree/master/repository/springboot-jolokia-logback-rce
IDEA加载源码,并配置一个Spring boot,就可以运行环境了
环境运行起来后,访问一下/jolokia接口
利用条件 目标网站存在 /jolokia 或 /actuator/jolokia 接口
目标使用了 jolokia-core 依赖(版本要求暂未知)并且环境中存在相关 MBean
目标可以请求攻击者的 HTTP 服务器(请求可出外网)
普通 JNDI 注入受目标 JDK 版本影响,jdk < 6u201/7u191/8u182/11.0.1(LDAP),但相关环境可绕过
利用方法 1、查看已存在的 MBeans
访问 /jolokia/list 接口,查看是否存在 ch.qos.logback.classic.jmx.JMXConfigurator 和 reloadByURL 关键词
2、准备要执行的 Java 代码
编写用来验证漏洞存在的java代码(Evil.java)
public class Evil{ public Evil() throws Exception{ Runtime.getRuntime().exec("calc.exe"); } } 使用兼容低版本 jdk 的方式编译:
javac -source 1.
XSS挑战之旅 level 1level 2level 3level 4level 5level 6level 7level 8level 9level 10level 11level 12level 13 实验环境: 使用docker搭建靶场 实验步骤: level 1 观察页面发现导航栏中name的值为什么页面就显示什么
查看源码,发现写入的数据在<>标签的外面
直接将name的值换成JS:<script>alert(1)</script>
level 2 使用第一关的方法尝试发现发现没有弹窗弹出,查看网页源码,发现<>都被过滤掉了,但value里面没有过滤掉。
尝试闭合value的值,输入 "><script>alert(1)</script>成功弹出窗口。
level 3 尝试使用第二关的payload发现失败,查看源码,发现在value中也将”、<、>注释掉了
我们可以用一个单引号对value前面的单引号进行闭合,再用一个单引号对后面的单引号进行闭合,在value后加入onclick。输入此payload后,首先先将这条语句写入源码,再次点击输入框后进入下一关。
level 4 尝试输入第三关的payload,查看源码,发现这里使用的是双引号,所以这里我们将单引号改为双引号
同样的方法,代码执行成功
level 5 输入第四关的payload
发现它对onclick,onmouseover,script进行了加"_"的操作,尝试了大写也没有用,但<>这两符号能正常写入。
我们可以添加a标签的方法,然后点击链接就可以跳到下一关。
payload:”><a href=”javascript:alert(1)”></a>
level 6 输入上一关的payload查看源码
经试验后,它对script,onclick,href,onmouseover进行了加"_“操作,但对”<>做任何处理,而且能大写绕过,故这里可以运行许多payload。
payload:”ONLICK=”alert(1)
level 7 输入上一关的payload查看源码
经实验,它会把script,on,href直接过滤掉,这里因为它过滤掉了,我们就可以考虑它会过滤一次还是几次或是直到没有为止,这里就可以用双写href和script来绕过
level 8 输入上一关的payload,查看源码
用前几关的payload尝试后,发现转义了 " <>,所以不能使用script标签和a标签来做。但是我们发现第八关多出>了一个可以点击的“友情链接”,查看页面代码后,发现输入的内容会进入到已有的a标签中的href中。因>此我们不需要像以前一样闭合input标签,再添加a标签,我们可以直接输入javascript:alert(1)。
这里将script用实体编号绕过。也可以对script的一个字母进行实体编号。
javascript:alert(1)
level 9 使用上一关的payload,查看源码
与0x08有一个区别,就是检测你的网址中有没有http://,没有就直接报错,这是我们可以在0x08的payload的基础上附上http://即可
javascript:alert(1)//http://
level 10 使用上一关的payload,查看源码
因为没有输入口,只能从URL入手,参数keyword对输入的"><做了过滤,显然不能利用了。查看页面源码后发现有三个input标签是hidden的。我们尝试利用这三个标签完成攻击。与在输入框中输入代码类似,只是在url中需要指定标签name,且需要修改type属性为text使输入框显示出来
问题描述: 在终端中执行 npm run dev 时报错:
Error: error:0308010C:digital envelope routines::unsupported
问题原因: 因为 Node.js 版本是 17 以上所以会运行失败, Node.js 17 版本中最近发布的 OpenSSL3.0, 而OpenSSL3.0 对允许算法和密钥大小增加了严格的限制,可能会对生态系统造成一些影响.
解决办法: 修改package.json,增加
"devnew": "set NODE_OPTIONS=\"--openssl-legacy-provider\" & npm run dev\n"
在终端中执行 npm run devnew
问题描述: 在终端中执行 npm install 时报错:
Could not resolve dependency:
npm WARN peer eslint@">=1.6.0 <7.0.0" from eslint-loader@2.2.1
问题原因: npm 升级到 7.x以上后,会出现上游依赖冲突;–legacy-peer-deps:安装时忽略所有 peerDependencie,默认使用npm 4-6版本的安装模式,安装过程中是会跳过对等依赖项。
解决办法: 在终端执行 npm i --legacy-peer-deps
如标题,用HbuilderX将vue项目打包成apk比较简单,网上都是教程,这里贴一个参考地址,就不多赘述了。
点我,我是参考教程
这边我要记录一个小小的坑,很久之前打包的项目,再次打开后,manifest.json文件不展示视图了,全是代码形式,此时点开 ‘发行-原生App云打包’的选项被禁用,无法操作。
解决方案:在项目名称上右键-----重新识别项目类型,关闭manifest.json文件重新打开,点开‘发行’,就可以发行app啦。
FString 转 Int
int IntVal = FCString::Atoi(*StrVal); Int 转 FString:
FString StrVal = FString::FromInt(IntVal); FString 转 Float
float FloatVal = FCString::Atof(*StrVal); Float 转 FString
FString StrVal = FString::SanitizeFloat(FloatVal); FString To double
FCString::Atod(*StrVal); double To FString
FString StrVal = FString::Printf(TEXT("%.15f"), DoubleVal); FString 转 FText
FText TextVal = FText::FromString(StrVal); FText 转 FString
FString StrVal = TextVal.ToString(); FString 转 FName
FName NameVal = FName(*StrVal); FName 转 FString
FString StrVal = NameVal.ToString(); FString 转 std::string
龙芯机器:
[root@localhost j2sdk-image]# cat /proc/cpuinfo | grep name | cut -f2 -d: | uniq -c
4 Loongson-3A R4 (Loongson-3A4000) @ 1800MHz
龙芯机器JDK安装和配置 下载 地址:http://www.loongnix.cn/zh/api/java/
选择JDK8,选择MIPS64进行下载
安装 tar -zxvf loongson8.1.11-jdk8u332b09-linux-loongson3a.tar.gz
配置环境变量 export JAVA_HOME=/root/cg/j2sdk-image
export CLASSPATH=.:$JAVA_HOME/lib:$JRE_HOME/lib:$CLASSPATH
export PATH=$JAVA_HOME/bin:$PATH
查看JAVA_HOME [root@localhost j2sdk-image]# echo $JAVA_HOME
/root/cg/j2sdk-image
查看jdk版本 [root@localhost j2sdk-image]# java -version
openjdk version "1.8.0_332"
OpenJDK Runtime Environment (Loongson 8.1.11-loongson3a-Fedora) (build 1.8.0_332-b09)
OpenJDK 64-Bit Server VM (build 25.332-b09, mixed mode)
kubectl 命令 kubectl cluster-info #查看集群 kubectl version #查看集群版本 kubectl get pod -A #显示所有namespasce中的pod kubectl get service -A #显示所有service kubectl get pod #查看默认namespace中的pod kubectl get pod -o wide #查看pod及更多详细信息 -o json #以json格式输出 -o yaml #以yaml格式输出 kubectl get namespace #显示所有namespace kubectl get pod -n kube-system #查看namespace kube-system中的pod kubectl get nodes #查看所有集群节点 kubectl get node -o wide #查看集群节点及更多信息 kubectl describe node 10.0.0.43 #显示node详细信息 kubectl describe pod nginx-web1 -n default #查看pod详细信息 kubectl run nginx-web3 --image nginx #运行并创建pod kubectl exec -it nginx-web1 -n default bash #进入pod kubectl logs nginx-web1 -n default #查看pod运行日志 #创建资源 kubectl create -f namespace.
VSCode连接远程服务器Jupyter Notebook 文章目录 VSCode连接远程服务器Jupyter Notebook一、配置SSH连接远程服务器二、python环境安装配置jupyter1.安装jupyter notebook2.设置jupyter登录秘钥3.配置jupyter3.1 生成配置文件3.2 配置 4. 启动4.1 终端输入4.2 报错处理4.2.14.2.2 三、vscode安装jupyter插件四、运行连接参考链接:Tip: 提示:以下是本篇文章正文内容,下面案例可供参考
一、配置SSH连接远程服务器 使用ssh连接远程服务器,并在vscode打开终端。
二、python环境安装配置jupyter 1.安装jupyter notebook 这里我使用的是预先装好的conda环境。
conda activate pytorch1 pip安装jupyter
pip install jupyter 或者 conda install jupyter 推荐使用以下pip
源清华: https://pypi.tuna.tsinghua.edu.cin/simple
阿里云: https://mirrors.aliyun.com/pypi/simplel
显示安装成功。
2.设置jupyter登录秘钥 可以设置密码,也可以取消密钥验证,这步可跳过。
终端输入:
ipython 执行上述语句,输入密码,会生成对应密钥。
3.配置jupyter 3.1 生成配置文件 终端输入
jupyter notebook --generate-config 3.2 配置 配置文件生成后,控制台打印其位置,找到配置文件jupyter_notebook_config.py,然后在配置文件顶部添加如下设置。(或者直接定位对应配置项修改,注意删除注释符号’#')。
默认目录应该是这个:
vim ~/.jupyter/jupyter_notebook_config.py 如果需要秘钥验证的话需要将其中的秘钥选项设置为True。
c.NotebookApp.notebook_dir = '' # jupyter默认目录 c.NotebookApp.open_browser = False c.NotebookApp.port = 5050 c.NotebookApp.allow_remote_access = True c.
1.定时器@Scheduled简介 @Scheduled注解可以用于做定时任务,再方法上加上@Scheduled注解,可以将这个方法定义为一个任务发放,可以搭配cron表达式进行任务的控制。
开启定时任务时在类上加注解 @EnableScheduling
2.cron表达式的用法 1.按顺序依次为
秒 分 时 天 月 周 年 表达式长度为6个或者7个
cron表达式是一个字符串,分为6或7个域,每两个域之间用空格分隔,其语法格式为:
“秒域 分域 时域 日域 月域 周域 年域”
其中,年域可以省略,省略时表示每年。
1 秒(0~59)
2 分钟(0~59)
3 小时(0~23)
4 天(0~31)
5 月(0~11)
6 星期(1~7 1=SUN 或 SUN,MON,TUE,WED,THU,FRI,SAT)
7.年份(1970-2099)
2.一些符号的意义
(1)* 表示可以匹配该域的所有值;
例如,"0 0 13 * * ?"表示每天的13点执行一次。
(2)?在cron表达式中必须出现且只能出现1次,用在日域或周域上,表示不确定值、不限制值;
它与*的区别是,并不能匹配到该域上的所有值,例如指定了3月份每个周五,那么3月份的周五可能只有4个值;
例如,"0 0 5 6 * ?"表示每个月6日5点钟执行而无论周几,"0 0 5 ? * 3"表示每个周三5点钟执行而无论是几号。
(3)- 表示匹配该域上的一个范围;
例如,"0 30 9-15 ? * *"表示每天的9:30-15:30每小时执行一次,"0 1-5 * ?
在设置页面,bulid,execution,deployment---Build Tools---maven中修改默认配置:
这样再新建项目,打开新idea窗口就不用修改maven配置了
一:Assembler的来龙去脉
二:自定义一个渲染组件(使用自定义的assembler挂载)
一:Assembler的来龙去脉: 之前的文章中提到和使用过assembler相关的技术,但是现在看来还是理解的不是很到位,
1: 首先看看那assembler是如何绑定到渲染组件的,随便找到一个渲染组件,比如说老生常谈的Sprite组件 cocos2d/cocos-engine-2.4.8/cocos2d/core/renderer/webgl/assemblers/sprite/index.js
import Assembler from '../../../assembler'; import { Type, FillType } from '../../../../components/CCSprite'; import Simple from "./2d/simple"; import Sliced from "./2d/sliced"; import Tiled from "./2d/tiled"; import RadialFilled from "./2d/radial-filled"; import BarFilled from "./2d/bar-filled"; import Mesh from './2d/mesh'; import Simple3D from "./3d/simple"; import Sliced3D from "./3d/sliced"; import Tiled3D from "./3d/tiled"; import RadialFilled3D from "./3d/radial-filled"; import BarFilled3D from "./3d/bar-filled"; import Mesh3D from './3d/mesh'; let ctor = { getConstructor(sprite) { let is3DNode = sprite.
生活中充满红蓝药丸的选择,红色是真相,痛苦却现实,蓝色是假象,快乐而愚昧。就像电影《黑客帝国》,亲爱的读者,你肯定也会选择红药丸,勇敢探寻 CMake 依赖关系的真相。想了解其中的水有多深,请继续阅读!
任何复杂的软件都有其依赖关系,无论是系统API还是其他库调用,都是静态或动态进行连接。作为构建系统生成器,CMake 可以帮助我们以最自然的方式管理这些依赖关系。
案例1:开发人员处理标准软件的 CMake 依赖关系 开发人员会知道编译项目需要哪些依赖关系。在 CMakeLists.txt 文件中,开发人员根据需要标记这些标准包。例如,如果 OpenCV 是一个包,没有它项目将无法编译,因此它将被标记为:
find_package(OpenCV REQUIRED)
备注:建议阅读博客《如何使用 OpenCV 和 CMake》以更好地理解:
一旦找到所需的包,你也会同时看到相关的头文件目录和其他设置。例如,你的项目需要 Boost 库,那么其 CMakeLists.txt 文件构造如下:
cmake_minimum_required (VERSION 3.8)project(cmake_boost_demo)
find_package(Boost REQUIRED COMPONENTS
date_time)include_directories(${Boost_INCLUDE_DIR})link_directories( ${Boost_LIBRARY_DIRS})set(Boost_USE_STATIC_LIBS OFF)set(Boost_USE_MULTITHREADED ON)set(Boost_USE_STATIC_RUNTIME OFF)set(BOOST_ALL_DYN_LINK ON)
add_executable( ${PROJECT_NAME}main.cpp)target_link_libraries( ${PROJECT_NAME} ${Boost_LIBRARIES})
如果找不到所需的包,则构建失败。你需要帮助 CMake 确定依赖关系,具体有两种方式:
使用 CMAKE_PREFIX_PATH使用包含 config.cmake 的特定 DIR 路径 下面的示例中使用了 Boost 库,我将用这个简单的例子分别演示这两种方法。这是主 .cpp 文件:
#include #include <boost/date_time/posix_time/posix_time_types.hpp>using namespace std;namespace pt = boost::posix_time;
int main(int argc, char** argv) {pt::ptime now = pt::second_clock::local_time();cout << “Year : ” << (int)now.
官网:https://www.wangeditor.com/
引入 CSS 定义样式 <link href="https://unpkg.com/@wangeditor/editor@latest/dist/css/style.css" rel="stylesheet"> <style> #editor—wrapper { border: 1px solid #ccc; z-index: 100; /* 按需定义 */ } #toolbar-container { border-bottom: 1px solid #ccc; } #editor-container { height: 500px; } </style> 定义 HTML 结构 <div id="editor—wrapper"> <div id="toolbar-container"><!-- 工具栏 --></div> <div id="editor-container"><!-- 编辑器 --></div> </div> 引入 JS 创建编辑器 <script src="https://unpkg.com/@wangeditor/editor@latest/dist/index.js"></script> <script> const { createEditor, createToolbar } = window.wangEditor const editorConfig = { placeholder: 'Type here...', onChange(editor) { const html = editor.
前言 本文,参考几篇博客,总结一下个人对SPI的理解。文中的一些文字、图片等来源自参考的博客。在文后,附上参考的博客链接。本文重点介绍一下SPI的概念和传输协议,以及FPGA之间通过SPI进行数据传输的方案分析。代码和仿真本文就不做了。
SPI接口主要应用在EEPROM、FLASH、实时时钟,AD转换器以及数字信号处理器和数字信号解码器之间。因此,在了解SPI协议后,可以阅读对应外设比如FLASH 的datasheet,加深理解。
FPGA 读写访问 Flash
1、SPI概述 SPI(Serial Peripheral Interface)——串行外围设备接口。SPI接口主要应用在EEPROM、FLASH、实时时钟,AD转换器以及数字信号处理器和数字信号解码器之间。SPI是一种高速,全双工,同步的通信总线,在芯片上只占用四根线(CS、MOSI、MISO、SCK),极大的节约了芯片的引脚。
SPI以主从方式工作,这种模式通常有一个主设备和一个或者多个从设备。图1是一个主设备一个从设备的物理连接示意图。
图中SCK是由主设备发送给从的时钟,该时钟决定了主设备发送数据的速率;
MOSI是主设备发送给从设备的数据;
MISO是从设备发送给主设备的数据;
CS是片选信号,即只有片选信号为预先规定的使能信号时(高电平或者低电平)对此芯片的操作才有效。
图1 图2 2、SPI通信协议 SPI通信协议:假设当前配置是SCK上升沿采样。IDLE状态没有时钟SCK。Master发送采样时钟SCK和数据MOSI,Slave在SCK上升沿采样MOSI的数据。同理,Master也是在SCK的上升沿采样MISO数据。
CPOL/CPHA及通讯模式 SPI 一共有四种通讯模式,它们的主要区别是总线空闲时 SCK 的时钟状态以及数据采样时刻。为方便说明,在此引入“时钟极性 CPOL”和“时钟相位CPHA”的概念。 时钟极性 CPOL :是指 SPI 通讯设备处于空闲状态时,SCK 信号线的电平信号(即 SPI 通讯开始前、 NSS 线为高电平时 SCK 的状态)。CPOL=0 时, SCK在空闲状态时为低电平,CPOL=1 时,则相反。
时钟相位 CPHA :是指数据的采样的时刻,当 CPHA=0 时,MOSI 或 MISO 数据线上的信号将会在 SCK 时钟线的“奇数边沿”被采样。当 CPHA=1 时,数据线在 SCK 的“偶数边沿”采样。 奇数采样 偶数采样 由CPOL/CPHA的不同状态,SPI分为四种模式,实际中采用较多的是“模式 0”与“模式 3”。 SPI模式CPOLCPHA空闲时SCK时钟电平采样时刻000低电平奇数边沿101低电平偶数边沿210高电平奇数边沿311高电平偶数边沿 3、基于FPGA实现SPI通信 以实现上文SPI模式0的时序为例。
这里仅是 仿照 SPI的通信协议进行两片FPGA之间的通信。
架构设计:
下面是两个FPGA之间进行串行通信,两个FPGA之间可能通过线缆进行数据传输,线缆上信号延迟可能达到几十个ns。
tx:是发送模块,将并行数据data[7:0]转成串行数据MOSI,SCK是MOSI的采样时钟,SCK上升沿时、从机(rx)对MOSI进行数据采样;
在日常应用场景中,可能会遇到这么一个情况,需要判断用户是否完整的观看完了一部视频,在这个场景中,和视频相关的事件大体涉及到几个部分,获取视频长度,视频开始播放,暂停播放和播放结束,下面来看下如何通过JavaScript来监听获取视频的这几种状态。、 (1)HTML页面视频标签大体如下 <video id="video" controls="controls"> <source type="video/mp4" src="mi.mp4"> </video> (2)视频加载后获取视频的长度 复制代码 <script> var elevideo = document.getElementById("video"); elevideo.addEventListener('loadedmetadata', function () { //加载数据 //视频的总长度 console.log(elevideo.duration); }); </script> 复制代码 (3)视频开始播放 复制代码 <script> var elevideo = document.getElementById("video"); elevideo.addEventListener('play', function () { //播放开始执行的函数 console.log("开始播放"); }); </script> 复制代码 (4) 视频正在播放中 复制代码 <script> var elevideo = document.getElementById("video"); elevideo.addEventListener('playing', function () { //播放中 console.log("播放中"); }); </script> 复制代码 (5)视频加载中 复制代码 <script> var elevideo = document.getElementById("video"); elevideo.addEventListener('waiting', function () { //加载 console.
NLP(VI):使用sklearn进行文本情感分类(上) 这一节我们使用sklearn训练分类模型以实现对文本数据的情感分类。
获得数据 这次的数据我已经上传了,可从以下链接下载:
训练集:https://download.csdn.net/download/swy_swy_swy/87581709
测试集:https://download.csdn.net/download/swy_swy_swy/87581702
数据标签为二分类标签,0为消极情绪,1为积极情绪。
加载数据 我们使用pandas处理csv文件。
import sklearn import pandas as pd import numpy as np def csv_loader(filepath): return pd.read_csv(filepath) twitter_train_df = csv_loader('sentiment-train.csv') twitter_test_df = csv_loader('sentiment-test.csv') 文本向量化 sklearn本质上是如何“阅读”一个文本呢?它本质上是不懂人类的语言的,一段文本对于它来说是一个词语的集合,或说“一袋子单词”(a bag of words)。在训练模型之前,需要对所有文本“向量化”,也就是每一个单词都有一个对应的编号,当然,相同的单词即使在统一数据集的不同样本中编号也是相同的。这样,一段文本就变成了一个编号序列,也就是一个向量。
我们使用sklearn的CountVectorizer来进行向量化:
from sklearn.feature_extraction.text import CountVectorizer def feature_extracter(train_df, test_df, binary_flag=False, m_features=1000, has_test=True): vectorizer = CountVectorizer(stop_words='english', max_features=m_features, binary=binary_flag) train_texts = np.array(train_df['text']).tolist() test_texts = [] if has_test: test_texts = np.array(test_df['text']).tolist() vecs = vectorizer.fit_transform(train_texts + test_texts).toarray() train_X = vecs[:len(train_texts)] test_X = [] if has_test: test_X = vecs[len(train_texts):] train_y = np.
打开文件时显示的右键菜单 win + R输入regedit打开注册表进入 “计算机\HKEY_CLASSES_ROOT*\shellex\ContextMenuHandlers”,这是用来管理右键菜单的注册表信息
打开文件夹时显示的右键菜单
进入"计算机\HKEY_CLASSES_ROOT\Directory\shellex\ContextMenuHandlers" 进行调整即可
概念 返回类型 定义方法在执行结束后是否有返回结果,描述它的数据类型(只能有一个)
方法在执行结束后,有需要返回的数据,用数据类型 (基本或引用数据类型都可以) 语法 : return 返回值; 1、如果 方法定义了具体返回类型,那么就必须使用 return 关键字,去返回数据 ;
2、当方法有返回值时,就可以把方法调用语句看做是一个数据,可以利用变量声明语句 或者 输出语句 或者运算符 对其进行操作
方法在执行结束后,没有需要返回的数据(无返回值)用 void
1、如果方法定义的返回类型为void,那么不能使用 return 返回值 这一语法,且不能调用该方法的语句视作数据进行操作
2、虽然不能使用return 返回值这一语法,但能使用return关键字,因为return关键字,除了可以用于返回数据之外,还可以用于结束方法
代码理解 看完上面的概念,我们趁热打铁,通过下面这道例题来深入理解
题目:
定义一个函数,接收一个字符串参数和一个字符,输出该字符在字符串中第一次出现的下标,如果没有输出-1
先把传参进来的字符内容转换成一个char数组,声明一个记录状态的int,通过循环遍历char数组,判断数组里有没有传进来的char,有相同的 就把它的数组下标 赋值给记录状态的 firstIndex,最后通过return 返回出去。 public static int getCharFirstIndex(String str,char c){ char[] charArray = str.toCharArray(); int firstIndex = -1; for(int i = 0;i < charArray.length;i++){ if(charArray[i] == c){ firstIndex = i; break; } } return firstIndex; } 此时,这个方法调用语句就可以把它看做是一个数据,可以进行各种操作 ,比如 下面的相加
前文简短的介绍了DDS的产生原理,其实相当的简单,所以也不需要多做解释,本文详细阐述一下在调试DDS的过程中所产生的一个bug
问题发现 正如上文所述,再用FPGA控制存储在rom中的波形信号输出之后,在上板之前,我们可以先用仿真软件仿真一下,看看波形是否有误。我们的测试条件要求为:从2550Hz开始,每间隔1s的周期以20Hz的步长向下递减至2310Hz的频率,仿真波形如下所示(为节省仿真时间,我们将扫频间隔缩短):
不知大家是否能看清上图中的周期结果分析,按照上图所示,2550Hz、2530Hz除开频率交接处会有一定的抖动之外,在扫频周期中的频率是比较稳定的,但是当我们看到2510Hz的扫频周期过程中却发现,波形的周期呈现为398420ns、398400ns的周期变化,虽然说二者的周期对应基本上都为2510Hz,但是对频率信号敏感的场合是不能接受的。本文便对这一问题进行考究。
问题探究 首先,我们追根溯源,DDS信号发生的来源就是ROM当中存储的波形数据,而波形数据的来源是所输入的地址addr,这么一来我们就将目光放在addr上面。
addr是一个12位的变量,来源于频率信号叠加寄存器的高12位,为什么要设置叠加器为32位,就像前文所述,为了提高但个周期的分辨率,使得输出更加精确。接下来让我们分别来看看398420 ns和398400 ns的波形细节。
我们发现多的20ns(一个CLK周期)来源于高电平期间的差异,所以我们进一步的查看高电平的细节。先来看看199220ns的这个高电平。
可见,高电平的持续时间应该为 20ns × 5 × (2048-0) = 204800ns,这和我们的波形图上实现显示的差了204800ns - 199220ns = 5,580ns。我们记为error1。
然后再来看199200ns的这个高电平。
上面两幅图的高电平的持续时间应该为 20ns × 5 × (2048-0) = 204800ns,这和我们的波形图上实现显示的差了204800ns - 199200ns = 5600ns。我们记为error2。
好了,通过分析波形我们发现逻辑设计上是没有问题的,该在什么时候下降,什么时候上升都符合要求,那么其中的error1、2是从何而来的呢?这时候我们注意到上面的这个5,代表5个时钟周期变化一次地址,那么此时我们不禁要问,这个5个时钟周期变化一次,它真的那么诚实可靠,人畜无害吗,答案是否定的。
像上面两幅这样的问题时序还有很多,相信数量也是5600ns / 20ns = 280个。好了接下来问题就是分析问什么会少一个了。
讲了这么久,终于该回到代码层面了。让我们看一下地址递增的部分代码。
reg [31:0] freq_cnt; assign addr = freq_cnt[31:20] + phase_offset; always @(posedge sys_clk or posedge sys_rst)begin if(sys_rst) freq_cnt <= 32'd0; else freq_cnt <= freq_cnt + freq_k; end 从上图中可以看到。此时的freq_k为215607,而我们的地址是从220开始进位的,也就是说计数220 = 1,048,576次之后,addr + 1。那么215607需要加多少次呢?如下表所示:(表中标红表示进位)
当汽车进入电动化、智能化赛道后,产品变革所衍生的名词困扰着消费者。例如关于芯片方面的CPU、GPU、NPU、SOC等等。这些参数格外重要,甚至不逊于燃油车时代的一些核心部件配置。
这次,我们进行一次芯片名词科普,一起扫盲做个电动化汽车达人。
关于芯片里的名词
1、CPU
汽车cpu是汽车中央处理器。其事就是机器的“大脑”,也是布局谋略、发号施令、控制行动的“总司令官”。
CPU的结构主要包括运算器(ALU, Arithmetic and Logic Unit)、控制单元(CU, Control Unit)、寄存器(Register)、高速缓存器(Cache)和它们之间通讯的数据、控制及状态的总线。
简单来说就是:计算单元、控制单元和存储单元。(架构如下图)
如果你看不懂,我可以把他翻译成中文。简单来说就是,计算单元主要执行算术运算,存储单元主要保存数据以及指令等;控制单元则对指令译码。
2、GPU
GPU叫做图形处理器,又称显示核心、视觉处理器、显示芯片。
图形处理你是不是想到了显卡?提到显卡和GPU,人们会想到游戏和电影中精美的三维图形。其实,早期显卡不但不能处理三维图形,甚至连二维图形都无法处理,它仅具备显示能力。今天,GPU不但能够处理复杂的三维图形,还能作为协处理器,在通用计算中使用。
电脑图形处理器的发展是从图形显示适配器开始的,到图形加速器,再到图形处理器即GPU,其功能在不断增强。
3、MCU
汽车mcu是微控制器,控制着汽车内所有的电子系统,比如多媒体、音响、导航、悬挂等。作为汽车电子控制系统的核心,mcu必须有着耐高温和坚固的特性,使之在复杂的汽车内部环境中不容易损坏。
MCU分为1位、4位、8位、16位、32位甚至64位单片机。4位MCU大部分应用在计算器、车用仪表、车用防盗装置。
4、NPU
近几年NPU特别火,我们可以理解为NPU就是AI芯片,普通芯片就是CPU。在自动驾驶和智能座舱都离不开NPU。
换句话说,npu是具备智能和学习的特性, 也就是说这个处理器它是会模仿人的大脑神经网络的。
在工作模式上,CPU主要是负责低精度,各种普通的数据,npu则是人工智能算法上面运行效率要高于另外两者。
5、SoC
SoC芯片是芯片的一种,简单的理解就是把几种不同类型的芯片集成到一块芯片上,比如把CPU、GPU、存储器、蓝牙芯片等集成到一个芯片上。
再例如,智能座舱上的wifi功能和蓝牙功能,都是集成在SoC芯片之上,例如8155就属于SoC芯片。
6、TOPS
TOPS也是我们常说的算力,1 TOPS代表处理器每秒钟可进行一万亿次。我们熟知的8155芯片算力是8TOPS,英伟达 orin芯片算力为254TOPS。
汽车从L1、L2、L3、L4、L5不断推进,某种意义上看,就是算力的竞赛,每往上进阶一级就意味着对算力的需求更高。
毫无疑问,当前的自动驾驶芯片市场发生了明显的变化,“大算力”正是一大趋势。除了英伟达,算力突破100TOPS的芯片陆续问世,比如已发布单颗芯片最高算力可达128TOPS的地平线征程5;单颗芯片最高算力可达176TOPS的Mobileye EyeQ Ultra等。
7、DMIPS
常常有人会把TOPS和DMIPS搞混,认为这两个词语都在表达同一种计算能力。其实并非如此,DMIPS是每秒处理机器语言指令数,而TOPS是每秒钟可以进行的操作数量。
例如8155芯片CPU能够达到105K DMIPS执行能力,算力是8TOPS,这显然是芯片两块不同领域的处理能力。
DMIPS是,用Dhrystone这套测试程序跑下来,每秒钟可以执行多少指令。
某种意义上,谁家的这个数字高,谁家的CPU就更牛。50000DMIPS就意味着每秒可以执行50000*100万条指令。
8、DPU
DPU和NPU的组合很像TOPS和DMIPS,很容易搞混。
DPU和NPU都是具有学习能力的芯片,只是DPU是深度学习处理器,是基于Xilinx可重构特性的FPGA芯片。而NPU不基于Xilinx。
不同于CPU的AI芯片,DPU可以机器学习、安全、电信和存储等应用,并提升性能。
汽车芯片的种类
汽车芯片的三大类:1、整车域的MCU。2、自动驾驶域的AI芯片。3、智能座舱域的CPU。这三大门类都需要芯片,但是难度系数却相差很多。
汽车芯片从MCU到自动驾驶座舱,虽然有如果说MCU芯片的弱鸡性能让汽车的面子有点挂不住,那自动驾驶域的AI芯片可以说是扳回一城了。
1、自动驾驶域的AI芯片
以英伟达orin为例,orin的CPU内核是12个Coretex-A78(代号Hercules),GPU是Ampere。
我们拿蔚来ET7举例。
CUBA单元:蔚来ET7搭载了四颗NVIDIA ORIN芯片(近1000TOPS),其CUBA(Compute Unified Device Architecture)单元达8096,接近8704CUBA核心的RTX3080显卡。
晶体管数量:蔚来ET7搭载四颗NVIDIA ORIN芯片的晶体管数量为680亿,同期“秒天秒地秒一切”的苹果A14芯片的晶体管数量为118亿。
数据处理量:特斯拉FSD芯片内置图片处理器ISP,最高以25亿像素/秒的速度处理图像,大概是往21块1080P的高清屏幕上塞60帧画面。
NPU:特斯拉FSD芯片的神经处理单元NPU高速缓存32MB,与零售价16999元的英特尔酷睿i9-9980XE的33.75MB SRAM缓存总量相当
2、智能座舱芯片
智能座舱的主芯片一般称之为SoC – System on Chip即片上系统,它包括CPU、GPU,AI引擎,还包括处理各种各样摄像头的ISP,支持多显示屏的DPU、集成音频处理等等。另外第3代的数字座舱系统,配备了个性化的计算机视觉和机器学习的计算机应用平台,包含AI加速器等等。同时,高通在SoC上也集成了先进的Wi-Fi、蓝牙技术,可以支持眼下最热的Wi-Fi6以及蓝牙5.1的技术。
<el-table ref="table" :data="tableData" style="width: 100%" height="220px" @cell-mouse-enter="mouseEnter" @cell-mouse-leave="mouseLeave" > <el-table-column prop="detectionSiteName" label="监测站点" /> <el-table-column prop="detectionProject" label="监测项目" /> <el-table-column prop="concentrationValue" label="浓度值" /> <el-table-column prop="alarmTime" width="150" label="报警时间" /> </el-table> // 鼠标移入 mouseEnter() { clearInterval(this.timer) this.timer = null }, //鼠标移出 mouseLeave() { this.handScroll() }, // 表格滚动 handScroll() { const table = this.$refs.table const divData = table.bodyWrapper this.timer = setInterval(() => { divData.scrollTop += 1 if (divData.clientHeight + divData.scrollTop == divData.scrollHeight) { divData.scrollTop = 0 } }, 60) },
一、概述 U2Net是针对SOD任务设计的网络(SOD任务:将图片中最吸引人的目标/区域分割出来;即只有前景和背景两个部分,是一个二分类问题)
二、网络结构 1.特征提取网络 在编码器阶段,每个block会下采样2倍(maxpool);在解码器阶段,在每个block前会上采样2倍(bilinear)。
EN_1和DE_1采用的模块为RSU-7(下采样5次,上采样5次,总压缩倍率为32),结构如下图所示。
EN_2和DE_2采用的是RSU-6,相较于RSU-7少了一个上采样和一个下采样,总压缩倍率变为了16倍;EN_3和DE_3采用的是RSU-5,(比RSU-6少2倍的压缩倍率);EN_4和DE_4采用的是RSU-4(比RSU-5少2倍的压缩倍率)
而EN_5、EN_6和DE_5采用的则是RSU-4F结构(如下图所示),相较于RSU-4,本结构没有下采样结构。采用此结构的原因是经过数次下采样后,特征图的尺寸已经很小了。如再下采样势必丢失一些信息。
2.特征融合网络 分别取DE_1、DE_2、DE_3、DE_4、DE_5和EN_6的输出特征图,分别进行3x3卷积(kernel=1,经过卷积后通道数为1);
再通过双线性插值将特征图还原为输入图的尺寸;
最后将这6个特征图进行concat拼接。拼接后的特征图经过1x1卷积核sigmoid激活函数得到最终的预测。
三、网络配置参数 上面的是标准网络,下面的是轻量化网络。对应的参数如下图。
四、损失函数 该损失函数可以分为两部分:表示6个特征图与标注的Ground Turth计算损失,为二值交叉熵损失。代表每个损失的权重;为最终结果与Ground Turth之间的损失。所有的权重默认为1。
五、评价指标 1.F-measure 的取值范围为0~1,值越大效果越好
2.MAE
文章目录 IDEA配置JDK1、点击File -->Project Structure;2、点击左侧标签页SDKs选项,再点击左上角“+”,选择JDK;3、在弹出框选择JDK安装路径,点击OK即可配置成功。 配置maven仓库(阿里云)1、配置好maven环境后我们要修改maven的settings.xml文件,首先找到maven的settings文件,在maven解压后的conf文件夹下:2、用编辑器打开settings文件,最好用notepa++,editplus等文本编辑工具打开,不要用记事本打开,打开后如下图:3、在下图截图圈出来的地方配置仓库地址 IDEA配置maven1、 在菜单选择file下的Settings2、在搜索框搜索maven。在Maven homedirectory选择maven文件地址:3、在Importing中勾选import Maven projects automatically; IDEA配置JDK 1、点击File -->Project Structure; 2、点击左侧标签页SDKs选项,再点击左上角“+”,选择JDK; 3、在弹出框选择JDK安装路径,点击OK即可配置成功。 下图可以看到JDK已经在IDEA中配置好了。
配置maven仓库(阿里云) 1、配置好maven环境后我们要修改maven的settings.xml文件,首先找到maven的settings文件,在maven解压后的conf文件夹下: 2、用编辑器打开settings文件,最好用notepa++,editplus等文本编辑工具打开,不要用记事本打开,打开后如下图: 3、在下图截图圈出来的地方配置仓库地址 D:/software/MavenCangKu
其中D:/software/MavenCangKu为配置的仓库路径。别有中文路径,仓库是空的
IDEA配置maven 1、 在菜单选择file下的Settings 2、在搜索框搜索maven。在Maven homedirectory选择maven文件地址: 在User settingS file 选择maven下的settings.xml文件在conf下;
Local repository 为maven仓库地址。(为maven配置环境是在settings.xml中设置)
最后点击Apply确认保存
3、在Importing中勾选import Maven projects automatically; 勾选Automatically download下的Sources和Documentation;
最后点击Apply确认保存
基本概念 概念: 弹性布局(flex-layout)是一套css3新增的自适应布局模式,用于替代传统的div+css布局或辅助
弹性布局主要是为了让盒子里面的子元素在面对容器不同宽度时都能够很好的适应。特别适合满足不同屏幕或设备。即对移动端友好。
原理: 给盒子设置css弹性布局的相关css属性来使用弹性布局。
基本使用 给容器设置css属性display:flex/inline-flex将该盒子变为一个弹性容器,它里面的子元素会以弹性布局的方式来处理。
display:flex; 会将盒子变为块级的弹性容器。对其他兄弟标签来说,就是一个普通的块级标签,对里面子元素来说,该盒子就是他们的弹性容器。
display:inline-flex; 会将盒子变为行内的弹性容器。对其他兄弟标签来说,就是一个普通的行内标签,对里面子元素来说,该盒子就是他们的弹性容器。
特点: 弹性容器只对自己的直接子元素有效
display:inline-flex和flex对自己的兄弟标签来说没有任何影响
对于弹性容器来说,高度是自适应的,无需设置高度。
主轴和侧轴: 通过flex-direction设置的方向为主轴,与之垂直的方向为侧轴。如果主轴是水平,侧轴就是垂直方向。
目的是为了更好理清弹性容器相关css属性
需要考虑的问题 如何开启弹性容器 display:flex/inline-flex
子元素是水平排列还是垂直排列 flex-direction
子元素多了是否允许换行 flex-wrap
子元素如何实现居中对齐 主轴居中:justify-content:center;
侧轴居中:align-item:center;
子元素如何处理间隔 间隔均分:
justify-content及align-items消化多余的空间(弹性空间):flex-grow 子元素高度如何占满父容器高度 align-items:
子元素如何完成自适应 开启弹性容器处理多余空间 如何设置单个弹性项目的对齐 align-self
如何改变弹性项目的显示顺序 order
如何设置弹性项目的默认宽度 flex-basis
弹性项目的实际宽度(优先级):flex-basis>width>宽度由内容确定
如果弹性容器的宽度容不下弹性项目的预期总宽度。 弹性容器会按照每个弹性项目的flex-shrink(默认1)的值来确定每个弹性项目要减少的的宽度
弹性布局相关CSS属性 给父元素设置 display:flex/inline-flex
flex-direction:设置子元素的排列方式,同时确定弹性容器的主轴。 row:默认
row-reverse
column:垂直排列
column-reverse
flex-wrap:设置弹性项目是否换行显示,默认不换行 nowrap:默认,不换行。
wrap:换行显示。
特点:设置换行之后,弹性项目的尺寸不会发生自适应变化
justify-content:处理主轴上的富裕空间;align-items:处理侧轴上的富裕空间; flex-start:默认。弹性项目跟主轴左部/顶部对齐
flex-end:弹性项目跟主轴右部/底部对齐
space-between:弹性项目之间的空间均匀分配
space-around:每个弹性项目两侧的距离是一样的
space-evenly:每个弹性项目之间的空隙完全一样,包含第一个和最后一个弹性项目
center:让弹性项目居中显示
stretch:当弹性项目没设置高度时,那么弹性项目的高度跟弹性容器一致(侧轴)
align-items:处理侧轴上的富裕空间 给子元素设置 flew-grow:设置弹性项目的弹性因子 需要一个数字,默认为1
一、加载静态资源 Nginx命令 cd /usr/local/nginx/sbin
./nginx -v 查看版本号
./nginx -t 检查配置文件nginx/conf/nginx.conf文件
【启动和停止】
./nginx 启动服务
./nginx -s stop 停止服务
ps -ef | grep nginx 查看进程
./nginx -s reload 重新加载配置文件
【nginx.conf配置】
全局块 nginx相关
events块 网络连接相关
http
-全局
-server 配置端口号;后续也可以用来配置负载均衡
-location 配置加载静态资源的路径和html和index
加载静态资源 把静态资源复制到/usr/local/nginx/html下,配置conf文件中的加载路径和server端口 即可访问
二、反向代理 正向代理: 一个位于客户端和原始服务器之间的服务器,为了从原始服务器取得内容,客户端向代理发送一个请求,并指定目标(原始服务器),然后代理向原始服务器提交请求,并将获得的内容返回给客户端。
正向代理的典型用途:在防火墙内的局域网客户端提供方位Internet的途径
在客户端设置代理服务器,通过代理服务器转发请求,最终访问到目标服务器
(客户端 正向代理服务器)Web服务器
反向代理: 位于用户与目标服务器之间,但是对于用户而言,反向代理服务器相当于目标服务器,用户直接访问反向代理服务器就可以获得目标服务器的资源,反向代理服务器负责将请求转发给目标服务器;
用户不需要知道目标服务器的地址,也无须在用户端做任何设定
反向代理隐藏了真正的目标服务器
(客户端)(反向代理服务器 Web服务器)
具体应用 在反向代理服务器的nginx的conf中配置server,将82端口的请求发送到101这台机器的8080端口
三、负载均衡 单点故障问题->多台服务器组成应用集群 水平扩展性能 避免单点故障出现
应用集群:将同一应用部署到多台机器上,组成应用集群,接受负载均衡器发送的请求,进行业务处理并返回响应数据负载均衡器:将用户请求根据对应的负载均衡算法分发到应用集群中的一台服务器进行处理
具体应用 用upstream指定一组服务器,配置在proxy pass中
配置nginx的服务器充当一个负载均衡器,分发请求给服务器
负载均衡算法 weight越大,被分发请求的概率越大
ip_hash url_hash 分别是通过ip和url计算hash值进行请求分发,只要ip、url不变,分发的服务器也不变
默认已安装git,GitHub已创建包含readme文件
先执行 git pull origin main --allow-unrelated-histories拉取readme文件到本地
执行此语句若进入编辑状态,输入“:q”退出编辑状态
仓库已存在readme文件不执行上诉操作会导致上传失败
1.将要上传的文件所在的文件夹进行初始化 在将要上传的文件所在的文件夹右键选择git bash here
进入命令行输入:git init
2.添加上传的文件 git add (具体文件名) 注:git add . 表示上次文件夹内所有文件
设置上传标识,简要描述上传文件信息,方便找回:git commit -m "文件信息描述"
3.选择分支 git branch -M main 上传到主分支(2020年后git设置main为主分支)
4.连接远程仓库 git remote add origin [github仓库的ssh地址]
5.添加版本号 git tag -a 1.0.1 -m “1.0.1”
6.上传 git push -u origin master
因为网速或者墙等原因,以上语句执行时会出现错误,执行成功命令行无返回或返回成功信息(是否失败请大家看返回信息描述),多次返回执行直到成功(或者科学上网 vpn)
推荐: Python全栈白宝书专栏,免费阶段订阅数量4300+,购买任意白宝书体系化专栏可加入TFS-CLUB 私域社区。福利:加入社区的小伙伴们,除了可以获取博主所有付费专栏的阅读权限之外,还有机会加入 星荐官共赢计划 ,详情请戳我 。推荐他人订阅,可获取扣除平台费用后的35%收益。 作者:不渴望力量的哈士奇(哈哥),十余年工作经验, 跨域学习者,从事过全栈研发、产品经理等工作,目前任某金融品类App负责人。荣誉:2022年度博客之星Top4、博客专家认证、全栈领域优质创作者、新星计划导师,“星荐官共赢计划” 发起人。现象级专栏《白宝书系列》作者,文章知识点浅显易懂且不失深度;TFS-CLUB社区创立者,旨在以“赋能 共赢”推动共建技术人成长共同体。 🏆 白宝书系列专栏 🏅 Python全栈白宝书🏅 产品思维训练白宝书🏅 全域运营实战白宝书🏅 大前端全栈架构白宝书 文章目录 ⭐️ 前言⭐️ 创作技巧🌟 受众与定位🌟 封面与标题🌟 关于导航🌟 优质内容 ⭐️ 榜单规则🌟 综合热榜规则🌟 热榜算法解读🌟 热榜参数解读 ⭐️ 套路可得人心🌟 增加曝光以及快速涨粉🌟 初心不变以待厚积薄发 ⭐️ 前言 本系列文章主要是分享个人在写作中的一些经验,收录于《新星计划》专栏。该专栏主要服务于参与《2023·新星计划-第1期~Python赛道》的小伙伴。
目前《新星计划》正在火热进行中,如果各位小伙伴想要获得写作、涨粉、上榜等经验,欢迎加入:新星计划·2023-第1期 - Python赛道
更多赛事信息,欢迎到比赛官方活动地址查询:2023年度·新星计划-第1期
⭐️ 创作技巧 许多小伙伴有时候会有疑问,感觉自己的文章写的挺好的,但是收获的阅读、关注却非常少。 这个问题是很多新人博主所面临的问题,原因往往是写文章时没有抓住重点所导致的,这时候就要巧妙地利用一些写作技巧来提升你文章的吸引力。
🌟 受众与定位 在决定开始写博客之前,首先需要决定的一件事情就是要思考清楚自己内容的一个定位,这个非常重要。
因为内容领域决定了内容的受众群体范围,想要在众多内容中脱颖而出,文章就要有自己的知识领域定位。
如果你的内容是Python领域,那么你的受众已经用户画像就是Python这个群体的用户。众所周知,Python领域所涉及的方向有很多,比如 爬虫、数据分析、数据挖掘、Web开发 等等。不同的职业领域涉及的范围也不相同,用户基础也不相等。如果选择的是人数多的方向,那么未来你的内容所影响的群体范围必然不会是少数。
除了考虑内容受众的用户范围之外,文章就要有自己的特色,包括但不限于从内容深度、文章排版、文章可读性等方面。
文章定位首先是要确定您要编写文章的一个方向,比如面试题系列,数据Python基础学习系列,数Python进阶学习系列等。
很多粉丝会因为阅读到你某一篇文章而进一步了解你,如果你的文章都是体系化的内容且可读性高,那就可以进一步转换成关注度,因为潜意识里他会认为以后会可能会学习或者遇到相类似的问题。
粉丝关注之后是可以持续通过平台粉丝管理,推送系列文章给粉丝,提高粉丝留存率,进而可以转换成收费专栏。
如果只是某一篇文章有帮助,很可能只会成点赞或者收藏,相对于关注来说,效果相差很大。
🌟 封面与标题 封面:
为什么说一篇文章的封面重要呢?
那是因为很多的C站的小伙伴,在不了解内容的情况下,第一眼看到的应该是有封面的文章,优质的封面不仅仅可以得到官方推荐,而且更容易吸引点击率。
PS:这里的优质封面指的是和文章相关的封面,而不是擦边球和无关紧要的图片,大家可以去 综合热榜 看看别人是如何选择封面的,也可以访问 可画 ,尝试自己动手设计一些封面,很多都是零基础或者是新手都可以轻松弄出来的封面。
标题:
什么是一个优质的标题?
论文题目:Mask R-CNN
论文链接:论文链接
论文代码:Facebook代码链接;Tensorflow版本代码链接; Keras and TensorFlow版本代码链接;MxNet版本代码链接
一、Mask R-CNN是什么,可以做哪些任务?
图1 Mask R-CNN整体架构
Mask R-CNN是一个实例分割(Instance segmentation)算法,可以用来做“目标检测”、“目标实例分割”、“目标关键点检测”。
1. 实例分割(Instance segmentation)和语义分割(Semantic segmentation)的区别与联系
联系:语义分割和实例分割都是目标分割中的两个小的领域,都是用来对输入的图片做分割处理;
区别:
图2 实例分割与语义分割区别
1. 通常意义上的目标分割指的是语义分割,语义分割已经有很长的发展历史,已经取得了很好地进展,目前有很多的学者在做这方面的研究;然而实例分割是一个从目标分割领域独立出来的一个小领域,是最近几年才发展起来的,与前者相比,后者更加复杂,当前研究的学者也比较少,是一个有研究空间的热门领域,如图1所示,这是一个正在探索中的领域;
图3 实例分割与语义分割区别
2. 观察图3中的c和d图,c图是对a图进行语义分割的结果,d图是对a图进行实例分割的结果。两者最大的区别就是图中的"cube对象",在语义分割中给了它们相同的颜色,而在实例分割中却给了不同的颜色。即实例分割需要在语义分割的基础上对同类物体进行更精细的分割。
注:很多博客中都没有完全理解清楚这个问题,很多人将这个算法看做语义分割,其实它是一个实例分割算法。
2. Mask R-CNN可以完成的任务
图4 Mask R-CNN进行目标检测与实例分割
图5 Mask R-CNN进行人体姿态识别
总之,Mask R-CNN是一个非常灵活的框架,可以增加不同的分支完成不同的任务,可以完成目标分类、目标检测、语义分割、实例分割、人体姿势识别等多种任务,真不愧是一个好算法!
3. Mask R-CNN预期达到的目标
高速高准确率(高的分类准确率、高的检测准确率、高的实例分割准确率等)简单直观易于使用 4. 如何实现这些目标
高速和高准确率:为了实现这个目的,作者选用了经典的目标检测算法Faster-rcnn和经典的语义分割算法FCN。Faster-rcnn可以既快又准的完成目标检测的功能;FCN可以精准的完成语义分割的功能,这两个算法都是对应领域中的经典之作。Mask R-CNN比Faster-rcnn复杂,但是最终仍然可以达到5fps的速度,这和原始的Faster-rcnn的速度相当。由于发现了ROI Pooling中所存在的像素偏差问题,提出了对应的ROIAlign策略,加上FCN精准的像素MASK,使得其可以获得高准确率。
简单直观:整个Mask R-CNN算法的思路很简单,就是在原始Faster-rcnn算法的基础上面增加了FCN来产生对应的MASK分支。即Faster-rcnn + FCN,更细致的是 RPN + ROIAlign + Fast-rcnn + FCN。
易于使用:整个Mask R-CNN算法非常的灵活,可以用来完成多种任务,包括目标分类、目标检测、语义分割、实例分割、人体姿态识别等多个任务,这将其易于使用的特点展现的淋漓尽致。我很少见到有哪个算法有这么好的扩展性和易用性,值得我们学习和借鉴。除此之外,我们可以更换不同的backbone architecture和Head Architecture来获得不同性能的结果。
二、Mask R-CNN框架解析
图6 Mask R-CNN算法框架
一、基础知识 漏洞介绍: Apache Log4j2 是一个开源的 Java 日志记录工具。Log4j2 是 Log4j 的升级版本,其优异的性能被广泛的应用于各种常见的 Web 服务中。
Log4j2 在特定的版本中由于启用了 lookup 功能,导致存在 JNDI 漏洞。lookup 函数是用于在日志消息中替换变量的函数,是通过配置文件中的${}语法调用的,例如:如果在日志消息中使用了${sys:my.property},那么 log4j2 将使用 lookup 函数从系统属性中查找名为 “my.property” 的属性值,并将其替换为实际值。
在某些情况下,攻击者可以通过构造带有 ${} 关键标识符的日志消息来触发 log4j2 的 lookup 函数,从而执行任意代码。
JNDI注入主要通过LDAP或RMI服务实现,两种利用方式类似。大致的流程就是程序通过 JNDI 的 LDAP 或 RMI 服务执行了 lookup 方法,执行远程 class 文件中的代码,成功利用此漏洞可以在目标服务器上执行任意代码。
什么是JDNI? JNDI即Java Naming and Directory Interface(JAVA命名和目录接口),它提供一个目录系统,并将服务名称与对象关联起来,从而使得开发人员在开发过程中可以使用名称来访问对象。
简单粗暴理解:有一个类似于字典的数据源,你可以通过JNDI接口,传一个name进去,就能获取到对象了。
那不同的数据源肯定有不同的查找方式,所以JNDI也只是一个上层封装,在它下面也支持很多种具体的数据源。
JNDI可访问的现有的目录及服务有:JDBC、LDAP、RMI、DNS、NIS、CORBA。
什么LDAP? LDAP 即 Lightweight Directory Access Protocol(轻量级目录访问协议),目录是一个为查询、浏览和搜索而优化的专业分布式数据库,它呈树状结构组织数据,就好像Linux/Unix系统中的文件目录一样。简单的理解为:有一个类似于字典的数据源,你可以通过LDAP协议,传一个name进去,就能获取到数据。
攻击者可以通过构造特殊的LDAP请求,在请求中包含恶意的Java代码,当服务器接收到请求并解析时,恶意代码就会被执行。
什么RMI? RMI 即 Remote Method Invoke(远程方法调用),是Java中的一种远程调用机制,可以在不同的JVM之间实现Java对象之间的交互和通信。攻击者可以通过构造恶意的RMI请求,向受漏洞影响的服务器发送请求并执行恶意代码。(两种利用方式都差不多)
需要注意: JDK 11.0.1、8u191、7u201、6u211 以上的版本中默认不支持LDAP协议,com.
前言 最近在系统对接的时候,遇到些问题,耽误了好长时间才找到原因,这边做下记录。
背景 我们自己开发的系统需要与外部系统做对接,需要做统一认证登录,即外部系统没有登录页面,共用我们系统的登录,在我们系统登录成功的用户可以直接跳转至外部系统。这边直接采用了OAuth2.0授权码模式来实现的,流程图如下:
问题 在测试环境测试通过后,部署到生产环境,但是在生产环境调试的时候却总是调不通,部署环境如下:
浏览器页面:
一开始访问会丢失cookie里面的session信息,定位到可能是做了redirect,所以外部系统获取登录状态、获取token、获取用户信息的请求地址都换成了政务外网的统一IP,这样确实没有丢失cookie里的session信息了,但是成功获取登录状态之后,一直卡第二个login中,直到超时,如上图所示。
解决 重温OAuth2授权码模式:
主要流程:
用户访问客户端,后者将前者导向授权服务器。用户选择是否给予客户端授权。用户给予授权,授权服务器将用户导向客户端事先指定的"重定向URI"(redirection URI),同时附上一个授权码。客户端收到授权码,附上早先的"重定向URI",向授权服务器申请令牌。这一步是在客户端的后台的服务器上完成的,对用户不可见。授权服务器核对了授权码和重定向URI,确认无误后,向客户端发送访问令牌(access token)和更新令牌(refresh token)。 还是对OAuth2的授权码模式没有理解清楚,外部系统获取用户登录状态请求是浏览器发出的,所以这里应该设置成政务外网统一IP,而获取token和获取用户信息是外部系统后台服务直接调用的,对用户不可见,所以这里应该直接配置成内网机器的IP。修改之后,问题解决。
Zookeeper https://zookeeper.apache.org/
简介/快速入门 ZooKeeper是一个集中的服务,用于维护配置信息、命名、提供分布式同步和提供组服务。所有这些类型的服务都以某种形式被分布式应用程序使用。每次它们被实现时,都会有大量的工作来修复不可避免的错误和竞争条件。由于实现这些服务的困难,应用程序最初通常会略过这些服务,这使得它们在出现更改时变得脆弱,并且难以管理。即使正确地执行了这些服务,在部署应用程序时,这些服务的不同实现也会导致管理复杂性
zookeeper由雅虎研究院开发,是 Google Chubby的开源实现,后来托管到 Apache,于2010年11月正式成为apache的顶级项目
大数据生态系统里由很多组件的命名都是某些动物或者昆虫,比如hadoop大象,hive就是蜂巢,zookeeper即管理员,顾名思义就算管理大数据生态系统各组件的管理员,如下所示:
应用场景 zookeepepr是一个经典的分布式数据一致性解决方案,致力于为分布式应用提供一个高性能、高可用,且具有严格顺序访问控制能力的分布式协调存储服务。
维护配置信息
分布式锁服务
集群管理
生成分布式唯一ID
维护配置信息
java编程经常会遇到配置项,比如数据库的url、 schema、user和 password等。通常这些配置项我们会放置在配置文件中,再将配置文件放置在服务器上当需要更改配置项时,需要去服务器上修改对应的配置文件。
但是随着分布式系统的兴起,由于许多服务都需要使用到该配置文件,因此有必须保证该配置服务的高可用性(highavailability)和各台服务器上配置数据的一致性。
通常会将配置文件部署在一个集群上,然而一个集群动辄上千台服务器,此时如果再一台台服务器逐个修改配置文件那将是非常繁琐且危险的的操作,因此就需要一种服务,能够高效快速且可靠地完成配置项的更改等操作,并能够保证各配置项在每台服务器上的数据一致性。
zookeeper就可以提供这样一种服务,其使用Zab这种一致性协议来保证一致性。现在有很多开源项目使用zookeeper来维护配置,如在 hbase中,客户端就是连接一个 zookeeper,获得必要的 hbase集群的配置信息,然后才可以进一步操作。还有在开源的消息队列 kafka中,也便用zookeeper来维护 brokers的信息。在 alibaba开源的soa框架dubbo中也广泛的使用zookeeper管理一些配置来实现服务治理。
分布式锁服务
一个集群是一个分布式系统,由多台服务器组成。为了提高并发度和可靠性,多台服务器上运行着同一种服务。当多个服务在运行时就需要协调各服务的进度,有时候需要保证当某个服务在进行某个操作时,其他的服务都不能进行该操作,即对该操作进行加锁,如果当前机器挂掉后,释放锁并 fail over到其他的机器继续执行该服务
集群管理
一个集群有时会因为各种软硬件故障或者网络故障,出现棊些服务器挂掉而被移除集群,而某些服务器加入到集群中的情况,zookeeper会将这些服务器加入/移出的情况通知给集群中的其他正常工作的服务器,以及时调整存储和计算等任务的分配和执行等。此外zookeeper还会对故障的服务器做出诊断并尝试修复。
生产分布式唯一ID
在过去的单库单表型系统中,通常可以使用数据库字段自带的auto_ increment属性来自动为每条记录生成一个唯一的ID。但是分库分表后,就无法在依靠数据库的auto_ Increment属性来唯一标识一条记录了。此时我们就可以用zookeeper在分布式环境下生成全局唯一ID。
做法如下:每次要生成一个新id时,创建一个持久顺序节点,创建操作返回的节点序号,即为新id,然后把比自己节点小的删除即可
Zookeeper的设计目标 zooKeeper致力于为分布式应用提供一个高性能、高可用,且具有严格顺序访问控制能力的分布式协调服务
高性能
zookeeper将全量数据存储在内存中,并直接服务于客户端的所有非事务请求,尤其用于以读为主的应用场景
高可用
zookeeper一般以集群的方式对外提供服务,一般3~5台机器就可以组成一个可用的 Zookeeper集群了,每台机器都会在内存中维护当前的服务器状态,井且每台机器之间都相互保持着通信。只要集群中超过一半的机器都能够正常工作,那么整个集群就能够正常对外服务
严格顺序访问
对于来自客户端的每个更新请求,Zookeeper都会分配一个全局唯一的递增编号,这个编号反应了所有事务操作的先后顺序
数据模型 zookeeper的数据结点可以视为树状结构(或目录),树中的各个结点被称为znode (即zookeeper node),一个znode可以由多个子结点。zookeeper结点在结构上表现为树状;
使用路径path来定位某个znode,比如/ns-1/itcast/mysqml/schemal1/table1,此处ns-1,itcast、mysql、schemal1、table1分别是根结点、2级结点、3级结点以及4级结点;其中ns-1是itcast的父结点,itcast是ns-1的子结点,itcast是mysql的父结点....以此类推
znode,间距文件和目录两种特点,即像文件一样维护着数据、元信息、ACL、时间戳等数据结构,又像目录一样可以作为路径标识的一部分
那么如何描述一个znode呢?一个znode大体上分为3个部分:
结点的数据:即znode data (结点path,结点data)的关系就像是Java map 中的 key value 关系
结点的子结点children
结点的状态stat:用来描述当前结点的创建、修改记录,包括cZxid、ctime等
结点状态stat的属性 在zookeeper shell 中使用 get 命令查看指定路径结点的data、stat信息
MMGEN-FaceStylor的环境配置总结 0. 引言1. Python环境配置2. 安装步骤2.1 创建虚拟环境2.2 安装MMCV和MMGEN2.3 克隆存储库并准备数据和权重 3. Play with MMGEN-FaceStylor3.1 Quick Try 0. 引言 编程环境配置:客户端(Window 11、PyCharm 2022.1.3),服务器端为Ubuntu,其中PyCharm使用SSH技术连接Ubuntu终端进行开发
1. Python环境配置 RTX 3090芯片(CUDA版本需要11.1及以上,否则会因为算力太高无法运行程序)
CUDA 11.1
Python 3
PyTorch ==1.9.0
MMCV-Full >= 1.4.2 <= 1.9.0
MMGeneration >= 0.3.0
2. 安装步骤 2.1 创建虚拟环境 我们首先创建conda虚拟环境并对它进行激活
conda create -n facestylor python=3.7 -y conda activate facestylor 假设您已经安装了CUDA 11.1,您需要使用CUDA 11.1安装预构建的PyTorch。
pip install torch==1.9.0+cu111 torchvision==0.10.0+cu111 torchaudio==0.9.0 -f https://download.pytorch.org/whl/torch_stable.html 2.2 安装MMCV和MMGEN 我们可以通过运行以下命令来安装MMCV
pip install mmcv-full==1.4.2 -f https://download.openmmlab.com/mmcv/dist/cu111/torch1.9.0/index.html 当然我们还可以通过MMCV文档进行安装(命令行安装或者源码编译)
1. 概念 信号槽指的是信号函数和槽函数,这是Qt在C++的基础上新增的特性,可以非常容易地实现Qt对象之间的通信。
实际上信号槽就是一种代码上的“约定”,在代码编写时指定某种前提条件和达到条件需要执行的代码,在代码运行中如果触发的前提条件就执行预设的代码,如果没有触发前提条件就不执行预设的代码。
使用信号槽需要有两个先决条件:
● 通信的对象必须是继承自QObject类,QObject类是Qt所有类型的基类。
● 类中要有Q_OBJECT宏
2. 信号槽连接 2.1 函数原型 信号函数与槽函数的使用,需要建立连接,这就是之前说的“约定”。
连接函数如下所示。
参数1:发射者,是前提条件中名词对应的对象。
参数2:信号函数,是前提条件中动词对应的函数,此函数属于发射者所有,信号函数通常使用过去时。信号函数需要使用SIGNAL()包裹。
参数3:接收者,是达到条件后执行代码的主体,也是名词对应的对象。
参数4:槽函数,是达到条件后执行动作对应动词函数,此函数属于接收者所有,槽函数通常使用现在时。槽函数需要使用SLOT()包裹。
为了讲解方便,把信号槽的连接分为三类:
2.2 自带信号→自带槽 【例子】点击按钮,关闭窗口。
分析:发射者——按钮对象
信号函数——clicked函数
接收者——窗口对象
槽函数——close函数
dialog.h
#ifndef DIALOG_H #define DIALOG_H #include <QDialog> #include <QPushButton> class Dialog : public QDialog { Q_OBJECT public: Dialog(QWidget *parent = 0); ~Dialog(); private: QPushButton* btn; }; #endif // DIALOG_H dialog.cpp
#include "dialog.h" Dialog::Dialog(QWidget *parent) : QDialog(parent) { resize(400,400); btn = new QPushButton("关闭",this); btn->move(200,200); // 建立信号槽连接 // 发射者——按钮对象 // 信号函数——clicked函数 // 接收者——窗口对象 // 槽函数——close函数 connect(btn,SIGNAL(clicked()),this,SLOT(close())); } Dialog::~Dialog() { delete btn; } 2.
前言 我们在以后的测试工作中,可能或多或少的会要去测试关于邮箱地址的功能,不管是登录,还是注册,还是绑定邮箱地址。
那么首先,我们得了解一下邮箱地址的组成
邮箱地址的组成,分为3个部分,即:
邮箱名 @ 域名
例如:3343787213@qq.com
例如:ya.meng@163.com
例如:ya_yameng@gmail.com
。。。。。。
那么,我们去测试的时候,就可以先从这3个部分去分别测试
邮箱名
现在还在使用的邮箱地址中,因为每家公司的限制不一样。以至于不太好进行归纳总结。
所以需要具体情况,具体分析
大致的需求如下:
长度:5~50
类型:字母,数字(有的邮箱名是不允许使用特殊字符的,但是在这里就不做限制了)
业务规则:一般不允许用"_(下划线)"开头或者结尾
那么测试点分析如下:
▲ 长度:
有效:5,6,49,50
无效:4,51
▲ 类型:
有效:纯字母,纯数字,数字+字母
无效:纯中文,纯符号,中文+符号
▲ 约束:
a、以 _ 开头
b、以 _ 结尾
c、为空,不填
d、前,中,后输入空格
@
▲ 需求:
必须要有@符号
▲ 测试点:
有效:邮箱地址中包含@
无效:邮箱地址中包不含@
域名
▲ 需求:
长度:2~20
类型:字母,数字(有的域名是不允许使用特殊字符的,但是在这里就不做限制了)
▲ 业务规则:
a、一般不允许用"_(下划线)"开头或者结尾
b、须包含 ".(点)"
c、必须包含.com或者.cn或者.com.cn
▲ 测试点:
长度:
有效:2,3,19,20
无效:1,21
类型:
有效:纯字母,数字+字母
无效:中文,符号,数字
约束:
有效:
a、以.com结尾
b、以.cn结尾
一、逻辑分析 汽车类(抽象父类) 含三个成员变量:品牌、车牌号、日租金;
含一个抽象方法用来计算租金;
轿车类(子类) 含一个特有属性,车型号;
重写父类抽象方法;
客车类(子类) 含一个特有属性,座位数;
重写父类抽象方法;
4.功能实现类(可以使用静态方法,方便调用) 初始化汽车仓库,使用Vehicle类对象数组;
主界面显示方法;
响应用户输入方法;
计算租金的方法;
5.主类main方法 由于静态方法,直接调用
二、上成品图 主界面
租汽车
3.租客车
4.错误输入提醒,并重新输入
三、源码 Vehicle类:
public abstract class Vehicle { //汽车车牌 private String numberplate; //品牌 private String brand; //租金 private double rent; //构造 public Vehicle() { } public Vehicle(String numberplate, String brand, double rent) { this.numberplate = numberplate; this.brand = brand; this.rent = rent; } //setter getter public String getNumberplate() { return numberplate; } public void setNumberplate(String numberplate) { this.
在MAC上彻底删除IntelliJ系列软件残留 1 将应用移至废纸篓进行删除 2 检查这些文件夹路径 ~/Library/Preferences/IntelliJIdea ~/Library/Caches/IntelliJIdea ~/Library/Application Support/IntelliJIdea ~/Library/ApplicationSupport/IntelliJIdea ~/Library/Logs/IntelliJIdea 3 rm -rf 清理以上文件夹内发现的app残留
在windows 环境下运行Hadoop例子,不打jar包,报错
Exception in thread “main” java.lang.UnsatisfiedLinkError: org.apache.hadoop.io.nativeio.NativeIO$Windows.access0
报错原因:本地的hadoop版本与lib文件中替换的编译hadoop.dll版本不对应。
先安装好Hadoop,并配置好环境变量。
解决办法有两个:
方法一:(推荐使用)
下载winutils,解压对应的hadoop版本,将bin目录下的hadoop.dll系统文件拷贝到C盘的C:\Windows\System32目录下
下载地址:https://github.com/kontext-tech/winutils
方法二:
1、在项目中创建一个包名为org.apache.hadoop.io.nativeio的包
2.在这个包下创建一个名为NativeIO.java的类
3.加入以下代码
/** * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License.
使用 JSON.parse(JSON.stringify()) 实现深拷贝是一种简单易用的方法,但也存在以下缺点:
无法处理函数和 undefined
JSON.stringify() 方法无法处理 JavaScript 中的函数和 undefined 值,这些值会被忽略掉,因此在使用该方法时需要注意。无法处理循环引用
如果原始对象中存在循环引用,即对象的某个属性引用了该对象本身,使用该方法就会抛出 TypeError 异常。 const obj = { a: 1, b: { c: 2 } }; obj.d = obj; // 报错:TypeError: Converting circular structure to JSON JSON.parse(JSON.stringify(obj)); 无法处理一些特殊对象
JSON.stringify() 方法无法处理某些特殊的 JavaScript 对象,如 RegExp、Error、Date 等,这些对象会被转换成空对象。 const obj = { a: /abc/, b: new Error('error'), c: new Date() }; const newObj = JSON.parse(JSON.stringify(obj)); console.log(newObj); // { a: {}, b: {}, c: '2022-02-22T12:34:56.
Spring中的观察者模式
发布的事件,Event,ApplicationEvent是一个抽象类继承了EventObject,EventObject是JDK中的类,所有的事件类都建议继承自EventObject。 public abstract class ApplicationEvent extends EventObject{} 事件监听器,ApplicationListener是一个接口,该接口继承了EventListener接口。EventListener接口是JDK中的接口,所有的事件监听器都建议继承EventListener接口。 @FunctionalInterface public interface ApplicationListener<E extends ApplicationEvent> extends EventListener {} 事件发布,ApplicationEventPublisher,ApplicationContext继承该接口,并在抽象实现类AbstractApplicationContext中做了实现。 applicationContext.publishEvent(new FileParseEvent(this, streamBean)); AbstractApplicationContext类中publishEvent方法实现:
/** * Publish the given event to all listeners. * @param event the event to publish (may be an {@link ApplicationEvent} * or a payload object to be turned into a {@link PayloadApplicationEvent}) * @param eventType the resolved event type, if known * @since 4.2 */ protected void publishEvent(Object event, @Nullable ResolvableType eventType) { Assert.
使用jetson xavier 运行jetson-io.py闪退 问题描述问题种类以及解决方法解决方法1.RuntimeError: Multiple APP partitions mounted!2.ImportError: cannot import name 'board'!3.No DTB found for NVIDIA Jetson Nano Developer Kit!’ 小结 问题描述 在配置gpio的时候,运行/opt/nvidia/jetson-io/jetson-io.py时界面一闪而过,无法正常使用配置。
问题种类以及解决方法 通过less参数来查看报错
sudo /opt/nvidia/jetson-io/jetson-io.py | less 解决方法 1.RuntimeError: Multiple APP partitions mounted! 首先创建patch.diff文件,并写入下面内容:
diff --git a/jetson-io/Jetson/board.py b/jetson-io/Jetson/board.py index 8d0eb86..aa540e2 100644 --- a/jetson-io/Jetson/board.py +++ b/jetson-io/Jetson/board.py @@ -117,6 +117,22 @@ def _board_get_dtb(compat, model, path): return dtbs[0] +def _board_root_partition_is_block_device(): + dev = syscall.call_out('mountpoint -q -d /') + if not dev or len(dev) !
最近有考研的打算,准备考研科目,先是数据结构部分。习题如下;
1、求从大到小排序的L1,L2,L3交集(其中可能有多个相同元素在里面),最终结果也要按照从大到小的顺序排列,且不允许有重复值!!!
Linklist Interaction(Linklist L1,Linklist L2,Linklist L3){ node *p = L1->next; node *q = L2->next; node *r = L3->next; L1->next=NULL; #条件是求L1,使其包含三个表的交集,所以保留L1的结构 free(L2); free(L3); while(p&&q&&r){ node *tep; #node *t; if(p->data == q->data == r->data)#都相等把元素插入到L1中,然后三个表都做后移操作,进行下一轮比较 { tem = p; p = p->next; tem->next = L1->next; L1->next = tem;#此法为前插法,后插法的操作是加一个指针t,移动t的位置进行插入,上述的让t=L1,然后把L1换成t, tem = q;#在这一步前面加上t=tem操作就可实现后插操作 q = q->next; free(tem); tem = r; r = r->next; free(tem); } if(p->data <= q->data&&p->data <= r->data) { tem = p; p = p->next; free(tem); } elif(q->data <= p->data&&q->data <= r->data) { tem = q; q = q->next; free(tem); } else { tem = r; r = r->next; free(tem); } while(p){#到这一步说明有一个表已经到最后了,这样其他的表里面剩余的元素就没有共同的了,全部删除就可 tem = p; p = p->next; free(tem); } while(q){ tem = q; q = q->next; free(tem); } while(r){ tem = r; r = r->next; free(tem); } return L1; } } #总结一下 ###三个表的元素一起拿出来比大小,最小的往后推一位, ####如果都相等就把元素插入(前插法)L1中(要是题目要求最后目标也是有顺序的话,可以进行后插法的操作 2、已知L为链表的头结点地址,表中共有m(m>3)个结点,从表中第i个结点l
前言:我们之前的文章提到了操作系统的三个抽象,它们分别是进程、地址空间和文件,除此之外,操作系统还要控制所有的 I/O 设备。操作系统必须向设备发送命令,捕捉中断并处理错误。它还应该在设备和操作系统的其余部分之间提供一个简单易用的接口。操作系统如何管理 I/O 是我们接下来的重点。
不同的人对 I/O 硬件的理解也不同。对于电子工程师而言,I/O 硬件就是芯片、导线、电源和其他组成硬件的物理设备。而我们程序员眼中的 I/O 其实就是硬件提供给软件的接口,比如硬件接受到的命令、执行的操作以及反馈的错误。我们着重探讨的是如何对硬件进行编程,而不是其工作原理。
1,I/O 设备 什么是 I/O 设备?I/O 设备又叫做输入/输出设备,它是人类用来和计算机进行通信的外部硬件。输入/输出设备能够向计算机发送数据(输出)并从计算机接收数据(输入)。
I/O 设备(I/O devices)可以分成两种:块设备(block devices) 和 字符设备(character devices)。
2,块设备 块设备是一个能存储固定大小块信息的设备,它支持以固定大小的块,扇区或群集读取和(可选)写入数据。每个块都有自己的物理地址。通常块的大小在 512 - 65536 之间。所有传输的信息都会以连续的块为单位。块设备的基本特征是每个块都较为对立,能够独立的进行读写。常见的块设备有 硬盘、蓝光光盘、USB盘与字符设备相比,块设备通常需要较少的引脚。
2.1块设备的缺点 基于给定固态存储器的块设备比基于相同类型的存储器的字节寻址要慢一些,因为必须在块的开头开始读取或写入。所以,要读取该块的任何部分,必须寻找到该块的开始,读取整个块,如果不使用该块,则将其丢弃。要写入块的一部分,必须寻找到块的开始,将整个块读入内存,修改数据,再次寻找到块的开头处,然后将整个块写回设备。
字符设备
另一类 I/O 设备是字符设备。字符设备以字符为单位发送或接收一个字符流,而不考虑任何块结构。字符设备是不可寻址的,也没有任何寻道操作。常见的字符设备有 打印机、网络设备、鼠标、以及大多数与磁盘不同的设备。
下面显示了一些常见设备的数据速率:
2.2设备控制器 首先需要先了解一下设备控制器的概念:
资料直通车:最新Linux内核源码资料文档+视频资料
内核学习地址:Linux内核源码/内存调优/文件系统/进程管理/设备驱动/网络协议栈
设备控制器是处理 CPU 传入和传出信号的系统。设备通过插头和插座连接到计算机,并且插座连接到设备控制器。设备控制器从连接的设备处接收数据,并将其存储在控制器内部的一些特殊目的寄存器(special purpose registers) 也就是本地缓冲区中。
特殊用途寄存器,顾名思义是仅为一项任务而设计的寄存器。例如,cs,ds,gs 和其他段寄存器属于特殊目的寄存器,因为它们的存在是为了保存段号。 eax,ecx 等是一般用途的寄存器,因为你可以无限制地使用它们。 例如,你不能移动 ds,但是可以移动 eax,ebx。
通用目的寄存器比如有:eax、ecx、edx、ebx、esi、edi、ebp、esp
特殊目的寄存器比如有:cs、ds、ss、es、fs、gs、eip、flag
每个设备控制器都会有一个应用程序与之对应,设备控制器通过应用程序的接口通过中断与操作系统进行通信。设备控制器是硬件,而设备驱动程序是软件。
I/O 设备通常由机械组件(mechanical component)和电子组件(electronic component)构成。电子组件被称为 设备控制器(device controller)或者 适配器(adapter)。在个人计算机上,它通常采用可插入(PCIe)扩展插槽的主板上的芯片或印刷电路卡的形式。
机械设备就是它自己,它的组成如下:
控制器卡上通常会有一个连接器,通向设备本身的电缆可以插入到这个连接器中,很多控制器可以操作 2 个、4 个设置 8 个相同的设备。