哈喽大家好,我是咸鱼

在《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. webgl 系列 —— 变换矩阵和动画

    其他章节请看: webgl 系列 变换矩阵和动画 动画就是不停地将某个东西变换(transform).例如将三角形不停地旋转就是一个动画 和 CSS transform 类似,变换有三种形式:平移.缩 ...

  2. PHP 循环语句

    循环机构,在一定的控制下,对此执行. 在PHP中,有以下几种循环 for循环.while循环.do-while循环.forech循环(针对数组) for 循环 语法 for (条件1;条件2;条件3) ...

  3. Linux命令示例记录-20230313【持续更新中】

    1. ip命令 1.1. 摘要 ip是iproute2软件包里面的一个强大的网络配置工具,它能够替代一些传统的网络管理工具.例如:ifconfig.route等.这个手册将分章节介绍ip命令及其选项. ...

  4. 初识Node和内置模块

    初识Node与内置模块 概述:了解Node.js,熟悉内置模块:fs模块.path模块.http模块 初识Node.js 浏览器中的JavaScript运行环境 运行环境是指代码正常运行所需的必要环境 ...

  5. 【Azure K8S | AKS】分享从AKS集群的Node中查看日志的方法(/var/log)

    问题描述 使用Azure Kubernetes服务(AKS),可以通过kubectl连接 pod 中查看日志,但是如何来查看节点的系统日志呢?如是否有ubuntu系统升级的记录? 问题解答 是的,可以 ...

  6. 声网Agora 实时音视频服务正式上线 HTC VIVE Sync App,支持非 VR 用户

    全球实时互动云服务开创者和引领者声网Agora(纳斯达克股票代码:API)宣布其视频 SDK 现已集成到领先的 VR/XR 远程协作及会议应用 HTC VIVE Sync App 中. 通过集成声网A ...

  7. GaussDB(DWS)运维:导致SQL执行不下推的改写方案

    摘要:本文就针对因USING子句的书写方式可能导致MERGE INTO语句的执行不下推的场景,对USING子句的SQL语句进行改写一遍,整个SQL语句可以下推. 本文分享自华为云社区<Gauss ...

  8. Git 操作命令清单 入门到精通(保姆级)

    一般来说,日常使用只要记住下图6个命令,就可以了.但是如果你想熟练使用它,要记住大概80个命令. 下面是常用的 Git 命令.几个专用名词的译名如下: Workspace:工作区 Index / St ...

  9. flutter widget---->Spacer

    如果你想灵活控制Flex容器(Row, Column)中子组件中的间隔,可以考虑使用Spacer.下面以Row为例子,来为它的子组件添加间距. use Spacer import 'package:f ...

  10. 7.远程代码执行漏洞RCE

    远程代码执行漏洞RCE 1.RCE Remote Code Execute 远程代码执行 Remote Command Execute 远程命令执行 2.危害 窃取服务器的敏感数据.文件 对电脑的文件 ...