操作系统与内存管理
操作系统内存管理
文章目录
- 操作系统内存管理
- 1. 虚拟地址空间
- 2. 内存地址空间含义及分配
- 3. 虚拟内存诞生的前世与今生?
- 3.1 内存管理的好处
- 3.2 **内存管理实现总体策略**
- 4. 不同进程如何划分内存地址空间?
- 5 内存分配与回收
- 5.1 buffer和cache
- 5.2 malloc背后发生了什么?
- 5.3 第一次访问刚分配的内存时,会发生什么?
- 5.4 内存缓冲区 Swap
- 5.5 内存碎片处理
1. 虚拟地址空间
虚拟内存管理
malloc
page-fault 缺页错误
物理内存空间
page-table 页表结构
mmap 内存映射
swap 内存交换区
2. 内存地址空间含义及分配
- 内存地址空间 ≠ 物理内存空间
Virtual address space ≠ Physical memory space
门牌号 ≠ 实际房屋
门牌号数量 ≥ 实际房屋数量 - 32bit vs 64bit
2^32 = 4GB
2^64 = 16EB = 16,384 PB = 1.7e17 TB
处理器支持:
ARMv7 (32bit), ARMv8 (64bit)
x86, amd64 (x86_64)
操作系统支持
编译器支持 - 具体内存划分如下图所示
物理内存 Physical Memory
DRAM: 泛指内存
DIMM: 特指一条内存
虚拟内存地址 物理内存地址
虚拟内存地址 Virtual Memory Address (VMA)
物理内存地址 Physical Memory Address (PMA)
保护模式下的代码(user/kernel)都使用VMA
CPU自动完成 VMA PMA 转换
分配粒度:a memory page = 4KB
Page Table: 记录VMA --> PMA映射的数据结构
Page Table 保存在 Kernel Address Space,由操作系统维护
每个进程有一个独立的 Page Table,用户空间 VMA -->PMA 映射各不相同
所有进程共享同一内核空间中VMA–>PMA映射
TLB用于加速 VMA --> PMA 转换
3. 虚拟内存诞生的前世与今生?
MMU诞生之前:
在传统的批处理系统如DOS系统,应用程序与操作系统在内存中的布局大致如下图:
- 应用程序直接访问物理内存,操作系统占用一部分内存区。
- 操作系统的职责是“加载”应用程序,“运行”或“卸载”应用程序。
如果我们一直是单任务处理,则不会有任何问题,也或者应用程序所需的内存总是非常小,则这种架构是不会有任何问题的。然而随着计算机科学技术的发展,所需解决的问题越来越复杂,单任务批处理已不能满足需求了。而且应用程序需要的内存量也越来越大。而且伴随着多任务同时处理的需求,这种技术架构已然不能满足需求了,早先的多任务处理系统是怎么运作的呢?
程序员将应用程序分段加载执行,但是分段是一个苦力活。而且死板枯燥。此时聪明的计算机科学家想到了好办法,提出来虚拟内存的思想。程序所需的内存可以远超物理内存的大小,将当前需要执行的留在内存中,而不需要执行的部分留在磁盘中,这样同时就可以满足多应用程序同时驻留内存能并发执行了。
从总体上而言,需要实现哪些大的策略呢?
- 所有的应用程序能同时驻留内存,并由操作系统调度并发执行。需要提供机制管理I/O重叠,CPU资源竞争访问。
- 虚实内存映射及交换管理,可以将真实的物理内存,有可变或固定的分区,分页或者分段与虚拟内存建立交换映射关系,并且有效的管理这种映射,实现交换管理。
这样,衍生而来的一些实现上的更具体的需求:
- 竞争访问保护管理需求:需要严格的访问保护,动态管理哪些内存页/段/区,为哪些应用程序所用。这属于资源的竞争访问管理需求。
- 高效的翻译转换管理需求:需要实现快速高效的映射翻译转换,否则系统的运行效率将会低下。
- 高效的虚实内存交换需求:需要在实际的虚拟内存与物理内存进行内存页/段交换过程中快速高效。
总之,在这样的背景下,MMU应运而生,也由此可见,任何一项技术的发展壮大,都必然是需求驱动的。这是技术本身发展的客观规律。
3.1 内存管理的好处
- 为编程提供方便统一的内存空间抽象,在应用开发而言,好似都完全拥有各自独立的用户内存空间的访问权限,这样隐藏了底层实现细节,提供了统一可移植用户抽象。
- 以最小的开销换取性能最大化,利用MMU管理内存肯定不如直接对内存进行访问效率高,为什么需要用这样的机制进行内存管理,是因为并发进程每个进程都拥有完整且相互独立的内存空间。那么实际上内存是昂贵的,即使内存成本远比从前便宜,但是应用进程对内存的寻求仍然无法在实际硬件中,设计足够大的内存实现直接访问,即使能满足,CPU利用地址总线直接寻址空间也是有限的。
3.2 内存管理实现总体策略
从操作系统角度来看,虚拟内存的基本抽象由操作系统实现完成:
- 处理器内存空间不必与真实的所连接的物理内存空间一致。
- 当应用程序请求访问内存时,操作系统将虚拟内存地址翻译成物理内存地址,然后完成访问。
从应用程序角度来看,应用程序(往往是进程)所使用的地址是虚拟内存地址,从概念上就如下示意图所示,MMU在操作系统的控制下负责将虚拟内存实际翻译成物理内存。
从而这样的机制,虚拟内存使得应用程序不用将其全部内容都一次性驻留在内存中执行:
节省内存:很多应用程序都不必让其全部内容一次性加载驻留在内存中,那么这样的好处是显而易见,即使硬件系统配置多大的内存,内存在系统中仍然是最为珍贵的资源。所以这种技术节省内存的好处是显而易见的。
使得应用程序以及操作系统更具灵活性。
- 操作系统根据应用程序的动态运行时行为灵活的分配内存给应用程序。
- 使得应用程序可以使用比实际物理内存多或少的内存空间。
细究 MMU(Memory Management Unit)内存管理单元 请参考:关于MMU那些事儿
4. 不同进程如何划分内存地址空间?
每个进程都独占整个用户态内存地址空间:
进程在用户态时,只能访问用户空间内存;只有进入内核态后,才可以访问内核空间内存。虽然每个进程的地址空间都包含了内核空间,但这些内核空间,其实关联的都是相同的物理内存,也就是共享动态链接库、共享内存等。当进程切换到内核态后,就可以很方便地访问内核空间内存。
并不是所有的虚拟内存都会分配物理内存,只有那些实际使用的虚拟内存才分配物理内存,并且分配后的物理内存,是通过内存映射来管理的。内存映射,其实就是将虚拟内存地址映射到物理内存地址。为了完成内存映射,内核为每个进程都维护了一张页表,记录虚拟地址与物理地址的映射关系。
不同进程存在于不
页表实际上存储在 CPU 的内存管理单元 MMU 中,这样,正常情况下,处理器就可以直接通过硬件,找出要访问的内存。而当进程访问的虚拟地址在页表中查不到时,系统会产生一个缺页异常,进入内核空间分配物理内存、更新进程页表,最后再返回用户空间,恢复进程的运行。
**CPU 上下文切换中的TLB(**Translation Lookaside Buffer,转译后备缓冲器)是 MMU 中页表的高速缓存。由于进程的虚拟地址空间是独立的,而 TLB 的访问速度又比 MMU 快得多,所以,通过减少进程的上下文切换,减少 TLB 的刷新次数,就可以提高 TLB 缓存的使用率,进而提高 CPU 的内存访问性能。
MMU(Memory Management Unit)内存管理单元: 规定了一个内存映射的最小单位,也就是页,通常是 4 KB 大小。这样,每一次内存映射,都需要关联 4 KB 或者 4KB 整数倍的内存空间。
4 KB大小的页,会导致整个页表会变得非常大,比如32位系统4GB/4KB=100多万个页表项。为了解决页表项过多的问题,Linux 提供了两种机制,也就是多级页表和大页(HugePage)。
多级页表就是把内存分成区块来管理,将原来的映射关系改成区块索引和区块内的偏移。由于虚拟内存空间通常只用了很少一部分,那么,多级页表就只保存这些使用中的区块,这样就可以大大地减少页表的项数。Linux 用四级页表来管理内存页,虚拟地址被分为 5 个部分,前 4 个表项用于选择页,而最后一个索引表示页内偏移。
大页,就是比普通页更大的内存块,常见的大小有 2MB 和 1GB。大页通常用在使用大量内存的进程上,比如 Oracle、DPDK 等。
通过这些机制,在页表的映射下,进程就可以通过虚拟地址来访问物理内存了。
5 内存分配与回收
malloc() 是 C 标准库提供的内存分配函数,对应到系统调用上,有两种实现方式,即 brk() 和 mmap()。
对小块内存(小于 128K),C 标准库使用 brk() 来分配,也就是通过移动堆顶的位置来分配内存。这些内存释放后并不会立刻归还系统,而是被缓存起来,这样就可以重复使用。
对大块内存(大于 128K),则直接使用内存映射 mmap() 来分配,也就是在文件映射段找一块空闲内存分配出去。
这两种方式的优缺点:
brk()方式的缓存,可以减少缺页异常的发生,提高内存访问效率。不过,由于这些内存没有归还系统,在内存工作繁忙时,频繁的内存分配和释放会造成内存碎片。
mmap()方式分配的内存,会在释放时直接归还系统,所以每次 mmap 都会发生缺页异常。在内存工作繁忙时,频繁的内存分配会导致大量的缺页异常,使内核的管理负担增大。这也是 malloc 只对大块内存使用 mmap 的原因。
需要注意的是:当这两种调用发生后,其实并没有真正分配内存。这些内存,都只在首次访问时才分配,也就是通过缺页异常进入内核中,再由内核来分配内存。
整体来说,Linux 使用伙伴系统来管理内存分配。前面我们提到过,这些内存在 MMU 中以页为单位进行管理,伙伴系统也一样,以页为单位来管理内存,并且会通过相邻页的合并,减少内存碎片化(比如 brk 方式造成的内存碎片)。
但在实际系统运行中,会有大量比页还小的对象,如不到1K,如果为它们也分配单独的页,会浪费大量的内存,那该怎么分配内存呢?
在用户空间,malloc 通过 brk() 分配的内存,在释放时并不立即归还系统,而是缓存起来重复利用。
在内核空间,Linux 则通过 slab 分配器来管理小内存。你可以把 slab 看成构建在伙伴系统上的一个缓存,主要作用就是分配并释放内核中的小对象。
内存回收:对内存来说,如果只分配而不释放,就会造成内存泄漏,甚至会耗尽系统内存。所以,在应用程序用完内存后,还需要调用 free() 或 unmap() ,来释放这些不用的内存。当然,系统也不会任由某个进程用完所有内存。在发现内存紧张时,系统就会通过一系列机制来回收内存,比如下面这三种方式:
(1)回收缓存,比如使用 LRU(Least Recently Used)算法,回收最近使用最少的内存页面。
(2)回收不常访问的内存,把不常用的内存通过交换分区(Swap)直接写到磁盘中。Swap 其实就是把一块磁盘空间当成内存来用。它可以把进程暂时不用的数据存储到磁盘中(这个过程称为换出),当进程访问这些内存时,再从磁盘读取这些数据到内存中(这个过程称为换入)。Swap 把系统的可用内存变大了,但通常只在内存不足时,才会发生 Swap 交换,并且由于磁盘读写的速度远比内存慢,Swap 会导致严重的内存性能问题。
(3)杀死进程,内存紧张时系统还会通过 OOM(Out of Memory,内核的一种保护机制),直接杀掉占用大量内存的进程.。OOM 监控进程的内存使用情况,并且使用 oom_score 为每个进程的内存使用情况进行评分:
一个进程消耗的内存越大,oom_score 就越大;
一个进程运行占用的 CPU 越多,oom_score 就越小。
这样,进程的 oom_score 越大,代表消耗的内存越多,也就越容易被 OOM 杀死,从而可以更好保护系统。
当然,为了实际工作的需要,管理员可以通过 /proc 文件系统,手动设置进程的 oom_adj,从而调整进程的 oom_score。oom_adj 的范围是 [-17, 15],数值越大,表示进程越容易被 OOM 杀死;数值越小,表示进程越不容易被 OOM 杀死,其中 -17 表示禁止 OOM。如用下面的命令,你就可以把 sshd 进程的 oom_adj 调小为 -16,这样, sshd 进程就不容易被 OOM 杀死。
5.1 buffer和cache
free命令中buffer和cache都表示缓存,但用途不一样
1、 Buffer,是内核缓冲区用到的内存,对应的是/proc/meminfo中的Buffer值
2、 Cache,是内核页缓存和Slab用到的内存,对应的是/proc/meminfo中的Cache和SReclaimable之和
简单来说,Buffer 是对磁盘数据的缓存,而 Cache 是文件数据的缓存,它们既会用在读请求中,也会用在写请求中。
cache(缓存)从CPU角度考虑,是为了提高cpu和内存之间的数据交换速度而设计的,例如平常见到的一级缓存、二级缓存、三级缓存。 cpu在执行程序所用的指令和读数据都是针对内存的,也就是从内存中取得的。由于内存读写速度慢,为了提高cpu和内存之间数据交换的速度,在cpu和内存之间增加了cache,它的速度比内存快,但是造价高,又由于在cpu内不能集成太多集成电路,所以一般cache比较小,以后intel等公司为了进一步提高速度,又增加了二级cache,甚至三级cache,它是根据程序的局部性原理而设计的,就是cpu执行的指令和****访问的数据往往在集中的某一块,所以把这块内容放入cache后,cpu就不用在访问内存了,这就提高了访问速度。当然若cache中没有cpu所需要的内容,还是要访问内存的。
从内存读取与磁盘读取角度考虑,cache可以理解为操作系统为了更高的读取效率,更多的使用内存来缓存可能被再次访问的数据。
**缓冲(buffers)**是为了提高内存和硬盘(或其他I/O设备)之间的数据交换的速度而设计的。把分散的写操作集中进行,减少磁盘碎片和硬盘的反复寻道,从而提高系统性能。linux有一个守护进程定期清空缓冲内容(即写入磁盘),也可以通过sync命令手动清空缓冲。
简单来说,buffer是即将要被写入磁盘的,而cache是被从磁盘中读出来的。 buffer是由各种进程分配的,被用在如输入队列等方面。一个简单的例子如某个进程要求有多个字段读入,在所有字段被读入完整之前,进程把先前读入的字段放在buffer中保存。
cache经常被用在磁盘的I/O请求上,如果有多个进程都要访问某个文件,于是该文件便被做成cache以方便下次被访问,这样可提高系统性能。
5.2 malloc背后发生了什么?
为什么可以运行?
因为malloc分配的是虚拟内存地址空间
分配小于 MMAP_THRESHOLD (128KB),从 Heap 分配
分配大于 MMAP_THRESHOLD (128KB),从 Memory Mapping Segment 分配
物理内存在第一次访问的时候才分配(demand paging)
每次分配一个物理内存页(4KB)
内存结构如下图所示:
5.3 第一次访问刚分配的内存时,会发生什么?
Page Fault 缺页错误
- 第一次访问一个新malloc出来的地址时,该Virtual Memory Address (VMA) 还未有与其对应的物理内存页
- CPU中的Memory Management Unit (MMU)单元会触发一个缺页错误的硬件中断
- 操作系统内核收到该中断后会去检查该VA是否处在一个合法的VMA区间
- 如果VMA不合法,则抛出段错误 (Segmentation fault) ,然后杀掉该进程,如果合法,则在空余的物理内存池中寻找一个内存页,通过修改页表 (Page table) 来完成 VMA到物理内存的对应关系
如何判断 VMA 是否合法?
- malloc() 会调用 brk() 或 mmap() 来向kernel注册合法的虚拟内存地址空间 Virtual Memory Area (VM Area),详细键 5.0开头。
这些VM Area由一棵红黑树来维护
5.4 内存缓冲区 Swap
当物理内存耗尽时,操作系统会将一部分访问不频繁的数据从内存搬移到硬盘中
-硬盘上用于保存这些数据的区域称为“内存缓冲区”(Swap)
这理论上可以让应用程序可以使用的内存和硬盘一样大
但是使用硬盘缓冲区会导致访问速度减慢100倍(20GB/s vs 200MB/s)
top 实例分析
VIRT (Virtual): 所声明的虚拟内存空间(包括分配未使用)
RES (Resident): 所使用的物理内存空间(不包括swap)
SHR (Shared): 和其他进程共享的内存空间
判断一个进程占用内存空间大小,关键看RES
5.5 内存碎片处理
内部碎片
已分配给某进程,但不能被该进程利用的物理内存空间
内部:物理内存页的内部
内存分配尽可能采用同样大小(或整数倍大小)
外部碎片
- 未分配给任一进程,但由于太小了无法分配给申请内存空间的进程的物理内存空间
- 通常发生在需要分配一段连续的物理内存空间时(例如 kmalloc,DMA)
- 外部碎片导致内存不足的情况相对罕见
内存碎片整理工具有用吗?
简单回答:没用
原因:内存碎片整理工具无法知道每一块内存被谁引用,直接移动会导致程序指针失效,程序崩溃
市面上的内存碎片整理工具干了啥?
step 1:申请一大块虚拟内存空间
step 2:访问这块虚拟内存空间,触发page fault
step 3:操作系统为该虚拟内存空间分配物理内存,进而将其他进程内存中的数据写到swap
step 4:碎片整理工具释放刚申请的内存
step 5:新启动的程序即时拥有可使用的内存
作用:
- 减少了新启动程序触发swap的耗时
- 一定程度上缓解了内存泄漏
副作用:让已经在运行的程序频繁触发swap
- Managed environments 自带内存碎片整理功能
- JVM / C# / Go / Rust
相关文章:

