【Linux】内存管理机制

article/2025/10/2 10:53:25

Linux内存管理机制

内存的表象层次依次为 逻辑地址------>线性地址----->物理地址

逻辑地址经过段机制转换成线性地址。

线性地址经过页机制转换成物理地址。

Linux将所有程序的段地址定为 0 - 4G(Linux中),所有虽然逻辑地址和线性地址不一样,但是在Linux中它们的值是一样的,可以认为是等价的。

问题:

  1. 进程空间地址如何管理?

  2. 进程地址如何映射到物理内存?

  3. 物理内存如何被管理?

进程内存空间

Linux使用虚拟内存管理技术,使得每个进程都有互不干涉的内存空间。该空间在32位操作系统上是4G的线性虚拟空间。用户所接触到的空间都是虚拟地址空间,无法看见实际的物理空间。使用这种技术不仅能保护操作系统,还可以获得比实际物理空间更大的地址。

  1. 4G虚拟地址空间被分为用户空间和内核空间。用户占0-3G,内核栈3G-4G。用户只能访问自己的虚拟地址空间,不能访问内核空间。之一用户进程进行系统调用(代表用户空间在内核态运行)才可以访问内核空间

  2. 用户空间对应进程,所以当进程切换时,用户空间就会变化。内核空间是内核负责映射的,并不会根据进程进行改变,是固定的。

    内核空间有自己的页表(init_mm.pgd),用户进程有不同的页表

  3. 每个进程的用户空间都是完全独立、互不相干的。

进程内存管理

进程内存管理的对象是进程线性地址空间上的内存镜像,这些内存镜像起始就是进程使用的虚拟内存区域。统一管理这么大的空间非常不容易。为了方便管理,虚拟空间被划分程成许多大小可变的内存区域(一般是4K),这些区域在进程线性地址中像停车场一样有序排列。这些区域的划分原则是将访问的属性一致的(可读、可写、可执行等)放在一起。

查看进程占用的内存区域: cat /proc/ /maps
在这里插入图片描述

每行的数据格式是:

开始地址 终止地址 访问权限 偏移量 主设备号:次设备号 i节点 文件。

在Linux内核中,对应的进程内存区域是:vm_area_struct,内核将每个内存区域作为一个单独的内存对象管理,相应的操作也一致。采用面向对象的方法,可以使vm_area_struct 表示多种类型的内存区域,比如内存映射文件或进程的用户空间栈。

vm_area_struct使用链表来管理虚拟空间,但是为了方便查找,它又使用红黑树来组织内存区域。链表用于遍历全部节点时使用,红黑树适用于地址空间中特定内存区域使用。

进程内存的分配和回收

创建进程 fork()

程序装载 execve()

映射文件 mmap()

动态内存分配 malloc()

都需要分配内存给进程,不过这时申请的不是实际内存,是虚拟内存。准确的是内存区域。

进程对内存区域的分配都会归结于do_mmap()函数上brk()调用单独以系统调用实现,不用do_mmap)

内核使用do_mmap函数创建一个新的线性地址空间。或者说该函数创建了一个新的VMA不是很准确,如果创建的地址区域和一个已经存在的地址空间相邻,并且它们具有相同的权限,那么两个区域将合并。如果不能合并,就是新的VMA了。

同样,释放一个内存区域do_ummap()

如何转换成物理空间

上面所有的进程所需要的 空间都转换成了虚拟空间。当进程需要内存时,从内核获得的仅仅是虚拟的内存区域,而不是实际的物理地址,进程并没有获得物理内存,获得的仅仅是对一个新的线性地址区间的使用权。实际的物理内存只有当进程真的去访问新获取的虚拟地址时,才会由 请求页机制 产生 缺页异常。

该异常是虚拟内存赖以存在的保障。它会告诉内核去真正的为进程分配物理页,并建立对应的页表,这之后虚拟地址才实实在在地映射到了系统的物理内存上。

这种请求页机制把页面的分配推迟到不能再推迟为止,并不急于把所有的事情都一次性做完。利用了内存的局部性原理,请求页的好处是节省了内存,提高了吞吐率。调用nopage函数。

系统物理内存管理

虽然应用程序操作的对象是虚拟内存,但是处理器操作的是物理内存。当一个应用访问虚拟内存时,首先必须将虚拟地址转化为物理地址,然后处理器才能解析地址访问请求。地址的转化工作需要通过查询页表才能完成,地址转换需要将虚拟内存分段,使每段虚地址都作为一个索引指向页表,而页表项则指向下一个级别的页表或者指向最终的物理页面。

每个进程都有自己的页表,进程描述符的pgd域指向的就是进程的页全局目录。

虚拟地址映射到页之前要分配物理页,并建立页表

