首页 > 系统相关 >Linux 内存管理 pt.3

Linux 内存管理 pt.3

时间:2023-05-17 17:57:19浏览次数:48  
标签:内核 系统 pt.3 4K Linux 分配 内存

哈喽大家好,我是咸鱼

在《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 杀死

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

标签:内核,系统,pt.3,4K,Linux,分配,内存
From: https://www.cnblogs.com/edisonfish/p/17409556.html

相关文章

  • linux-安装系统Ubuntu Server 14.04,16.04和17.10
    安装系统UbuntuServer14.04,16.04和17.10 本文以14.04位案例进行安装,其他版本相关问题会做注解1.选择要安装的系统语言本界面建议选择English,之后再选择中文安装对于14.x版本选择中文没有问题,但是对于16.04和17.10版本,该步骤选择中文后面会报错:2.选择安装过程中需要的语......
  • 在Linux/Windows/Mac上刷新DNS缓存的方法
    在Linux/Windows/Mac上刷新DNS缓存的方法刷新dns缓存让你可以得到新的域名解析。当你无法正确访问一个新注册的域名时就可以刷新dns缓存试试。但是不同的系统,Windows、MacOS和Linux上的方法是不一样的。1.Windows系统刷新DNS缓存开始-->运行-->输入cmd并回车在打开的命......
  • Jmeter部署到Linux实现分发压测时,controller机器回收测试报告时卡死
    问题检查与定位:检查slave-A和slave-B两台执行机,执行机已经finished,无报错,说明执行机已完成测试任务采集到的日志批量分析后得出的结论:在完成并发测试后,vuser要进行释放,由于没有完全释放导致controller机器一直等待(像卡死),而实际上是等待,问题定位后,进行检查发现:问题1: reportge......
  • 监控centos7系统CPU,内存,磁盘空间
    [catmonitor2.py#!/usr/bin/envpython#coding=UTF-8importdatetimeimportsocketimportpsutilimportsmtplibfromemail.mime.textimportMIMETextfromemail.mime.multipartimportMIMEMultipart#全局变量current_time=datetime.datetime.now().strftime("%Y-%m......
  • linux-cmd-zip-unzip
    linux-cmd-zip-unzip参考地址https://www.runoob.com/linux/linux-comm-zip.html1.zip压缩1.1.zip语法参数zip[-AcdDfFghjJKlLmoqrSTuvVwXyz$][-b<工作目录>][-ll][-n<字尾字符串>][-t<日期时间>][-<压缩效率>][压缩文件][文件...][-i<范本样式>][-x<范本样式>]#......
  • linux标准输入输出
    linux标准输入输出STDIN是标准输入,默认从键盘读取信息;STDOUT是标准输出,默认将输出结果输出至终端;STDERR是标准错误,默认将输出结果输出至终端。由于STDOUT与STDERR都会默认显示在终端上,为了区分二者的信息,就有了编号的0,1,2的定义,用1表示STDOUT,2表示STDERR2>&1,准错误重新定向到......
  • linux下查看局域网内所有存活主机和MAC进址
    linux下查看局域网内所有存活主机和MAC进址安装nmap软件yuminstallnmap-y1.常用,探测网络上的存活主机,可以简单判断主机的类型nmap-sP192.168.1.0/24nmap-sP172.27.20.0/242.常用,探测指定网络上的存活主机及其开放的端口nmap-sS192.168.1.0/24nmap-PU192.168.1.......
  • linux-cmd-kill
    kill命令介绍kill命令用了关闭执行中的进程。是通过向进程id发送信号来工作。默认的信号为SIGTERM(15),通知进程关闭。语法参数语法:kill[-ssignal|-p][--]pid...kill-l[signal]常用参数:-l<信息名或数字>:默认-l参数会列出全部的信号名称,指定信......
  • Linux安装Kafka
    1.Kafka简介Kafka也是开源与Apache开源基金会的项目,由Scala和Java编写。Kafka是一种高吞吐量的分布式发布订阅消息系统。在百度百科是这样介绍的:Kafka是由Apache软件基金会开发的一个开源流处理平台,由Scala和Java编写。Kafka是一种高吞吐量的分布式发布订阅消息系统,它可以处......
  • linux-cmd-nc端口测试
    nc命令检测端口监听TCP端口33333nc-l33333检测TCP端口连通性172.20.0.1端口33333nc-vz172.20.0.133333检测UDP端口连通性172.20.0.1端口40001nc-vzu127.0.0.140001......