linux delete内存不下降_linux内存分配管理
linux内存分配管理
一、前言
作为从事与C/C++程序开发人员,我们一直需要很好的管理内存,申请和释放;可能很多只知道使用malloc、new去申请,使用free、delete去释放,但是,去根究其内部的原理,可能就不是很清楚了;
这里主要对linux平台的内存管理进行一下总结和梳理;
二、内存申请释放
Linux虚拟内存管理相关概念请移步至详解linux虚拟内存原理;
这里主要说说的是我们的内存是怎么申请的:
在C/C++中,使用malloc
进行内存分配,C++使用的new
,但是其底层也是使用malloc
;在系统调用上面,一般使用的是brk()
和mmap()
函数;
我们说一说这两个函数的使用场景:
brk():
当内存分配使用小于
128K
对于小于
128K
的小块内存,系统会使用brk()
来分配,也就是通过移动堆顶的位置来分配内存。这些内存释放后并不会立刻归还系统,而是被缓存起来,这样就可以重复使用。**注:**使用
brk()
分配内存时,只分配虚拟空间,不对应物理内存,只有第一次读/写数据时,引起内核缺页中断,内核才分配对应的物理内存,然后在虚拟地址上建立映射关系;回收内存
申请内存使用完毕之后,内存并不是真正的释放掉了,而是只回推了**_edata**指针,内存可以被重复利用;
brk分配的内存需要等到高地址内存释放以后才能释放brk分配的内存需要等到高地址内存释放以后才能释放,所以会产生内存碎片;
但是当最高地址空间超过了
128k
,就会执行trim
(内存紧缩)操作;
mmap():
大于
128K
大块内存(大于
128K
),则直接使用内存映射mmap()
来分配,也就是在文件映射段找一块空闲内存分配出去。注意:这个和
brk()
是一样的,只有第一次使用的时候才会真正分配物理内存;回收内存
mmap
回收内存时是直接释放归还,不会进行重复利用,所以这种会导致每次mmap
都会发生缺页异常。在内存工作繁忙时,频繁的内存分配会导致大量的缺页异常,使内核的管理负担增大。这也是malloc
只对大块内存使用mmap
的原因。
参考:Linux内存分配小结--malloc、brk、mmap
三、linux内存管理
伙伴算法
定义:由一个母实体分成的两个各方面属性一致的两个子实体,这两个子实体就处于伙伴关系。在操作系统分配内存的过程中,一个内存块常常被分成两个大小相等的内存块,这两个大小相等的内存块就处于伙伴关系
伙伴系统的宗旨就是用最小的内存块来满足内核的对于内存的请求。在最初,只有一个块,也就是整个内存,假如为
1M
大小,而允许的最小块为64K
,那么当我们申请一块200K
大小的内存时,就要先将1M
的块分裂成两等分,各为512K
,这两分之间的关系就称为伙伴,然后再将第一个512K
的内存块分裂成两等分,各位256K
,将第一个256K
的内存块分配给内存,这样就是一个分配的过程;伙伴系统特点
1)两个块大小相同;2)两个块地址连续;3)两个块必须是同一个大块中分离出来的;
作用
伙伴系统是以page为单位进行操作的,一般管理的是大内存分配
具体详细参考:Linux伙伴系统(一)--伙伴系统的概述
- slab 分配器
linux
内核中会采用伙伴算法进行内存分配管理,但是分配的内存区是以页框为基本单位的。对于内核中小块连续内存的请求,比 如说几个字节或者几百个字节,如果依然分配一个页框来来满足该请求,这样的话就会有内存碎片产生;
定义
slab分配器中用到了对象这个概念,所谓对象就是内核中的数据结构以及对该数据结构进行创建和撤销的操作。它的基本思想是将内核中经常使用的对象 放到高速缓存中,并且由系统保持为初始的可利用状态。比如进程描述符,内核中会频繁对此数据进行申请和释放。当一个新进程创建时,内核会直接从slab分 配器的高速缓存中获取一个已经初始化了的对象;当进程结束时,该结构所占的页框并不被释放,而是重新返回slab分配器中。如果没有基于对象的slab分 配器,内核将花费更多的时间去分配、初始化以及释放一个对象。
slab分配器有以下三个基本目标:
1.减少伙伴算法在分配小块连续内存时所产生的内部碎片;
2.将频繁使用的对象缓存起来,减少分配、初始化和释放对象的时间开销。
3.通过着色技术调整对象以更好的使用硬件高速缓存;
参考:Linux内存管理中的slab分配器
作用
- 高速缓存
- 分配小块内存
具体详细参考:【Linux 内核】内存管理(三)slab分配器
说明:这是linux中比较重要的两个内存管理的方式,我对这块也只是了解状态,并没有深入去研究,这里只是简单概括一下,以后有时间细细研究一下,现在大概知道这个原理和概念就行了;
四、回收内存
那么上面说了内存分配相关的内容,那么,如果内存出现了紧张
,那系统自己会怎么办?
其实,linux自己也做了一套机制,来进行内存回收;
回收缓存,比如使用 LRU(Least Recently Used)算法,回收最近使用最少的内存页面;
原理
LRU(Least recently used,最近最少使用)算法根据数据的历史访问记录来进行淘汰数据,其核心思想是“如果数据最近被访问过,那么将来被访问的几率也更高”。
实现
最常见的实现是使用一个链表保存缓存数据,详细算法实现如下:
新数据插入到链表头部;
每当缓存命中(即缓存数据被访问),则将数据移到链表头部;
当链表满的时候,将链表尾部的数据丢弃。
分析
【命中率】
当存在热点数据时,
LRU
的效率很好,但偶发性的、周期性的批量操作会导致LRU
命中率急剧下降,缓存污染情况比较严重。【复杂度】
实现简单。
【代价】
命中时需要遍历链表,找到命中的数据块索引,然后需要将数据移到头部。
Swap:回收不常访问的内存,把不常用的内存通过交换分区直接写到磁盘中;
回收不常访问的内存时,会用到交换分区,也称为Swap。
Swap 其实就是把一块磁盘空间当成内存来用。它可以把进程暂时不用的数据存储到磁盘中(这个过程称为换出),当进程访问这些内存时,再从磁盘读取这些数据到内存中(这个过程称为换入),Swap 把系统的可用内存变大了。
通常只有在内存不足时,才会发生 Swap 交换。
相对于内存来说,磁盘读写的速度很慢,所以Swap 会导致严重的内存性能问题。
OOM:杀死进程,内存紧张时系统还会通过 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。
五、查看内存命令
一般我们会使用free
来查看内存,当然,我们还可以使用ps/top
等命令
先看一下free
命令吧
root@iZuf67on1pthsuih96udyfZ:~/# free total used free shared buff/cache availableMem: 953036 388052 65808 2860 499176 377200Swap: 0 0 0
简单的看一下每个字段的意义:
total
是总内存大小;used
是已使用内存的大小,包含了共享内存;free
是未使用内存的大小;shared
是共享内存的大小;buff/cache
是缓存和缓冲区的大小;available
是新进程可用内存的大小。
这就是大概是linux内存相关的一些知识点,这里写的比较乱,相当于做个笔记了~~~
想了解学习更多C++后台服务器方面的知识,请关注:微信公众号:====CPP后台服务器开发====
扫码CPP后台服务器开发转载是一种动力 分享是一种美德
linux delete内存不下降_linux内存分配管理相关推荐
- linux 内存越界判断_linux 内存越界判断
printf("aaa\n");这不是在打印a字符吗?,而且,只有段越界才会引起进程的段错误信号,你访问的地址仍然在进程的合法空间范围内,当然空指针这类地址基本不合法.回复 @xx ...
- 11 操作系统第三章 内存管理 内存的基本知识 内存管理 内存空间扩充 连续分配管理方式
文章目录 1 内存概念 1.1 内存作用 1.2 逻辑地址VS物理地址 1.3 装入的三种方式 1.3.1 绝对装入 1.3.2 可重定位装入 1.3.3 动态重定位装入 1.4 链接的三种方式 1. ...
- 【Linux】free命令查询服务器内存信息
Linux的free命令对于很多的Linux运维来说,应该是非常熟悉的了.但作为一个经常使用linux系统的小白来说,我们也需要了解一下free命令. free 命令显示系统内存的使用情况,包括物理内 ...
- 内存管理之非连续分配管理方式的详细解释
如果帮到你的话,请点个赞,创作不易,谢谢 非连续分配方式允许将一个程序分散地装入不连续的内存空间.在连续分配管理方式中,即使内存有超过2GB的存储空间,但是没有连续的2GB内存空间,则需要2GB内存空 ...
- linux 程序收到sigsegv信号_linux下定位多线程内存越界问题实践总结
最近定位了在一个多线程服务器程序(OceanBase MergeServer)中,一个线程非法篡改另一个线程的内存而导致程序core掉的问题.定位这个问题历经曲折,尝试了各种内存调试的办法.往往感觉就 ...
- linux内存管理_Linux内存管理(转)
声明:这篇文章是从网上转来的,本来想注上原作者,发现不少相同文章不同作者都标注原创,这就尴尬了...后来,我看此文章中插图都是英文,用图片搜索到原英文作者及出处,发现CSDN上真是TM乱七八糟,直接拿 ...
- 【Linux 内核 内存管理】物理分配页 ⑧ ( __alloc_pages_slowpath 慢速路径调用函数源码分析 | 获取首选内存区域 | 异步回收内存页 | 最低水线也分配 | 直接分配 )
文章目录 一.获取首选内存区域 二.异步回收内存页 三.最低水线也分配 四.直接分配内存 在 [Linux 内核 内存管理]物理分配页 ② ( __alloc_pages_nodemask 函数参数分 ...
- Linux性能学习(2.3):内存_为什么分配的内存比申请的内存大16个字节
文章目录 1 验证申请不同内存,系统分配机制 1.1 代码 1.2 测试 1.3 结论 2 为什么会多分配内存 3 为什么会有4字节不可使用 参考资料: https://www.gnu.org/sof ...
- linux系统堆、栈及内存分配、CPU寄存器
堆和栈: 栈主要用来存放局部变量, 传递参数, 存放函数的返回地址.esp 始终指向栈顶, 栈中的数据越多, esp的值越小. 堆用于存放动态分配的对象, 当你使用 malloc , new 等进行分 ...
最新文章
- 3天,我把MySQL索引、锁、事务、分库分表撸干净了!
- 如何在JavaScript中区分深层副本和浅层副本
- ubuntu 如何卸载qt_UBuntu14.04下安装和卸载Qt5.3.1
- Python和它高大上的插件们
- 快进来,详解MySQL游标
- SketchUp Pro 2021 v21.0.391 草图大师安装说明
- 浅述BLP和Biba模型
- java茌首字母_获取输入字符的首字母(中文为拼音首字母)
- 电商商家如何利用商品信息制定价格策略?
- 银联云闪付产品分析报告
- 关于LR和PS显示颜色和到处颜色不同的处理办法
- 应广单片机系列MCU
- 王朝落日,读《万历十五年》
- 记录、总结、复盘的重要性和方法(另有周报、月报、年度总结撰写方法)
- 解决servlet请求转发、响应重定向无法实现页面跳转问题
- [日常] NOIWC 2018爆零记
- Tableau绘制标靶图
- 大学生可以参加的计算机比赛
- 日本知名汽车零部件公司巡礼系列之株式会社123
- 关于Mask-Rcnn中标注工具VIA(VGG Image Annotator)使用的详解
热门文章
- (相当全面)node.js 初体验
- opacity:0.99;
- 4.1.3数据报与虚电路
- 操作系统——文件基本概念
- Leetcode--198. 打家劫舍
- druid seata 配置_架构设计 | 基于Seata中间件,微服务模式下事务管理
- java 几种引用类型_Java 四种引用类型总结-Fun言
- python获取mac窗口坐标_[代码全屏查看]-Python3根据IP地址获取MAC地址
- oracle常见单词_Oracle中常见的英语单词
- c++卸载工具_win7系统如何卸载office2007兼容包