物理内存管理(页管理)

Linux内核管理物理内存是通过分页机制实现的,它将整个内存划分成无数个4k大小的页,从而分配和回收内存的基本单位便是内存页。

利用页表可以灵活的分配地址,不需要连续的内存。但是使用连续的内存可以减少对页表的索引,提高效率。

内核采用伙伴的关系来管理页面。分配最小单位只能是2的幂次方的大小。内核中分配空闲页面的基本函数是get_free_page / get_free_pages,它是分配单页或是指定的页面(2、4、8、。。。页)

注意:get_free_page是在内核中分配内存,如果当前内存不够容纳对空间,会以页面大小的倍数为单位,进行扩张或收缩对应的内存空间。

​malloc是在用户空间分配内存。实际上是调用的brk()系统调用

​brk是通过实际的请求修改,而不是页面大小。

​因此,malloc在用户空间分配内存可以以字节为单位,但是在内部会以页为单位。

物理页由struct page描述,系统中所有的页面都存放在mem_map[]数组中,可以通过该数组找到系统中的每一页(空闲或者非空闲),空闲页面可以使用伙伴关系组织的空闲页链表(free_area[MAX_ORDER])来索引。

内核内存使用

Slab

以页为最小分配内存对于内核管理系统中物理内存比较方便,但是实际内存自身使用的内存还是很小的,比如:文件描述符、进程描述符、虚拟内存描述符等行为所需的内存都不到一页。

为了这种需求,Linux采用了一种叫slab分配器的技术,Slab分配器实现非常复杂,核心就是存储池的运用。内存片段被看作对象,当被使用完后,并不直接释放而被缓存到存储池中,留作下次使用。

减少伙伴系统分配算法的调用次数(放置内存碎片过多,找不到大的连续内存)

种叫slab分配器的技术,Slab分配器实现非常复杂,核心就是存储池的运用。内存片段被看作对象,当被使用完后,并不直接释放而被缓存到存储池中,留作下次使用。

减少伙伴系统分配算法的调用次数(放置内存碎片过多,找不到大的连续内存)

Slab并非是脱离伙伴关系而独立存在的一种内存分配方式,slab仍然是建立在页面基础之上,换句话说,Slab将页面(来自于伙伴关系管理的空闲页面链表)撕碎成众多小内存块以供分配,slab中的对象分配和销毁使用kmem_cache_alloc与kmem_cache_free。


http://chatgpt.dhexx.cn/article/XhAH4CZ8.shtml

相关文章

Linux操作系统基础知识

〇、操作系统基础 1、什么是操作系统 操作系统(Operating System, OS),介于硬件资源和应⽤程序之间的⼀个系统软件。 2、操作系统的功能 操作系统位于硬件资源之上,管理硬件资源;应⽤程序之下,为应⽤程序提供服务,同…

Python描述 LeetCode 23. 合并K个升序链表

Python描述 LeetCode 23. 合并K个升序链表 大家好,我是亓官劼(q guān ji ),在【亓官劼】公众号、CSDN、GitHub、B站等平台分享一些技术博文,主要包括前端开发、python后端开发、小程序开发、数据结构与算法、docker、…

进程间通信【Linux】

文章目录 1. 进程间通信1.1 什么是进程间通信1.2 进程间通信的必要性1.3 进程间通信的本质1.4 进程间通信的方式 2. 匿名管道2.1 匿名管道的概念2.2 匿名管道的原理注意 2.3 实现匿名管道pipe函数步骤1. 创建管道2. 创建子进程3. 构建单向信道子进程父进程构建一个变化的字符串…

Java岗大厂面试百日冲刺 - 日积月累,每日三题【Day33】—— 手撸算法2

大家好,我是陈哈哈,北漂五年。相信大家和我一样,都有一个大厂梦,作为一名资深Java选手,深知面试重要性,接下来我准备用100天时间,基于Java岗面试中的高频面试题,以每日3题的形式&…

合并k个已排序的链表

