哈喽大家好,我是咸鱼

在《Linux 内存管理 pt.2》中我们学习了多级页表和大页,我们知道了由于历史遗留的问题,Linux 的页通常为 4KB

这样就会导致一个页表里面会有特别多页,为了解决这个问题,Linux 提供了两种解决方案——多级页表和大页

那么今天继续我们的 Linux 内存管理学习,我们今天要学习的是——内存的分配和回收

在 Linux 中,内存是如何被分配和回收的呢?

内存分配

在 Linux 中,内存的分配通常由 C 标准库提供的内存分配函数 malloc() 实现

当malloc() 函数需要分配内存时,它会调用这两个系统调用——即 brk() 和 mmap()

  • brk()

对于小块内存(小于 128K大于 4K),使用 brk() 来分配,通过移动堆顶的位置来分配内存

这些内存释放后并不会立刻归还系统,而是被缓存起来,这样就可以重复使用

优缺点:

  1. 减少缺页异常的发生,提高内存访问效率

  2. 由于不会立刻归还释放的内存给系统,所以在内存工作繁忙时,频繁的内存分配和释放会造成内存碎片

  • mmap()

对于大块内存(大于 128K),则直接使用内存映射 mmap() 来分配,也就是在文件映射段找一块空闲内存分配出去,释放时直接归还系统

优缺点:

  1. 在释放时直接归还系统,所以每次 mmap 都会发生缺页异常

  2. 在内存工作繁忙时,频繁的内存分配会导致大量的缺页异常,使内核的管理负担增大。这也是 malloc 只对大块内存使用 mmap 的原因

需要注意的是,一开始调用内存分配函数的时候,其实是没有真正分配到物理内存

只有在进程首次访问时才分配,即通过缺页异常进入内核中,再由内核来分配内存

Linux 伙伴系统(buddy)

在 Linux 中,光知道如何分配内存还不行,还得知道该怎么分配

伙伴管理器是 Linux 系统中一种常见的内存分配算法,它可以让系统在分配物理内存时,快速地找到相应大小的可用内存块

前面说到,MMU 是一种硬件设备,负责虚拟内存和物理内存的映射关系。当内核需要访问某个虚拟内存时,MMU 将该虚拟地址转换为对应的物理内存地址,并通过伙伴系统的分配算法来定位相应的内存块

当内存释放时,伙伴系统将其标记为空闲,用于重新分配给其他进程。因此,伙伴系统和 MMU 相互协作,实现 Linux 操作系统的内存管理功能

上面说到,对于4K 至 128K 的内存用 brk() 来分配,对于大于 128k 的内存使用内存映射 mmap() 来分配。那如果要分配的内存小于 4K 呢?

实际系统运行的时候,有着许多内存小于 4K 的对象,如果为他们分配单独的页,那就太浪费内存了

所以 Linux 通过下面两种方式来分配小于 4K 的内存:

1、伙伴系统

当需要分配小于4K的内存时,内核会为之保留一个完整的物理页,并尽量将物理页分割成大小相同的小块。当有多个小块被请求时,内核会合并这些小块,最终分配

2、slab分配器

slab 分配器是 Linux 内核中的一个重要组成(你可以将slab 看成构建在伙伴系统上的一个缓存)它将一小块内存分配称为缓存(cache)

当需要分配小于 4K 的内存时,Slab 分配器会创建一个小的缓存来保存请求内存的块。每个缓存都有一个物理页的大小

如果已经分配完了所有内存块,Slab 分配器会重新分配一个完整的物理页作为缓存,以供后续请求使用

为了防止内存碎片化,slab 分配器会保留已经使用完的 slab 块并重复使用其中未被使用的空间,而不是将其释放回系统

内存回收

如果内存只分配而不释放,就会造成内存泄漏,甚至会耗尽系统内存

所以,在应用程序用完内存后,还需要调用 free() 或 unmap() ,来释放这些不用的内存

那么系统是如何回收内存的呢?

1、使用 LRU(Least Recently Used)算法,回收最近使用最少的内存页面

2、回收不常访问的内存,把不常用的内存通过交换分区(swap)直接写到磁盘中

Swap 其实就是把一块磁盘空间当成内存来用

它可以把进程暂时不用的数据存储到磁盘中(这个过程称为换出),当进程访问这些内存时,再从磁盘读取这些数据到内存中(这个过程称为换入)

通常只在内存不足时,才会发生 Swap 交换。并且由于磁盘读写的速度远比内存慢,Swap 会导致严重的内存性能问题

3、杀死进程,内存紧张时系统还会通过 OOM(Out of Memory),直接杀掉占用大量内存的进程

OOM(Out of Memory),其实是内核的一种保护机制,使用 oom_score 为每个进程的内存使用情况进行评分

一个进程消耗的内存越大,oom_score 就越大;

一个进程运行占用的 CPU 越多,oom_score 就越小

进程的 oom_score 越大,代表消耗的内存越多,也就越容易被 OOM 杀死

感谢阅读,喜欢作者就动动小手[一键三连],这是我写作最大的动力

