java进程内存一直没释放_五分钟彻底搞懂你一直没明白的Linux内存管理

现在的服务器大部分都是运行在Linux上面的,所以,作为一个程序员有必要简单地了解一下系统是如何运行的。对于内存部分需要知道:

  1. 地址映射
  2. 内存管理的方式
  3. 缺页异常

先来看一些基本的知识,在进程看来,内存分为内核态和用户态两部分,经典比例如下:

dffc5f956f8ac528a132004fc3a441a7.png

从用户态到内核态一般通过系统调用、中断来实现。用户态的内存被划分为不同的区域用于不同的目的:

981a9cc8fe1c7d01649a536f424747cd.png

当然内核态也不会无差别地使用,所以,其划分如下:

f240d9c021d0d96b9258c042ad4f45dd.png

下面来仔细看这些内存是如何管理的。

地址

在Linux内部的地址的映射过程为逻辑地址–>线性地址–>物理地址,物理地址最简单:地址总线中传输的数字信号,而线性地址和逻辑地址所表示的则是一种转换规则,线性地址规则如下:

bf559707131b3115cd74674412080b6b.png

这部分由MMU完成,其中涉及到主要的寄存器有CR0、CR3。机器指令中出现的是逻辑地址,逻辑地址规则如下:

f5edd031fda7a411e737e93490fbad7b.png

在Linux中的逻辑地址等于线性地址,也就是说Inter为了兼容把事情搞得很复杂,Linux简化顺便偷个懒。

内存管理的方式

在系统boot的时候会去探测内存的大小和情况,在建立复杂的结构之前,需要用一个简单的方式来管理这些内存,这就是bootmem,简单来说就是位图,不过其中也有一些优化的思路。

bootmem再怎么优化,效率都不高,在要分配内存的时候毕竟是要去遍历,buddy系统刚好能解决这个问题:在内部保存一些2的幂次大小的空闲内存片段,如果要分配3page,去4page的列表里面取一个,分配3个之后将剩下的1个放回去,内存释放的过程刚好是一个逆过程。用一个图来表示:

bbfa5f7d24cd1ca0738f5f947eb8a34d.png

可以看到0、4、5、6、7都是正在使用的,那么,1、2被释放的时候,他们会合并吗?

static inline unsigned long
__find_buddy_index(unsigned long page_idx, unsigned int order)
{
return page_idx ^ (1 << order);// 更新最高位,0~1互换
}

从上面这段代码中可以看到,0、1是buddy,2、3是buddy,虽然1、2相邻,但他们不是。内存碎片是系统运行的大敌,伙伴系统机制可以在一定程度上防止碎片~~另外,我们可以通过cat /proc/buddyinfo获取到各order中的空闲的页面数。

伙伴系统每次分配内存都是以页(4KB)为单位的,但系统运行的时候使用的绝大部分的数据结构都是很小的,为一个小对象分配4KB显然是不划算了。Linux中使用slab来解决小对象的分配:

dae1d1071a2f4a359a40524c6be1577d.png

在运行时,slab向buddy“批发”一些内存,加工切块以后“散卖”出去。随着大规模多处理器系统和NUMA系统的广泛应用,slab终于暴露出不足:

  1. 复杂的队列管理
  2. 管理数据和队列存储开销较大
  3. 长时间运行partial队列可能会非常长
  4. 对NUMA支持非常复杂

为了解决这些高手们开发了slub:改造page结构来削减slab管理结构的开销、每个CPU都有一个本地活动的slab(kmem_cache_cpu)等。对于小型的嵌入式系统存在一个slab模拟层slob,在这种系统中它更有优势。

小内存的问题算是解决了,但还有一个大内存的问题:用伙伴系统分配10 x 4KB的数据时,会去16 x 4KB的空闲列表里面去找(这样得到的物理内存是连续的),但很有可能系统里面有内存,但是伙伴系统分配不出来,因为他们被分割成小的片段。那么,vmalloc就是要用这些碎片来拼凑出一个大内存,相当于收集一些“边角料”,组装成一个成品后“出售”:

bfe5e364c350c7174ad7d54d4a6c6c43.png

之前的内存都是直接映射的,第一次感觉到页式管理的存在:D 另外对于高端内存,提供了kmap方法为page分配一个线性地址。

进程由不同长度的段组成:代码段、动态库的代码、全局变量和动态产生数据的堆、栈等,在Linux中为每个进程管理了一套虚拟地址空间:

9920d2d184413602ffcbbd09f71eed24.png

在我们写代码malloc完以后,并没有马上占用那么大的物理内存,而仅仅是维护上面的虚拟地址空间而已,只有在真正需要的时候才分配物理内存,这就是COW(COPY-ON-WRITE:写时复制)技术,而物理分配的过程就是最复杂的缺页异常处理环节了,下面来看!

