转自:深入理解Linux进程调度(0.4)_进程调度 城_城中之城的博客-CSDN博客
一、进程调度概览
进程调度是操作系统最重要的内容之一,也是学习操作系统的重点和难点。关于进程本身的实现和管理请参看《深入理解Linux进程管理》。关于进程调度,我们首先就会问出一些问题,什么是进程调度,为什么要进程调度,如何进行调度。下面我们用一幅图把这些问题关联起来:
在这里插入图片描述
这张图把进程调度的所有问题和知识点都关联了起来,本文后面所有的内容都是对这张图的解释和扩展延伸,下面让我们来一一讲解。
1.1 什么是调度
什么是调度?调度是CPU资源管理器。操作系统的作用之一就是系统资源管理器。CPU是计算机系统中最重要的资源,当然也要管理。所有进程的运行都需要CPU,对CPU该如何管理呢?对于直接共享型的事物,我们有两种管理方法:一种是时间分割管理,另一种是空间分割管理。由于CPU自身的特性,没有空间分割相似性,只有时间分割相似性,所以我们只能对CPU进行时间分割管理。对CPU进行时间分割管理的具体做法就叫做进程调度。
那么调度的是什么呢?进程调度,调度的当然是进程啦,也对也不对。我们知道进程是资源分配的单位,线程是执行的单位。早期的时候没有多线程,进程就是线程,线程就是进程,所以此时进程调度调度的是进程。但是当有了多线程之后,线程变成了执行的单位,进程不再是执行的单位,进程调度调度的就是线程了。不过由于历史原因,大家都习惯叫进程调度,所以现在这个领域的名称还是叫进程调度。后文中说到调度进程的地方都是调度的线程,由于习惯问题,我们还说调度进程不说调度线程,请大家要注意。
对线程的调度可以有两种方式:一种是直接调度线程,不考虑它们所属的进程,这种方式叫做直接调度或者一级调度;另一种是先调度进程,再在进程内部调度线程,这种方式叫做间接调度或者二级调度。POSIX规定,操作系统可以选择这两种方式中的任何一种都行。Linux选择的是一级调度,为什么会这么选择呢?主要是为了提高进程的并发性,充分利用多CPU多核的优势。如果使用二级调度的话,看似每个进程之间都公平了,但是有些进程的计算量比较大,就无法通过多开线程提高自己的性能,这样对系统整体的性能是有害的,也不利用发挥计算机多CPU的优势。一级调度看似对有些进程不公平,但是计算量小的进程少开线程,计算量大的进程多开线程,相对还是很公平的。
就像国家希望每个企业都做大做强,但是同时也会反垄断一样。Linux也推出了cgroup组调度机制,来限制某个或者某一类进程对CPU资源的过度占用。本文中不讲cgroup组调度机制,后文的讲解都是假设没有cgroup组调度。
1.2 为什么要调度
我们知道了什么是调度,那么为什么要调度呢,没有调度会怎么样呢?最早的计算机是没有调度的,程序只能一个一个地运行,一个进程死亡之后才能去运行下一个进程。这里面首先存在的问题就是我们没法同时运行多个进程。其次就算我们不需要同时运行多个进程,程序在运行的过程中如果要等IO,CPU就只能空转,这也十分浪费CPU资源。于是最早的多任务——协作式多任务诞生了,当程序由于要等IO而阻塞时就会去调度执行其它的进程。但是协作式多任务存在着很大的问题,就是每个进程运行的时间片长短是不确定的,而且是很偶然很随机的。如果一个进程它一直在做运算就是不进行IO操作,那么它就会一直霸占CPU。针对这个问题,当时想出的方法是道德解决方案。内核向进程提供系统调用sched_yield,它会使进程主动放弃CPU让其它进程来执行。然后要求所有的程序员在程序中合适的地方尽量多地加入sched_yield调用。这个方法在当时是管用的,因为当时计算机的使用者(同时也是程序员)仅限于少数科研机构和政府机关的部分人员,一台电脑的共同使用者都认识,面子上还得过得去。
后来随着计算机的普及,以及计算机的使用者和程序员这两个角色的分离,主要靠道德约束的协作式多任务已经行不通了,我们需要强制性多任务,也就是抢占式多任务。抢占式多任务使得每个进程都可以相对公平地平分CPU时间,如果一个进程运行了过长的时间就会被强制性地调度出去,不管这个进程是否愿意。有了抢占式多任务,我们在宏观上不仅可以同时运行多个进程,而且它们会一起齐头并进地往前运行,不会出现某个进程被饿死的情况,这样我们使用电脑的体验就非常完美了。抢占式多任务和协作式多任务不是对立的,它们是相互独立的,可以同时存在于系统中。
抢占又分为用户抢占和内核抢占。由于抢占对进程来说是异步的,进程被抢占时不一定运行在什么地方,有可能运行在用户空间,也有可能运行在内核空间(进程通过系统调用进入内核空间)。如果抢占点是在用户空间,那么抢占就是安全的,如果在内核空间就不一定安全,这是为什么呢?因为对于用户空间来说,如果抢占会导致线程同步问题,那么用户空间有责任使用线程同步机制来保护临界区,只要用户空间做好同步就不会出问题。如果内核也做好了同步措施,内核抢占也不会出问题,但是内核最初的设计就没有考虑内核抢占问题,所以刚开始的时候内核是不能抢占的。后来内核开发者对内核进行了完善,把内核所有的临界区都加上了同步措施,然后内核就是可抢占的了。内核能抢占了不代表内核一定会抢占,内核会不会抢占由config选项控制,可以开启也可以关闭,因为内核抢占还会影响系统的响应性和性能。开启内核抢占会提高系统的响应性但是会降低一点性能,关闭内核抢占会降低系统的响应性但是会提高一点性能。因此把内核抢占做成配置项,可以让大家灵活配置。服务器系统一般不需要与用户交互,所以会关闭内核抢占来提高性能,桌面系统会开启内核抢占来提高系统的响应性,来增加用户体验。
现在我们再来看一下为什么要调度。因为如果没有调度的话,就不能实现多任务,一次就只能运行一个程序,我们使用电脑的体验就会大大降低。有了调度就有了多任务,我们就能同时在电脑上做很多事情,使用体验就会非常好。
1.3 为什么能调度
我们再来看看为什么能调度呢。我们把协作式多任务叫做主动调度,抢占式多任务叫做被动调度。为什么能调度分为两部分:为什么能触发调度和为什么能执行调度。对于主动调度,调度是进程主动触发的,这个是肯定能的。对于被动调度,在图灵机模型中是做不到的,因为图灵机是一条线性一直往前走的,进程在执行时,进程要是不主动,是不可能跳到其它进程来执行的。被动调度能做到的原因关键就在于中断机制,因为中断是强行在正常的执行流中插入了一段代码,它能改变后续代码的走向。有了中断机制,我们就可以创建一个定时器中断,以固定的时间间隔比如每10ms来触发中断,检测进程是否运行时间过长,如果过长就触发调度。这样任何进程都不可能霸占CPU,所以进程都能公平地共享CPU时间。关于中断的原理,请参看《深入理解Linux中断机制》。这里引用其中的一幅图来看一下:
在这里插入图片描述
可以看到在纯图灵机模型中,进程如果不主动进行调度,是没有外力强迫进程进行调度的,进程就能一直霸占CPU。有了中断机制之后,在中断的处理中可以触发调度,在中断返回的点可以执行调度,这样就可以避免进程霸占CPU了。
前面说的是为何能触发进程调度,主动调度是进程自己触发的,被动调度是在中断中触发的。现在来看看为何能执行调度,执行调度包括两部分:选择进程和切换进程。选择进程是纯软件的,肯定能实现。切换进程是怎么切换呢?一个进程执行的好好的,怎么就切换了呢,需不需要硬件的支持呢?进程切换主要是切换执行栈和用户空间,这两个都需要用到CPU特定的指令。进程切换的具体原理和细节我们在2.7节中讲。
1.4 何时调度
我们前面已经讲了主动调度(协作式多任务)和被动调度(抢占式多任务)。
对于主动调度,触发调度和执行调度是同步的、一体的,触发即执行。主动调度发生的时机有IO等待、加锁失败等各种阻塞操作以及用户空间主动调用sched_yield。
对于被动调度,触发调度和执行调度是异步的、分离的,触发调度并不会立马执行调度,而是做个需要调度的标记,然后在之后的某个合适的地方会检测这个标记,如果被设置就进行调度。触发调度的点有:在定时器中断中发现当前进程超时了,在唤醒进程时发现新进程需要抢占当前进程,在迁移进程时发现新进程需要抢占当前进程,在改变进程优先级时发现新进程需要抢占当前进程。其中第一个触发点是当前进程需要被抢占,它是用来保证公平调度,防止进程霸占CPU的,后三个触发点是新进程需要抢占当前进程,它是用来提高系统响应性的。执行调度的点有:系统调用完成之后即将返回用户空间,中断完成之后即将返回用户空间,如果开启了内核抢占的话则还有,中断完成之后即将返回内核,如果中断发生在禁止抢占临界区中,那么中断完成之后返回内核是不会执行调度的,而是会在临界区结束的时候执行调度。下面我们借用《深入理解Linux中断机制》中的几个图来看一下这几个执行调度检测点:
在这里插入图片描述
系统调用完成之后即将返回用户空间和中断完成之后即将返回用户空间,是非常好的执行进行调度的点,也就是此图中的三个箭头的地方。CPU异常在意义上不是系统调用,但是在形式上和逻辑上相当于是系统调用。
在这里插入图片描述
在这里插入图片描述
中断发生在内核空间的场景,如果开启了内核抢占,如果被抢占的内核代码不是在禁用抢占临界区,中断返回时是执行调度的点。如果被抢占的内核代码在禁用抢占临界区中,在执行调度的点被推迟到了临界区的出口处。
1.5 如何调度
现在到了执行调度的时刻了。执行调度分为两步:一是选择下一个要执行的进程,二是切换进程。选择下一个要执行的进程,这就是调度算法了。首先调度算法只能从Runnable的进程中进行选择,不能选择Blocked进程,因为选择了也没有意义。其次算法还要区分进程类型,比如普通进程与实时进程,肯定要优先选择实时进程,在同一类型的进程中还要有具体的算法来决定到底选择哪个进程。在Linux中一共把进程分为了5类,每一类都有一个具体的算法。类之间的关系是优先选择高类的进程,只有当高类没有Runnable进程时才会去选择低类进程。
进程选择好了之后就要切换进程了。切换进程分两步:第一步是切换用户空间,第二步是切换执行栈(线程栈)。如果要切换的两个线程属于同一个进程就不需要切换用户空间了。切换用户空间是一个CPU架构相关的事情,在x86 CPU上是给CR3寄存器赋值新进程的页表树的根指针。此时切换的执行栈是线程的内核栈,执行栈代表的是当前线程的执行情况,切换执行栈就是切换线程。线程的用户栈信息都在内核栈里保存着。切换完内核栈之后,线程继续执行就会返回用户空间,由于此时用户空间已经切换完成,内核栈上也保存着用户栈的信息,所以线程能返回到正确的用户空间线程上去。
下面我们画个图来看一下:
在这里插入图片描述
对于一个CPU来说,永远只有一个当前进程在运行,当执行进程调度时,需要从其它进程中选择一个进程,把它旋转到最下方作为当前进程,它就开始运行了。
1.6 调度均衡
前面所说的都是针对一个CPU的情况,对于多个CPU来说,每个CPU也是这样的逻辑。但是有一点不同的是,如果一个系统上的多个CPU忙的忙死闲的闲死,显然不太好,因此多个CPU之间会进行调度均衡。调度均衡可以分为个体均衡和总体均衡。个体均衡是从进程的角度出发选择到一个相对清闲的CPU上去运行。总体均衡是从CPU的角度出发如何从别的CPU上拉取一些进程到自己这来执行,使得所有CPU的工作量尽量平均。个体均衡的触发点有三个:一是新进程刚创建时,二是进程要执行新程序时,三是进程被唤醒时,在这三个点进程都可以选择去哪个CPU的运行队列上去等待执行。在个体均衡下,每个进程都尽量选择相对清闲的CPU,所以所有CPU的负载应该还是会比较均衡的。但是时间长了可能还是会出现负载不均衡的情况,此时就要进行总体均衡了。总体均衡的触发点有三个:一是CPU即将idle前会去找到最忙的CPU然后拉取一些任务过来;二是定时器中断的周期性检测,会检查是否所有的CPU都一样忙,如果忙闲差别太大就会进行进程迁移,使得所有CPU忙闲程度接近;三是在idle进程中如果CPU发现自己太忙而有的CPU在idle就会唤醒那个CPU进行负载均衡。
1.7 调度器评价
狭义的调度器指的是具体的调度算法,广义的调度器指的是整个调度体系。不过两者的评价指标是相同的,所以我们这里不具体区分调度器是指调度算法还是调度体系。调度器的评价指标有以下几个:
1.响应性,当一个进程发生事件需要去处理的时候能否及时被调度。这一点和使用体验是密切相关的,当我们用鼠标点击一个程序的时候,肯定希望程序立即能做出响应,如果程序过了好几秒才有反应,那我们肯定会很烦的。
2.吞吐量,系统在相同的时间内能够运行更多的程序、执行更多的指令。这个首先要求调度器本身的代码要尽量的高效。如果调度器写得非常复杂,运行一次就需要好几毫秒的话,那留给进程运行的时间就不多了。其次进程调度的频率要低,如果进程调度的频率比较高的话,那调度器执行的次数就比较多,从而占用了较多的CPU时间,而且频繁切换进程也会影响缓存的性能。从这一点来看响应性和吞吐量是有矛盾的,提高响应性会增加进程切换的频率,而这会降低系统的吞吐量。
3.公平性,指的是相对公平性,每个进程实际获得的时间份额与应当获得的时间份额都相差不大。不会出现有些进程饥饿的情况,也不会出现有些进程获得过多时间份额的情况。
4.适应性,指的是系统无论是调度几个进程还是调度几万个进程,都能撑得住,都能收放自如,各项指标都不能受到太大的影响。
5.节能性,自从智能手机越来越普及,而手机的电池技术一直没有较大的突破,所以省电对手机来说就是一项非常重要的任务,调度器也不可避免地要考虑省电问题了。
1.8 调度器历史
Linux的调度器经历了长久的发展,是内核中被优化最多目前最完善的模块之一。下面我们来看一下Linux调度器发展的历史。
Traditional Scheduler: v1.0 – v2.4
这一阶段的调度器和传统的UNIX上的调度器逻辑是一样的。全局只有一个运行队列,所有进程都放在一个队列上。进程区分IO密集型和CPU密集型,根据进程的睡眠时间计算动态优先级,按照动态优先级决定进程的调度顺序,按照优先级分配进程的时间片大小,时间片大小是等差数列。进程在运行队列上并没有特定的排序,每次选择下一个进程的时候都要遍历整个队列,所以算法的时间复杂度是O(n)。在SMP上也只有一个运行队列,当CPU比较多进程也比较多的时候,锁冲突比较严重。
O(1) Scheduler: v2.5 – v2.6.22
此调度器主要是针对传统调度器进行了改进。首先把运行队列从单一变量变成了per-CPU变量,每个CPU一个运行队列,这样就不会有锁冲突了,不过这样就需要调度均衡了。其次把运行队列的一个链表分成了两个链表数组:活动数组和过期数组。时间片没用耗尽的进程放在活动数组中,时间片耗尽的进程放在过期数组中,当所有进程的时间片都耗尽的时候交换两个数组,重新分配时间片。两个数组都使用动态优先级排序,并用bitmap来表示哪个优先级队列中有可运行的进程,把选择进程的算法复杂度降低到了O(1)。对进程区分IO密集型和CPU密集型并计算动态优先级这一点和传统调度器一样没有变。
SD Scheduler:(未合入)
目录 1.前言1.打开设置2. 点击到project >> Python interpreter3. 选择环境4. 确定之后等待加载就行了 1.前言 嗨嗨,大家好啊,我是小曼~
刚入门python的伙伴们,一开始也会很多的问题。今天来给大家分享一下python新手必须学会的技巧 :pycharm中配置python解释器
1.打开设置 依次点击file - settings 打开设置
2. 点击到project >> Python interpreter 依次点击 project:Pythonproject → Python interpreter
3. 选择环境 依次选择,点击设置。
左边
第一个是选择Python
第二个是选择anaconda
右边
第一个是从pycharm里面下载模块
第二个是选择你安装的环境,从它里面调用已经安装的模块。
注:如果是安装的anaconda
4. 确定之后等待加载就行了 点击应用,点击OK即可。
好啦,今天的分享到这里就结束了 ~
对文章有问题的,或者有其他关于python的问题,可以在评论区留言或者私信我哦
觉得我分享的文章不错的话,可以关注一下我,或者给文章点赞(/≧▽≦)/
.Net Core 如何数据导出 Excel?(EPPlus->OfficeOpenXml 实现固定列和动态列导出) 阅读目录
〇、前言一、根据已知类型对象 List 下载 二、动态列数据库下载 回到顶部
〇、前言 特别注意:本文设计的包(OfficeOpenXml.Extension.AspNetCore)依赖于 EPPlus 5.0.3 等更高版本,属于限制商业用途版本,因此只能用作个人或公司小范围内部使用。
对于将数据以 Excel 表格文件输出,还是比较常用的,也存在诸多情况,比如列固定或不固定、数据类型为 List<T>或 Json 对象等。
本文通过包 OfficeOpenXml.Extension.AspNetCore 实现两个方法导出列数固定和不固定的数据。
注意:OfficeOpenXml.Extension.AspNetCore 是一个基于 OfficeOpenXml 拓展,它依赖于 EPPlus,用于根据模板输出 Excel。
包控制台安装:
NuGet> Install-Package OfficeOpenXml.Extension.AspNetCore -Version 1.0.0 回到顶部
一、根据已知类型对象 List 下载 本章节方法适用背景:
数据列数固定,且可罗列。
对于对象 List<T> 的属性,一般不会命名为汉字,那么就需要将列名转换为汉字,以方便数据清晰显示。
如下为一个基于 WebAPI 项目的固定列数,动态行数的下载实例:
// 安装包:OfficeOpenXml.Extension.AspNetCore // 支持 Core 3.1 及以上,Standard 2.0 及以上using OfficeOpenXml;using OfficeOpenXml.Style;using Microsoft.AspNetCore.Mvc; // File 支持[HttpGet]public FileContentResult DownloadInfo(){try{string sql_datalist = "";var resultlist = dapperFactory.
摘要 YOLOX把YOLO 系列的检测头换成了anchor free的方式,并且采取了一些优化策略:样本分配策略:simOTA,decoupled head(解耦头)的思想。
1.介绍 YOLO家族一直以来都是把最流行的技术加入,并进行优化,追求精度和速度的最佳平衡(比如YOLOv2中引入的Anchor,YOLOV3中引入的残差块,YOLOv4中的Mosich数据增强)最近出的YOLOv5,性能达到了最高,但是近两年大热的Anchor free、先进的标签分配策略、端到端检测(NMS-free)没有被考虑进去,因此YOLOX诞生了。
由于考虑到YOLOv4、v5基于Anchor base可能有限过度优化,因此YOLOX基于YOLOv3-SPP版本进行改进。加入上述策略之后,我们boost the YOLOv3 to 47.3%;再加入YOLOV5里面的CSP结构和PAN结构,YOLOX-L achieves 50.0%。
2. YOLOX 2.1 YOLOX-DarkNet53 采用Darknet53作为BackBonend an SPP layer,具体训练设置如下:
在YOLOV3的backbone上基础上进行了如下训练策略改进:
添加了EMA权重更新余弦学习率衰减策略,IoU损失和IoU感知分支。 我们使用 BCE Loss 来训练 cls 和 obj 分支,使用 IoU Loss 来训练 reg 分支。这些一般的训练技巧与YOLOX的关键改进是正交的,因此我们把它们放在基线上。只进行RandomHorizontalFlip,ColorJitter(颜色抖动)和多尺度的数据增强。
并放弃了RandomResizeCrop策略,因为我们发现RandomResizeCrop与采用的的Mosich增强有点重叠。 通过这些增强功能,我们的基线在COCO val上实现了38.5%的AP,如下图所示
2.2 Decoupled head 我们的两个分析实验表明,耦合检测头可能会损害性能。
1)用解耦的头代替YOLO的头可以大大提高收敛速度。
2)解耦头对于YOLO的端到端版本至关重要(将在下面描述)。从下图可以看出,对于耦合磁头,端到端属性降低了 4.2% 的 AP,而对于解耦磁头,端到端属性的 AP 降低到 0.8%。因此,我们将YOLO检测头替换为精简版解耦头。
具体而言,它包含一个1×1个Conv层来减小每个FPN对应的输出通道尺寸到256,然后是两个平行分支,分别具有两个3×3个Conv层。
2.3 Strong data augmentation 增加Mosaic and MixUp数据增强,并且在最后15epoch关闭。
实验发现数据增强后,预训练没有意义,因此,实验都是从头开始训练以下所有模型。
2.4 Anchor-free YOLv4和YOLOv5都是基于Anchor base的,基于Anchor的机制有许多缺点:
首先,为了实现最佳检测性能,需要在训练之前进行聚类分析以确定一组最佳锚点。其次,锚定机制增加了检测头的复杂性,以及每个图像的预测数量 Anchor free 机制大大减少了需要手动设计参数的数量和涉及的许多技巧(例如,锚点聚类[24],网格敏感[11]),以获得良好的性能,使检波器,特别是其训练和解码阶段,相当简单[29]。
前端、后端都可以生成二维码,轮子很多,今天分别来分享一下前后端如何使用轮子生成二维码的方法。
后端:选择一款合适的二维码生成库,如zxing、qrcode等,并在后端代码中引入该库。编写代码,根据业务需求生成相应的二维码图像,并将其输出为二进制流。
前端:使用HTML5提供的canvas元素,创建一个画布,并在画布上绘制出后端输出的二维码图像。将画布上的图像转换为DataURL格式,通过img标签显示在页面上,或者直接将DataURL传给后端,生成可供下载的二维码图片。
内容概览:
一、前端生成二维码二、后端生成二维码附:下载二维码 一、前端生成二维码 package.json 引入依赖: “qrcodejs2”: “0.0.2”代码中引入并使用 <template> <div> <el-button type="text" @click="refreshQrCode"><i class="el-icon-refresh"></i>点击刷新二维码</el-button> <div id="qrCodeUrl" style="margin-left: 40%;height:250px"></div> </div> </template> <script setup> import QRCode from 'qrcodejs2'; export default { name: 'Template', data() { return { originUrl:'http://www.baidu.com' } }, methods: { refreshQrCode() { this.$nextTick(function () { document.getElementById("qrCodeUrl").innerHTML = ""; let qrCodeUrl = new QRCode("qrCodeUrl", { width: 250, height: 250, text: this.originUrl, #这里就是二维码内的信息,一般可以扫描连接进行调整或其他 colorDark: "#409EFF", colorLight: "#fff" }); }); } } } </script> <style lang="
OptaPlanner使用 0. 总述1. 问题建立1.1 问题说明1.2 问题建模与类的设计1.3 映射到OptaPlanner1.4 类设计相关代码 2. 约束建立2.1 约束类2.2约束方法编写 3. 约束测试4. 总结 最近项目里需要使用optaplanner,学习了一下,来做个总结。
官网:OptaPlanner官网
例程下载:OptaPlanner例子
OptaPlanner Quick Start
参考:OptaPlanner相关资料
0. 总述 OptaPlanner是用于规划问题的优化,也就是对于有约束问题,如何设计实现目标函数的最优。官网中提到了很多可以用OptaPlanner求解的优化问题,比如员工排班、课表设计、资源分配等。
OptaPlanner整体的逻辑是对问题建模后,对某个方案进行评估,得到一个分数,越高的分数说明方案越好。
我主要通过quick start中spring boot下的课表规划Time Table问题说起。
1. 问题建立 课表设计问题的官网说明
1.1 问题说明 我们为学校优化设计出一个适合学生和教师的时间表,每个课程Lesson需要被分配时间 Timeslot、房间Room、教师Teacher、学生Student。
具体来说,这个问题有以下的要求:
一个Room同时至多只有一个Lesson一个Teacher同时至多教一个Lesson一个Student同时至多参加一个Lesson一个Teacher更倾向于在同一个Room教所有的Lesson一个Teacher更倾向于教的Lesson之间没有时间间隔 1.2 问题建模与类的设计 首先要明确我们的目标是为了获得什么? -> 一个时间表TimeTable
如何获得一个Time Table? -> 通过把每个Lesson分到不同的Time Slot和Room
所以我们能设计得到如下的类图:
通过这些类的具体分配关系,可以得到TimeTable。
所以设计的类一共有四个:TimeTable、Lesson、Room、TimeSlot
1.3 映射到OptaPlanner 对于这个问题,想要获得的结果是一个TimeTable,所以在构建项目时,对这个类加上@PlanningSolution,标识这是我们想要解决得到的结果。
那如何构成TimeTable呢?细想Lesson、Room、TimeSlot三者之间的关系,哪些是会变化,哪些是不变的?彼此之间的分配关系又是什么呢?
我们实际上是把Room和TimeSlot分配给Lesson的。一定要明白这个逻辑关系。
(具体谁分配给谁这个逻辑自己要确定好,我感觉这个不是固定的,一个问题也不是只有一种建模方式,目前是参考着官网给出的方案进行说明。)
所以说,Room和TimeSlot是不会变化的,Room的名字一直保持如此,TimeSlot表示的时间段也一直如此,而变化的是Lesson,因为它所在的Room和所在的TimeSlot是需要被分配的。
那么,会变化的Lesson类就用@PlanningEntity标识。
另外,在TimeTable类中,也需要标识出来这三个部分。会变化的Lesson用@PlanningEntityCollectionProperty标识,不会变化的Room和TimeSlot用@ProblemFactCollectionProperty标识。
1.4 类设计相关代码 构造器啥的我就不放了,根据文章开头的链接可以直接下载源码的,这里主要是为了说明注解的使用和类的设计,所以主要放一下每个类的属性。
Room类:
@Entity public class Room { @PlanningId @Id @GeneratedValue private Long id; private String name; } TimeSlot类:
未完成事项:
32个可屏蔽中断通道
4个可编程优先级
电源管理控制
PM0215 编程手册
Q:内部线仅在STOP模式下采样。是仅仅在STOP模式下生效吗?
A:系统处于STOP模式时,可以触发与内部相关的中断或事件。如果系统仍在运行,则不回生成中断\事件。
Q:内部中断线,默认情况下在中断屏蔽寄存器中启用了中断?
A:是的。内部中断线默认开启。
Q:EXTI 哪些是内部中断线?
A:USB、I2C1、USART1等外设都是内部中短线。见下图。
Q:内部中断线,都必须配置中断屏蔽寄存器,不使用事件屏蔽寄存器吗?
EXTI 是扩展中断控制器,可以实现中断源的扩展。
EXTI 管理的事件包括外部事件和内部事件。差异包括:
1、边沿选择:对于外部线来说,边沿是可以选择的。对于内部中断,有效边沿始终是上升沿。
2、中断标志。外部中断有EXTI标志置位。内部中断,没有EXTI标志置位,由发起中断的IP处标志指示。
3、软件中断事件:外部线路,可以在软件中断事件寄存器中写1来生成请求。
Q:NVIC 进入ISR后,会自动清除挂起状态吗?
A:是的。可见编程手册。
Q:如果NVIC 没有使能,仅仅使能了外设中断,那么会导致NVIC挂起?
A:是的。
最近写需求的时候遇到问题
在进行国际化操作的时候
由于每列表头的 中英文 文字描述的长度是不一样的
而且我还使用了 fixed 来固定列,导致固定列的样式不会像其他列一样跟着变化
如图:
然后第一时间想到在 饿了么 文档查询有没有解决的办法
如图,进行重新布局
但是网上找的方法都是基于 vue2 写的
而我的是使用 vue3 中的 setup 里写的
而存在差异
其他博文写法:
我的写法:
这个问题困扰了一天,记录一下
这里的 refs 值是绑定表格的 ref
续: 由于使用了 onUpdated 导致其他问题发生,如使下拉列表 动画显得生硬,
原因: 在每次进行动画操作的时候都会触发 onUpdated 方法。
解决: 欢迎大家留言!
第一章 计算机视觉概述 1.1计算机视觉简介 通常来说,完成视觉任务需要通过图像或视频来理解场景。这两个任务是相互促进,彼此关联的。
从工程学角度来看,计算机视觉主要研究的是 通过图像或视频来重建和理解场景,完成人类视觉可以完成的任务。
近年来,计算机视觉的目标有所改变:从识别出场景中所包含的物体以及场景中正在发生的事件
到推测视频中人的目的和意图,帮助人们理解视频中一些状态变化的原因以及对人的下一步行为进行预测
计算机视觉是一门交叉学科,涉及图像处理、模式识别、机器学习、人工智能、认知学以及机器人学等诸多学科。
图像处理是计算机视觉的基础。图像处理研究的是图像到图像的变换,输入和输出都是图像。
常用图像处理操作:图像压缩、图像增强、图像恢复等。
计算机视觉的输入是图像,而输出则是对图像的理解,在此过程中要用到很多图像处理的方法
模式识别研究是指使用不同的数学模型(包括统计模型、神经网络、支持向量机等)来对不同模式进行分类
模式识别的输入可以是图像、语音、文本等数据计算机视觉中很多问题都可以视为分类问题 计算机视觉的目标:填充图像像素与高层语义之间的鸿沟。
理解:计算机看到的图像是数值矩阵,最终处理目标是将这些数值宗和奇,赋予图像一定的高层语义。
计算机视觉技术可以从图像或视频中获取两类信息:
第一类:语义信息(能够根据图像或视频得到对应场景的语义描述)
第二类:三维的度量信息
计算机视觉可以通过两幅或多幅二维图像恢复场景的三维信息,得到场景中物体距离摄像机的远近信息(深度信息)
深度图可以视为一幅图像,每个像素的值表示了该像素对应的场景中的点距离摄像机距离的远近。
计算机视觉分为三个层次
底层视觉
主要研究图像底层特征的提取与表示,包括边缘检测、角点检测、纹理分析以及特征点的匹配和光流的计算等内容。 中层视觉
主要研究场景的几何和运动,包括立体视觉与运动视觉、图像分割以及目标跟踪等内容。 高层视觉
主要研究物体的检测识别以及场景理解等具有高层语义的内容。 1.2计算机视觉的发展历史 计算机视觉研究的开端:1966年,麻省理工学院(MIT)人工智能实验室Marvin Minsky要求他的学生Gerald Jay Sussman等利用一个暑假的时间完成一个将相机连接到计算机上,使计算机能够描述它所看到的场景的项目。计算机视觉早期对于场景理解的研究主要是针对积木世界(blocks world)进行的,检测边缘和对边缘的拓扑结构进行分析可以得到物体三维结构。里程碑:马尔——《视觉:从计算的视角研究人的视觉信息表达与处理》1982年出版 1.3 计算机视觉领域的学术会议和期刊 三大顶级会议分别是:CVPR,ICCV,ECCV。 ICCV(IEEE International Conference on Computer Vision)国际计算机视觉会议。ICCV由美国电气与电子工程师学会(InstituteofElectrical&ElectronicEngineers,IEEE)主办,由美洲、欧洲以及亚洲的一些科研实力将强的国家轮流举办。通常是每两年举行一次。首届ICCV于1987年在伦敦揭幕。ICCV最佳论文奖名为马尔奖。
CVPR(IEEE Conference on Computer Vision and Pattern Recognition)国际计算机视觉与模式识别会议,通常是每年举行一次,第一届1983年美国华盛顿举行,但举行地点一直是美国本土,美国西部、中部、东部地区之间轮换。大约是每年6月。CVPR有着较为严苛的录用标准,会议整体的录取率通常不超过30%,而口头报告的论文比例更是不高于5%。
ECCV(European Conference on Computer Vision)欧洲计算机视觉国际会议,通常两年举行一次。举办地点在欧洲国家中循环。每次会议在全球范围录用论文300篇左右,主要的录用论文都来自美国、欧洲等顶尖实验室及研究所,中国大陆的论文数量一般在10-20篇之间。ECCV2010的论文录取率为27%。
+数据参考:https://www.codenong.com/cs106899065/
其他著名学术会议 亚洲计算机视觉会议(Asian Conference on Computer Vision,ACCV)图像处理国际会议(International Conference on Image Processing, ICIP)模式识别国际会议(International Conference on Pattern Recognition, ICPR)英国计算机视觉会议(British Machine Vision Conference ,BMVC) 顶级学术期刊 IEEE模式分析与机器智能(IEEE Transactions on Pattern Analysis and Machine Intelligence, TPAMI)汇刊计算机视觉国际(International Journal of Computer Vision ,IJCV)期刊IEEE图像处理事务(Transactions on Image Processing ,TIP)汇刊 1.
List 移除某个元素 四种方式:
方式一,使用 Iterator ,顺序向下,如果找到元素,则使用 remove 方法进行移除。方式二,倒序遍历 List ,如果找到元素,则使用 remove 方法进行移除。方式三,正序遍历 List ,如果找到元素,则使用 remove 方法进行移除,然后进行索引 “自减”。方式四,使用jdk1.8新增的Stream流操作
1.Iterator 迭代器 @Test public void fun9(){ List<String> list = new ArrayList<>(); list.add("赵云"); list.add("黄忠"); list.add("马超"); list.add("关羽"); list.add("张飞"); // 获取迭代器 Iterator<String> it = list.iterator(); while(it.hasNext()){ String str = it.next(); if("关羽".equals(str)){ it.remove(); } } System.out.println(list); } 2.倒序遍历
@Test public void fun10(){ List<String> list = new ArrayList<>(); list.add("赵云"); list.add("黄忠"); list.add("马超"); list.add("关羽"); list.add("张飞"); for (int i = list.
尚医通开发笔记 一、项目分析 项目在线地址:http://syt.atguigu.cn测试帐号:17720125002 首页 home
header
全局组件布局 左:logo 、title中:初始隐藏 搜索框 公共组件显示条件:在页面滚动到页面内搜索框的位置显示 右: 帮助中心登录/注册 如果登录:显示 帐号名 ,有下拉框:显示 : 实名认证、挂号订单、就诊人管理、退出登录 footer
全局公共组件布局 左:京ICP备13018369号 电话挂号010-56253825右: 联系我们 合作伙伴 用户协议 隐私协议 contanier 路由显示区域
轮播图
banner 搜索
search
公共组件 tab切换
title 标题可抽取,随便tabbox title tab-titletab bar 全部 … content 显示区域
卡片
公共组件
布局
左 title card-titledescribe icon+ desc右 logo 分页
公共组件 hospital 布局
左 menu 右 根据menu的选择,显示路由
menu-item
预约挂号
title 与首页卡片里的title相似 ,可酌情抽取icon+医院等级 introduce 布局: 左 医院logo 右 intro- item 公共组件挂号规则 intro-item item-titleitem-content subtitle + subcontent 医院预约规则 intro-item item-titleitem-content rule-text 选择科室 title 首页 【医院title】相似,可服用 tabbar 点击科室 具体内容【xxxx门诊】 检测登录: 未登录,弹出登录弹窗已登录,跳转至【预约挂号】 医院详情
Vue.js + Electron 的跨平台桌面应用程序开发 本文介绍了 Vue.js 和 Electron 的基本特点和原理,并分析了它们在桌面应用程序开发中的优势和应用场景。在基于 Vue.js 和 Electron 的桌面应用程序开发实践中,本文详细介绍了项目的搭建和配置,包括环境的准备、项目的初始化和依赖的安装等步骤。然后,本文介绍了使用 Vue.js 进行界面设计和组件开发的方法,并提供了相关的示例代码和实现细节。接下来,本文探讨了 Electron 主进程和渲染进程的开发,包括窗口管理、文件系统访问和与底层系统交互等方面的内容。最后,本文对基于 Vue.js 和 Electron 的桌面应用程序开发做出了总结,并展望了未来的发展方向和应用前景。
文章目录 Vue.js + Electron 的跨平台桌面应用程序开发1 Vue.js 和 Electron 简介1.1 Vue.js 概述1.2 Electron 概述1.3 Vue.js 和 Electron 的结合优势 2 桌面应用程序开发实践2.1 环境准备与项目搭建2.2 Vue.js界面设计和组件开发2.3 Electron主进程开发2.4 Electron渲染进程开发 3 实验与结果分析3.1 实验设计和实施3.2 结果展示和分析3.3 性能评估和比较分析 4 总结与展望4.1 总结4.2 创新点和局限性4.3 发展方向和应用前景 1 Vue.js 和 Electron 简介 1.1 Vue.js 概述 Vue.js 是一个流行的 JavaScript 前端框架,用于构建用户界面。它采用了 MVVM(Model-View-ViewModel)的架构模式,通过双向数据绑定将视图和数据进行关联。Vue.js 的设计目标是使开发者能够逐步采用和应用它,同时也能够与已有的项目和库进行无缝集成。
以下是 Vue.
目录 引言一、性能天花板-Nginx概念深入浅出二、Nginx环境搭建三、Nginx反向代理-负载均衡Nginx请求分发原理 四、Nginx动静分离五、Nginx资源压缩六、Nginx缓冲区七、Nginx缓存机制缓存清理 八、Nginx实现IP黑白名单九、Nginx跨域配置跨域问题产生的原因Nginx解决跨域问题 十、Nginx防盗链设计十一、Nginx大文件传输配置十二、Nginx配置SLL证书十三、Nginx的高可用Keepalived+重启脚本+双机热备搭建Nginx高可用性测试 十四、Nginx性能优化优化一:打开长连接配置优化二、开启零拷贝技术优化三、开启无延迟或多包共发机制优化四、调整Worker工作进程优化五、开启CPU亲和机制优化六、开启epoll模型及调整并发连接数 总结 引言 早期的业务都是基于单体节点部署,由于前期访问流量不大,因此单体结构也可满足需求,但随着业务增长,流量也越来越大,那么最终单台服务器受到的访问压力也会逐步增高。时间一长,单台服务器性能无法跟上业务增长,就会造成线上频繁宕机的现象发生,最终导致系统瘫痪无法继续处理用户的请求。
“
从上面的描述中,主要存在两个问题:①单体结构的部署方式无法承载日益增长的业务流量。②当后端节点宕机后,整个系统会陷入瘫痪,导致整个项目不可用。
因此在这种背景下,引入负载均衡技术可带来的收益:
「系统的高可用:」 当某个节点宕机后可以迅速将流量转移至其他节点。「系统的高性能:」 多台服务器共同对外提供服务,为整个系统提供了更高规模的吞吐。「系统的拓展性:」 当业务再次出现增长或萎靡时,可再加入/减少节点,灵活伸缩。 OK~,既然引入负载均衡技术可给我们带来如此巨大的好处,那么又有那些方案可供选择呢?主要有两种负载方案,「「硬件层面与软件层面」」 ,比较常用的硬件负载器有A10、F5等,但这些机器动辄大几万乃至几十万的成本,因此一般大型企业会采用该方案,如银行、国企、央企等。而成本有限,但依旧想做负载均衡的项目,那么可在软件层面实现,如典型的Nginx等,软件层的负载也是本文的重点,毕竟Boss们的准则之一就是:「「能靠技术实现的就尽量不花钱。」」
“
当然,如果你认为本文对你而言有帮助,记得点赞、收藏、关注三连噢!
一、性能天花板-Nginx概念深入浅出 Nginx是目前负载均衡技术中的主流方案,几乎绝大部分项目都会使用它,Nginx是一个轻量级的高性能HTTP反向代理服务器,同时它也是一个通用类型的代理服务器,支持绝大部分协议,如TCP、UDP、SMTP、HTTPS等。
Nginx与Redis相同,都是基于多路复用模型构建出的产物,因此它与Redis同样具备 「「资源占用少、并发支持高」」 的特点,在理论上单节点的Nginx同时支持5W并发连接,而实际生产环境中,硬件基础到位再结合简单调优后确实能达到该数值。
先来看看Nginx引入前后,客户端请求处理流程的对比:
原本客户端是直接请求目标服务器,由目标服务器直接完成请求处理工作,但加入Nginx后,所有的请求会先经过Nginx,再由其进行分发到具体的服务器处理,处理完成后再返回Nginx,最后由Nginx将最终的响应结果返回给客户端。
了解了Nginx的基本概念后,再来快速搭建一下环境,以及了解一些Nginx的高级特性,如动静分离、资源压缩、缓存配置、IP黑名单、高可用保障等。
二、Nginx环境搭建 ❶首先创建Nginx的目录并进入:
[root@localhost]# mkdir /soft && mkdir /soft/nginx/ [root@localhost]# cd /soft/nginx/ ❷下载Nginx的安装包,可以通过FTP工具上传离线环境包,也可通过wget命令在线获取安装包:
[root@localhost]# wget https://nginx.org/download/nginx-1.21.6.tar.gz 没有wget命令的可通过yum命令安装:
[root@localhost]# yum -y install wget ❸解压Nginx的压缩包:
[root@localhost]# tar -xvzf nginx-1.21.6.tar.gz ❹下载并安装Nginx所需的依赖库和包:
[root@localhost]# yum install --downloadonly --downloaddir=/soft/nginx/ gcc-c++ [root@localhost]# yum install --downloadonly --downloaddir=/soft/nginx/ pcre pcre-devel4 [root@localhost]# yum install --downloadonly --downloaddir=/soft/nginx/ zlib zlib-devel [root@localhost]# yum install --downloadonly --downloaddir=/soft/nginx/ openssl openssl-devel 也可以通过yum命令一键下载(推荐上面哪种方式):
ini文件结构 ini配置文件由节、键、值组成。
【参数】(键=值):
INI所包含的最基本的“元素”就是参数(parameter),每个参数都有一个name和一个value,name和value由等号“=”隔开,name在等号的左边。如:
[section] 1=A 代码示例 using System.Collections; using System.Collections.Generic; using UnityEngine; using System.Runtime.InteropServices; using static System.Collections.Specialized.BitVector32; using UnityEngine.Experimental.UIElements; public class ConfigIni : MonoBehaviour { /// <summary> /// 为INI文件中指定的节点取得字符串 /// </summary> /// <param name="section">欲在其中查找关键字的节点名称</param> /// <param name="key">欲获取的项名</param> /// <param name="val">指定的项没有找到时返回的默认值</param> /// <param name="filePath">INI文件完整路径</param> [DllImport("kernel32")] private static extern long WritePrivateProfileString(string section,string key,string val,string filePath); /// <summary> /// 为INI文件中指定的节点取得字符串 /// </summary> /// <param name="section">欲在其中查找关键字的节点名称</param> /// <param name="key">欲获取的项名</param> /// <param name="val">指定的项没有找到时返回的默认值</param> /// <param name="
idea登录copilot read ECONNRESET, request id: 20, error code: -32603
解决办法:
先确定github copilot是否给了权限
在idea中设置HTTP代理 ip:127.0.0.1,端口是clash的端口,走代理。修改HTTP代理后需要重启idea,重启,重启!
<el-table ref="multipleTable"> ...内容 </el-table> <el-pagination @current-change="handleCurrentChange"/> handleCurrentChange(val){ this.pageNum.currentPage = val this.dataList()更新列表数据 --重要内容-- this.$nextTick(() => { this.$refs.multipleTable.setScrollTop(0) console.log(this.$refs.multipleTable) }) } 先上代码
主要有两个步骤
1.在el-table中添加ref=“mutipleTable”
2.在对应的切换页码的方法中加上
this.$nextTick(() => {
this.$refs.multipleTable.setScrollTop(0)
})
注意:之前在各平台搜索一直给出的解答是使用Wraper.scrollTop = 0,但是使用后无效,原因可能是因为elementPlus的el-table没有这个属性;所以直接打印this.$refs.multipleTable,可以查看所能使用的属性,对应文档使用即可(还是要多看看文档╥﹏╥)
GET /jv_app_spu_prod_fix/_mapping
GET /jv_app_spu_prod_fix/_settings
新建索引
PUT /jv_app_spu_prod_fix
{
setting
mapping
}
数据迁移
POST _reindex?wait_for_completion=false {
//源
"source": {
"index": "jv_app_spu_prod_fix"
},
//目标
"dest": {
"index": "jv_app_spu_prod"
}
}
Problem - A - Codeforces
AC代码:
#include<iostream> #include<vector> #include<algorithm> #include<set> #include<cmath> #include<numeric> using namespace std; #define endl '\n' #define ll long long #define all(x) (x).begin(),(x).end() #define rall(x) (x).rbegin(),(x).rend() #define pii pair<int,int> const int N = 2e5 + 100; void func() { int n, k; cin >> n >> k; vector<int>a(n); vector<pii>dif(n-1); vector<int>vis(n, 0); for (auto& x : a)cin >> x; int ans = 0; int zu = n; if (k == n)//一组一个人 { //k==1==n||k==n>1 ans = 0; } else//k<n { if (k == 1)//一个组且k!
1.CF1842B
Problem - B - Codeforces
注意:只能一个一个拿,前面的不拿后面也拿不了(后面都不要了)
#include<iostream> #include<vector> #include<algorithm> #include<set> #include<cmath> #include<numeric> using namespace std; #define endl '\n' #define ll long long #define all(x) (x).begin(),(x).end() #define rall(x) (x).rbegin(),(x).rend() #define pii pair<int,int> void func() { int n, x; cin >> n >> x; int y = 0; for (int i = 0; i < 3; i++) { bool k = 1; for (int j = 0; j < n; j++) { int tt; cin >> tt; if ((x | tt) !
平台应用安全 1 平台应用安全1.1 敏感数据1.1.1 应用数据1.1.2 Secret基础1.1.3 Secret案例11.1.4 Secret案例2 1.2 数据访问1.2.1 网络体系解读1.2.2 Service实践1.2.3 Service进阶1.2.4 Service解读 1.3 应用流量1.3.1 Ingress基础1.3.2 Ingress实践1.3.3 Ingress进阶1.3.4 Ingress认证1.3.5 Ingress高阶1.3.6 Ingress扩展 1 平台应用安全 1.1 敏感数据 1.1.1 应用数据 学习目标
这一节,我们从 基础知识、资源对象、小结 三个方面来学习
基础知识
Docker存储
Docker的文件系统 与Docker容器具有相同的生命周期,但是Docker容器肯定会遇到同时运行到多节点场景中,这个时候,会因为节点崩溃、服务崩溃、网络原因,导致容器异常退出,所以一旦我们将数据存储到容器内部,肯定会导致数据丢失。 - Docker镜像是只读的文件,Docker容器可读可写,但是不能够数据持久化。 所以为了避免这种数据异常丢失的情况,我们一般会将 容器的数据(程序状态数据、应用存储数据等),存储在容器的文件系统之外。 - 通过引入外部的存储空间来实现 数据的可持久化效果。 存储方式
Docker的两种文件存储机制: host存储方式 - 通过数据卷 或者 数据卷容器,将当前宿主机上面的文件系统目录与容器里面的工作目录进行一一的关联。 - 即使我们对本地是磁盘做 raid等冗余功能,但是这种等级的安全很鸡肋。 网络存储方式 - 通过网络的方式,将外部的存储空间挂载到当前宿主机,然后借助于host机制实现容器数据的可持久化。 资源对象
资源对象体系
k8s集群中的容器数据存储
k8s集群中的多pod中多容器间的数据存储机制,有两个关键点: 1 容器引擎对共享式存储设备的支持类型: - 多路并行读写 - 多个容器内可以同时对同一个存储设备进行读写操作 - 多路只读 - 多个容器内可以同时对同一个存储设备进行只读操作 - 单路读写 - 多个容器内可以通过同一个中间容器对同一个存储设备进行读写操作 2 pod内部容器使用存储卷有两步: - 在Pod上定义存储卷,并关联至目标存储服务上 - 在需要用到存储卷的容器上,挂载其所属的Pod的存储卷 资源对象属性
1、什么是SDK(Software Development Kit) 广义上的SDK: 指的是为特定的软件包、软件框架、硬件平台、操作系统等建立应用程序时所使用的开发工具的集合。比如你在编辑器里敲代码的时候它会自动补全代码,自动错误检查,你点一下Run,它会调用编译器来自动编译,编译完它会调用iPhone的模拟器来运行,这就是SDK,提供整套的开发工具供开发者使用。 第三方SDK 主要有三种风形式:.jar、.so、.aar jar文件:Java 提供的SDK 文件类型,里面包含的是纯Java编译过后的代码so文件:一般是 C和 C++打包的成库的文件。aar文件:aar 名字来源于 Android Archive,见名知义,是一个 Android 库项目的二进制归档文件。aar 库文件里面,包含了 jar 和 so,还有资源res等文件,结构等同一个app。 补充:什么是API(Application Programming Interface) 翻译成中文就是"应用程式介面",其实这样翻译不好,应该说是"程式沟通介面"。翻译为介面,顾名思义就要沟通两个不同的东西用的,通常由一组函式库所组成。在一个 同一个平台 下的 两个不同东西(程式 or 系统),为了能取用对方的功能等等,所以一个 【程式X】 写了一组函式,让 同一平台的其他程式 取用 【程式X】 的功能,那组函式就可以说是那个 【程式X】 对外开放的 API。 2、利用Android Stuido生成aar 2.1、新建module 2.2、创建方法,配置代码混淆 LeonAPI是暴露给外部的API,所以不能混淆,混淆后就找不到了 package com.leon.leonlib import androidx.annotation.Keep /** * 放置被代码混淆掉 ,在Kotlin中可以使用@Keep注解 */ @Keep object LeonAPI { fun getCurrentTime(): String { return "系统当前时间:${LeonTime().time()}" } } LeonTime实现业务功能的核心代码,需要混淆,防止被别人看到 package com.leon.leonlib import java.
《计算机视觉》 0.1书籍信息 书名:《计算机视觉》 Computer Vision
作者:梁玮 裴明涛编著
出版社:北京理工大学出版社
出版时间:2021.01.01
页数:174页
0.2简介 计算机视觉是研究让计算机能够像人一样来理解图像、视频等视觉信息的科学。
通过摄像机代替人眼获取场景或视频,通过智能算法代替大脑进行分析,获得对于场景中图片或视频的理解。
主要内容: 图像的形成、基本的图像处理方法、图像特征、纹理分析、图像分割、模型拟合、三维重建、物体的检测、跟踪、识别等内容,并对2006年开始兴起的深度学习在计算机视觉中的典型应用进行介绍。
章节目录: 总共12章
1.计算机视觉概述
2.图像的形成
3.图像处理
4.图像的局部特征
5.纹理分析
6.图像分割
7.模型拟合
8.三维重建
9.视觉目标跟踪
10.图像分类
11.物体检测
12.深度学习与计算机视觉
接下来会更新每一章节的笔记整理版本,主要是做一个学习的记录,方便以后查看。如果大家有需要的话,可以自行取用,希望能帮到你!
Ambari-2.7.5在麒麟V10操作系统中的集群部署(二) 之前通过修改os-check.py文件,解决了Ambari安装过程中无法识别kylin系统的问题。
最后成功在三台kylin V10系统上安装了Ambari,并登录前端页面。
本文解决在Ambari页面部署hdp集群的过程中所出现的问题以及解决方案。
1、 在confirm hosts步骤中出现的问题。 Ambari官方建议的是使用全限定类名来扫描hosts,也就是说在/etc/hosts文件中应该是:
#ip地址 全限定类名 简称 192.168.1.101 node1.test.com node1 192.168.1.102 node2.test.com node2 192.168.1.103 node3.test.com node3 我也没有多余的尝试使用简称到底行不行,没什么意义,但是见过成功案例,理论上应该都可以。
下载之前安装的ssh免密服务的密钥,在~/.ssh/目录下,名为id_rsa的文件。将其上传,然后进入confirm阶段。
在此过程中如果总是失败,就重试。
如果卡在preparing阶段,在每一台agent安装的机器上执行如下命令:
vim /etc/ambari-agent/conf/ambari-agent.ini #在[security]下,添加一行代码 force_https_protocol=PROTOCOL_TLSv1_2 [security] keysdir=/var/lib/ambari-agent/keys server_crt=ca.crt passphrase_env_var_name=AMBARI_PASSPHRASE ssl_verify_cert=0 credential_lib_dir=/var/lib/ambari-agent/cred/lib credential_conf_dir=/var/lib/ambari-agent/cred/conf credential_shell_cmd=org.apache.hadoop.security.alias.CredentialShell force_https_protocol=PROTOCOL_TLSv1_2 2、在Install,Start and Test出现问题(重点) 首先最直接的,进入到这一步骤,上来就报错,无论勾选几个服务,在Activity Analyzer Install这里一直报错。
File "/usr/lib/ambari-agent/lib/ambari_commons/repo_manager/yum_manager.py", line 211, in install_package elif context.is_upgrade or context.use_repos or not self._check_existence(name): File "/usr/lib/ambari-agent/lib/ambari_commons/repo_manager/yum_manager.py", line 278, in _check_existence return self.yum_check_package_available(name) File "/usr/lib/ambari-agent/lib/ambari_commons/repo_manager/yum_manager.py", line 287, in yum_check_package_available import yum # Python Yum API is much faster then other check methods.
1.卸载秘钥
2.勾选失败的秘钥后 点击确定
3.重新安装GDLK秘钥
4.安装完毕后重新点击第二个就可以激活office
小程序商城的开发费用因多种因素而异,包括以下几点:
一、功能需求:商城的功能要求不同,开发所需的工作量也会有所不同。例如,基本的商品展示和购买功能相对较简单,而复杂的订单管理、支付、物流等功能可能需要更多的开发工作。
二、设计与界面:商城的设计和界面对用户体验至关重要。如果我们需要进行个性化设计和定制,这可能会增加开发成本和时间。
三、数据库和服务器:商城需要一个稳定的数据库和服务器来存储商品信息、用户数据和其他相关数据。根据数据规模和访问量的大小,选择合适的服务器和数据库方案可能会影响到开发成本。
四、平台与技术选择:小程序可以在不同的平台上开发,如微信小程序、支付宝小程序等。选择不同的平台和技术框架也可能会导致开发成本的不同。
但我们今天给大家推荐一个在线小程序商城制作平台,助力商家自助搭建商城,一键生成小程序商城,微商城,电脑商城,解决商家搭建,运营,营销的诉求
特点,优势:多终端覆盖,个性化装修,海量精美模板,无需代码,一键生成,丰富的营销玩法,完整分销体系,全方位商城管理,广泛适用性,适配多种需求!!
1.CF1845A
Problem - A - Codeforces
#include<iostream> #include<vector> #include<algorithm> #include<set> #include<cmath> #include<numeric> using namespace std; #define endl '\n' #define ll long long #define all(x) (x).begin(),(x).end() #define rall(x) (x).rbegin(),(x).rend() #define pii pair<int,int> void func() { int n, k, x; cin >> n >> k >> x; if (x != 1) { cout << "YES\n"; vector<int>ans(n, 1); cout << n << endl; for (int i = 0; i < n; i++) { cout << 1 << "
1 随机剔除(Dropout)代码实现:
def random_point_dropout(point,max_dropout_ratio=0.875): ''' point:batch*1024*3,numpy类型 随机剔除 随机选取一部分点来用第一个点代替 ''' for batch in range(point.shape[0]): dropout_ratio=np.random.random()*max_dropout_ratio # 0~0.875 # 获取随机剔除的点的索引 drop_idx=np.where(np.random.random((point.shape[1]))<=dropout_ratio)[0] if len(drop_idx)>0: point[batch,drop_idx,:]=point[batch,0,:] return point 随机缩放
物体随机缩放,点云数据的每个点的(x,y,z)数值大小在[scale_low,scale_high]之间随机改变,
def random_point_scale(point,scale_low=0.8,scale_high=1.25): ''' point: Batch*N*3,numpy类型 随机缩放 每个点的数值大小在scale_low~scale_high之间随机改变 ''' B,N,C=point.shape scales=np.random.uniform(scale_low,scale_high,B) for batch in range(B): point[batch,:,:] *= scales[batch] return point 随机平移 点云数据所有点的坐标值(x,y,z)同时加(减)一个数,实现物体的平移
def random_point_shift(point,shift_range=0.1): ''' point:Batch*N*3,numpy类型 随机平移 每个点的数值随机加(减)范围为(-shift_range,shift_range)的随机数 ''' B,N,C=point.shape shifts=np.random.uniform(-shift_range,shift_range,(B,3)) for batch in range(B): point[batch,:,:] += shifts[batch,:] return point 4 在XYZ上加高斯噪声
def jitter_point(point, sigma=0.
1.dll动态链接库准备 unity连接mysql数据库需要以下几个dll
2.mysql数据库准备 ip:本地ip 端口3306 用户名root 密码root 库名cs
在数据库中新建一张表(任意表即可)
3.代码示例 using System.Collections; using System.Collections.Generic; using UnityEngine; using MySql.Data; using MySql.Data.MySqlClient; using System.Data; using System; public class SqlDataBase : MonoBehaviour { private void Start() { ConnectSql(); } public static void ConnectSql() { //建立链接sql语句 string constr = "server=127.0.0.1;User Id=root;password=root;Database=recognizeimg;allow zero datetime = true;charset=utf8"; //建立链接 MySqlConnection mysqlconnection = new MySqlConnection(constr); //打开链接 mysqlconnection.Open(); //插入数据 string inster = "inster into t_version(version_id,create_id,create_TIME) values(1,1,1)"; MySqlCommand mysqlcommandins = mysqlconnection.
const XLSX = require('xlsx') let elt0 = document.getElementById('') let wb = XLSX.utils.table_to_book(elt0,{sheet:'sheet 1',raw:true}) //设置通用样式 let font = { sz:'10', bold:false } let borderAll={ top:{style:'thin'}, bottom:{style:'thin'}, left:{style:'thin'}, right:{style:'thin'} } //添加表头zuo wb.Sheets['Sheet 1']['A1']={t:'s',v:'丫丫',s:{border:borderAll,font{bole:true},fill:{fgColor:{rgb:'cccccc'}}}} wb.Sheets['Sheet 1']['B1']={t:'s',v:'丫丫',s:{border:borderAll,font{bole:true},fill:{fgColor:{rgb:'cccccc'}}}} //循环添加数据 shuju.forEach((item,index)=>{ wb.Sheets['Sheet 1']['A'+(index+2)]={t:'s',v:item.name,s:{border:borderAll,fill:{fgColor:{rgb:'cccccc'}}}} wb.Sheets['Sheet 1']['B'+(index+2)]={t:'s',v:item.title,s:{border:borderAll,fill:{fgColor:{rgb:'cccccc'}}}} }) //添加表头you wb.Sheets['Sheet 1']['G1']={t:'s',v:'丫丫',s:{border:borderAll,font{bole:true},fill:{fgColor:{rgb:'cccccc'}}}} wb.Sheets['Sheet 1']['H2']={t:'s',v:'丫丫',s:{border:borderAll,font{bole:true},fill:{fgColor:{rgb:'cccccc'}}}} //循环添加数据 shuju2.forEach((item,index)=>{ wb.Sheets['Sheet 1']['G'+(index+2)]={t:'s',v:item.name,s:{border:borderAll,fill:{fgColor:{rgb:'cccccc'}}}} wb.Sheets['Sheet 1']['H'+(index+2)]={t:'s',v:item.name,s:{border:borderAll,fill:{fgColor:{rgb:'cccccc'}}}} }) wb.Sheets['Sheet 1']['!fullref']='A1:H'+(shuju.length+1) wb.Sheets['Sheet 1']['!ref']='A1:H'+(shuju.length+1) wb.Sheets['Sheet 1']['!cols']=[{wch:40},{wch:5}] var wopts={bookType:'xlsx',bookSST:false,type:'binary'} var wbout =XLSXStyle.weite(wb,wopts) FileSaver.saveAs(new Blob([this.s2ab(wbout )],{type:''}),`标的名字${}.xls`) s2ab(s){ var buf=new ArrayBuffer(s.
文章目录 1 概述1.1 总结 2 逻辑运算2.1 与:`"×"`、`"·"`、`"∧"`2.2 或:`"+"`、`"∨"`2.3 非:`"¬"`、`"!"`、`"—"`2.4 同或:`"⊙"`2.5 异或:`"⊕"` 3 扩展3.1 网工软考真题 1 概述 1.1 总结 逻辑运算中,1:真(True),0:假(False) 逻辑运算运算规则举例常见运算符与有 0 为 0,全 1 为 11 × 1 = 1
1 × 0 = 0"×"、"·"、"∧"或有 1 为 1,全 0 为 01 + 1 = 1
0 + 0 = 0"+"、"∨"非1 为 0,0 为 1¬1 = 0
¬0 = 1"¬"、"!"、"—"同或相同为 1,不同为 01 ⊙ 1 = 1
1 ⊙ 0 = 0"
文章目录
目录
一、使用scanf
二、使用getchar
三、使用gets函数
一、使用scanf 示例:
使用scanf可以输入字符串,但只能输入中间没有空格的字符串,输入有空格的字符串他会把空格当作结束标志。 二、使用getchar getchar是从控制台获取一个字符,赋予给一个char类型变量,再把字符存放到数组中,需要另外创建一个char类型和int类型变量,且通过while循环来实现,可以输入带空格字符串。 三、使用gets函数 函数介绍 在完成复制后会返回str的首地址。 使用gets函数也可以输入有空格的字符串。
在Vue中,你可以使用v-bind指令来动态绑定行内样式。要添加背景图片,你可以使用background-image属性,并将其值设置为图片的URL。如果你想同时添加多个class,可以使用数组语法。
<template> <div :style="{'background-image': 'url(' + imageUrl + ')'}" :class="[class1, class2]"> <!-- 内容 --> </div> </template> <script> export default { data() { return { imageUrl: require("../../assets/images/"), class1: 'class1的名称', class2: 'class2的名称' }; } }; </script> 值得注意的是在data中的url引入要写commn.js的引入方式去实现
1. RANSAC基本思想 在一组含有”外点”的数据中,不断迭代,最终正确估计出最优参数模型的算法。其中内点是符合最优参数模型的点,反之为外点。外点是一般指的数据中的噪声或无效点,比如说匹配中的误匹配和估计曲线中的离群点。所以也属于一种外点检测算法。
目的:为提高(点)特征的匹配率,提出剔除误匹配对,在特征匹配中,是为了寻找最佳的匹配模型。
1.1 算法步骤 在样本N中随机采样K个点;对这K个点进行模型拟合(这里的模型是什么模型?);计算其他点到该拟合模型的距离,并设置阈值,若大于阈值,为外点,则对该点进行舍弃,小于阈值,为内点,统计内点个数。阈值的设置为经验值,由具体应用和数据集决定;然后以新的内点为基础,再次进行步骤2,得到新的拟合模型,迭代M次,选择内点数最多的模型,此时的模型为最优模型;除此之外也可以在此基础上,选择出内点数最多的模型,然后对它进行重新估计,估计的时候可以采用最小二乘法来拟合。 1.2 迭代次数的公式 RANSAC算法中需要进行M次的迭代过程,且迭代的次数也是可以进行估算的。
n数据中内点所占的比例(内点的概率p):
是K个点都是内点的概率,选取的K个点至少有一个是外点的概率:
因此就能得到迭代M次的情况下,选取点都是外点的概率,进而得到迭代M次中,至少有一次选取点k个点都是内点的概率,也就是正确模型的概率:z一般要求满足大于95%即可。
最终得到迭代次数M
2.举例(拟合最佳单应性矩阵) "单应性矩阵"这个概念通常出现在计算机视觉和图像处理等领域,尤其是在处理图像投影变换时。在数学中,这个概念通常被称为"射影矩阵"或"射影变换"。
单应性矩阵是一个3x3的矩阵,用于描述二维投影变换,如旋转、缩放、剪切和透视等。它可以描述一个二维图像平面如何映射到另一个二维图像平面。这种映射保持了直线的直线性(也就是说,任何在原始图像中的直线在变换后的图像中仍然是直线),但不一定保持角度和长度。换句话说,图像中的线段可能在投影后的图像中扭曲或伸缩。
单应性矩阵H的一般形式如下:
H = [[h11, h12, h13], [h21, h22, h23], [h31, h32, 1]]
这里的hij代表矩阵中的元素,最后一个元素固定为1。矩阵中的其他元素定义了如何将一个二维坐标(x,y)映射到另一个二维坐标(x',y'):
[x', y', 1] = H * [x, y, 1]
其中x'和y'是变换后的坐标,*代表矩阵乘法。
在计算机视觉中,单应性矩阵通常用于矫正图像,使得从一个视角拍摄的图像可以被转换为从另一个视角拍摄的图像。例如,可以用单应性矩阵将一个倾斜的平面(如路面)的图像转换为从正上方观察的图像,这种技术通常用于车辆导航和无人驾驶等领域。
2.1 用RANSAC算法来寻找最佳单应性矩阵H 在特征匹配中,我们最终要得到一个3*3的单应性矩阵。通常令h33=1来归一化矩阵,因此单应性矩阵有8个自由度h11-h32,求这八个未知数,至少要包含四个匹配点对。
其中(x,y)表示目标图像角点位置,(x’,y’)为场景图像角点位置,s为尺度参数。
h33=1来归一化矩阵?
H单应性矩阵,描述两个平面的映射关系,平面中点的坐标是二维的,第三维取1,为了简单化,将h33=1,为最简单的非零值,来归一化矩阵。
步骤:
通过SIFT算法已经进行了粗匹配,然后利用RANSAC算法来进精匹配;首先在得到的匹配点中,随机选择4个匹配点对(不共线),其他匹配点为外点;根据4对内点计算单应性矩阵;根据此矩阵来测试其他匹配点(计算的是其他匹配点与该模型的投影误差),并设置阈值,若小于为新内点,若大于则为外点,也就是误匹配对,因此通过计算出的单应性矩阵,就能实现一次误匹配点的剔除;将所有的内点统计进行内点更新,在此基础上再次进行步骤3,迭代M次,最终得到含有内点最多的模型,此时模型为最优模型,也就是我们最终所需要的单应性矩阵。
大体步骤确定后,我们还需要进行两个参数的确定,阈值和迭代次数。阈值一般是经验值,迭代次数根据上述迭代次数M公式计算得到。
如何用寻找到的单应性矩阵H来测试该模型下的其他匹配点?根据代价函数计算,代价函数最小的模型为最优模型。根据统计的内点数目,数目最多的为最优模型。
2.2 RANSAC 代码 3. 最小二乘法与RANSAC算法区别: RANSAC算法:适用于含有较大的噪声或无效点的情况;
最小二乘法:适用于误差比较小的情况;
引入特征点对的误差能量来改进RANSAC,提升了算法运行效率和识别准确率。
优缺点:
优点:当数据中有着大量的异常数据时,也能高精度的进行估计拟合
缺点:对于异常数据超过50%的时候,拟合效果不佳。需要设置特定于问题的闽值。迭代次数若受到限制,那么达到迭代次数时拟合出来的模型可能并不是最佳模型。特定数据只能拟合出一个模型,一般多模型拟合采用霍夫变换。
目录
前言
一、TCP/IP是什么?
二、网际互联及OSI七层模型
三、TCP/IP 寻址
IP地址
IP 地址包含 4 组数字:
32 比特 = 4 字节
IP V6
域名
总结
前言 TCP/IP协议(Transmission Control Protocol/Internet Protocol)是一种用于互联网通信的协议套件。它起源于上世纪70年代早期,由美国国防部的研究项目ARPANET发展而来,旨在建立一个分散的、具有冗余性的网络架构,以保证网络的可靠性和稳定性。
在当时,各种计算机和网络系统使用不同的协议,无法相互通信。因此,为了实现全球范围的互联网络,需要一种通用的协议来连接不同类型的设备和网络。TCP/IP协议应运而生,成为了互联网的基础通信协议。
TCP/IP协议的设计目标是实现一种分层的协议体系,每一层都负责特定的功能,通过层与层之间的接口协同工作。这种分层设计使得协议的实现更加灵活和可扩展,同时也增加了协议的可靠性和可维护性。
TCP/IP协议套件包含了许多不同的协议,其中最重要的是TCP和IP。TCP负责提供可靠的数据传输服务,保证数据在网络中有序地到达目标设备。IP负责实现数据包的路由和寻址,将数据从源地址传送到目标地址。除了TCP和IP,还有许多其他的协议,如UDP、ARP、ICMP等,共同构成了TCP/IP协议套件。
随着互联网的迅速发展,TCP/IP协议成为了事实上的标准,被广泛应用于各种网络环境和设备中。无论是计算机、手机、智能设备还是网络设备,几乎所有连接到互联网的设备都使用TCP/IP进行通信。
总而言之,TCP/IP协议套件在全球范围内实现了互联互通,成为了互联网通信的基石,为我们提供了现代化的网络通信基础设施。
一、TCP/IP是什么? TCP/IP(Transmission Control Protocol/Internet Protocol)是一组用于互联网通信的网络协议。它是互联网的核心协议,定义了数据在网络中的传输方式和规则。
TCP/IP协议由两个主要部分组成:传输控制协议(TCP)和网际协议(IP)。TCP负责将数据分割成小的数据包,并确保这些数据包在网络中按顺序到达目标设备。它提供了一种可靠的数据传输机制,可以进行错误检测和重传。IP负责将数据包从源地址路由到目标地址,它定义了数据在网络中的寻址和传输方式。
TCP/IP协议不仅限于传输层和网络层,它涵盖了较高层的协议,如应用层协议(如HTTP、SMTP、FTP等),以及底层的网络接口协议(如以太网、Wi-Fi等)。它提供了一种灵活可靠的通信机制,支持各种类型的应用和服务。
TCP/IP协议是互联网的基础,几乎所有连接到互联网的设备都使用TCP/IP进行通信。它不仅在全球范围内实现了互联互通,还为各种网络应用(如网页浏览、电子邮件、文件传输等)提供了支持。因此,TCP/IP被广泛应用于各种网络环境,包括局域网、广域网和互联网。
简单的说:
TCP/IP 是供已连接因特网的计算机进行通信的通信协议。
TCP/IP 指传输控制协议/网际协议(Transmission Control Protocol / Internet Protocol)。
TCP/IP 定义了电子设备(比如计算机)如何连入因特网,以及数据如何在它们之间传输的标准。
二、网际互联及OSI七层模型 物理层、数据链路层、网络层、传输层、会话层、表示层、应用层
物理层
作用:定义一些电器,机械,过程和规范,如集线器;
PDU(协议数据单元):bit/比特
设备:集线器HUB;
注意:没有寻址的概念;
数据链路层
作用:定义如何格式化数据,支持错误检测;
典型协议:以太网,帧中继(古董级VPN)
PDU:frame(帧)设备:以太网交换机;
备注:交换机通过MAC地址转发数据,逻辑链路控制;
网络层
作用:定义一个逻辑的寻址,选择最佳路径传输,路由数据包;
典型协议:IP,IPX,ICMP,ARP(IP->MAC),IARP;
PDU:packet/数据包;
设备:路由器
备注:实现寻址
传输层:
一、Android环境搭建 根据官网:搭建开发环境 · React Native 中文网,必须安装的依赖有:Node、JDK 和 Android Studio。
1、安装Homebrew 2、安装node、npm 3、安装 Watchman 的工具 前三步参考:React Native 环境搭建_爱踢球的小前端的博客-CSDN博客
4、安装 JDK 安装 Java Development Kit(JDK),搭建 Java 开发环境。
众所周知,Android 依赖 Java 开发环境,这里我们搭建 Java 环境使用的工具是 Zulu。
Zulu 是一款 Java 运行环境,它是基于 OpenJDK(一个 Java 编程语言的开源实现的源代码)构建的。Zulu 提供了 Intel 和 M1 Mac 的 JDK,这使得 JDK 的安装更为方便。
由于 Zulu 是一个图形界面程序,需要手动安装,为了方便这里我们借助 Cask 一键安装。你需要先借助 Homebrew 安装 Cask 再安装 Zulu。命令如下:
brew tap homebrew/cask-versions
brew install --cask zulu11
安装成功后,可以运行 java --version 检查 Java 运行时环境(JRE)的版本,或运行 javac --version 检查 Java 开发工具包(JDK)中 Java 编译器(javac)的版本。
综合【安全科普】系列前两篇文章内容,我们可以得知,攻击者在横向移动过程中,其最终目的是登陆目标主机并窃取机密数据。
因此我们必须采取多种防护措施,以防止攻击者窃取密码或进行凭证传递。除此之外,还可利用监控手段来探查攻击者的踪迹,并增加系统配置以提高域内安全性。
接下来将会详细介绍以上所述:
一、防止攻击者窃取密码
在使用WDigest(摘要式身份验证)的系统中,密码会以明文形式存储在内存,攻击者通过Mimikatz可以直接抓取密码。为了防止密码泄露,我们可以关闭WDigest。
但该功能只有在Windows Server 2012以上版本的系统才能被关闭,而在Windows Server 2012以下版本的系统中只能通过安装补丁KB2871997来解决问题。
KB2871997支持RDP 网络登录,即在登录过程中使用登录令牌来进行身份验证。这种方法不会在RDP服务器中存储用户凭证,用户注销时,也会清除主机缓存中的凭证,以此来保护凭证安全。
同时,KB2871997支持创建“受保护的用户”组。只要把域功能级别设置为Windows Server 2012 R2,系统就会创建受保护的组,在该组中的用户只能使用Kerberos协议进行身份验证。相比于WDigest,Kerberos验证方式更安全,因为它不会在内存中存储明文密码。
想要防止密码被盗的话,除了安装补丁,我们还需要对攻击者常用的工具进行防范,比如Mimikatz。
由于Mimikatz与内存(LSASS进程)交互需要Debug权限,我们可以将拥有Debug权限的本地管理员从Administrators组中移出。这样,当攻击者以本地管理员身份登录时,就没有权限使用Mimikatz从内存导出密码。
二、防护哈希传递攻击
通过以上手段,我们能有效防止黑客从系统中窃取明文密码,但是当黑客窃取到了用户凭据,使用哈希传递等手段登录系统时,并没有一个能彻底解决哈希传递的方法,我们只能减轻这种攻击。
这里介绍两种方法——Defender ATP和微软管理层模型。
Defender ATP : 是微软提供的一种安全工具,它能检测攻击者访问LSASS进程的行为。如果发现某时刻LSASS进程被读取的内存数量过多,就会报警,提示管理员“敏感凭据内存读取”。
微软管理层模型 : 将不同权限的用户划分到不同层级,并规定高层级不能登录低层级。举例来说,将能够访问网络上所有关键服务器的管理员划分为第0级,将工作站管理员划分为第2级,那么即使黑客窃取到了关键服务器管理员的凭证,以管理员身份也无法登录关键服务器。
三、监控异常活动
攻击者横向移动过程通常难以被察觉,但我们可以分析其行为特征,监控是否有存在满足其特征的活动来确定系统是否被入侵。
对于在目标范围内安装恶意软件的横向攻击行为,我们可以监控应用安装情况。例如当安装应用的时间固定在一个时间段,而其它时间段的安装行为都将被认为是异常的。
攻击者进行横向移动攻击的另一个典型行为就是窃取信息。通过监控文件创建行为和SMB传输文件行为,可以发现远程文件复制活动;通过监控可移动介质上的文件访问,能识别可移动介质复制行为;通过监控多文件写入共享能发现共享文件污染行为等。
如果攻击者已进入内网,为了防止他横向移动到更多主机,我们可以监测内网中活跃的用户账号,将这些账户设置为高风险账户,降低其权限,阻止其使用内网资源。
监控内网中的异常活动,能帮助我们发现攻击者侵入企业内网的行为,以便及时采取措施阻止其损害企业利益。
四、更改系统配置
给系统配置防火墙是防范一般网络攻击的重要手段,对横向移动攻击也能起到一定的作用。比如,通过配置防火墙的进站/出站规则阻止445端口的连接,能防范利用SMB协议漏洞的攻击;启用防火墙禁止RDP流量能防止RDP远程连接系统;启动域防火墙能阻止DCOM对象实例化。
此外,我们也可以通过配置Windows系统规则来防范横向移动攻击。
当攻击者利用Windows打印机后台处理程序来执行特权操作时,我们可以禁用“允许打印后台处理程序接收客户端连接”,也可以直接禁用打印后台处理程序服务。
当系统遭受NTLM中继攻击时,我们可以禁用NTLM并切换成Kerberos验证,或启用SMB签名和LDAP签名等。(NTLM中继攻击:攻击者劫持受害者会话,将受害者凭证转发到其它服务器获取信任)
正确配置系统规则,不仅能防范横向移动攻击,还能保护系统资源的合法使用
结语
攻击者进行横向移动的手法多种多样,以上方法并不能完全防范横向移动攻击。要有效阻止横向移动,需要分析具体事件来制定有针对性的防护措施。
尤其是在企业等组织机构中,由于内网的复杂性,攻击团伙的手段也比较高超,一般的防护手段不能有效地防范横向移动攻击,要保护企业内网安全,最好选择专业的运营团队。
横向移动,是攻击者侵入企业系统时,获取相关权限及重要数据的常见攻击手法。了解横向移动的原理有助于个人和企业更好地维护网络安全。
中安网星特此推出了横向移动科普系列,本系列共有三篇文章。
横向移动是在复杂的内网攻击中被广泛应用的一种方式,也是APT(高级可持续威胁)攻击的重要组成部分。横向移动主要在APT的后续攻击中发挥作用,用于窃取大量信息资产以及进行更深入的渗透。
除APT威胁事件以外,当前企业所面临的勒索问题和内部威胁也大多与〝横向移动〞有关。接下来我们将分别讨论横向移动是如何威胁密码安全、主机安全以及信息安全的:
一、横向移动威胁
1.威胁密码安全
黑客横向移动的过程可能导致密码失窃,从而威胁到计算机内文件数据的安全。
在企业办公网络中,大部分办公电脑都设置有密码、登录凭证,用以防止数据等相关私密文件被他人查看。这种情况下,黑客想要横向移动到加密主机,就要通过一些手段来获取密码,或窃取登录凭证。
与其他的攻击方式相同,“弱口令”是黑客获取密码最简单的一类途径。尤其是主机RDP相关的弱口令,这类系统远控桌面服务的弱口令一旦被黑客利用,就能通过“撞库”等方式暴力破解,进而实现内网计算机的远程控制。
而黑客窃取登陆凭证的方式主要包括:lsass内存读取、注册表读取、ntds 数据库读取等。在通过一系列手段窃取到登陆凭证后,黑客就能通过哈希传递、票据传递的方式登录目标主机。
以上两种方式作为黑客横向移动的初始步骤,被广泛应用于APT攻击及横向移动攻击相关的威胁事件中。
例如,在前不久的美国燃油管道勒索攻击事件中,darkside攻击团伙从文件、内存和域控制器中收集凭据,并利用这些凭据来登录其它主机,再对重要数据和控制端口进行加密,进而实施勒索。
由此可见,横向移动造成的密码失窃严重威胁到包括关键基础设施在内的多种网络设施安全。
2.威胁主机安全
黑客在横向移动中使用远程控制目标主机的方式,导致主机安全受到威胁。
由于Windows系统自带连接远程主机执行命令的功能。在黑客获得账号密码的情况下,可以通过IPC(进程间通信)连接目标主机,建立安全通道,在该通道传输加密数据。
而Windows的计划任务功能也常被黑客利用来定时激活病毒木马,达到长期威胁内网主机的目的。
除了windows系统自带功能,黑客还经常使用一些工具来进行远程控制:
Psexec由于其强大的提权和远程命令执行能力,在横向移动中应用非常普遍。它不仅能以system权限来运行指定应用程序,还能在本机生成命令提示符窗口,只要输入命令,就能在远程主机上执行并返回结果。
Psexec被众多安全厂商加入查杀黑名单后,近几年,通过调用WMI来进行远程操作的工具也屡见不鲜。(WMI是一项Windows管理技术,通过它可以访问、配置、管理几乎所有计算机资源。)
相比于Psexec,使用WMI执行远程命令基本不会在远程主机上留下日志,让黑客的行为显得更隐蔽。
调用WMI来进行横向移动的工具包括WMIEXEC.exe、WMIEXEC.vbs脚本、Invoke-Command.ps1脚本和Invoke-WMIMethod.ps1脚本。
其中WMIEXEC.vbs脚本可以获取远程主机的半交互式Shell,执行单条命令并返回显示结果。(Shell为用户提供了可以访问操作系统内核服务的界面)
3.威胁信息安全
黑客进行横向移动攻击,会窃取和泄漏大量信息,直接威胁信息安全。
几乎所有针对企业进行攻击的事件都与信息窃取相关。一旦突破安全边界进入内网,黑客们就会使用各种手段横向移动渗透内网其它主机,尤其是敏感信息存放主机。
在勒索攻击事件中,最常见的勒索方式是:攻击者将信息加密后,以公开其机密数据的方式要挟赎金。
比如,著名的勒索攻击团伙海莲花,其常用手法是在内网中建立立足点后使用Cobalt Strike进行横向移动。通过Cobalt Strike扫描内网中存在的各类漏洞和配置问题,利用扫描结果进一步控制其它主机。最终窃取包括商业机密、机密谈话日志和进度计划等在内的各种资料,严重威胁制造、媒体、银行、酒店和基础设施的网络安全。
二、横向移动威胁的特点
由上,我们可以总结出横向移动威胁的特点,即威胁面大,威胁性强。
1.如何理解威胁面大?
从目标对象来说,横向移动威胁的不是某一台主机,而是多台主机,甚至整个内网。
从黑客目的来说,黑客要利用他掌握的信息威胁企业,必须掌握到关键且大量的数据,就要通过横向移动不断扩大资产范围。
2.如何理解威胁性强?
黑客为了造成更大影响,通常选择重要的信息系统,如金融、电信、交通、能源等计算机系统,利用横向移动进行大面积网络攻击,导致系统瘫痪,严重影响基本的社会生活。
如前文提到的美国燃油管道勒索攻击事件,和爱尔兰医疗服务机构遭受Conti勒索软件攻击事件,还有加拿大保险公司guard.me遭受网络攻击事件……
另外,横向移动造成的影响让企业在后续恢复中也面临较大的困难。企业需要消耗许多人力财力对本次攻击溯源,找到并修补内网存在的漏洞,还需要耗费大量时间精力还原被黑客破坏的文件等资源,重新启动业务系统。
三、结语
黑客横向移动的手段已经非常成熟。除了病毒中的自动化横向移动模块,目前也已经有许多横向移动的工具被广泛使用。
因此,对横向移动的防护是目前内网安全防护中的重中之重。其核心目标是,即使黑客进入企业内网,也能通过一系列防护手段阻止他渗透到更多主机,为相关权限及关键数据提供安全防护。
在下一篇“横向移动”系列文章中,我们将为大家详细介绍“横向移动”防护的相关内容。
横向移动,是攻击者侵入企业系统时,获取相关权限及重要数据的常见攻击手法。了解横向移动的原理有助于个人和企业更好地维护网络安全。
中安网星特此推出了横向移动科普系列,本系列共有三篇文章。
近年来,随着网络攻击、勒索事件频发,企业安全防护需求迅速上升,传统安全防护中以密码和权限管理为核心的单一防护模式愈发不能满足目前的网络安全环境。因而,深入了解攻击思路,“对症下药”,是目前网络安全行业发展的重要方向。
本篇文章将就“横向移动”这一典型攻击行为进行简单阐述,从攻击者视角还原“横向移动”攻击过程中的典型场景,为深入剖析“横向移动”攻击行为提供简单参考。
简单来讲,横向移动是指攻击者成功攻击一台计算机后,由该计算机横向跨越到另一台计算机,获取相关权限,进而窃取敏感信息的活动。
从定义上来看,我们不难发现,“横向移动”攻击的主要目标是企业关键信息及相关管理权限,而横向跨越的攻击属性也表明这一攻击行为多数情况下发生在企业内网中。
换个角度来讲,也正是由于企业内网中计算机存在聚集性,以及内网中一些集权管理设备储存有大量身份凭证信息及关键数据,使得企业内网更容易成为攻击者的目标,也就成为了横向移动的重灾区。
基于这样的前提,本篇文章将以“企业内网中的横向移动”攻击路径为例,尽量全面的展示“横向移动”攻击的思路与方法。
一、企业内网中的横向移动
假设一家企业将保存有所有计算机用户账号密码信息的文件存放在域控主机上,同时设置只有管理员才可以查看。
现在有一位经验丰富的黑客想要窃取该文件。
Step 1 : 【信息收集】
首先黑客通过一系列攻击手段进入一台普通员工的计算机,但是这台计算机上只有该员工平时工作使用的PPT,文件等内容,没有高敏感信息。
此时他将收集域内信息,探查可能保存机密文件和敏感信息的主机位置,确定横向移动的目标。
分析后,黑客发现该企业采用的是AD域来管理内网计算机用户,根据经验得知,域控上存储有所有计算机用户的账号密码信息,于是他决定横向移动到域控主机。
Step 2 :【域控登录】
一般情况下,域控主机设置有高加密型的登录验证方式,如果黑客能够获得域控主机的登录密码,那么他就可以伪装成正常用户登录。
在采用kerberos登录验证的域环境中,正常用户登录时先输入密码在Kerberos服务器上进行验证,验证成功后,该服务器会发送给用户一个凭证证明其合法性,用户利用该凭证才可以登录计算机使用内网资源。
但一般情况下,域控主机的密码不会在普通主机上留下记录,也较难通过暴力破解的方式获取明文密码。
此时,黑客会在已控制的普通主机上查找与目标主机和环境相关的信息,获知目标主机开放的端口、存在的漏洞等,然后利用该漏洞渗透目标主机获取凭证,再使用哈希传递、黄金白银票据等方式进行登录。
尽管黑客完成了登录步骤,但是在最终的文件获取环节上,域控通常还有一道防线,即“权限限制”。
Step 3 : 【权限获取】
这正是我们设置的第二层防护——对特定文件实行白名单制度,限制用户查看权限。
这种情况下,黑客通常会通过一些提权手法来突破限制,比如系统溢出漏洞提权、数据库提权、系统配置错误提权等,我们将这类手法统称为“权限提升”。
横向移动与权限提升同属攻击链的上下游位置。就攻击效果来说,前者主要体现在被控制计算机的数量,后者主要体现在对单个计算机控制的程度,一个作用于扩大作战区域,一个作用于收刮区域资源。
所以现在黑客离窃取我们的用户信息文件只差最后一步了——通过权限提升的方法来获取相应文件的查看权限。
最终,通过横向移动、登录突破、权限提升的过程,黑客完成了对关键信息与敏感数据的获取。除此以外,还能以域控主机为跳板,横向移动到其它域内主机,通过已获取的密码直接登录目标主机,执行远程命令,完成域内控制,进而以关键信息与权限为由,实施勒索行为。
二、结语
通过上文的攻击实例,我们展示了一个相对简单的“横向移动”攻击链路模型。
实际上,在横向移动攻击过程中,攻击者不仅可以运用相关技术与思路访问共享文件夹、凭证等敏感信息,也可以通过“横向移动”的方法渗透其它主机,窃取商业数据、财务信息等。正因如此,“横向移动”的技术与攻击思路被广泛应用于网络攻击,尤其是针对企业用户的APT(高级可持续性威胁)攻击中。
在下一篇“横向移动”系列文章中,我们将为大家详细介绍“横向移动”攻击对于企业网络安全防护造成的重大威胁。
实验目的 通过本实验,了解php封装伪协议,掌握filter协议和data协议的用法
实验环境 操作机:kali
靶机:Windows Server 2003
实验地址:http://靶机ip/exp/include2/filter/
http://靶机ip/exp/include/include3.php
用户名:college
密码:360College
实验原理 php内置又很多内置URL风格的封装为协议,利用这些伪协议可以读取文件内容、命令执行等操作。
实验内容 靶机phpstudy开启服务;
filter协议文件包含 1.登录“Kali-Desktop”操作机,打开火狐浏览器,输入地址:http://靶机ip/exp/include2/filter/点击超链接,发现URL是http://【ip】/exp/include2/filter/index.php?file=show.php,应该是关于文件包含的
2.页面没有任何可利用的信息(因为内容被解析成php是看不见的),因此需要使用?file=php://filter/read=convert.base64-encode/resource=index.php,读取到base64加密的index.php文件
3.解密得到flag:flag{edulcni_elif_lacol_si_siht}
data协议 命令执行 1.登录“Kali-Desktop”操作机,打开火狐浏览器,输入地址:http://靶机ip/exp/include/include3.php
2.使用?page=data://text/plain,<?php phpinfo();?>,发现报错,需要在服务器端开启php.ini配置文件的allow_url_include参数(参见上文),然后重启Apache服务,刷新页面
3.代码得到执行,同样也可以写入一句话木马,再用菜刀进行连接
实验总结 掌握data协议和filter协议的用法
目录
一、什么是方法?
1.方法的格式
最简单的方法的定义和调用
带参数的方法的定义和调用
带返回值的方法的定义和调用
2.方法的重载
3.关于方法的两个练习
4.方法的内存
方法调用的基本内存原理
方法传递基本数据类型的内存原理
方法传递引用数据类型的内存原理
5.ststic 关键字
二、面向对象基础
1.类与对象
如何定义类
如何得到类的对象
如何使用对象
定义类的补充注意事项
2.构造方法
构造方法的格式
构造方法的注意事项
3.标准的JavaBean类
4.对象内存图
一个对象的内存图
两个对象的内存图
5.封装
private关键字
get和set方法
6.继承(extends)
继承的构造顺序
7.重写
8.super关键字
9.就近原则和this关键字
就近原则
this关键字的作用
this关键字的本质
10.final 关键字(最终)
11.访问权限
12.克隆
13.抽象类(abstract)
14.接口
三、字符串
字符串常用的一些方法
字符串的比较
StringBuffer 和 StringBuilder 区别
正则表达式
练习1--模拟用户登录
练习2--遍历字符串和统计字符次数
四、常用类
1.常用的数学类
2.包装类
一、什么是方法? 方法是程序中最小的执行单元
优点:1.提高代码的复用性 2.提高代码的可维护性
1.方法的格式 最简单的方法的定义和调用 定义格式:
public static void 方法名(){
方法体(就是打包起来的代码);
目 录
前言
1 系统需求分析
1.1 系统功能需求分析
1.1.1 额度警告功能
1.1.2 多平台记账功能
1.1.3 人机交互界面
1.1.4 管理功能
1.2 系统非功能需求分析
2 系统设计
2.1 系统功能模块划分
2.2 数据库设计
2.2.1 用户管理信息表
2.2.2 帐户信息管理表
2.2.3 科目管理表
2.2.4 收支流水信息管理表
2.2.5 超额警报管理表
2.2.6 财务报表信息表
2.3 类和接口设计
2.3.1 注册类设计
2.3.2 登录类设计
2.3.3 管理页面设计
2.3.4 记账管理类
2.3.5 账户管理类
2.3.6 科目管理类
2.3.7 账单管理类
2.3.8 警告管理类
2.3.9 个人信息管理类
2.3.10 美化类
3 系统实现
3.1 注册界面实现
3.2 登陆界面实现
3.3 记账管理界面实现
3.4 账户管理界面实现
3.5 科目管理界面实现
报错: Field userDetailsService in com.zhao.security.config.WebSecurityConfig required a bean of type 'org.springframework.security.core.userdetails.UserDetailsService' that could not be found. The injection point has the following annotations: - @org.springframework.beans.factory.annotation.Autowired(required=true) The following candidates were found but could not be injected: - Bean method 'inMemoryUserDetailsManager' in 'UserDetailsServiceAutoConfiguration' not loaded because @ConditionalOnMissingBean (types: org.springframework.security.authentication.AuthenticationManager,org.springframework.security.authentication.AuthenticationProvider,org.springframework.security.core.userdetails.UserDetailsService,org.springframework.security.oauth2.jwt.JwtDecoder,org.springframework.security.oauth2.server.resource.introspection.OpaqueTokenIntrospector; SearchStrategy: all) found beans of type 'org.springframework.security.authentication.AuthenticationManager' authenticationManager Action: Consider revisiting the entries above or defining a bean of type 'org.springframework.security.core.userdetails.UserDetailsService' in your configuration.
目录
一、什么是Ajax?
二、Ajax的原理是什么?
三、Ajax是怎样实现的?
(1)创建 Ajax的核心对象 XMLHttpRequest对象
(2)通过 XMLHttpRequest 对象的 open() 方法与服务端建立连接
(3) 构建请求所需的数据内容,并通过XMLHttpRequest 对象的 send() 方法发送给服务器端
(4) 绑定onreadystatechange事件,XMLHttpRequest 对象提供的 onreadystatechange 事件监听服务器端你的通信状态
四、原生整体流程
五、jquery插件封装的ajax请求
(1)如果是自己进行封装
(2) 如果是使用jQuery插件,首先需要引入插件,然后调用Ajax方法
一、什么是Ajax? AJAX全称(Async Javascript and XML),即异步的JavaScript 和XML,是一种创建交互式网页应用的网页开发技术。
特点:异步发送请求;无需重新刷新当前页面,采用部分刷新。
二、Ajax的原理是什么? 相当于在用户和服务器之间加了一个中间层,使用户操作和服务器响应异步化,并不是所有的用户请求都提交给服务器,像一些数据处理可以交给Ajax引擎来做,只有确定需要从服务器读取新数据时再由Ajax引擎代为服务器提交请求。
三、Ajax是怎样实现的? (1)创建 Ajax的核心对象 XMLHttpRequest对象 通过XMLHttpRequest() 构造函数用于初始化一个 XMLHttpRequest 实例对象
const xhr = new XMLHttpRequest(); (2)通过 XMLHttpRequest 对象的 open() 方法与服务端建立连接 xhr.open(method, url, [async][, user][, password]) //method:表示当前的请求方式,常见的有GET、POST //url:服务端地址 //async:布尔值,表示是否异步执行操作,默认为true //user: 可选的用户名用于认证用途;默认为null //password: 可选的密码用于认证用途,默认为null (3) 构建请求所需的数据内容,并通过XMLHttpRequest 对象的 send() 方法发送给服务器端 xhr.
问题描述 org.apache.spark.shuffle.FetchFailedException: The relative remote executor(Id: 21), which maintains the block data to fetch is dead.
最近在做Spark的性能优化,测试使用不同CPU核数和内存对计算性能的影响,由于是在测试集群进行测试的,硬件配置比生产上面的要少和低,遇到了不少的问题,其中一个值得说一下的就是org.apache.spark.shuffle.FetchFailedException:Failed to connect to /xxx:43301
一、运行环境 1.1 硬件 3台测试服务器,分别为A,B,C,每台4核,16GB内存
每台部署HDFS的DataNode和Spark的Worker
其中A同时部署了HDFS的NameNode
其中B同时部署了Spark的Master
其中C是Spark的Driver
1.2 软件 HDFS 2.7.3,集群
Spark 2.1.0,标准集群模式
Java 1.8.0_131
二、Spark启动参数 2.1 测试1 2.1.1 测试参数 spark.driver.cores 没有配置,默认使用1
spark.driver.maxResultSize 配置2g,默认是1g
spark.driver.memory 配置3g,默认是1g
spark.executor.memory 配置8g,默认是1g
spark.executor.cores 没有配置,默认使用Worker全部核数,这里是4
2.1.2 测试结果 Spark集群每个Worker创建了1个Executor,每个Executor使用了4核和8g内存,可以得出结果,耗时2小时
2.2 测试2 2.2.1 测试参数 spark.driver.cores 没有配置,默认使用1
spark.driver.maxResultSize 配置2g,默认是1g
spark.driver.memory 配置3g,默认是1g
因为想每个Worker创建多于1个Executor,测试多个Executors是否能提高性能,所以修改以下参数:
spark.executor.memory 配置4g,是测试1的一半
spark.executor.cores 配置2,是测试1的一半
CentOS7
firewalld(默认安装) 和 iptables 都不是防火墙,它们只是防火墙的管理程序
防火墙的开启、关闭、禁用命令
设置开机启用/禁用防火墙:systemctl enable/disable firewalld.service
启动/关闭防火墙:systemctl start/stop firewalld
检查防火墙状态:systemctl status firewalld使用firewall-cmd配置端口
查看防火墙状态:firewall-cmd --state
重新加载配置:firewall-cmd --reload
查看开放的端口:firewall-cmd --list-ports
开启防火墙端口:firewall-cmd --zone=public --add-port=9200/tcp --permanent
命令含义:
–zone #作用域
–add-port=9200/tcp #添加端口,格式为:端口/通讯协议
–permanent #永久生效,没有此参数重启后失效
注意:添加端口后,必须用命令firewall-cmd --reload重新加载一遍才会生效
关闭防火墙端口:firewall-cmd --zone=public --remove-port=9200/tcp --permanent Ubuntu
ubuntu的ufw与iptables
在Ubuntu系统进行安装的时候默认安装了ufw防火墙,如果没有安装可以使用命令sudo sudo apt-get install ufw进行安装
查看防火墙的状态 sudo ufw status 系统提示: “Status: inactive”状态:不活跃。表示没有开启防火墙,并不是没有安装防火墙;开启后提示Status: active并显示开放的端口
关闭防火墙 sudo ufw disable 开启防火墙 sudo ufw enable 注意:Command may disrupt existing ssh connections. Proceed with operation (y|n)?
这里以四台为例
连线方式
第一台的51口 连第二台的51口
第二台的52口 连第三台的51口
第三台的52口 连第四台的51口
第四台的52口 连第一台的52口
--------------DeviceA configuration----------
system-view
interface ten-gigabitethernet 1/0/51
shutdown
quit
interface ten-gigabitethernet 1/0/52
shutdown
quit
irf-port 1/1
port group interface ten-gigabitethernet 1/0/51
irf-port 1/2
port group interface ten-gigabitethernet 1/0/52
quit
interface ten-gigabitethernet 1/0/51
undo shutdown
quit
interface ten-gigabitethernet 1/0/52
undo shutdown
quit
irf member 1 priority 32
save force
irf-port-configuration active
--------------DeviceB configuration----------
system-view
irf member 1 renumber 2
y
quit
https://www.mapstruct.plus/https://www.mapstruct.plus/
# 博主技术栈如下 springboot:2.4.5 lombok:1.8.20 mapstruct-plus:1.3.4 knife4j:4.0.0 目录
一、添加依赖(谨防依赖冲突)
二、如果依赖下不下来,要在maven的setting文件中加入腾讯云的镜像
三、 实战测试(将User转成UserDto)
一、添加依赖(谨防依赖冲突) <properties> <java.version>1.8</java.version> <mapstruct-plus.version>1.3.4</mapstruct-plus.version> </properties> <dependency> <groupId>io.github.linpeilie</groupId> <artifactId>mapstruct-plus-spring-boot-starter</artifactId> <version>${mapstruct-plus.version}</version> </dependency> <dependency> <groupId>com.github.xiaoymin</groupId> <artifactId>knife4j-openapi2-spring-boot-starter</artifactId> <version>4.0.0</version> <exclusions> <exclusion> <groupId>org.mapstruct</groupId> <artifactId>mapstruct</artifactId> </exclusion> </exclusions> </dependency> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.8.1</version> <configuration> <source>1.8</source> <!-- 这里根据自己的需要进行切换 --> <target>1.8</target> <!-- 这里根据自己的需要进行切换 --> <annotationProcessorPaths> <path> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>${lombok.version}</version> </path> <path> <groupId>io.github.linpeilie</groupId> <artifactId>mapstruct-plus-processor</artifactId> <version>${mapstruct-plus.version}</version> </path> <path> <groupId>org.projectlombok</groupId> <artifactId>lombok-mapstruct-binding</artifactId> <version>0.2.0</version> </path> </annotationProcessorPaths> </configuration> </plugin> </plugins> </build> 二、如果依赖下不下来,要在maven的setting文件中加入腾讯云的镜像 <mirror> <id>nexus-tencentyun</id> <mirrorOf>*</mirrorOf> <name>Nexus tencentyun</name> <url>http://mirrors.
硬件:联想拯救者y7000
安装Ubuntu18.04 安装Ubuntu首先你要想好是这个Ubuntu你要放在哪里,常见的有3个方法:
1、放在VMware虚拟机里
2、弄成双系统
3、放在大容量硬盘或者U盘上挂载
考虑到自己是用在深度学习上,虚拟机和移动硬盘挂载可能不是特别适合我(原因可以自己去百度)所以我决定使用双系统方案。
那为什么要用18版不用20版的Ubuntu呢,因为18的时间比20长你遇到的坑别人绝大多数都踩过,网上可供参考的资料会更多,懂的都懂
安装准备 1、 Ubuntu系统镜像链接
2、 USB刻录软件Rufus
3、4G左右的U盘
烧录镜像与分配空间 其实这个烧录也没什么好说的你可以用Rufus,也可以用软碟通,只要把镜像ISO文件录进去就行了,这里就不过多解释,详细操作自己试一次就知道了。
首先不要急着去重启安装,要分配好所需要的磁盘空间,在桌面的“计算机”上右键,选择“管理”,进入如下窗口,点击“磁盘管理”(这图不是我的,因为我在Ubuntu里面写,所以没有专门去截图)。
我建议为Ubuntu分配50G到100G左右的空间(看你有多大的盘),选中一个盘(别选C盘,信我),我的是D盘分配了200G。选中D 盘,按鼠标右键,选择“压缩卷”,在新弹出的窗口上输入200000M就OK了。做完这些准备工作就可以正式安装了。
安装Ubuntu 第一步连接电源,插入U盘,关机重启,在电脑进入logo阶段时,快速长按bios键进入boot界面,注意是boot界面不是BIOS界面(我的电脑是拯救者,进入boot界面的BIOS键是F12)。bios设置u盘启动,这个网上依据不同机型教程各不相同,我就不说了自己查。
第二步在boot界面里有一个UEFI的U盘启动入口(如果你的不是UEFI或者没有的,可以去参考一下这篇博客),键盘控制进去,可以看见一个类似下图的的界面。
用键盘控制,选择 Install Ubuntu 回车进入安装。(我看见有的人会在回车后卡住,可是我没有遇到这种情况,不过我把别人的方法贴出来,注意不要急着去安装驱动)
第三步这里就要注意了,一些选项不要选错了:
选择 Install Ubuntu
选择中文汉语(选别的就自己看着办)
先不要连WiFi,不然在安装时会同时下载别的东西会很慢,跳过
这个选择第一个,第二个都行,区别是第一个会多配上一些工作软件,安装时间会长一点;第二个就比较空白(第三个就别选了,很多人都不建议所以我没试过,如果你试过可以去评论区告诉我)
必选其他选项,很重要,你的启动盘、系统盘和用户盘等都是在这里做的,然后继续
点击其它选项后继续,会弹出这个界面
选择空闲设备,这个空闲设备容量大约是200000M,它就是我们前面所压缩出来的200G硬盘。把这个硬盘分成4个(分多少个,每个分多少,看个人,别乱分就行),如下表:
名称分区格式大小/boot逻辑分区Ext4500M/主分区Ext450Gswap逻辑分区swap8G/home逻辑分区Ext4剩余 我们选择空闲设备,然后点击下面的+号进行分区,在创建分区界面进行配置。
最后分区结束后,不要急着下一步安装,先点击+号下面一行的“安装启动引导器设备”选项,选择你之前分了500M左右的那个/boot设备。
右下角继续安装将改动写入磁盘,继续配置时间地图、账号和密码,然后就开始安装等待了。
安装网卡和NVIDIA驱动 安装准备 1、更换清华源
清华源地址
打开终端
将系统自带的该文件做个备份: sudo cp /etc/apt/sources.list /etc/apt/sources.list.backup 备份后输入命令更换文件里面的内容: sudo gedit /etc/apt/sources.list sudo apt-get update 更新源 sudo apt-get upgrade 更新软件 有线网络无法连接,安装gcc和make后安装驱动 ,先跳过这一步,离线安装显卡驱动,安装后会有网卡驱动的。
无线网络无法连接,估计是驱动不匹配,比如我的型号是Intel® Wi-Fi 6E AX211 160MHz,参考这篇博客安装新驱动
(js)new Date() 怎么取年月日 <div class="time"> <span>{{time}}</span> </div> data() { return { time: new Date().toLocaleDateString(), } }, 解决参考地址