Linux 内存管理 pt.3的更多相关文章

  1. Linux 内存管理 pt.1

    哈喽大家好,我是咸鱼 今天我们来学习一下 Linux 操作系统核心之一:内存 跟 CPU 一样,内存也是操作系统最核心的功能之一,内存主要用来存储系统和程序的指令.数据.缓存等 关于内存的学习,我会尽 ...

  2. linux内存管理---物理地址、线性地址、虚拟地址、逻辑地址之间的转换

    linux内存管理---虚拟地址.逻辑地址.线性地址.物理地址的区别(一) 这篇文章中介绍了四个名词的概念,下面针对四个地址的转换进行分析 CPU将一个虚拟内存空间中的地址转换为物理地址,需要进行两步 ...

  3. 浅谈Linux内存管理机制

    经常遇到一些刚接触Linux的新手会问内存占用怎么那么多?在Linux中经常发现空闲内存很少,似乎所有的内存都被系统占用了,表面感觉是内存不够用了,其实不然.这是Linux内存管理的一个优秀特性,在这 ...

  4. linux内存管理

    一.Linux 进程在内存中的数据结构 一个可执行程序在存储(没有调入内存)时分为代码段,数据段,未初始化数据段三部分:    1) 代码段:存放CPU执行的机器指令.通常代码区是共享的,即其它执行程 ...

  5. Linux内存管理原理

    本文以32位机器为准,串讲一些内存管理的知识点. 1. 虚拟地址.物理地址.逻辑地址.线性地址 虚拟地址又叫线性地址.linux没有采用分段机制,所以逻辑地址和虚拟地址(线性地址)(在用户态,内核态逻 ...

  6. 了解linux内存管理机制(转)

    今天了解了下linux内存管理机制,在这里记录下,原文在这里http://ixdba.blog.51cto.com/2895551/541355 根据自己的理解画了张图: 下面是转载的内容: 一 物理 ...

  7. Linux内存管理原理【转】

    转自:http://www.cnblogs.com/zhaoyl/p/3695517.html 本文以32位机器为准,串讲一些内存管理的知识点. 1. 虚拟地址.物理地址.逻辑地址.线性地址 虚拟地址 ...

  8. Windows内存管理和linux内存管理

    windows内存管理 windows 内存管理方式主要分为:页式管理,段式管理,段页式管理. 页式管理的基本原理是将各进程的虚拟空间划分为若干个长度相等的页:页式管理把内存空间按照页的大小划分成片或 ...

  9. linux 内存管理——内核的shmall 和shmmax 参数

    内核的 shmall 和 shmmax 参数 SHMMAX= 配置了最大的内存segment的大小 ------>这个设置的比SGA_MAX_SIZE大比较好. SHMMIN= 最小的内存seg ...

  10. linux内存管理子系统

    一.Linux内存管理模型 1.虚拟地址与物理地址的映射 2.物理地址的分配二.虚拟地址与物理地址的映射 1.虚拟地址空间分布 32位处理器有32根地址总线,可访问4G的物理空间.其中有0-3G为用户 ...

随机推荐

  1. uni-popup 遮不住头部标题的解决办法

    要做一个小程序,会有弹窗,但是uni-app的API组件uni.showModal不足以满足我的需求,于是我用HBuilderX引入了uni-popup. 代码是这样的 <button @cli ...

  2. R 字符串操作超全总结

    paste函数和paste0()函数 连接字符 > paste("a", 1:3) #默认空格符连接,即sep=" " [1] "a 1&quo ...

  3. Spring-设计模式

    1.1开闭原则 开闭原则(open-closed principle,OCP)是指一个软件实体(如类,模块和函数)应该对扩展开放,对修改关闭.所谓的开闭,也正是对扩展和修改两个行为的一个原则. 强调用 ...

  4. 如何通过C++ 将数据写入 Excel 工作表

    直观的界面.出色的计算功能和图表工具,使Excel成为最流行的个人计算机数据处理软件.在独立的数据包含的信息量太少,而过多的数据又难以理清头绪时,制作成表格是数据管理的最有效手段之一.这样不仅可以方便 ...

  5. Python学习笔记--PySpark的相关基础学习(一)

    PySpark包的下载 下载PySpark第三方包: 构建PySpark的执行环境入口对象 PySpark的编程模型 数据输入 对于SparkContext对象里面的成员方法parallelize,支 ...

  6. 初认Spring

    官网地址:https://spring.io/ Spring Framework的系统架构 1.Core Contiainer:核心容器 2.AOP:面向切片编程 3.Aspects:AOP思想实现 ...

  7. BeautifulSoup模块的使用方法

    本篇文章主要讲bs4模块(BeautifulSoup),这个模块能做么呢?用一句话来概括的话:beautifulsoup4 从HTML或XML文件中提取数据的Python库,用它来解析爬取回来的xml ...

  8. 分布式 WEB应用中Session(会话管理)的变迁之路

    一.Session 介绍 Session 一词直译为 "会话",意指有始有终的一系列动作/消息.Session 是 Web 应用蓬勃发展的产物之一.在 Web 应用中隐含有&quo ...

  9. 如何使用Photino创建Blazor项目进行跨平台

    Photino是什么 Photino是一组使用Web (HTML/CSS/JavaScript)UI创建桌面应用程序的技术.TryPhotino.io 维护 .NET 构建,并鼓励社区开发 Photi ...

  10. Vue2数据驱动渲染(render、update)

    上一篇文章我们介绍了 Vue2模版编译原理,这一章我们的目标是弄清楚模版 template和响应式数据是如何渲染成最终的DOM.数据更新驱动视图变化这部分后期会单独讲解 我们先看一下模版和响应式数据是 ...