缺页异常

在实际需要某个虚拟内存区域的数据之前,和物理内存之间的映射关系不会建立。如果进程访问的虚拟地址空间部分尚未与页帧关联,处理器自动引发一个缺页异常。在内核处理缺页异常时可以拿到的信息如下:

  1. cr2:访问到线性地址
  2. err_code:异常发生时由控制单元压入栈中,表示发生异常的原因
  3. regs:发生异常时寄存器的值

处理的流程如下:

e9429fe1561c1361d265277dae642b15.png

发生缺页异常的时候,可能因为不常使用而被swap到磁盘上了,swap相关的命令如下:

bf4b151cd8c0e96afeabeaf8bd218c5f.png

如果内存是mmap映射到内存中的,那么在读、写对应内存的时候也会产生缺页异常。

来源:WsztRush
链接:http://wsztrush.github.io/%E7%BC%96%E7%A8%8B%E6%8A%80%E6%9C%AF/2015/05/13/Linux-Memory.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/506310.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

c语言basic解释器,要理解解释器,做一个小解释器----小话c语言(20)

该楼层疑似违规已被系统折叠 隐藏此楼查看此楼}list->tail->next obj;list->tail obj;return obj;}void cc_arg_list_free(cc_arg_list *list){cc_arg_obj *head list->head;while(head){cc_arg_obj *next head->next;cc_arg_obj_free(head);head next;}}v…

ehcache使用_Mybatis整合(Redis、Ehcache)实现二级缓存,恕我直言,你不会

目的&#xff1a;Mybatis整合Ehcache实现二级缓存Mybatis整合Redis实现二级缓存Mybatis整合ehcache实现二级缓存ssm中整合ehcache在POM中导入相关依赖org.springframework spring-context-support ${spring.version}org.mybatis.caches mybatis-ehcache 1.1.0net.s…

c语言利用栈将字符串逆序输出,【C语言】利用栈将数组中字符串逆序

该楼层疑似违规已被系统折叠 隐藏此楼查看此楼#include"stdio.h"#include"stdlib.h"#define STACK_INIT_SIZE 100#define STACKINCREMENT 10typedef struct{char *base;char *top;int stacksize;}SqStack;main(){SqStack S;char a[4];int i;InitStack(&…

取证 c语言实现日志导出_日志与日志不一样:五种不能忽略的日志源

给日志源分出主次大有利于开展有效事件响应。就像分诊护士一样&#xff0c;安全人员也必须给数据分出个优先主次&#xff0c;以帮助他们更好地识别问题&#xff0c;使公司企业及其数据和设备能够避免入侵者和网络攻击的伤害。但是&#xff0c;记录和监视IT环境中的所有相关事件…

c语言 多文件 学生系统,编的学生成绩管理系统 从文件中读取保存数据总会多读入一组乱码数据...