ojbk...开始以为这题没有内存要求,所以就用来一个很简单的方法合并。创建第三条链表,结果部分案例过不去。 这个代码: /*** Definition for singly-linked list.* struct ListNode {* int val;* ListNode *next;* ListNode(int x) : val(x)…

LeetCode 88. 合并两个有序数组 C/C++/Python

欢迎加入【Linux C/C/Python社区】一起探讨和分享Linux C/C/Python/Shell编程、机器人技术、机器学习、机器视觉、嵌入式AI相关领域的知识和技术。 88. 合并两个有序数组 C语言版C版Python版 题目描述 给你两个按 非递减顺序 排列的整数数组 nums1 和 nums2,另有两个…

C语言——如何较为高效的方法合并两个有序数组,使之成为一个有序数组

题目:有两个有序数组arr1[]和arr2[],将它们合并成数组arr[],要求arr[]也是有序数组。 思路:新定义一个数组arr,最大长度为100,从两数组最左边开始比起,把小的放入新集合,然后相应的i…

Linux(Centos6、Centos7)常用关机命令(halt命令需针对不同版本)

1、Centos6关机命令 CentOS6立即关机一共有三种形式: ① shutdown命令: [rootlocalhost ~]# shutdown -h 0② init命令: [rootlocalhost ~]# init 0③ halt命令(与Centos7不同): [rootlocalhost ~]# h…

centos----关机重启命令

1.shutdown 参数 时间 shutdown -h now/具体时间,关机 shutdown -r now/具体时间,重启 shutdown -c 取消上次关机或者重启命令 2.其他关机重启命令 关机:halt/poweroff/init 0不过这些相对不安全,不能保持当时的状态 重启:reboot/init …

centos8关机命令

centos6.8怎样重启vsftpd服务 安装了vsftpd,发现使用systemctlstopvsftpd,还是可以匿名登录FTP。 然后修改了vsftpd.conf禁用了匿名,但是无法重新启动vsftpd,然后还是可以登录FTP。 [rootnichevsftpd]#whereisvsftpd vsftpd:/usr/…

【sql语句】注释

sql语句注释有两种 一种是块注释语句:和java C里面的注释一样 /* 内容 */ 还有一种是嵌入行内的注释语句: “--”(双减号)用来创建单行文本注释语句。 --后面需要有一个空格,就是我没敲空格做题才出了问题 空格 …

SQL SERVER创建字段注释

第一种方法是用SQL SERVER的管理工具 表设计中的列属性自带说明,填写会自动生成注释 第二种方法 如果在navicat等工具上无法可视化创建注释的,需要执行语句 EXEC sys.sp_addextendedproperty nameNMS_Description, valueN这是活动类型 , level0typeNSCHE…

SQL Server中怎么给表添加注释

在 SQL Server 中,可以使用 sp_addextendedproperty 存储过程为表添加注释。具体步骤如下: 打开 SQL Server Management Studio,连接到相应的数据库。 在“对象资源管理器”中,展开数据库,找到要添加注释的表。 右键…

SQL注入中,注释#、 --+、 --%20、 %23到底是什么意思?sqli-labs-master

1.# 和 -- (有个空格)表示注释,可以使它们后面的语句不被执行。在url中,如果是get请求**(记住是get请求,也就是我们在浏览器中输入的url)** ,解释执行的时候,url中#号是用来指导浏览器动作的&am…

sql语句,sql文件加注释

单行注释通用-- 如:sql server、oracle、db2等; 多行注释/**/ 如:sql server,其他不知道 access 好象不可以有注释 注释后面好像需要加“;”号 多行的不能直接跟在sql语句后面 单行的添加在sql语句后即可

SQL注入基础知识总结

SQL注入—基础知识总结 1、注释符1.1、Mysql中注释符有三种1.2、总结 2、information_schema库2.1、了解information_schema库2.2、常用注入语句 3、order by3.1、了解order by3.2、order by之判断列数 4、union select4.1、了解union select 1、注释符 SQL注入的时候经常会用到…

linux清理缓存cache,Linux清理cache缓存

当cache缓存占用太大,服务起不来,需要查看清理缓存 查看缓存: free -m 输入运行下面一行: echo 3 > /proc/sys/vm/drop_caches # 释放缓存区内存的方法 1)清理pagecache(页面缓存) # echo 1 > /proc/sys/vm/drop_caches 或者…

linux清空buff,linux 清理缓存buff/cache

清理缓存 echo 1 > /proc/sys/vm/drop_caches echo 2 > /proc/sys/vm/drop_caches echo 3 > /proc/sys/vm/drop_caches 清理脚本 purgeCache.sh #!/bin/bash mem_nowfree -m | awk NR2 | awk {print $4} buff_nowfree -m | awk NR2 | awk {print $6} if [ $mem_now -l…

Linux系统清理缓存方法

Linux运行主要看物理内存和交换空间SWAP(虚拟内存)的使用情况,一般物理内存小则设置虚拟内存大点,物理内存大,则设置虚拟内存小点。 在旧版系统中虚拟内存常常设置为物理内存的两倍,但是新版新硬件&#xf…

Linux缓存命令(查看、清理)

查看命令: free -m free-h 介绍: Mem:内存的使用信息 Swap:交换空间的使用信息 total ——系统总的可用物理内存大小(内存总数) used ——已被使用的物理内存大小 free ——空闲的物理内存数(…