圆形 LBP 特征
template <typename _Tp> staticinline void elbp_(InputArray _src, OutputArray _dst,int radius, int neighbors) {// 得到数据矩阵Mat src _src.getMat();// 输出矩阵_dst.create(src.rows-2*radius, src.cols-2*radius, CV_32SC1);Mat dst _dst.getMat();// 初始化…

40个Java多线程问题总结
(转) 这篇文章作者写的真是不错 40个问题汇总 1、多线程有什么用? 一个可能在很多人看来很扯淡的一个问题:我会用多线程就好了,还管它有什么用?在我看来,这个回答更扯淡。所谓"知其然知其所…

SLAM十四讲笔记1
文章目录ch02 初识SLAMch02-01 经典视觉SLAM框架ch02-02 SLAM问题的数学表述ch03 三维空间刚体运动ch03.01 旋转矩阵:点和向量,坐标系01 向量a在线性空间的基[e1,e2,e3][e_1,e_2,e_3][e1,e2,e3]下的坐标为[a1,a2,a3]T[a_1,a_2,a_3]^T[a1,a2,a3]T.02 向量…

12、OpenCV实现图像的空间滤波——图像平滑
1、空间滤波基础概念 1、空间滤波基础 空间滤波一词中滤波取自数字信号处理,指接受或拒绝一定的频率成分,但是空间滤波学习内容实际上和通过傅里叶变换实现的频域的滤波是等效的,故而也称为滤波。空间滤波主要直接基于领域(空间域…

计算 LBP 特征
#include <opencv2/opencv.hpp> #include <opencv2/highgui/highgui.hpp> #include <opencv2/features2d/features2d.hpp> #include <opencv2/features2d/features2d.hpp> // 计算原始LBP特征 cv::Mat OLBP(cv::Mat& srcImage) {const int nRows …

三维重建【四】-------------------结构光 三维重建----论文调研
1. 动态目标实时三维重建-结构光方案 动态目标 三维重建 Stripe boundary codes for real-time structured-light range scanning of moving objects 我们提出了一种新的实时结构光扫描方法。在分析现有结构光技术的基本假设之后,我们基于编码投影条纹之间的边界&…

APP开发定制
app是什么意思? APP,application的简称,是智能手机的第三方应用程序,常见的有微信、手机qq、今日头条、手机支付宝、腾讯视频、微店等,随着智能手机和ipad等移动终端设备的普及,人们逐渐习惯了使用APP客户端上网的方式…

Haar 特征提取
double HaarExtract(double const ** image ,int type_, cv::Rect roi) {double value;double wh1, wh2;double bk1, bk2;int x roi.x;int y roi.y;int width roi.width;int height roi.height;switch (type_){// Haar水平边缘case 0: // HaarHEdgewh1 calcIntegral(image…

awk的基本⽤法
awk的基本⽤法 awk是报告⽣成器,格式化⽂本输出,有多种版本。centos中的是gawk即GNU awk版本。 awk⼯作原理:第⼀步:执⾏BEGIN{action;...}语句块中的语句。第⼆步:从⽂件或标准输⼊(stdin)读取…
视音频数据处理入门:RGB、YUV像素数据处理【转】
转自:http://blog.csdn.net/leixiaohua1020/article/details/50534150 视音频数据处理入门系列文章: 视音频数据处理入门:RGB、YUV像素数据处理 视音频数据处理入门:PCM音频采样数据处理 视音频数据处理入门:H.264视频…

SVO(SVO: fast semi-direct monocular visual odometry)
SVO(SVO: fast semi-direct monocular visual odometry)翻译 文章目录SVO(SVO: fast semi-direct monocular visual odometry)翻译1、介绍2、系统概述3、符号4、运动估计4.1、 基于稀疏模型的图像对齐4.2、 通过特征对齐松弛4.3、…

MSER 候选车牌区域检测
#include "opencv2/highgui/highgui.hpp" #include "opencv2/features2d/features2d.hpp" #include "opencv2/imgproc/imgproc.hpp" #include <iostream> // Mser车牌目标检测 std::vector<cv::Rect> mserGetPlate(cv::Mat srcImage…

从HelloWorld看Knative Serving代码实现
为什么80%的码农都做不了架构师?>>> 摘要: Knative Serving以Kubernetes和Istio为基础,支持无服务器应用程序和函数的部署并提供服务。我们从部署一个HelloWorld示例入手来分析Knative Serving的代码细节。 概念先知 官方给出的这…

svo_note
SVO论文笔记1.frame overviews2. Motion Estimate Thread2.1 Sparse Model-based Image Alignment 基于稀疏点亮度的位姿预估2.2 Relaxation Through Feature Alignment 基于图块的特征点匹配2.3 Pose and Structure Refinement3 Mapping Thread3.1 depth-filter3.2 初始化参考…

Druid 配置 wallfilter
这个文档提供基于Spring的各种配置方式 使用缺省配置的WallFilter <bean id"dataSource" class"com.alibaba.druid.pool.DruidDataSource" init-method"init" destroy-method"close">...<property name"filters" v…

vue下的bootstrap table + jquery treegrid, treegrid无法渲染的问题
在mian.js导入的包如下:该bootstrap-table-treegrid.js需要去下载,在复制到jquery-treegrid/js/ 1 import $ from jquery 2 import bootstrap/dist/css/bootstrap.min.css 3 import bootstrap/dist/js/bootstrap.min 4 import bootstrap-table/dist/boot…

内存和缓存的区别
今天看书的时候又看到了内存和缓存,之所以说又,是因为之前遇到过查过资料,但是现在又忘了(图侵删)。 所以又复习一遍,记录一下,有所纰漏的地方,欢迎指正。 同志们,上图并不是内存和缓存中的任何…

【Boost】noncopyable:不可拷贝
【CSDN】:boost::noncopyable解析 【Effective C】:条款06_若不想使用编译器自动生成地函数,就该明确拒绝 1.example boost::noncopyable 为什么要boost::noncopyable 在c中定义一个类的时候,如果不明确定义拷贝构造函数和拷贝赋…

BigData NoSQL —— ApsaraDB HBase数据存储与分析平台概览
一、引言时间到了2019年,数据库也发展到了一个新的拐点,有三个明显的趋势: 越来越多的数据库会做云原生(CloudNative),会不断利用新的硬件及云本身的优势打造CloudNative数据库,国内以阿里云的Cloud HBase、POLARDB为代…

ubuntu clion 创建桌面快捷方式
ubuntu clion 创建桌面快捷方式 首先在终端下输入 cd /usr/share/applications/进入applications目录下,建立一个clion.desktop文件 sudo touch clion.desktop然后在vim命令下编辑该文件 sudo vim clion.desktop进入vim后,按i插入开始编辑该文件&…

Flex 布局:语法篇
2019独角兽企业重金招聘Python工程师标准>>> 布局的传统解决方案,基于盒状模型,依赖 display 属性 position 属性 float 属性。它对于那些特殊布局非常不方便,比如,垂直居中就不容易实现。 2009年,W3C 提…

特征运动点估计
cv::Mat getRansacMat(const std::vector<cv::DMatch>& matches, const std::vector<cv::KeyPoint>& keypoints1, const std::vector<cv::KeyPoint>& keypoints2, std::vector<cv::DMatch>& outMatches) {// 转换特征点格式std::vecto…

Vue+Element-ui+二级联动封装组件
通过父子组件传值 父组件: 1 <template>2 <linkage :citysList"citysList" :holder"holder" saveId"saveId"></linkage>3 </template>4 <script>5 import linkage from ./common/linkage6 export de…

MOG2 成员函数参数设定
pMOG2->setDetectShadows(true); // 背景模型影响帧数 默认为500 pMOG2->setHistory(1000); // 模型匹配阈值 pMOG2->setVarThreshold(50); // 阴影阈值 pMOG2->setShadowThreshold(0.7);前景中模型参数,设置为0表示背景,255为前景ÿ…
webpack 大法好 ---- 基础概念与配置(1)
再一次见面! Light 还是太太太懒了,距离上一篇没啥营养的文章已经过去好多天。今天为大家介绍介绍 webpack 最基本的概念,以及简单的配置,让你能快速得搭建一个可用的 webpack 开发环境。 webpack的安装 webpack 运行于 node 环境…

Zookeeper迁移(扩容/缩容)
zookeeper选举原理在迁移前有必要了解zookeeper的选举原理,以便更科学的迁移。快速选举FastLeaderElectionzookeeper默认使用快速选举,在此重点了解快速选举:向集群中的其他zookeeper建立连接,并且只有myid比对方大的连接才会被接…

SVO Without ROS环境搭建
Installation: Plain CMake (No ROS) 首先,建立工作目录:workspace,然后把下面的需要的都在该目录下进行. mkdir workspace cd workspace Boost - c Librairies (thread and system are needed) sudo apt-get install libboost-all-dev Eige…

BackgroundSubtractorGMG 背景建模
#include <opencv2/bgsegm.hpp> #include <opencv2/video.hpp> #include <opencv2/opencv.hpp> #include <iostream> #include <sstream> using namespace cv; using namespace std; using namespace bgsegm; // GMG目标建模检测 void detectBac…

启动webpack-dev-server只能本机访问的解决办法
修改package.json的dev启动设置,增加--host 0.0.0.0启动后localhost更换为本机IP即可访问

TCP/IP:IP选项处理
引言 IP输入函数要对IP 进行选项处理,。RFC791和1122规定了IP选项和处理规则。一个IP首部可以跟40个字节的选项。 选项格式 选项的格式,分为两种类型,单字节和多字节。 ip_dooptions函数 这个函数用于判断分组转发。用常量位移访问IP选项字段…