网盘分享吧

 找回密码
 立即注册

QQ登录

只需一步,快速开始

查看: 1587|回复: 0

[转载] Linux内存管理机制

[复制链接]

主题
1
积分
51
热心值
23
金币
63
注册时间
2023-1-29
最后登录
2023-4-14
在线时间
13 小时

活跃会员最佳新人

发表于 2023-1-29 03:31 | 显示全部楼层 |阅读模式

赞助VIP可享受免金币查看特权  点击这里充值金币或者开通VIP 购买前先点击分享链接验证是否有效!
BT资源无法下载:戳这里,如何发布售价资源帖?:戳这里      《避免 分享链接失效 的方法?》



摘要本章首先以应用程序开发者的角度审视Linux的进程内存管理,在此基础上逐步深入到内核中讨论系统物理内存管理和内核内存的使用方法。
前言本文主要从开发者的角度谈谈对内存管理的理解,并把内核开发中使用内存的经验和对Linux内存管理的认识与大家共享。其中也会涉及到一些诸如段、页等内存管理的基本理论,但会点到为止,不做深究。
进程与内存进程如何使用内存?毫无疑问,所有进程(执行的程序)都必须占用一定的内存,它或是用来存放从磁盘载入的程序代码,或是存放取自用户输入的数据等等。
对任何一个普通进程来讲,它都会涉及到5种不同的数据段。具体如下:
代码段:代码段是用来存放可执行文件的操作指令,也就是说是它是可执行程序在内存中的镜像。代码段需要防止在运行时被非法修改,所以是不可写的。
数据段:数据段用来存放已初始化的全局变量,换句话说就是存放程序静态分配的变量和全局变量。



BSS段:BSS段包含了未初始化的全局变量,在内存中bss段全部置零。

:堆是用于存放进程运行中被动态分配的内存段,它的大小并不固定,可动态扩张或缩减。当进程调用malloc等函数分配内存时,新分配的内存就被动态添加到堆上(堆被扩张);当利用free等函数释放内存时,被释放的内存从堆中被剔除(堆被缩减)。
:栈是用户存放程序临时创建的局部变量,也就是说我们函数括弧“{}”中定义的变量(但不包括static声明的变量,static意味着在数据段中存放变量)。除此以外,在函数被调用时,其参数也会被压入发起调用的进程栈中,并且待到调用结束后,函数的返回值也会被存放回栈中。由于栈的先进先出特点,所以栈特别方便用来保存/恢复调用现场。从这个意义上讲,我们可以把堆栈看成一个寄存、交换临时数据的内存区。
进程如何组织这些区域?上述几种内存区域中数据段、BSS和堆通常是被连续存储的——内存位置上是连续的,而代码段和栈往往会被独立存放。有趣的是,堆和栈两个区域关系很“暧昧”,他们一个向下“长”(i386体系结构中栈向下、堆向上),一个向上“长”,相对而生。但你不必担心他们会碰头,因为他们之间间隔很大。
下图简要描述了进程内存区域的分布:
下面我们就继续进入操作系统内核看看,进程对内存具体是如何进行分配和管理的。
从用户向内核看,所使用的内存表象形式会依次经历逻辑地址——线性地址——物理地址几种形式。逻辑地址经段机制转化成线性地址;线性地址又经过页机制转化为物理地址。(但是我们要知道Linux系统虽然保留了段机制,但是将所有程序的段地址都定死为0-4G,所以虽然逻辑地址和线性地址是两种不同的地址空间,但在Linux中逻辑地址就等于线性地址,它们的值是一样的)。沿着这条线索,我们所研究的主要问题也就集中在下面几个问题。
1.     进程空间地址如何管理? 2.     进程地址如何映射到物理内存? 3.     物理内存如何被管理?
以及由上述问题引发的一些子问题。如系统虚拟地址分布;内存分配接口;连续内存分配与非连续内存分配等。




进程内存空间Linux操作系统采用虚拟内存管理技术,使得每个进程都有各自互不干涉的进程地址空间。该空间是块大小为4G的线性虚拟空间,用户所看到和接触到的都是该虚拟地址,无法看到实际的物理内存地址。利用这种虚拟地址不但能起到保护操作系统的效果(用户不能直接访问物理内存),而且更重要的是,用户程序可使用比实际物理内存更大的地址空间(具体的原因请看硬件基础部分)。
在讨论进程空间细节前,这里先要澄清下面几个问题:
  • 4G的进程地址空间被人为的分为两个部分——用户空间与内核空间。用户空间从0到3G(0xC0000000),内核空间占据3G到4G。用户进程通常情况下只能访问用户空间的虚拟地址,不能访问内核空间虚拟地址。只有用户进程进行系统调用(代表用户进程在内核态执行)等时刻可以访问到内核空间。
  • 用户空间对应进程,所以每当进程切换,用户空间就会跟着变化;而内核空间是由内核负责映射,它并不会跟着进程改变,是固定的。内核空间地址有自己对应的页表(init_mm.pgd),用户进程各自有不同的页表。
  • 每个进程的用户空间都是完全独立、互不相干的。不信的话,你可以把上面的程序同时运行10次(当然为了同时运行,让它们在返回前一同睡眠100秒吧),你会看到10个进程占用的线性地址一模一样,这说明它们都是在各自内部的虚拟地址空间上运行。
进程内存管理进程内存管理的对象是进程线性地址空间上的内存镜像,这些内存镜像其实就是进程使用的虚拟内存区域(memory region)。进程虚拟空间是个32或64位的“平坦”(独立的连续区间)地址空间(空间的具体大小取决于体系结构)。要统一管理这么大的平坦空间可绝非易事,为了方便管理,虚拟空间被划分为许多大小可变的(但必须是4096的倍数)内存区域,这些区域在进程线性地址中像停车位一样有序排列。这些区域的划分原则是“将访问属性一致的地址空间存放在一起”,所谓访问属性在这里无非指的是可读、可写、可执行等。
对于一个进程来说往往需要多个内存区域来描述它的虚拟空间,如何关联这些不同的内存区域呢?大家可能都会想到使用链表,的确vm_area_struct结构确实是以链表形式链接,不过为了方便查找,内核又以红黑树(以前的内核使用平衡树)的形式组织内存区域,以便降低搜索耗时。并存的两种组织形式,并非冗余:链表用于需要遍历全部节点的时候用,而红黑树适用于在地址空间中定位特定内存区域的时候。内核为了内存区域上的各种不同操作都能获得高性能,所以同时使用了这两种数据结构。






楼主热帖

① www.wpfx8.com 欢迎您分享自己的网盘资源!分享越多,金币越多!资源互利共享,我为人人,人人为我!
② 每个人都可以在本站发布资源帖,同时本站所有资源都需要金币才能下载!但是,只要你发布几十个优秀资源帖,基本上,你就会源源不断地获得金币了!
③ 如果发现违规广告资源,请点击帖子正文右下角的“举报”按钮。一般资源发布是有效的,时过境迁因为各种各样的原因,资源有可能失效。如果购买后发现资源失效或者资源和帖子内容描述不符,请到首页 [问题/意见反馈区] 发帖说明原因后申请退币。如“资源失效,申请退币”,管理员核实后会退币给您的。

点击按钮快速添加回复内容: 超赞 高兴 激动 给力 收藏 支持 期待 顶帖 精彩 感谢
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

站长邮箱|sitemap|手机版|小黑屋|百度统计|标签搜索|网盘分享吧

GMT+8, 2024-5-4 10:00 , Processed in 0.098522 second(s), 19 queries , Redis On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表