open 打开文件 file=open(“文件名”,“读写模式”)
操作文件 代码段
关闭文件 file.close()
注意事项:使用open方法,文件操作完毕之后必须手动关闭,否则长期保持对文件的连接状态,造成内存溢出的现象发生。 with open 打开文件 with open (“文件名”,“读写模式”) as file:
操作文件 代码段
关闭文件(自动关闭) 注意事项:是自动关闭文件 如果对软件测试、接口测试、自动化测试、持续集成、面试经验。感兴趣可以进到893694563,群内会有不定期的分享测试资料。还会有技术大牛,业内同行一起交流技术
Static关键字 1. 修饰局部变量
**作用:**延长局部变量的生命周期
一般的局部变量在定义后,会在其所在的函数结束时自动释放空间,而static修饰的局部变量会将其生命周期延长到整个程序运行结束,然后再释放。
2. 修饰全局变量
**作用:**该全局变量只能在,其定义的文件内被调用,不能被其他文件调用
static定义的全局变量在静态区/(全局区)分配内存,定义全局变量时用static修饰可以保证数据的安全性。 3. 修饰函数
**作用:**被修饰函数的作用域被限定在当前源文件,其他文件不能访问该函数。
***以上为本人拙见,欢迎指正,如有侵权立删。***
RViz可视化 显示Costmap代价地图
点击左下角的add,选择Map类型
topic选择/move_base/global_costmap/costmap,即为全局代价地图
topic选择/move_base/local_costmap/costmap,即为局部代价地图 显示Plans规划结果
点击左下角的add,选择Path类型
topic选择/move_base/NavfnROS/plan,即为全局规划结果
topic选择/move_base/TrajectoryPlannerROS/local_plan,即为局部规划结果
2D工具
2D Pose Estimate可以提供初始位姿
2D Nav Goal可以提供导航目标点
这里两个工具在RViz的工具栏里,如果没有可以点击工具栏右侧的加号将其显示出来,并且此时Global Options中的Fixed Frame必须为map不然工具无法生效。
move_base节点 它的功能主要是把机器人从当前位置移动到目标位置。其本质上是一个SimpleActionServer的实现,即所谓的action(ROS三大通讯方式之一)的服务器,它使用geometry_msgs/PoseStamped格式的消息,因此我们可以使用SimpleActionClient向move_base发送目标点。
同时move_base提供了一个话题move_base/goal作为导航堆栈的输入,我们可以简单地将目标点发布至这个话题即可触发整个move_base的工作链。
查看topic列表会发现,move_base和其他action一样也提供了五个话题用于获取过程数据以及发送取消目标和获取结果。
move_base/goal (move_base_msgs/MoveBaseActionGoal)
move_base/cancel (actionlib_msgs/GoalID)
move_base/feedback (move_base_msgs/MoveBaseActionFeedback)
move_base/status (actionlib_msgs/GoalStatusArray)
move_base/result (move_base_msgs/MoveBaseActionResult)
使用RViz的2D Nav Goal工具发布一个目标位姿,其本质就是向move_base/goal主题发布了一条消息,下面我们监听move_base的这几个话题来看看在发布一个目标后发生了什么。
使用这种方式进行导航时,机器人会在规划生成后开始运动,如果你只是想查看规划结果又不想移动机器人,那么可以使用move_base提供的/make_plan这个服务接口,它可以只生成规划但不移动机器人。
现在我们知道,当move_base收到一个目标姿势, 它会链接到 global planner(全局规划器), local planner(局部规划器), recovery behaviors(恢复行为)以及costmaps(代价地图)等组件,并 生成一个消息类型为 geometry_msgs/Twist的速度命令输出 , 将其发送到 /cmd_vel 主题来移动机器人。
全局规划器 全局规划器就是在运动之前,根据接收到的目标位姿基于global_costmap提供的全局地图调用对应的路径规划算法生成一条从当前位置到目标位置的路径,这里的global_costmap就是根据之前加载的map.pgm数据而生成的,也就是说它在规划的过程中并未获取当前传感器的数据,这和局部规划器是有区别的,后面会讲到。
我们可以用第一节中使用的现实世界中导航的例子来说,这个全局规划器就相当于根据预先采集的地图数据,计算一条从当前位置到目标位置的可行(或最优)路径,但它不会考虑路况,也不会帮你避开拥堵路段,因为它的数据来源只有地图,并没有实时路况数据。
当前ROS中提供了三个全局规划器的插件:navfn,carrot_planner以及global_planner。其中navfn是最常见的也是默认的全局规划器,使用的是Dijkstra's算法来计算初始位置和目标位置之间的最短路径。carrot_planner的适用性不强,一般在某些特定的场景较为有效(比如让机器人移动到离障碍物尽可能近的场景)。global_planner可以说是navfn的升级版本,虽然navfn内置有Dijkstra's和A*的两种算法的实现,但是在早期版本中A*算法的实现有些bug未修复,故认为navfn使用的是Dijkstra's算法,而在之后版本的升级中为了兼容老版本,所以保留了navfn但也推出了global_planner,global_planner既提供了Dijkstra's和A*算法的实现,还支持自定义的全局规划器插件,可以说比navfn更为灵活。
这里选择global_planner做为全局规划器,对于global_planner的具体参数,这里创建一个global_planner_params.yaml文件,用于管理相关参数,完整参数介绍可参见:http://wiki.ros.org/global_planner
GlobalPlanner:
allow_unknown: false #默认true,是否允许路径穿过未知区域
default_tolerance: 0.2 #默认0.0,目标容差
visualize_potential: false #默认false,是否显示从PointCloud2计算得到的势区域
use_dijkstra: true #默认true,true表示使用dijkstra's否则使用A*
684. 冗余连接 思路:有一系列的边连成的图,找出一条边,移除它之后该图能够成为一棵树。 Input: [[1,2], [1,3], [2,3]] Output: [2,3] Explanation: The given undirected graph will be like this: 1 / \ 2 - 3 如果移除一条边可以成为一棵树那就意味着这个图存在环路,那么移除这个环的任意边即可(题目要求是最后一条边),所以我们可以使用并查集来记录每个节点的最前前驱节点,也就是父节点,如果两个节点的父节点相同,证明这两个节点是相连的,如果这两个节点不相连,我们可以将其父节点改成相同来使这两个节点连同。现在我们来定义并查集的数据结构:
class DSU{ int[] parent; public DSU(int N){ parent = new int[N+1]; for(int i=0;i<N;i++){ parent[i] = i; } } public int find(int x){ if(parent[x] != x) parent[x] = find(parent[x]); return parent[x]; } public void union(int x,int y){ parent[find(x)] = find(y); } } 然后创建一个DSU对象进行上述操作,在本题中,我们只要遇到两个不相连的节点,如果遍历到他们的边,则将其联通,如果本身就联通又遍历到他们的边,那证明存在环,移除即可。
public int[] findRedundantConnection(int[][] edges) { int N = edges.
Centos 升级内核 升级Centos内核版本,同时添加fake numa node 配置
1. 下载内核源码 由于,光从官网上上找不到对应的历史版本,可以参考博客 https://blog.csdn.net/a20132848/article/details/90754387 进行下载。
如下载5.4
wget http://cdn.kernel.org/pub/linux/kernel/v5.x/linux-5.4.tar.xz 2. build内核 参考博客 https://blog.51cto.com/191226139/2059117
https://www.linuxidc.com/Linux/2017-11/148276.htm
2.1. 解压并清理 官网要求将源码放到 /usr/src下面,其实放到哪里都可以。
# 解压内核 tar -Jxvf linux-5.4.tar.xz mv linux-5.4 /usr/src/kernels # 清理内核 cd /usr/srckernels/linux-5.4 make mrproper && make clean 2.2. 生成编译配置表 kernel在编译时需要一个配置文件(.config),用于描述开启哪些特性等,
我们采用 make menuconfig方式来获取配置文件。运行命令时,会看到报缺少对应库的错误,直接安装重新运行就行。
# 安装缺少的库 yum install -y ncurses-devel flex bison # 运行配置,默认就可以 make menuconfig 然后,根据需要修改配置文件(.config)
如,我们的目标一,开启虚拟numa支持,
numa配置如下:参考 http://linux-hacks.blogspot.com/2009/07/fake-numa-nodes-in-linux.html
# 打开配置选项 CONFIG_NUMA = y,CONFIG_NUMA_EMULATION = y numa=fake=2 2.
查看ubuntu系统版本的命令通常有
查看内核版本信息
uname -a 查看ubunutu版本号,如14.04,16.04
lsb_release -a 但是具体到判断是否为UbuntuKylin(优麒麟)版本的时候,上面两种方法就失效了。
不过可以通过下面两个命令判断
gedit /etc/apt/sources.list 或者 vim /etc/apt/sources.list 有图形界面的建议使用gedit,没有的话建议使用vim或者vi命令查看 /etc/apt/sources.list 这个文件。
打开sources.list 文件以后,只要看第一行就行。
如下图所示
这是常见的ubuntu版本。
这是汉化的ubuntuKylin(优麒麟),汉化版的ubuntu系统。
RT 安装vs时,前期用不到的工作负载没有下载。后期需要时,总是忘记如何安装工作负载。
记录一下,防止忘记。
工具 ——> 获取工具和功能
激活函数123 Sigmoid1. 公式2. 导数导数推导导数分析 3. sigmoid性质带来的问题饱和区Saturation problem: non zero-centered优化方向 Gradient Vanishing tanh1. 公式2. 导数导数推导导数分析 3. 优点与问题Saturation ProblemGradient Vanishingzero-centered relu1. 公式2. 导数3.优势No Gradient VanishingRepresentational Sparsity 3. 问题dying ReLu problem原因Solution Reference 写这篇文章的起因是我被问了一个问题: ”Sigmoid和tanh的不同是什么?“ Sigmoid 1. 公式 S i g m o i d ( x ) = e x 1 + e x = 1 1 + e − x \begin{aligned} Sigmoid(x)&=\frac{e^x}{1+e^x} \\ &=\frac{1}{1+e^{-x}} \end{aligned} Sigmoid(x)=1+exex=1+e−x1
值域为 ( 0 , 1 ) (0,1) (0,1)非对称 S i g m o i d ( 0 ) = 0.
本文主要记录了一次通过结合环境光与HDR贴图来实现3D场景的渲染。(Threejs版本 r0.118.0)
依赖包的导入 import { Scene, PerspectiveCamera, Color, WebGLRenderer, LinearToneMapping, AmbientLight, Vector3, Group, PMREMGenerator, UnsignedByteType, HemisphereLight, } from 'three'; import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls'; // 控制器 import { GLTFLoader, GLTF } from 'three/examples/jsm/loaders/GLTFLoader'; // gltf文件加载 import { RGBELoader } from 'three/examples/jsm/loaders/RGBELoader'; 添加环境光 // this.scene = ... this.scene.add(new AmbientLight(0xffffff, 1)); const hemiLight = new HemisphereLight(0xffffff, 0x000000, 1); hemiLight.position.set(0, 100, 0); this.scene.add(hemiLight); 设置WebGLRenderer // this.threeContainer = document.getElementById( // 'xxxx' // ) as HTMLElement; this.
121-只允许买卖一次 n * 2 空间的dp表:
class Solution { public: int maxProfit(vector<int>& prices) { const int n = prices.size(); if (n == 0) return 0; // 初始化第0天的情况 vector<vector<int>> dp(n, vector<int>(2, 0)); dp[0][0] = 0; dp[0][1] = -prices[0]; for(int i = 1; i < n; i++) { dp[i][0] = max(dp[i-1][0], dp[i-1][1] + prices[i]); dp[i][1] = max(dp[i-1][1], -prices[i]); //-prices[i]之前不需要加dp[i-1][0],因为只允许买一次,之前都是0 } return dp[n-1][0]; } }; 简化空间开销:
class Solution { public: int maxProfit(vector<int>& prices) { const int n = prices.
一、前言 还记得上次我写过几篇在实际项目中如何使用jwt《公众号授权 + jwt》、《小程序授权+ jwt》、《微信支付》
紧接着,就有个小伙伴,问了我一个这样的问题:授权使用=jwt签发token后,登录、注册等,用户是不需要token的,此时,应该怎么排除这些请求的url呢?
得嘞,今天咱们就掰扯掰扯这件事,如何使用“过滤器”或“拦截器”实现登录、注册的过滤
二、 是不是有人也这么写过? 在写此文时,我曾想到小编曾经的SAO操作,回看自己的代码,我滑稽的笑了。
因为小编的Controller层代码都是类似这样写的:
@RestController public class LoginController { @Resource private HttpServletRequest request; @Resource private JwtUtil jwtUtil; @ApiOperation(value = "根据订单id删除订单接口") @PostMapping(value = "/deleteById") public RespResult deleteById(String id) { String header = request.getHeader("token");//获取头信息,头中key为token if (StringUtils.isEmpty(header)) { return new RespResult(400, "请求头不能为空"); //头为空返回权限不足 } if (!header.startsWith("Bearer ")) { // 和前端约定,头的值是Bearer + 空格 + jwt签发的token return new RespResult(400, "token错误");//头不符合约定,返回权限不足 } String token = header.substring(7); //提取头中的token Claims claims = jwtUtil.
使用先电IaaS云平台创建云主机 创建云主机的操作流程 使用先电IaaS云平台创建云主机* 创建外部网络* 创建内部网络* 创建路由* 关联网络* 上传 centos 7云主机镜像* 创建安全组* 创建云主机* 绑定浮动IP* 使用远程连接工具连接云主机 1、登录先电IaaS云平台。如图所示。
2、创建网络
* 创建外部网络 * 创建内部网络 * 创建路由 * 关联网络 * 上传 centos 7云主机镜像 * 创建安全组 * 创建云主机 * 绑定浮动IP * 使用远程连接工具连接云主机 至此,创建云主机完成。
1.组成原理相关 冯诺依曼结构,哈佛结构 单片机为了存储器管理的方便(便于支持操作系统),一般采用指令、数据空间统一编码的冯·诺依曼结构。 DSP为了提高数据吞吐的速度,基本上都是指令、数据空间独立的哈佛结构。
因为ARM7系列采用冯·诺依曼体系结构,而ARM9~ARM11采用哈佛体系机构
ROM,RAM RAM又被称作“随机存储器”,有片内ram,也有片外ram,
片内ram用来存放中断处理handler、RTOS调度器、任务上下文切换、内存分配释放等使用频率最高的代码和中断堆栈这种读写频率极高的内存区,如果有多余的部分也可以放一些经常被引用到的全局变量。
片外RAM一般就是用来存储全局变量,bss,以及我们常用到的malloc所分配的堆空间等。
ROM一般是有两种,一种是指集成在CPU芯片内部的一块只读存储区域,一般是几K到几十K字节大小,用来存储系统刚上电时对cpu和一些核心外设(如时钟,串口,MMU、DRAM、Flash等)进行初始化的代码,它在程序运行中也是不可写的,要对它执行写操作只能使用硬件烧写器进行,也就是一般所说的下载程序,这部分的代码在芯片测试阶段可以进行编程器下载更新,量产后一般就会固化,不能做任何修改的;
ROM另一种指的就是flash。首先需要说明的是,很多做嵌入式应用开发的同学一直把flash比作PC上的硬盘,其实它们指的是Nand flash,而对于很多小型的嵌入式系统,就只有一个2M或者4M的Nor Flash,它和硬盘有一个显著的区别:flash里存放的代码是可以由CPU直接取指并执行的,而PC上硬盘里的程序都需要加载到内存里才能运行。flash并不是绝对的运行时不可写,有时候应用程序需要保存一些配置信息到flash里,类似于PC程序的配置文件,以保证掉电了之后它的内容不会丢失,下次开机时可以直接从flash读取到。
首先考虑一下,有没有什么东西必须放在ROM里? 当然有,引导程序(系统的初始化代码)就必须放到ROM里。在CPU刚上电时,只能去一个默认的地址去取第一条指令,开始干活,这个地址都是映射到片内的ROM里,原因很简单,此时,作为外设的flash和DDR等都还没有初始化,CPU根本无法从它们那里读写数据,片内ROM里的这些代码就需要完成这些模块的初始化。另外,一个项目的处理器和主要外设确定了以后,这部分初始化代码在很长的时间里,都不需要做任何修改的。 用户空间与内核通信方式有哪些? 1)首先想到的是系统调用,用户空间进程通过系统调用进入内核空间,访问指定的内核空间数据;
2).其次是驱动程序,用户空间进程可以使用封装后的系统调用接口访问驱动设备节点,以和运行在内和空间的驱动程序通信;
3).共享内存mmap,在代码中调用接口,实现内核空间与用户空间的地址映射,在实时性要求很高的项目中为首选,省去拷贝数据的时间等资源,但缺点是不好控制;
4).最后,copy_to_user()、copy_from_user(),是在驱动程序中调用接口,实现用户空间与内核空间的数据拷贝操作,应用于实时性要求不高的项目中。
系统调用read()/write(),内核具体做了哪些事情 用户空间read()-->内核空间sys_read()-->scull_fops.read-->scull_read();
该过程分为两个部分:用户空间的处理和核心空间的处理。在用户空间中通过 0x80 中断的方式将控制权交给内核处理,内核接管后,经过6个层次的处理最后将请求交给磁盘,由磁盘完成最终的数据拷贝操作。在这个过程中,调用了一系列的内核函数
内核态与用户态的区别 系统态(也称为管态或核心态),操作系统在系统态运行——运行操作系统程序
用户态(也称为目态),应用程序只能在用户态运行——运行用户程序
当一个进程在执行用户自己的代码时处于用户运行态(用户态),此时特权级最低,为3级,是普通的用户进程运行的特权级,大部分用户直接面对的程序都是运行在用户态。Ring3状态不能访问Ring0的地址空间,包括代码和数据;当一个进程因为系统调用陷入内核代码中执行时处于内核运行态(内核态),此时特权级最高,为0级。执行的内核代码会使用当前进程的内核栈,每个进程都有自己的内核栈。
用户运行一个程序,该程序创建的进程开始时运行自己的代码,处于用户态。如果要执行文件操作、网络数据发送等操作必须通过write、send等系统调用,这些系统调用会调用内核的代码。进程会切换到Ring0,然后进入3G-4G中的内核地址空间去执行内核代码来完成相应的操作。内核态的进程执行完后又会切换到Ring3,回到用户态。这样,用户态的程序就不能随意操作内核地址空间,具有一定的安全保护作用。这说的保护模式是指通过内存页表操作等机制,保证进程间的地址空间不会互相冲突,一个进程的操作不会修改另一个进程地址空间中的数据。
系统的启动过程 整个系统的加载启动任务就完全由BootLoader来完成。BootLoader就是在操作系统内核运行之前运行的一段小程序。通过这段小程序,我们可以初始化硬件设备、建立内存空间的映射图,从而将系统的软硬件环境带到一个合适的状态,以便为最终调用操作系统内核准备好正确的环境。
启动顺序:bootloader->linuxkernel->rootfile
后者需要前者提供功能支持,前者的目的就是启动后者。
嵌入式Linux系统启动过程Linux引导的整个过程:当系统首次引导时,或系统被重置时,处理器会执行一个位于Flash/ROM中的已知位置处的代码,Bootloader就是这第一段代码。它主要用来初始化处理器及外设,然后调用Linux内核。Linux内核在完成系统的初始化之后需要挂载某个文件系统作为根文件系统(RootFilesystem),然后加载必要的内核模块,启动应用程序。(一个嵌入式Linux系统从软件角度看可以分为四个部分:引导加载程序(Bootloader),Linux内核,文件系统,应用程序。)
嵌入式Linux系统通过Bootloader引导,一上电,就要执行Bootloader来初始化系统。在完成对系统的初始化任务之后,它会将非易失性存储器(通常是Flash或DOC等)中的Linux内核拷贝到RAM中去,然后跳转到内核的第一条指令处继续执行,从而启动Linux内核。Bootloader和Linux内核有着密不可分的联系。
进程相关 IPC(进程间通信)机制中最快的,共享内存,只需要两次拷贝而已
内核抢占
内核抢占:如果进程正在执行内核函数时(即它在内核态运行时),允许发生内核切换(被替换的进程是正在执行内核函数的进程),这个内核就是抢占的。
运行在内核态的进程可以自动放弃cpu,称为计划性进程切换,抢占式内核中,进程被迫放弃CPU,称为强制性进程切换。抢占内核的主要特点是:一个内核态运行的进程,可能在执行内核函数期间被另一个进程取代。
Linux内核同步方式总结 https://blog.csdn.net/yyf_it/article/details/52416994
为什么自旋锁不能睡眠 而在拥有信号量时就可以
自旋锁禁止处理器抢占;而信号量不禁止处理器抢占。
基于这个原因,如果自旋锁在锁住以后进入睡眠,由于不能进行处理器抢占,其他系统进程将都不能获得CPU而运行,因此不能唤醒睡眠的自旋锁,因此系统将不响应任何操作(除了中断或多核的情况,下面会讨论)。而信号量在临界区睡眠后,其他进程可以用抢占的方式继续运行,从而可以实现内存拷贝等功能而使得睡眠的信号量程序由于获得了等待的资源而被唤醒,从而恢复了正常的代码运行。
内存模块相关 简述处理器在读内存的过程中,CPU核、cache、MMU如何协同工作?画出CPU核、cache、MMU、内存之间的关系示意图加以说明。 现代操作系统普遍采用虚拟内存管理(Virtual Memory Management) 机制,这需要MMU(Memory Management Unit,内存管理单元) 的支持。有些嵌入式处理器没有MMU,则不能运行依赖于虚拟内存管理的操作系统。
也就是说:操作系统可以分成两类,用MMU的、不用MMU的。用MMU的是:Windows、MacOS、Linux、Android;不用MMU的是:FreeRTOS、VxWorks、UCOS……与此相对应的:CPU也可以分成两类,带MMU的、不带MMU的。带MMU的是:Cortex-A系列、ARM9、ARM11系列;不带MMU的是:Cortex-M系列……(STM32是M系列,没有MMU,不能运行Linux,只能运行一些UCOS、FreeRTOS等等)。
CPU通过地址来访问内存中的单元,如果CPU没有MMU,或者有MMU但没有启动,那么CPU内核在取指令或者访问内存时发出的地址(此时必须是物理地址,假如是虚拟地址,那么当前的动作无效)将直接传到CPU芯片的外部地址引脚上,直接被内存芯片(物理内存)接收,这时候的地址就是物理地址;
如果CPU启用了MMU(一般是在bootloader中的eboot阶段的进入main()函数的时候启用),CPU内核发出的地址将被MMU截获,这时候从CPU到MMU的地址称为虚拟地址,而MMU将这个VA翻译成为PA发到CPU芯片的外部地址引脚上,也就是将VA映射到PA中。
MMU将VA映射到PA是以页(page)为单位的,对于32位的CPU,通常一页为4k,物理内存中的一个物理页面称页为一个页框(page frame)。虚拟地址空间划分成称为页(page)的单位,而相应的物理地址空间也被进行划分,单位是页框(frame)。页和页框的大小必须相同。
1.CPU内核(图1中的ARM)发出VA请求读数据,TLB(translation lookaside buffer)接收到该地址,那为什么是TLB先接收到该地址呢?因为TLB是MMU中的一块高速缓存(也是一种cache,是CPU内核和物理内存之间的cache),它缓存最近查找过的VA对应的页表项,如果TLB里缓存了当前VA的页表项就不必做translation table walk了,否则就去物理内存中读出页表项保存在TLB中,TLB缓存可以减少访问物理内存的次数;
2.页表项中不仅保存着物理页面的基地址,还保存着权限和是否允许cache的标志。MMU首先检查权限位,如果没有访问权限,就引发一个异常给CPU内核。然后检查是否允许cache,如果允许cache就启动cache和CPU内核互操作;
3.如果不允许cache,那直接发出PA从物理内存中读取数据到CPU内核;
4.如果允许cache,则以VA为索引到cache中查找是否缓存了要读取的数据,如果cache中已经缓存了该数据(称为cache hit)则直接返回给CPU内核,如果cache中没有缓存该数据(称为cache miss),则发出PA从物理内存中读取数据并缓存到cache中,同时返回给CPU内核。但是cache并不是只去CPU内核所需要的数据,而是把相邻的数据都取上来缓存,这称为一个cache line。ARM920T的cache line是32个字节,例如CPU内核要读取地址0x30000134~0x3000137的4个字节数据,cache会把地址0x30000120~0x3000137(对齐到32字节地址边界)的32字节都取上来缓存
jedis、redisson、lettuce
https://cloud.tencent.com/developer/article/1500854 概况 Jedis是Redis的Java实现的客户端,其API提供了比较全面的Redis命令的支持;Jedis中的方法调用是比较底层的暴露的Redis的API,也即Jedis中的Java方法基本和Redis的API保持着一致,了解Redis的API,也就能熟练的使用Jedis。Redisson实现了分布式和可扩展的Java数据结构,提供很多分布式相关操作服务,例如,分布式锁,分布式集合,可通过Redis支持延迟队列。和Jedis相比,功能较为简单,不支持字符串操作,不支持排序、事务、管道、分区等Redis特性。Redisson的宗旨是促进使用者对Redis的关注分离,从而让使用者能够将精力更集中地放在处理业务逻辑上。Redisson中的方法则是进行比较高的抽象,每个方法调用可能进行了一个或多个Redis方法调用。Lettuce:高级Redis客户端,用于线程安全同步,异步和响应使用,支持集群,Sentinel,管道和编码器。目前springboot默认使用的客户端。 伸缩性: Jedis:使用阻塞的I/O,且其方法调用都是同步的,程序流需要等到sockets处理完I/O才能执行,不支持异步。Jedis客户端实例不是线程安全的,所以需要通过连接池来使用Jedis。Jedis仅支持基本的数据类型如:String、Hash、List、Set、Sorted Set。Redisson:基于Netty框架的事件驱动的通信层,其方法调用是异步的。Redisson的API是线程安全的,所以可以操作单个Redisson连接来完成各种操作。Redisson不仅提供了一系列的分布式Java常用对象,基本可以与Java的基本数据结构通用,还提供了许多分布式服务,其中包括(BitSet, Set, Multimap, SortedSet, Map, List, Queue, BlockingQueue, Deque, BlockingDeque, Semaphore, Lock, AtomicLong, CountDownLatch, Publish / Subscribe, Bloom filter, Remote service, Spring cache, Executor service, Live Object service, Scheduler service)。Lettuce:基于Netty框架的事件驱动的通信层,其方法调用是异步的。Lettuce的API是线程安全的,所以可以操作单个Lettuce连接来完成各种操作。 说说Redission特性 详见: https://github.com/redisson/redisson/wiki/%E7%9B%AE%E5%BD%95
功能说明如下: 1. 概述2. 配置方法 2.8.1. 主从模式设置2.8.2. 通过JSON、YAML和Spring XML文件配置主从模式2.7.1. 哨兵模式设置2.7.2. 通过JSON、YAML和Spring XML文件配置哨兵模式2.6.1. 单节点设置2.6.2. 通过JSON、YAML和Spring XML文件配置单节点模式2.5.1. 云托管模式设置2.5.2. 通过JSON、YAML和Spring XML文件配置云托管模式2.4.1. 集群设置2.4.2. 通过JSON、YAML和Spring XML文件配置集群模式2.2.1 通过JSON或YAML格式配置2.2.2 通过Spring XML命名空间配置2.1. 程序化配置2.2. 文件方式配置2.3. 常用设置2.4. 集群模式2.5. 云托管模式2.6. 单Redis节点模式2.7. 哨兵模式2.8. 主从模式3.
前言 低频下,按电池理解二极管即可,但是当高频信号加在二极管两端时,就要考虑二极管的动态特性了。
二极管的单向导电特性并不十分理想,这是因为二极管的本质是有P型半导体和N型半导体接触形成的PN结。
PN结除了除了构成单向到点的二极管外,还存在一个结电容:
结电容导致"双向"导电 结电容对二极管当然不是什么好事,这实际上使二极管可以流过一定量的反向电荷。
实际二极管需要一定的时间来恢复反向阻断能力。Trr称为反向恢复时间(reverse revovery)。
二极管的结电容大小 不同工艺结构可以使结电容的大小不一样。
1、点接触的PN结,可以减小结电容,但会降低二极管的通流能力。
2、面接触,通流能力强,但是结电容更大。
看下面两个例子:
1N4007 (面接触型)
1N4148(点接触型)
结电容对单向导电性的影响 1、低频时,反向导电占整个周期的比例很小,二极管仍可以看成是单向导电的。
2、高频时,如果反向导电占整个周期的比例很大,二极管称为“双向导电”器件,也就无法使用了。
二极管反向恢复过程 实际二极管的反向恢复曲线如图所示,蓝色是反向恢复电流曲线,黄色是反向恢复电压曲线。
在Tf时刻前,二极管正向导通,Uf就是通常说的0.7V,If很大。
随后电路试图给二极管加反压,但是反压不是立马能加上去的,二极管的电流If在t0 时刻降到0。
t0 - t1 这段时间,二极管电流不仅不消失,反而成为反向电流,且不断增加。这段时间称为Td (delay),表示的含义是(不服从控制)延迟时间。
t1时刻反向电流达到最大,t1 - t2 时间段反向电流最终减小到0,称之为下降时间Tf(fall)。
td 和 tf 加起来就是反向恢复时间Trr。这段时间二极管是反向导通的。
可以想象,如果加在二极管上的信号周期与反向恢复时间Trr 在数量级上可比拟的话,二极管实际效果是全通的。
所以。反向恢复时间Trr决定了二极管可适用的频率场合。
简单对二极管反向恢复电压进行分析,反向恢复电流达到峰值Irp以后急剧减小,也就说明下降时间Tf其实很小。
这样一来在线路上的寄生电感上会产生尖峰电压Urp(reveres peak ),这是十分有害的,可能会击穿二极管。
恢复系数 Tf/Td 用来描述二级管反向回复的“软度”,恢复系数越大,约不容易产生有害高压。
也就是一方面我们希望反向恢复时间Trr越短越好,另一方面我们还希望下降时间Tf所占的时间比重越大越好。
我们来看看高频二极管1N4148的反向恢复时间: 4ns
思考 二极管的反向恢复时间跟结电容大小有关系么?
1. 前向传播和反向传播 在讲解梯度消失和梯度爆炸之前,我们需要先了解什么是前向传播和反向传播。
前向传播: 输入层数据开始从前向后,数据逐步传递至输出层。
反向传播: 损失函数从后向前,梯度逐步传递至第一层。
在讲解前向传播和反向传播计算过程之前,我们先介绍一下计算图的概念,通过计算图可以很清楚的了解后向传播的计算过程,以3层网络为例。
蓝色圆圈表示运算操作,分别为乘法,激活函数,乘法,损失函数;白色框框表示传播的数值;蓝色框框表示权重;
前向传播不同多说,不断的乘以权重在通过激活函数即可;
反向传播的计算过程本质是链式求导过程。下面为 W 1 W_1 W1的计算过程,从后向前逐步进行计算。
2. 梯度消失和梯度爆炸产生的原因 了解了前向传播和反向传播机制之后,再去了解梯度消失、爆炸就很简单了。
以5层网络为例,激活函数为 f ( z ) f(z) f(z), f i + 1 = f ( f i ⋅ x ) f_{i+1} = f(f_i \cdot x) fi+1=f(fi⋅x),通过计算图给出 W 1 W_1 W1的梯度推导公式,我们将根据这个公式进行梯度消失、爆炸的分析。
Δ W 1 = ∂ l o s s ∂ o u t ∂ o u t ∂ f 3 ∂ f 3 ∂ 2 ∂ f 2 ∂ f 1 ∂ f 1 ∂ W 1 = ∂ l o s s ∂ o u t W 4 f ′ W 3 f ′ W 2 f ′ x Δ W 2 = ∂ l o s s ∂ o u t ∂ o u t ∂ f 3 ∂ f 3 ∂ f 2 ∂ f 2 ∂ W 2 = ∂ l o s s ∂ o u t W 4 f ′ W 3 f ′ f 1 \Delta W_1 = \frac {\partial loss} {\partial out} \frac {\partial out} {\partial f3} \frac { \partial f3} {\partial 2} \frac {\partial f2} {\partial f1} \frac {\partial f1} {\partial W_1} \\ \quad \\ = \frac {\partial loss} {\partial out} W_4f'W_3f'W_2f'x \\ \quad \\ \Delta W_2 = \frac {\partial loss} {\partial out} \frac {\partial out} {\partial f3} \frac { \partial f3} {\partial f_2} \frac {\partial f_2} {\partial W_2} \\ \quad \\ = \frac {\partial loss} {\partial out} W_4f' W_3f'f_1 ΔW1=∂out∂loss∂f3∂out∂2∂f3∂f1∂f2∂W1∂f1=∂out∂lossW4f′W3f′W2f′xΔW2=∂out∂loss∂f3∂out∂f2∂f3∂W2∂f2=∂out∂lossW4f′W3f′f1
easyexcel 日期、数字格式化 ********************* 相关注解
@DateTimeFormat:标注在字段上
@Target({ElementType.FIELD}) @Retention(RetentionPolicy.RUNTIME) @Inherited public @interface DateTimeFormat { String value() default ""; boolean use1904windowing() default false; } 写入excel sheet中时,转换为指定格式(value)的字符串;
从excel sheet中读取value格式的字符串,转换为对应的日期类型
@NumberFormat:标注在字段上
@Target({ElementType.FIELD}) @Retention(RetentionPolicy.RUNTIME) @Inherited public @interface NumberFormat { String value() default ""; RoundingMode roundingMode() default RoundingMode.HALF_UP; } 写入excel sheet中时,转换为指定格式(value)的字符串;
从excel sheet中读取value格式的字符串,转换为对应的数字类型
********************* 示例
*************
head 类
Order
@Data public class Order { private Integer id; private Date createTime; @DateTimeFormat("yyyy-MM-dd") private Date payTime; @NumberFormat("##.00") private Double totalFee; } *************
用的是transformers,进入 hugging face 的这个网站:bert-base-chinese · Hugging Face
在 Files and Versions 中对应下载或另存为(有的下完要重命名一下)
所需要的就是 config.json, pytorch_model.bin, vocab.txt 这几个文件
建立了如下文件夹路径来存放这些文件
└─bert
│ vocab.txt
│ └─bert-base-chinese
config.json
pytorch_model.bin
from transformers import BertTokenizer vocab_file = 'bert/vocab.txt' tokenizer = BertTokenizer(vocab_file) from transformers.modeling_bert import BertModel bert = BertModel.from_pretrained("bert/bert-base-chinese/") 此处用的 transformers的版本是3.2.0
往下具体再怎么使用,可以去github找一些具体任务,
如文本分类之类的项目代码,看处理步骤。
放一个我以前跟着做的法研杯的一个任务,有基线代码
学会使用pytorch的bert也是从这个基线代码学到的,不过单机多卡的分布式训练还没搞懂:
CAIL2020-Argument-Mining/model.py at master · gaoyixu/CAIL2020-Argument-Mining · GitHubhttps://github.com/gaoyixu/CAIL2020-Argument-Mining/blob/master/model.py#L28
CAIL2020-Argument-Mining/data.py at master · gaoyixu/CAIL2020-Argument-Mining · GitHubhttps://github.com/gaoyixu/CAIL2020-Argument-Mining/blob/master/data.py#L117
本文介绍另一个控件Scrollbar,在tkinter-Text详解一文中有提到过Scrollbar,但是没有做过多的说明。因此本文将详解Scrollbar及其使用场景。
文章目录 Scrollbarelementorientactivebackgroundbackgroundcursorjumprepeatdelayrepeatintervaltakefocuscommandset()什么是可滚动控件?scrollbar和可滚动控件的关系?scrollbar与可滚动控件的绑定 Scrollbar Scrollbar 一般和其他控件联合使用,当被显示的控件的内容大于可显示区域时,使用Scrollbar可显示更多的内容。一般垂直滚动条(vertical scrollbar)和Listbox, Text and Canvas联合使用;水平滚动条(horizontal scrollbar)也可作用于Entry。
首先还是介绍Scrollbar的常用属性和方法,最后再举几个结合其他控件的实例。
element scrollbar的5个elements
arrow1,arrow2 指滚动条两端的箭头
slider 指scrollbar中的滑块
trough1,trough2 指非slider区域,可以称为槽
可通过slider拖动来改变视图,也可点击 arrow1或arrow2来改变视图,也可点击 trough1或trough2来改变视图。所谓视图,简单讲就是滑块的位置发生了改变,相应的显示内容也跟着变化。
orient 滚动条方向属性,通常有两个值"vertical"(默认值)和"horizontal"。即垂直滚动条和水平滚动条。
# bar = Scrollbar(main_win, orient=VERTICAL) bar = Scrollbar(main_win, orient=HORIZONTAL) bar.pack() activebackground 当鼠标在滑块(slider)或箭头(arrowhead)上时,显示的背景颜色。windows上实测无效。
bar = Scrollbar(main_win, activebackground='red') bar.pack() background 指定背景颜色。window上实测无效
bar = Scrollbar(main_win, background='red') bar.pack() cursor 指定光标样式
bar = Scrollbar(main_win, cursor='cross') bar.pack() jump 控制用户拖动滑块时发生的动作。默认(jump=0)每拖动一次滑块,就会使command指定的回调函数被调用。如果jump=1,回调函数只在用户放开鼠标按键时被调用一次,在拖动过程中不会被触发。windows上实测无效。
repeatdelay 延迟x秒移动滑块。鼠标左键按下x秒数后,滑块在某个方向开始持续移动。通常用于滚动条中的向上和向下的箭头。windows上实测无效。
repeatinterval 一旦滑块在某方向的持续移动开始,repeatinterval决定了相邻两次移动动作的时间间隔, 一般和repeatdelay联合使用。windows上实测无效。
takefocus 可以使用tab键将焦点切换到scrollbar。如果takefocus=0,那么将关闭该功能。
command 对于scrollbar非常重要的交互属性。通常用于指定可滚动控件(scrollable widget)的xview或yview函数。
因为滚动条有两种动作: ‘moveto’和’scroll’,'moveto’对应slider的拖动,'scroll’对应arrow或trough的点击。我们来看看怎样指定command对应的回调函数。
暂定,还没时间写
教程地址 (借鉴) VMware虚拟机安装macOS 10.14教程
虚拟机解锁工具 macOS Unlocker for VMware v3.0.3
虚拟机安装macos 分辨率不正常修改不了,不能全屏如何解决
VMware15 安装 mac OS 10.14 分辨率调整为1920*1080?
VMware虚拟机已设置NAT,仍无法连接网络
VMware 三种网络连接模式的详细介绍和区别
VMware虚拟机三种联网方法及原理
%pylab inline
是matplotlib的代码,但只有jupyter notbook,要用到
plt未定义,用import matplotlib.pyplot as plt#定义plt
import pandas as pd train_df = pd.read_csv('F:/NLP/train_set.csv', sep='\t', nrows=100) train_df.head()#显示前五行 #句子长度分析 train_df['text_len'] = train_df['text'].apply(lambda x: len(x.split(' '))) print(train_df['text_len'].describe()) import matplotlib.pyplot as plt#定义plt #给句子长度绘制直方图 _ = plt.hist(train_df['text_len'], bins=200) plt.xlabel('Text char count') plt.title("Histogram of char count") #新闻类别分布 train_df['label'].value_counts().plot(kind='bar') plt.title('News class count') plt.xlabel("category") #字符分布统计 from collections import Counter all_lines = ' '.join(list(train_df['text'])) word_count = Counter(all_lines.split(" ")) word_count = sorted(word_count.items(), key=lambda d:d[1], reverse = True) print(len(word_count)) # 6869 print(word_count[0]) # ('3750', 7482224) print(word_count[-1]) # ('3133', 1) train_df['text_unique'] = train_df['text'].
5. Flink State管理跟恢复 Flink 是一个默认就有状态的分析引擎,前面的 WordCount 案例可以做到单词的数量的累加,其实是因为在内存中保证了每个单词的出现的次数,这些数据其实就是状态数据。但是如果一个 Task 在处理过程中挂掉了,那么它在内存中的状态都会丢失,所有的数据都需要重新计算。从容错和消息处理的语义(At -least-once 和 Exactly-once)上来说,Flink 引入了 State 和CheckPoint。
State 一般指一个具体的 Task/Operator 的状态(Task Slot/ 转换算子),State 数据默认保存在 Java 的堆内存中。CheckPoint(可以理解为CheckPoint是把State数据持久化存储了)则表示了一个 Flink Job 在一个特定时刻的一份全局状态快照,即包含了所有Task/Operator 的状态。
1. 常用 State Flink 有两种常见的 State 类型,分别是:
Keyed State(键控状态)Operator State(算子状态) 1. Keyed State(键控状态) Keyed State:顾名思义就是基于 KeyedStream上的状态,这个状态是跟特定的 Key 绑定的。KeyedStream 流上的每一个 Key,都对应一个 State。Flink 针对 Keyed State 提供了 以下可以保存 State 的数据结构:
ValueState<T>:
保存一个可以更新和检索的值(如上所述,每个值都对应到当前的输入数据的 key,因此算子接收到的每个 key 都可能对应一个值)。 这个值可以通过 update(T) 进行更新,通过 T value() 进行检索。ListState<T>:
保存一个元素的列表。可以往这个列表中追加数据,并在当前的列表上 进行检索。可以通过 add(T) 或者 addAll(List) 进行添加元素,通过 Iterable get()获得整个列表。还可以通过 update(List) 覆盖当前的列表。ReducingState<T>:
通过create-react-app创建react项目,亲测.eslintrc.js文件中的配置可以生效,可以使用
1、安装eslint:
yarn add eslint;方式1、项目目录下安装 npm install -g eslint ;方式2、全局安装 npm install eslint --save-dev ;方式3、本地安装 我在电脑上使用yarn add eslint,安装到了我的项目目录下
2、初始化配置文件和在package.json中添加依赖,这些问题答案视自己的项目情况而定,中间会有很多警告,对这个没有什么影响。
eslint --init 此时项目中出现了.eslintrc.js文件,在package.json中查看可以发现多了新的依赖项:
3、在vscode中添加插件eslint
4、修改文件->首选项->设置->settings.json的配置
setting.json配置:
{ "editor.fontSize": 16, "editor.codeActionsOnSave": { "source.fixAll.eslint": true }, "eslint.validate": [ "javascript", "javascriptreact", "vue" ], "files.autoSave": "off", "editor.formatOnType": true, "editor.formatOnSave": true, "files.associations": { "*.js": "javascriptreact" }, "workbench.colorTheme": "Default Dark+", "emmet.triggerExpansionOnTab": true, "vsicons.projectDetection.disableDetect": true, "workbench.iconTheme": "vscode-icons", "editor.tabSize": 2, "[json]": { "editor.defaultFormatter": "vscode.json-language-features" } } 此时,在项目目录ctrl+shift+p输入eslint,确保eslint已经启用了,此时保存时eslint就可以自动检测代码了,像双引号还可以自动修复为单引号。
注意:配置 "
1. 前言 前面学习了 SpringCloudAlibaba之服务注册与发现Nacos 以及 SpringCloudAlibaba之配置中心Nacos,其中Nacos服务都部署在本地,那么现在把它部署到服务器上。
在服务器上部署Nacos,有多种方式,
单机:
方式一: 拷贝三份编译后的 Nacos Server,分别修改端口,以及编写 cluster.conf 文件方式二: 启动三个 Nacos Server 的 Docker 容器方式三: 使用 docker-compose 编排三个 Nacos Server 服务 三台及以上:
方式一: 每台都拷贝一份编译后的 Nacos Server,以及编写 cluster.conf 文件方式二: 每台都启动一个 Nacos Server 的 Docker 容器方式三: 每台都使用 docker-compose 编排一个 Nacos Server 服务 最方便的当然是使用 docker-compose 来编排服务,本篇博客也是使用的 docker-compose 方式(单机)。这里除了会编排三个 Nacos Server 服务,还会增加 MySQL 服务和 Nginx 服务,这也是官方推荐的部署架构:
至少使用三个Nacos节点使用MySQL作为数据源,方便观察数据存储的基本情况使用Nginx作为统一入口,扩展节点的时候不影响后端应用 2. 源码 GitHub 地址:https://github.com/intomylife/Docker
Docker Hub 地址:https://hub.docker.com/r/intomylife
3. 部署 整个部署所需要的文件都在 build 目录中
一:漏洞名称: 用户名枚举 描述: 存在于系统登录页面,利用登陆时输入系统存在的用户名错误密码和不存在的用户名错误密码,返回不同的出错信息可枚举出系统中存在的账号信息。
检测条件: 1.已知Web网站具有登录页面。
2.登录错误回显不一至。
检测方法: 找到网站或者web系统登录页面。在web系统登录页面,通过手工方式,(注:利用工具和字典直接跑更方便,通常能枚举出来的用户名,一般密码都是弱口令)利用系统中存在的用户名和不存在的用户名,密码随意,尝试登录,查看其回显内容。例如:输入存在的用户名admin,回显如下:密码错误;输入不存在的用户名test,回显如下:用户不存在。如图所示: 漏洞修复: 建议对网站登录页面的判断回显信息修改为一致:用户名或密码错误
其他补充说明: 暂无。
对于head->next = p;和p=head->next;之间的区别,可能对于刚接触链表的你有点难理解其实结合图片就很容易理解
其实在说这两个之前我们可以用一个简单的语句来铺垫一下,比如int a=5;我们知道a就是一个整形数值的变量,下面的数值只代表一部分,此时我们令a=5;我们就让a指向5,把5赋值给a.
然后我们再先来说一说head->next = p;
然后我们再来说一说p=head->next;如果理解了上面的那个语句,那这个就不难了
网上对与head->next的理解也是不一样的,在链表中next是结点的指针域,我个人倾向于head->next表示的即为head的下一个结点,这在代码中感觉能更好地帮助理解,如有理解不对的地方,希望读者可以在评论区给予修正。
一、完成基于RTL8211E的千兆以太网外围电路的PCB实现
1.PCB的板级分析
采用了八层PCB板的制作工艺,层级分布分别为
TOP->GND->SIG1->PWR->PER2 ->SIG2->GND->BUTTOM.
其中,top层摆放主要器件并布放控制类信号线以及PHY连接RJ45的差分线;
GND层为参考层;
SIG1主要布放PHY至FPGA端的TX等长信号线;
PWR层主要提供AVDD10和DVDD10的供电电压;
PWR2层主要提供VCC33、DVDD33和AVDD33三种供电电压;
SIG2层主要布放PHY至FPGA端的RX等长信号线;
GND层为参考层;
BUTTOM层为布放因其他原因无法走线的电路;
2.电源设计
电源设计共占用两层PCB板,包括由排针引脚为芯片供电的3.3V电源及芯片内部转换为自身供电的1.05V供电。3.3V供电的原理图如下:
VCC3.3V通过电容滤波后,经过磁珠的隔离,分为为芯片供电的数字电和模拟电两种,按照芯片引脚的位置,划分电源平面。形成的PCB板层如图所示:
根据芯片手册VDD1.05V电压通过芯片自身的switching regulator转换,另外通过外接0电阻与去耦电容形成模拟或数字1.05V电源。switching regulator只能给芯片自身的AVDD10和DVDD10供电,不能给其它外部电路供电。以下是原理图:
芯片regout引脚为自身提供1.05V电压,通过串联电感,并联电容进行滤波后,分为数字电源和模拟电源两部分,同3.3V电源层,1.05V电压在电源层根据芯片供电引脚位置,共分为数字和模拟两部分区域,因参考电路是原芯片厂商给定的外围参考电路,因此,此处对电阻电容的值不做任何改动,其中0欧姆的电阻在原理图中暂时不进行改动,此处0欧姆电阻在此处也起到隔离数字电源和模拟电源的作用。
在整体电源设计时,应注意去耦电容的摆放。
3.接地
GND层作为参考层,为信号层以及与电源形成电容提高整体EMI性能。
在PHY芯片内打过孔以连接地,起到散热,导流的作用。
在其他位置添加过孔。
3.PHY至RJ45电路设计
MDI连接属于高速信号连接,对MDI线路设计时时需特别注意,到RJ-45接口的路径需要尽可能短。考虑到信号串扰等原因,这里使用4对差分对进行数据传输,设置等长,差分对间距,阻抗100欧姆,设置规则如下。
以太网接口速率较高,会产生较大的干扰,会在铜皮产生感应电流,在RJ45接口处需将除差分引脚外的信号全部挖空,挖空区避免走线。
4.PHY至FPGA电路设计
RGMII接口设计:TXC与RXC分别为数据传输中发送与接收的频率,在千兆以太网中,分别为125MHz。接收数据的端口为RX[0…3],控制使能为TX_CTL;发送数据的端口为TX[0…3],控制使能为RX_CTL。
为了处理时钟信号,后期调试及EMI等问题,加入0欧姆电阻,对TXC和RXC进行过滤,当信号失真时,将时钟电路中的0电阻更换为值较小的电容。
其中要保证RXC、RX_TCL、RX[0…3]做到等长,TXC、TX_TCL、TX[0…3]做到等长,以避免数据和时钟的不匹配现象。TX与RX分别分配到信号质量最好的中间信号层,如图所示:
为了匹配阻抗,需要串联小电阻22欧姆,串联电阻同时也可以解决输入电压过冲的问题。
为了保证信号质量,如果信号线过长,可对该线路实行端接的处理办法,可以有效的解决信号失真等情况。
其他注意事项及未完成事项:
1.示例板中有表层敷铜,表层敷铜为GNDnet,这块板没有表层敷铜。
2.板层厚度如何考虑。
3.阻抗匹配在cadence中的实际操作。因信号反射的原因,在实际布线的过程中必须考虑阻抗匹配的问题。
二、相关知识点总结
1.表层敷铜
1、对内层信号提供额外的屏蔽防护及噪声抑制;
2、提高PCB的散热能力;
3、在PCB生产过程中,节约腐蚀剂的用量;
4、避免因铜箔不均衡造成PCB过回流焊时产生的应力不同而造成PCB起翘变形。
2.PCB板层选择
TOP->GND->SIG1->PWR->PER2 ->SIG2->GND->BUTTOM这种八层PCB板是最常见的PCB板层设计之一,好处在于每个布线层都有一个GND参考层相连,保证了电路的回流,减小阻抗。有较好的信号完整性,信号层与街底层相邻,电源层与接地层配对,每个走线层的阻抗都可较好控制。两个街底层能良好吸收侧离线,并且在电源地层完整的情况下,为每个信号层都提供较好的回流路径。
其他的八层板设计有top-gnd-sig1-pwr-gnd-sig3-gnd-buttom等。
常用的六层板叠层设计有TOP-GND-SIG2-PWR-GND-BUTTOM.
因为该芯片供电采用了1.05V和3.3V混合供电,其中又包括了AVDD和DVDD两种,一层电源层可以解决问题,但效果不如两层电源层更好,因此没有选择六层板;
在八层板里,SIG1和SIG2这两层信号层的信号质量最好,因为可用来布高速信号(RX和TX)。因为芯片中RX和TX挨得很近,所以最好将这两组信号拆开放入不同层中,这样效果更好。
3.磁珠的作用
磁珠有很高的电阻率和磁导率,等效于电阻和电感串联,磁珠用bai来吸收超高频信号,像一些RF电路,PLL,振荡电路,含超高频存储器电路都需要在电源输入部分加磁珠,从而提高调频滤波效果。
此处放置磁珠是为了起到隔离数字与模拟电源的作用。这样可以防止一些高频噪声进入模拟区域。因为数字器件有噪声容限,而模拟器件则对噪声非常敏感。
4.电阻的作用
当较快的信号沿驱动一段较长的走线,而走线上没有有效的匹配时,往往会产生过冲。在电路设计中,最小化过冲与减小上升时间的目标会发生冲突。
过冲就是第一个峰值或谷值超过设定电压——对于上升沿是指最高电压而对于下降沿是指最低电压。
对付过冲的一般方法是匹配,或叫端接。端接可总结为两种形式:远端串联匹配消除二次反射,终端并联匹配消除一次反射。
5.电容的作用
应用于电源电路,实现旁路、去藕、滤波和储能方面电容的作用。滤波是电容的作用中很重要的一部分。几乎所有的电源电路中都会用到。从理论上说,电容越大,阻抗越小,通过的频率也越高。
大电容滤掉频率比较低的信号,小电容滤掉频率比较高的信号,通过的信号的频率就是在这两个电容滤掉之间那一段。
大电容是电解电容,有极性,对交流电不起作用,对不平滑的直流电滤波,使之趋于平滑。小电容是无极电容,是滤除交流高频杂波。
6.信号的反射
信号沿传输线向前传播时,每时每刻都会感受到一个瞬态阻抗,这个阻抗可能是传输线本身的,也可能是中途或末端其他元件的。对于信号来说,它不会区分到底是什么,信号所感受到的只有阻抗。如果信号感受到的阻抗是恒定的,那么他就会正常向前传播,只要感受到的阻抗发生变化,不论是什么引起的(可能是中途遇到的电阻,电容,电感,过孔,PCB转角,接插件),信号都会发生反射。
衡量信号反射量的重要指标是反射系数,表示反射电压和原传输信号电压的比值。假设PCB线条的特性阻抗为50欧姆,传输过程中遇到一个100欧姆的贴片电阻,暂时不考虑寄生电容电感的影响,把电阻看成理想的纯电阻,那么反射系数为:1/3,信号有1/3被反射回源端。如果传输信号的电压是3.3V电压,反射电压就是1.1V。
由于反射现象的存在,信号传播路径中阻抗发生变化的点,其电压不再是原来传输的电压。这种反射电压会改变信号的波形,从而可能会引起信号完整性问题。
7.信号的串扰
串扰是指当信号在传输线上传播时,因电磁耦合对相邻的传输线产生的不期望的电压噪声。
串扰是由电磁耦合引起的。
Could not retrieve transation read-only status server
查找原因:
是连接mysql的jdbc驱动包和mysql 的版本对不上,
解决Could not retrieve transation read-only status server_有天你会让我妒忌的.-CSDN博客_could not retrieve transation https://blog.csdn.net/q343509740/article/details/79527132/
ssm+mysql遇到的问题Could not retrieve transation read-only status server。。。_legendaryhaha的博客-CSDN博客_could not retrieve transation read-only status ser https://blog.csdn.net/legendaryhaha/article/details/82631229
Pands 两个数据列表合并方法总结; merge() 函数用于合并两个 DataFrame 对象或 Series,数据处理时经常会用到这个函数,官网给出该函数的定义如下:
pandas.merge(left, right, how: str = ‘inner’, on=None, left_on=None, right_on=None, left_index: bool = False, right_index: bool = False, sort: bool = False, suffixes=’_x’, ‘_y’, copy: bool = True, indicator: bool = False, validate=None)
先介绍一下 各参数的含义作用;
left左边的 DataFrameright右边要合并的 DataFramehow合并方式,一共四种: left,right,inner,outer,默认为 inner
left 仅使用来自左边frame的键进行匹配; right 仅使用来自右边frame 的键进行匹配;
outer 取来自左右frame 键的并集;匹配不到的话元素设为Null
inner 取来自左右frame 键的交集,匹配不到的话元素丢失;onlabel or list
选取合并的基准列也就是键名,前提该键名在两个 DataFrames 中有存在,如果未设置的话,默认为左右两个 DataFrame 的列名交集;left_onlabel、list、array_list
左边 DataFrame 中的列或索引级别作为键;可为列名或索引名right_onlable、list、array_list
右边DataFrame中 的列或索引级别作为键;可为列名或索引名left_indexbool,默认False
本文介绍一下关于 Pandas 中 apply() 函数的几个常见用法,apply() 函数的自由度较高,可以直接对 Series 或者 DataFrame 中元素进行逐元素遍历操作,方便且高效,具有类似于 Numpy 的特性。
apply() 使用时,通常放入一个 lambda 函数表达式、或一个函数作为操作运算,官方上给出的 apply() 用法:
DataFrame.apply(self, func, axis=0, raw=False, result_type=None, args=(), **kwds func 代表的是传入的函数或 lambda 表达式;axis 参数可提供的有两个,该参数默认为0/列 0 或者 index ,表示函数处理的是每一列;1 或 columns ,表示处理的是每一行; raw ;bool 类型,默认为 False; False ,表示把每一行或列作为 Series 传入函数中;True,表示接受的是 ndarray 数据类型; apply() 最后的是经过函数处理,数据以 Series 或 DataFrame 格式返回。
下面用几个例子来介绍一下 apply() 的具体使用;
DataFrame 使用apply() 1,计算每个元素的平方根
这里为了方便,直接用到 numpy 的 sqrt 函数;
>>> df =pd.DataFrame([[4,9]]*3,columns = ['A','B']) >>> df A B 0 4 9 1 4 9 2 4 9 >>> df.
unordered_map介绍 unordered_map记录元素的hash值,根据hash值判断元素是否相同。map相当于java中的TreeMap,unordered_map相当于HashMap。无论从查找、插入上来说,unordered_map的效率都优于hash_map,更优于map;而空间复杂度方面,hash_map最低,unordered_map次之,map最大。
unordered_map与map的对比 存储时是根据key的hash值判断元素是否相同,即unordered_map内部元素是无序的,而map中的元素是按照二叉搜索树存储(用红黑树实现),进行中序遍历会得到有序遍历。所以使用时map的key需要定义operator<。而unordered_map需要定义hash_value函数并且重载operator==。但是很多系统内置的数据类型都自带这些。
成员函数 1. 迭代器
begin 返回指向容器起始位置的迭代器(iterator)
end 返回指向容器末尾位置的迭代器
cbegin 返回指向容器起始位置的常迭代器(const_iterator)
cend 返回指向容器末尾位置的常迭代器
元素的键值分别是迭代器的first和second属性。使用(*it).first或者it->first获取。
2. 容量
size 返回有效元素个数
max_size 返回 unordered_map 支持的最大元素个数
empty 判断是否为空
3. 元素插入与删除
insert 插入元素
erase 删除元素 ,可以通过迭代器或者key进行删除
clear 清空内容
swap 交换内容
unordered_map<int,int> mymap; //插入 mymap.insert({1,0});//数组插入 mymap[1] = 0;//键值插入 mymap.insert(mymap2.begin(),mymap2.end());//插入另一个哈希表中的元素 mymap.insert(pair<int,int>(0,1)); //删除 mymap.erase(mymap.begin()); mymap.erase(1); mymap.clear(); 4. 查找
find 通过给定主键查找元素,没找到:返回unordered_map::end
count 返回匹配给定主键的元素的个数
equal_range 返回值匹配给定搜索值的元素组成的范围
if (mymap.find(0) != mymap.end()) cout << "not found" << endl; else cout << "
android 原生集成flutter问题记录 1.老项目集成flutter提示androidx冲突的问题
解决方案:一定要先升级Androidx之后再集成flutter!!!!如果先集成flutter后升级androidx会有各种意想不到的问题,凉凉。
2.Android 集成flutter之后,flutter plugin 的lib中的资源文件找不到了
解决方案:在原生的项目根目录下的 build.gradle 中的 allprojects 添加如下内容: allprojects { repositories { flatDir { dirs project(':push_flow_plugin').file('libs') } } } 其中 push_flow_plugin 对应的 flutter plugin 的名称
格式: execution(modifiers-pattern? ret-type-pattern declaring-type-pattern? name-pattern(param-pattern)throws-pattern?) execution(modifiers-pattern? ret-type-pattern declaring-type-pattern? name-pattern(param-pattern)throws-pattern?) 解释: 修饰符匹配(modifier-pattern?)返回值匹配(ret-type-pattern)可以为*表示任何返回值,全路径的类名等类路径匹配(declaring-type-pattern?)方法名匹配(name-pattern)可以指定方法名 或者 *代表所有, set* 代表以set开头的所有方法参数匹配((param-pattern))可以指定具体的参数类型,多个参数间用“,”隔开,各个参数也可以用“*”来表示匹配任意类型的参数,如(String)表示匹配一个String参数的方法;(*,String) 表示匹配有两个参数的方法,第一个参数可以是任意类型,而第二个参数是String类型;可以用(..)表示零个或多个任意参数异常类型匹配(throws-pattern?)其中后面跟着“?”的是可选项 使用方法 多个execution连接方法: #在多个表达式之间使用 ||,or表示 或,使用 &&,and表示 与,!表示 非.
expression=”execution(* pp.business.*.*(..)) or execution(* pp.business.impl.*.*(..))”
文章目录 小知识RadioButton实战MainActivity.javaactivity_main.xmlRadioButtonActivity.javaactivity_radio_button.xmlselector_blue.xml 效果 小知识 xml文件名不能有大写字母
RadioButton实战 MainActivity.java 今天的MainActivity.java里用方法代替了以往稍显冗杂的代码
package com.example.myapplication; import androidx.appcompat.app.AppCompatActivity; import android.content.Intent; import android.os.Bundle; import android.view.View; import android.widget.Button; import android.widget.EditText; public class MainActivity extends AppCompatActivity { private Button mbtnTextView; private Button mbtnButton; private Button mbtnEditText; private Button mbtnRadioButton; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mbtnTextView=findViewById(R.id.btn_textview); mbtnButton=findViewById(R.id.btn_button); mbtnEditText=findViewById(R.id.btn_edittext); mbtnRadioButton=findViewById(R.id.btn_radiobutton); setListeners();//这个方法给每个按钮加上了点击事件onclick,而onclick的构造器能够根据调用他的对象的名字创建相应的点击事件 } private void setListeners(){ Onclick onclick=new Onclick(); mbtnRadioButton.setOnClickListener(onclick); mbtnEditText.setOnClickListener(onclick); mbtnTextView.setOnClickListener(onclick); mbtnButton.setOnClickListener(onclick); } private class Onclick implements View.
在网上看了很多方法,都没有奏效。
本文方法:
1、编写test.sh脚本
#!/bin/bash ### BEGIN INIT INFO # Provides: starter # Required-Start: $remote_fs $syslog # Required-Stop: $remote_fs $syslog # Default-Start: 2 3 4 5 # Default-Stop: 0 1 6 # Short-Description: start starter # Description: start starter ### END INIT INFO #chkconfig: 2345 80 90 #description:auto_run su --l username cd /path/ python test.py exit 0 2、在ubuntu左上角搜索框查找Startup Applications 点击
点击add
Name:定义名字,test
Command:/usr/bin/gnome-terminal -x bash -c “/path/test.sh;exec bash”
#其中/usr/bin/gnome-terminal为开机打开终端。
bash -c “/path/test.
一 概述 字符串实际上是由多个字符组成的,字符串中的第一个字符使用字符串[0]即可得。[0]中的0称为下标获取字符串中的第一个字符使用的下标是0,则字符串中最后一个字符的下标是字符串的长度减1C#语言如果要获取字符串的长度,使用Length属性即可字符串.Length 二 实例 2.1 实例一 在 Main 方法中从控制台输入一个字符串,输出该字符串的长度,以及字符串中的第一个字符和最后一个字符。 2.1.1 代码
复制 1 2 3 4 5 6 7 8 9 10 class Program { static void Main(string[] args) { string str = Console.ReadLine(); Console.WriteLine("字符串的长度为:" + str.Length); Console.WriteLine("字符串中第一个字符为:" + str[0]); Console.WriteLine("字符串中最后一个字符为:" + str[str.Length - 1]); } } 2.1.1 执行结果
2.2 实例二 在 Main 方法中从控制台输入一个字符串,并将字符串中的字符逆序输出 2.2.1 代码
复制 1 2 3 4 5 6 7 8 9 10 11 class Program { static void Main(string[] args) { string str = Console.
geometry类型,对应mybatis自动生成类型为:Object,
遇见这个错误,是因为使用
#{}来获参数。应该使用${},这样的话,就不会报错了。
当执行数据添加时,使用
${},又会缺少 ‘’
两种解决方法
①前端提供数据里面,为:“ ‘data’ ”
②mybatis中,使用 ‘ ${} ’,这种方式也可以。
遇到这个错误,暂时找到这两种方法。
cisco路由器vty
最近,我写了一篇文章,解释了如何使用Quagga路由套件实现开放式最短路径优先(OSPF)。 可以使用多个软件套件代替Quagga来实现不同的路由协议。 一种这样的选择是自由范围路由(FRR)。 财务报告率 FRR是一个路由软件套件,它是从Quagga派生的,并根据GNU GPL2许可进行分发。 与Quagga一样,它为Unix类平台提供了所有主要路由协议的实现,例如OSPF,路由信息协议(RIP),边界网关协议(BGP)和中间系统到中间系统(IS-IS)。 建筑 FRR是一组守护程序,它们可以共同构建路由表。 每个主要协议都在自己的守护程序中实现,这些守护程序与核心和独立于协议的守护程序Zebra对话,后者提供内核路由表更新,接口查找以及不同路由协议之间路由的重新分配。 每个特定于协议的守护程序负责运行相关协议并根据交换的信息构建路由表。 VTY外壳 VTYSH是FRR路由引擎的集成外壳。 它将每个守护程序中定义的所有CLI命令合并,并在单个shell中将它们呈现给用户。 它提供了类似于Cisco的模式CLI,并且许多命令类似于Cisco IOS命令。 CLI的模式不同,某些命令仅在特定模式下可用。 建立 在本教程中,我们将实现路由信息协议(RIP)以使用FRR配置动态路由。 我们可以通过两种方式来做到这一点-通过在编辑器中编辑协议守护程序配置文件或使用VTY Shell。 在此示例中,我们将使用VTY Shell。 我们的设置包括两个名为Alpha和Beta的CentOS 7.7主机。 这两台主机都有两个网络接口,并共享对192.168.122.0/24网络的访问。 我们将宣传10.12.11.0/24和10.10.10.0/24网络的路由。 对于主持人Alpha: eth0 IP:192.168.122.100/24 网关:192.168.122.1 eth1 IP:10.10.10.12/24 对于主机Beta: eth0 IP:192.168.122.50/24 网关:192.168.122.1 eth1 IP:10.12.11.12/24 安装包 首先,我们需要在两个主机上都安装FRR软件包。 可以按照FRR官方文档中的说明进行操作。 启用IP转发 对于路由,我们需要在两个主机上都启用IP转发,因为这将由Linux内核执行。 sysctl -w net.ipv4.conf.all.forwarding = 1 sysctl -w net.ipv6.conf.all.forwarding = 1 sysctl -p 启用RIPD守护程序 安装后,所有配置文件都将存储在/ etc / frr目录中。 必须通过编辑/ etc / frr / daemons文件显式启用守护程序 。 该文件确定启动FRR服务时激活了哪些守护程序。 要启用特定的守护程序,只需将相应的“否”更改为“是”。 随后的服务重新启动应启动守护程序。 防火墙配置 由于RIP协议使用UDP作为其传输协议并分配了端口520,因此我们需要在firewalld配置中允许该端口。 firewall-cmd --add-port = 520 / udp –permanent firewalld-cmd -reload 现在,我们可以使用以下命令启动FRR服务: systemctl start frr 使用VTY进行配置 现在,我们需要使用VTY Shell配置RIP。 在主持人Alpha上: [ root @ alpha ~ ] # vtysh Hello, this is FRRouting ( version 7.
1.在centos7创建文件夹/root/dist
2.把html项目代码放在/root/dist/下
3.配置nginx文件
这里需要注意的是user 配置为root,否则启动之后无访问权限
查看nginx配置是否正确
nginx -t
正确之后重启nginx -s reload
然后就可以重启访问自己配置的域名了
rust vs java
自从我正确地学习了计算机或人类这门新语言以来,已经很长时间了。 也许25年。 那是Java语言,尽管与此同时我不得不写一点点C(很少)和JavaScript,但我写过很多实际代码的唯一两种语言是Perl和Java。 我是一个名为Enarx的项目的联合创始人,该项目几乎完全用Rust编写。 这些天来,我称自己为“建筑师”,距离我编写任何生产代码已经很长时间了。 在2019年圣诞节之前,我完成了我几年来写的第一个重要项目:围绕Java专利申请实现一组算法。 这是让我重新投入代码的好机会,对此我感到非常满意。 从具有强大的面向对象背景的Java开发人员的角度来看,这是我对Rust的一些想法。 1. Rust感到很熟悉 尽管您会发现许多教程和书籍都是用C和C ++编写的,但是Java与Java的相似性足以使通用语言感到熟悉。 我使用最多的两个教程是Rust编程语言 (在线)和规范的Rust书籍(采用死树格式),后者经常引用与其他语言的相似之处和不同之处,不仅包括C,C ++和Java,以及Python,JavaScript等。 诸如控制结构和类型之类的东西与Java足够相似,它们通常很容易理解,尽管存在一些主要差异,但是您应该能够很轻松地理解该语言的基础知识。 但是要当心:我一直遇到的最大的初始问题之一是Rust有时感觉太熟悉了,所以我开始尝试以错误的方式做事,不得不退后一步,尝试找到对Rust更加惯用的方法。 我还有很长的路要走! 2.引用很有意义 在Rust中,您最终不得不使用引用,即通过内存地址访问数据。 坦白说,当我查看C或C ++时,引用和取消引用变量对我来说从来没有多大意义,但是这次,我感觉很明白。 如果您习惯于通过引用和值传递Java变量,并且知道何时需要采取措施在特定情况下以不同的方式进行操作,那么您就可以开始理解Rust引用了。 您需要了解的另一件事是Rust 为什么需要使用它们:这是因为Rust对内存管理非常非常小心,而且无论走到哪里都没有垃圾回收器可以清理(就像Java中一样) 。 您不能在willy-nilly周围传递字符串:例如,Rust会坚持要求您知道变量的生命周期,并考虑何时可以“删除”该变量。 这意味着您需要认真考虑范围,并且引入了一个复杂的概念:所有权。 3.所有权会很有意义 老实说,我还没到。 我已经在Rust中学习和编码了不到两个星期,并且我开始着手解决所有权问题。 对于我(我怀疑,对于许多新手来说),这是从Java或大多数其他语言(所有权)转向Rust的重大转变。 如前所述,您需要了解何时使用变量以及变量可以使用多长时间。 但是,它还不止这些,对于Java开发人员来说,真正获得它对于我来说有点陌生:您需要了解栈和堆 ,这是Java充分掩盖了我的区别,但是许多C和C ++开发人员可能会更容易理解。 这里不是解释这个概念的地方(我发现Rust编程中的图表特别有用),但是为了管理内存中变量的生命周期,Rust需要知道每个组件拥有什么组件。 当您习惯于创建对象并使用来自各处的变量实例化它们时(例如在Java中),这变得很复杂,并且需要进行一些重要的重新思考。 将其与生命周期的明确标记相结合是我现在必须执行的最大的概念更改。 4.货运很有帮助 货物二进制文件只做正确的事情,例如,当它意识到您已经对依赖项进行了更改时,看到它完成其工作就令人惊讶。 它会执行自动测试,自动优化,生成文档-这么多有用的任务,全部都在一个软件包中。 将其与Git存储库结合使用,项目管理将变得更加简洁明了。 5.编译器很棒 最后但最不重要的是编译器。 我喜欢Rust编译器:它确实在尽力帮助您。 制作和维护Rust的社区1的成员显然会竭尽所能,为您在犯错时纠正您提供有用的指导,而我(其中一个)就犯了很多错误。 而不是其他语言的编译器可能会熟悉的口头声明,您将获得带有颜色,警告和错误的色编码文本,以及有关您可能实际尝试执行的操作的建议。 您甚至会得到如下输出: For more information about this error , try rustc -- explain E0308 当您尝试这样做时,您(通常!)会获得有用的解释和代码段。 有时,尤其是当您仍在使用该语言的时候,并不是总是很清楚您在做错什么,但是淡入错误中可以帮助您以与消息完全不同的方式来理解概念。例如,我习惯于从javac工具获取信息。 结论 我不希望写大量的Rust产品,也不要真正地达到大师的地位(老实说,用Rust或任何其他语言),但是我真的认为Rust可以说很多。 纵观我的旅程,到目前为止,我一直在点头我的头和思考,“这是一个好办法做到这一点”,或者“啊,才使得这么多比我习惯的方式更有意义。” 这不是一篇关于Rust 为什么这么好用的语言的文章-那里有很多-也不是学习Rust的最佳方法-也有很多这样的书,但是我可以说我很享受。 这是具有挑战性的,但是教程,书籍和其他学习材料都擅长的一件事就是解释Rust做出选择的原因,这对我来说既有帮助,也可以帮助我解决挫败感,也可以尝试内部化。 Java和Rust之间的一些区别。 如果我能真正投入到Rust中,说实话,我认为我不可能再写任何Java了。 我不确定我还有25年的编码经验,但是我认为我现在和Rust一起工作很长一段时间。 我是Rustacean(萌芽)。 1.
legend(x, y = NULL, legend, fill = NULL, col = par(“col”),
border = “black”, lty, lwd, pch,
angle = 45, density = NULL, bty = “o”, bg = par(“bg”),
box.lwd = par(“lwd”), box.lty = par(“lty”), box.col = par(“fg”),
pt.bg = NA, cex = 1, pt.cex = cex, pt.lwd = lwd,
xjust = 0, yjust = 1, x.intersp = 1, y.intersp = 1,
adj = c(0, 0.5), text.width = NULL, text.
SQL Server 对日期的操作函数的使用 在编写sql的时候,会碰到对日期的处理,特别是日期区间对业务数据的限制。
如:用户数据的是一个固定月份 2020-03 这个时候需要匹配数据就是2020-03-01 ~ 2020-03-31的数据。对于此类处理,就需要编写sql的人员进行运算转化出两个日期去限制数据区间了。
网上搜了一些处理方式,大部分都是拼接而成,在各种比较下,如下的处理方式比较合理与准确。
--当前日期 select getdate() CurrentDate; --当月第一天 select dateadd(day,-day(getdate())+1,getdate()) current_Month_FirstDay; --当月最后一天 select dateadd(month,datediff(month,0,dateadd(month,1,getdate())),-1) current_Month_EndDay; --当年第一天 select dateadd(YEAR,datediff(YEAR,0,getdate()),0) current_Year_FirstDay; --当年最后天 select dateadd(YEAR,datediff(YEAR,0,dateadd(YEAR,1,getdate())),-1) current_Year_EndDay; --下年第一天 select dateadd(YEAR,datediff(YEAR,0,dateadd(YEAR,1,getdate())),0) next_Year_Firstday; --下年最后一天 select dateadd(YEAR,datediff(YEAR,0,dateadd(YEAR,2,getdate())),-1) next_Year_Endday; --上年第一天 select dateadd(YEAR,datediff(YEAR,0,dateadd(YEAR,-1,getdate())),0) last_Year_Firstday; --上年最后一天 select dateadd(YEAR,datediff(YEAR,0,getdate()),-1) last_Year_Endday; 解释:
0 表示1990-01-01, datediff(YEAR,0,getdate()) 表示1990到当前日期是多少年 dateadd(YEAR,datediff(YEAR,0,getdate()),0) 表示从1990年加datediff(YEAR,0,getdate()) 年,刚好就是当前日期所在年度的一月一号 其他的几种表示方式,以此思路类推,包括month,day等关键词
介绍两个重要的函数(DATEDIFF 、DATEADD)
DATEDIFF (Transact-SQL)
此函数返回指定的 startdate 和 enddate 之间所跨的指定 datepart 边界的计数(作为带符号整数值) 。 语法 DATEDIFF ( datepart , startdate , enddate ) 参数
今天看知乎的时候,看到这样一个问题:“作为一名程序员,最大的成就感来自哪里?” 下面有一条回答蛮有意思的,拿出来跟大家分享一下。
其实,程序员更愿意自己被称为开发者,因为最大的成就感,就是来自开发、创造、改变。
我们是开发者,是一群用自己的双手构建新世界的人,看到自己的造物,成功运转,成就感自然就会瞬间充斥全身。
在普通人眼里,在如今这个数字化的世界中,程序员已经越来越接近无所不能的“造物主”。
隔壁刘叔叔、村头张大妈的电脑蓝屏了,第一时间想起的可能就是我们程序员。
想创业做电商的张三,可能第一个找的也是程序员,搂着肩膀问你能不能 2 天做一个百度,一周做一个淘宝,预算 5000。
公司漂亮的行政小姐姐,需要把几百个不同的兑换码,用邮件分别发给公司几百员工时,第一个想起的还是程序员。
有时,程序员还是希望大家忘记自己,比如张三和隔壁刘叔叔、村头张大妈的事情。
但对于行政小姐姐,程序员写个简单脚本,就能解决他们需要花费数周才能搞定的工作。
生活中,这类情况屡见不鲜。
就比如,你想把自己网易云上的歌单,喜欢的歌曲统统搬运到QQ音乐上。
假设你只需要搬运 3-5 首音乐,那人肉操作就可以了,但倘若你要搬运 300-1000 首呢?
有程序员给出了答案:做个小软件,爬一下网易云歌单,然后登陆 QQ 音乐后搜索并添加不就完事了?
热心的程序员用 Python 快速地做了出来,并且放到了 GitHub 上,可以在 1 分钟左右配置完毕,代码也易懂,推荐新手阅读代码。
传送门:
https://github.com/Denon/syncPlaylist/blob/master/README_CN.md
瞧,利用编程,就可以帮自己和朋友们节省机械化操作,不再一边气得骂骂咧咧,又不得不继续搬运。甚至都不需要有多么高深的水平,只要入门级别的程序员就能做出类似的工具。
这就是技术最好的使用场景,用技术来替代人类,去完成那些枯燥乏味的工作。
编程语言的学习过程,也是充满了成就感。
就例如非常简单的 Python。
想要高效学习 Python,必然是要伴随着实践,先为自己输入一些知识,随后在符合自己能力范围内去尝试使用这些知识。
当你让字母成功组合,发挥出神奇功效时,你一定会知道什么是成就感。
就像你当初第一次打开电脑连接网络,随后就打开了新世界的大门。
如果你刚刚入门 Python,那强烈建议你来试试这 20 个“小玩具”,可以给你刚学会的知识一个用武之地,让你的知识可以变成生产力。相信我,当你掌握其中某一项时,你就再也不发愁成就感的来源了。
1. batch_file_rename.py - 批量重命名指定目录下面所有文件的后缀名。
2. create_dir_if_not_there.py - 检查用户主目录中是否存在目录,如果不存在则创建目录。
3. Fast Youtube Downloader- 使用aria2c多线程快速下载YouTube视频。
4. Google Image Downloader- 查询指定词语并从Google中下图。
5. dir_test.py 测试目录是否testdir存在,如果不存在,它将为您创建目录。
6. env_check.py -将检查是否已设置所需的所有环境变量。
这个命题应该是仁者见仁智者见智吧。现在无论是新闻、社交、短视频都是个性推荐。有些人喜欢八卦、有些人喜欢美女,正所谓萝卜白菜各有所爱。无论是新闻、社交、短视频都有很多正能量的内容,如果你经常耍一些正能量的内容,那还是很有帮助。利用碎片化时间看一些时事新闻、看一些古诗词、看一些跟自己行业相关的信息还是能带来不小的收获。只要不是贪图享受短暂的快乐,我觉得都能带来一些进步的思想。
1问题
Failed to load resource: the server responded with a status of 403 (Forbidden) 原因Nginx 访问权限
解决方法
解决办法时设置nginx的用户user为root
设置nginx.conf 的user root;
设置完后重启Nginx
本文翻译自:Regex: matching up to the first occurrence of a character
I am looking for a pattern that matches everything until the first occurrence of a specific character, say a ";" 我正在寻找一个匹配所有内容的模式, 直到第一次出现特定字符,比如“;” - a semicolon . - 分号 。 I wrote this: 我写了这个: /^(.*);/ But it actually matches everything (including the semicolon) until the last occurrence of a semicolon. 但它实际上匹配所有内容(包括分号),直到最后一次出现分号。 #1楼 参考:https://stackoom.com/question/8Rhk/正则表达式-匹配第一次出现的字符
#2楼 "/^([^\\/]*)\\/$/" worked for me, to get only top "
本人用:mybatis-plus 3.2.0 在启动类中XXXXApplication加入"com.baomidou.mybatisplus.core.mapper"
@MapperScan(value={"xxxxx.xxxxx","com.baomidou.mybatisplus.core.mapper"})
原文:https://blog.csdn.net/MyfishCake/article/details/107048159
公司创建了开放源代码计划办公室(OSPO),以管理其与所依赖的开放源代码生态系统的关系。 通过了解公司的开源生态系统,OSPO可以最大化公司的投资回报率,并降低使用,贡献和发布开源软件的风险。 此外,由于公司依赖其开源生态系统,因此,确保其健康和可持续性将确保公司的健康,可持续增长和发展。 OSPO如何对公司及其开源生态系统变得至关重要? 马克·安德森(Marc Andreessen)曾说过“软件正在吞噬世界”,最近,可以说开源正在吞噬软件世界。 但是,该过程如何进行? 从OSS入站的角度来看,公司使用它来构建自己的解决方案和自己的基础架构。 之所以引入OSS,是因为OSS是其技术提供商使用的代码的一部分,或者是因为其自己的开发人员向公司的信息技术(IT)基础架构添加了开源组件。 从OSS出站角度来看,一些公司为OSS项目做出了贡献。 这种贡献可能是公司对解决方案的要求的一部分,而这些解决方案需要在上游项目中进行某些修复。 例如,三星为某些与图形相关的项目做出了贡献,以确保其硬件在进入市场后就具有软件支持。 在另一些情况下,为OSS做出贡献是一种通过允许人们为不同于日常工作的项目做出贡献而留住人才的机制。 一些公司发布自己的开源项目作为出站OSS流程。 对于像Red Hat或GitLab这样的公司,这是可以预期的。 但是,越来越多的非软件公司发布了许多OSS,例如Lyft。 OSS入站和出站流程 最终,入站和出站OSS流程中涉及的所有这些项目都是公司的OSS生态系统。 像任何生物一样,公司的健康和可持续性也取决于周围的生态系统。 OSPO职责 跟随物种及其生态系统,OSPO团队中的工作人员可以被视为组织OSS生态系统中的护林员。 他们照顾生态系统及其与公司的关系,以保持一切健康和可持续。 当公司使用开源软件项目时,他们需要了解许可证和合规性,检查项目的运行状况,确保不存在安全漏洞,并在某些情况下确定有才华的社区成员以进行潜在的招聘流程。 当公司为开源软件项目做出贡献时,他们需要确保没有知识产权(IP)问题,以确保公司的贡献和在项目中的领导地位,有时还需要帮助人才与他们保持联系公司通过他们的贡献。 当公司发布并维护开源项目时,他们负责确保社区参与和发展,检查是否存在IP问题,确保公司保持足迹和领导地位,并可能吸引新的人才到公司。 您是否了解OSPO团队所需的全部技能? 当我问过OSPO工作人员的团队规模时,每1000名开发人员中大约有1-5人。 这是一个很小的团队,负责监视很多人及其潜在的OSS相关活动。 如何管理OSPO 有了OSPO中的所有这些活动,人们的思想和他们需要担心的所有资源,他们如何能够管理所有这些? 至少有几个开源社区为他们提供了宝贵的知识和资源: TODO Group是“一个开放的公司集团,希望就实践,工具和其他方式进行合作,以运行成功且有效的开源项目和程序。” 例如,他们拥有一整套针对OSPOS公司的指南以及最佳实践。 CHAOSS(用于开源软件的社区健康分析)社区开发了用于管理开源项目的健康和可持续性的指标,方法和软件。 (请参阅下面有关CHAOSS的活跃社区和工作组的更多信息)。 OSPO经理需要向公司其他部门报告大量信息,以回答与他们的OSS入站和出站流程相关的许多问题,即,我们在组织中使用的是哪个项目? 这些项目的健康状况如何? 这些项目的关键人物是谁? 我们为哪些项目做出贡献? 我们发布了哪些项目? 我们如何处理社区贡献? 谁是关键贡献者? 数据驱动的OSPO 正如威廉·爱德华兹·戴明(William Edwards Deming)所说:“没有数据,您只是一个有意见的人。” 发表意见并不是一件坏事,但是基于数据发表意见无疑会更容易理解,讨论和确定最适合您的公司及其目标的流程。 推荐使用CHAOSS社区,以获取有关度量标准策略和工具的指南。 最近,CHAOSS社区发布了一组新的度量标准定义 。 这些指标只是每个工作组(WG)重点领域中讨论的所有指标的子集: 通用工作组 :定义两个工作组使用的或对社区健康很重要的指标,但这些指标不能完全适合其他现有工作组之一。 关注的领域包括组织隶属关系,响应能力和地理覆盖范围。 多样性和包容性工作组 :收集关于开源项目中的多样性和包容性的经验,其目的是从质和量的角度理解如何衡量多样性和包容性。 Evolution WG :改进可告知演化并与软件实现一起使用的指标。 风险工作组 :完善可告知风险并与软件实施一起使用的指标。 价值工作组 :专注于开放源代码中经济价值的行业标准指标。 他们的主要目标是发布可信赖的行业标准价值指标,这是一种用于软件开发的S&P,并且是有关指标重要性和行业规范的权威来源。 在加工方面,项目一样, 预言者 , Cregit和GrimoireLab是与OSPO活动的参考工具,报告这些指标,但也有许多人。 它们也是OSS社区(如Cauldron.
简易安装方式 安装 sudo apt-get install ffmpeg 版本查看 ffmpeg -v ffmpeg version 3.4.6-0ubuntu0.18.04.1 Copyright (c) 2000-2019 the FFmpeg developers built with gcc 7 (Ubuntu 7.3.0-16ubuntu3) 卸载 此卸载方法只适用于刚刚那条简易安装指令,如果通过其他方法安装,该指令不适用。
sudo apt-get purge ffmpeg 以上安装方法有一个问题,就是ffmpeg版本很低(目前用该命令安装的ffmpeg为3.4.6),与官网最新稳定版差距很大(大版本已到4以上),在一些底层操作上可能会有出入,例如读取某个视频时就会出现两个版本读出来帧数不一致的问题。所以尽量还是从ffmpeg官网下载最新稳定版手动安装。
官网下载最新包安装 解压 tar -xvf ffmpeg_4.2.2.orig.tar.xz 安装yasm sudo apt install -y yasm 设置编译项 基础选项:
./configure --enable-shared --prefix=/usr/local/ffmpeg 额外增加H264支持(可能需要额外安装,参考这里):
./configure --prefix=/usr/local/ffmpeg --enable-shared --disable-static --disable-doc --enable-gpl --enable-libx264 如果需要额外增加GPU(CUDA)加速支持,则需要在尾部增加:
--enable-cuda --enable-cuvid 同时下载并编译安装 FFmpeg NVIDIA headers (“ffnvcodec”):
git clone https://git.videolan.org/git/ffmpeg/nv-codec-headers.git cd nv-codec-headers (# 有多个分支,根据GPU驱动版本可能需要切换分支,如git checkout sdk/9.
在本教程中,我们将继续构建播客站点。 我们将开始设计帖子索引的样式,创建一个漂亮的小页脚,并在混合中添加一些颜色。 所有这些都使用Sass和Bourbon套件。 我们的职位索引 是的,我们在哪里? 目前,我们的网站看起来还不太好: 目前,我们的帖子除了左侧没有对齐之外,因此我们需要一个网格来修复此混乱情况。 我们心爱的波旁王朝整装待发 ! 首先,我们将添加一个类posts作为我们的帖子的包装,并使其成为在页面上居中放置内容的outer-container 。 在“ source / index.html.erb”中: <div class="posts"> <% page_articles.each_with_index do |article, i| %> <h2><%= link_to article.title, article %> <span><%= article.date.strftime('%b %e') %></span> </h2> <!-- use article.summary(250) if you have Nokogiri available to show just the first 250 characters --> <%= article.body %> <% end %> </div> 然后,我们需要为索引样式创建一个新的Sass部分,并应用一些魔术,因此在“ source / stylesheets / all.sass”中: @import 'index_posts' 在“ source / stylesheets / _index_posts.