该楼层疑似违规已被系统折叠 隐藏此楼查看此楼getch();return L;}}void SearchData(Stu L){Stu p;int num;pL->next;printf("Input the ID of the student you want to search:");scanf("%d",&num);while(p!NULL){if(p->numnum) { printf("…

codesoft指定打印机打印_巧用win32print来控制windows系统打印机并推送打印任务

小爬最近接到的一个需求是&#xff1a;将windows系统下的打印任务批量有序传输给网络打印机&#xff0c;实现批量有序打印。用户先从公司的OA(B/S模式)系统下 打印指定内容的表单以及表单中的附件内容。这个问题可以这样分解&#xff1a;1、抓包&#xff0c;得到OA对应的任务接…

c语言磁盘文件只有写没读,C语言的磁盘文件问题

匿名用户1级2010-04-06 回答C语言文件操作函数1,两种文件存取方式(输入,输出方式)顺序存取直接存取2,数据的两种存放形式文本文件二进制文件13.2文件指针定义文件类型指针变量的一般形式:FILE *指针变量名;例如:FILE *fp1,*fp2;13.3打开文件在使用文件之前,需打开文件.在C里使用…

crmeb pc端模板下载_PC端人人影视下载速度如何提高

首先下载最新版本的人人影视我的是这个&#xff0c;右下角版本号1022然后在下载设置那里把连接数调高一点大致就这样我的就是调了一下然后下载速度高了许多&#xff0c;刚开始只有1M左右的速度&#xff0c;现在4&#xff0c;5M每秒

android 编辑自定义可编辑表格,smart 框架 列表 可编辑表格

可编辑表格常用属性colModel: [{label: "主键ID", name: "hellop1",hidden:true},{label: "列明", name: "hellop2",align: "center", editable: true, edittype: text, editrules: { required: true } }editable&#xff1…

dos虚拟机如何全屏显示_实用工具 | 虚拟机软件VirtualBox详细使用介绍

前言&#xff1a;搞自动化控制的工程师&#xff0c;要擅于利用工具和软件&#xff0c;其中&#xff0c;虚拟机就是很好的工具&#xff0c;安装操作系统以后&#xff0c;就相当于多了一台电脑&#xff0c;可以用来测试网络&#xff0c;测试软件&#xff0c;或者直接用来调试设备…

python中type用法_Python中type的用法

(TOC)描述python类型的函数有两个用法,当只有一个参数,它将返回对象的类型。当有三个参数,返回一个类对象。语法类型(对象)类型(名称、基地、dict)使用一个参数类型(对象)返回一个对象的类型,如:[1],[2] 10:类型(A) [2]: int的三个参数打字(名称、基地、dict)父类类名基地名称t…

android style边界显示兼容问题,android – IDE“无法解析@ style/Theme.Appcompat”时使用v7兼容性支持主题...

这不是一个真正的问题&#xff0c;因为我的项目仍然构建和运行正确(使用gradle)&#xff0c;但我有麻烦让Android Studio来识别在API 18 SDK中发布的应用程序兼容性主题(允许操作栏支持android 2.1以上)。我有支持库加载成功&#xff0c;因为代码完成是可能的ActionBar类在java…

axure原型案例_Axure RP9原型案例:制作一个可以滑动的菜单

摘要&#xff1a;在PC端的产品中我们会常常见到滑动式菜单&#xff0c;当鼠标移入菜单上方&#xff0c;向下或向右自动滑动弹出子菜单&#xff0c;当页面信息层级较多或功能较多时&#xff0c;在产品设计时经常会用到这种滑动式菜单。今天就和大家分享如下制作滑动式菜单的交互…

android edittext 正则限制,Android EditText 使用正则表达式进行输入过滤

近期在一个项目中用到修改密码这个功能&#xff0c;不过对于密码的输入&#xff0c;我们不希望用户输入汉字或者特殊字符&#xff0c;所以我们需要对用户进行输入的输入框进行过滤&#xff0c;下面是一个对EditText进行过滤的小代码片段&#xff1a;1.首先给Edittext 添加一个T…

一会404一会500_没网络就是404?这锅可不能乱背!

在那个房价未突破天际&#xff0c;一台计算机还可以占着几间房的年代。数据库被存放在一个神秘的房间中。如果无法找到请求者所需要的文件&#xff0c;用户将会得到file not found的信息。而这件房间的门牌就是404。404https://www.zhihu.com/video/1168484640850579456当然以上…

android8 呼吸灯,红米note8pro呼吸灯颜色如何设置?

红米note8pro支持呼吸灯功能&#xff0c;当有未读通知的时候&#xff0c;指示灯就会闪烁提醒。此外&#xff0c;我们还可以根据自己的喜好设置呼吸灯的颜色&#xff0c;下面为大家带来详细的设置教程。红米note8pro怎么设置呼吸灯颜色1、首先&#xff0c;进入手机桌面&#xff…

java string 返回匹配正则的字符串的起始位置_【Python】正则表达式

概述正则表达式是一个特殊的字符序列&#xff0c;它能帮助你方便的检查一个字符串是否与某种模式匹配。 Python 自1.5版本起增加了re 模块&#xff0c;它提供 Perl 风格的正则表达式模式。re 模块使 Python 语言拥有全部的正则表达式功能。 compile 函数根据一个模式字符串和可…

html九图拼图游戏代码,HTML5拼图游戏

拼图游戏介绍 拼图游戏将一幅图片分割成若干拼块并将它们随机打乱顺序。当将所有拼块都放回原位置时&#xff0c;就完成了拼图(游戏结束)。 在“游戏”中&#xff0c;单击滑块选择游戏难易&#xff0c;“容易”为3行3列拼图游戏&#xff0c;中间为一个4行4列拼图游戏&#xff0…

access驱动程序_Linux驱动程序学习二 (续) scull 源码在内核5.4.0上的编译调试

《LINUX设备驱动程序》第三章提供了源码scull,但是由于我用的是5.4.0内核,书中的是2.6.10内核,内核发生了很大的变化,因此编译scull源码花费了不少时间,下面是编译调试记录。&#xff08;这个编译调试记录应该是目前网络上适应内核版本最高的&#xff0c;所以也希望给近期加入《…

android评论嵌套,android 嵌套的listview示例(可参照实现朋友圈评论)

android 嵌套的listview示例(可参考实现朋友圈评论) 最近在项目中用到listview中再嵌套一个listview&#xff0c;两层也有监听&#xff0c;都没有问题。其实&#xff0c;主要解决里面那一层的listview的高度计算就可以&#xff0c;外面那一层listview自动计算。加上里面那层展开…