`
ruilin215
  • 浏览: 1104275 次
  • 性别: Icon_minigender_2
  • 来自: 成都
文章分类
社区版块
存档分类
最新评论

对Linux内存管理的思考

阅读更多

转自:http://bbs.chinaunix.net/thread-1925077-1-1.html

经典!看了对低端物理内存和高3

内核的虚拟内存被连续映射到最低端的物理内存。这是所有问题的开始。

为什么要把内核的虚拟地址空间连续地映射到物理内存最低端?这个根本不是个问题。开发人员或是出于效率的原因或是出于实现的原因,就是做了这样的设计。但这种设计却引发了很多令人困惑的问题。

假设我们使用32位版本内核,系统装有2G物理内存,下面所说的“内核的虚拟内存”是指内核前896M虚拟内存。

"内核将自己的虚拟内存连续映射到低端物理内存"到底会产生什么样的结果?是说低端那896M物理内存已被内核所占而不能另做它用?昨天讨论内存的帖子里给出了否定答案,看起来这是个很老的问题了。

书上往往会还有这样的话语:内核只能使用最低端896M物理;超过896M的内存称之为“高端内存”,无法被内核直接使用。初学者读到这里,总觉得哪里不对劲,却又道不出个所以然来。

既然内核已将自己的虚拟内存映射了,内核页表里entries是怎样的呢?在entry中,我们当前感兴趣的有两项:映射地址与Present标志位。映射地址嘛,肯定安排好了。Present标志位是不是1呢?不妨认为是1。这样一来,从内核的页表上来看,前896M的物理内存的的确确被内核所“占用”,只要内核引用相应的虚拟地址,内核就会访问到相应的物理地址,不会发生任何意外。但是,如前面所说,进程也是可以使用这块内存的。如果某个进程的某个虚拟地址映射到了前896M中的某一段,那么内核与进程都可通过各自的页表访问到这块内存。这样会不会发生冲突呢?

描述页帧的数据结构是page结构体,一个页帧是否空闲正是取决于对应page结构体中的引用数。那么内核映射的那896M物理内存是否空闲呢?除了内核代码及静态数据所占的物理页外,其它的全是空闲状态。也就是说《内存管理子系统》可以把这些内存分配出去。昨天帖子里说的“被内核映射了不等于被内核使用了”就是这么回事。内核页表里的内容是说,前896M物理内存处于一种Ready to use的状态,然而没有被内核使用的内存,进程也可以使用。在896M内存中,内核不能使用“被进程使用的内存”,即内核不能引用相应的页表里的内容,即内核不可使用相应的虚拟地址。

内核是怎么使用自己的虚拟地址的呢?她怎么知道哪一段的虚拟地址已经《被自己使用了》或者《因为进程而不能使用》?即内核如何管理自己的虚拟地址。

先看内核如何管理进程的虚拟地址。当进程需要内存时,内核首先会为进程分配一段虚拟地址,即所谓的Memory Region。由于进程虚拟地址的使用情况记录在vm_area_struct中,所有的vm_area_struct都按照顺序连接在一个链表上,因此寻找某大小的虚拟地址十分简单,扫描这个链表,碰到一块大于或等于[所申请内存大小]的连续地址,便用新的vm_area_struct记录下来,并插到链表的合适位置,这块虚拟地址便被标记为“已用”了。其实这就是操作系统理论里所讲的first fit。早期的Unix就是这样管理物理内存的,而这里用之管理进程的虚拟内存。内核为进程分配内存的步骤如下:
一、找到合适大小的虚拟地址段;
二、向{内存管理子系统}申请物理页帧;
三、在进程页表中建立两者的映射关系。

然而内核为<自己>分配内存时,只有#第二步#。

没有第三步,是因为一开始的时候,内核页表已经做好了映射。那第一步呢?内核为什么没有像进程一样<<寻找合适大小的虚拟地址段>>这一步骤?

内核自己需要内存时,总是向Slab层申请(?)。需要创建新的数据结构,需要一个buffer时,Slab便为之分配一块连续的内存。内核不需要对这块内存做映射,只要这块连续的物理内存在前896M之内,它本来就处于一种“预备被内核使用”的状态。从Slab里分出来后,它就“正式被内核使用”。那么说到底,内核怎么管理虚拟地址呢?内核没有“额外管理”,具体使用哪一块虚拟内存取决于Slab分配哪块物理内存。Slab分配哪块物理内存又取决了{内存管理子系统}。{内存管理子系统}={Buddy System}

结论是:Buddy System管理了内核的虚拟内存。严格来说,Buddy System在管理前896M物理内存时随便把内核的虚拟内存也管理了。对进程来说,分配虚拟内存与分配物理内存是分开的步骤;对于内核来说,分配了物理内存就等于分配了虚拟内存。内核为自己分配的内存究竟在虚拟内存的什么位置取决于分[配到的内存的页帧]在物理内存中的哪个位置。进程需要额外的结构体记录虚拟内存的使用的情况;内核虚拟内存的使用情况就是前896M物理内存的使用情况。换句话说,一旦进程申请到了前896M物理内存中的某一块,就相当于侵占了内核的虚拟地址空间,就相当于内核对应的虚拟地址段已经被使用。由于所有对物理内存的申请都由Buddy System应答,内核为自己申请内存时,不可能再获得被[进程占用的物理内存]所对应的[虚拟地址],也就不可能去[引用相应的页表],冲突也就避免了。当然,如果内核有BUG,指针使用不慎,很容易破坏进程的内存。

这样一来,问题都解决了。前896M物理内存由内核与进程混用。但内核只能使用这896M物理内存(因为它的页表映射是固定的),而进程可以使用任何地方的物理内存(因为它的页表可以随意设置)。内核高128M留作其它用途,可以随意映射。内核不能直接使用的内存即“高端内存”。当内核的线性地址空间大于物理内存时,“高端”便不存在了。这种情况实际上有两种可能:一是内核线性地址空间太大,如使用64位系统;二是系统物理内存太小,如机器仅配有512M内存。两者都是{内核线性地址空间大于物理内存}的结果。

管理进程虚拟内存时,利用分页,可以把虚拟地址随意映射到任何物理地址,这才是我们印象中“分页机制的常规用法”。相反的,内核管理自己的虚拟内存时,利用分页,把“一块虚拟内存固定到一块物理内存”,反倒限制内核能使用的内存在物理内存中的位置,与我们印象中分页机制的常规作用相悖。初学者总有种“说不清道不明的不协调感”,大概就是这个原因吧。

分享到:
评论

相关推荐

    Linux内存管理编程

    1.实验目的 (1) 学习Linux内存编程方法,掌握Linux内存映射和解除映射的方法 (2) 掌握在内存打开文件和读取文件的方法

    内存管理内存管理内存管理

    对实际编程来说,理解您的内存管理器的能力与局限性至关重要。在大部分系统语言中,比如 C 和 C++,您必须进行内存管理。本文将介绍手工的、半手工的以及自动的内存管理实践的基本概念。 追溯到在 Apple II 上...

    操作系统(内存管理)

    文将对 Linux™ 程序员可以使用的内存管理技术进行概述,虽然关注的重点是 C 语言,但同样也适用于其他语言。文中将为您提供如何管理内存的细节,然后将进一步展示如何手工管理内存,如何使用引用计数或者内存池来半...

    嵌入式Linux应用程序开发标准教程(第2版全)

    7.1.4 Linux下的进程管理 7.2 Linux进程控制编程 7.3 Linux守护进程 7.3.1 守护进程概述 7.3.2 编写守护进程 7.3.3 守护进程的出错处理 7.4 实验内容 7.4.1 编写多进程程序 7.4.2 编写守护进程 7.5 本章小结 7.6 ...

    华清远见嵌入式linux应用程序开发技术详解下载(内部资料).rar

     3.6 Make工程管理器  3.7 使用autotools   3.8 实验内容   本章小结   思考与练习  第4章 嵌入式系统基础   4.1 嵌入式系统概述   4.2 ARM处理器硬件开发平台   4.3 嵌入式软件开发流程   ...

    嵌入式Linux应用程序开发详解

    7.1.4 Linux下的进程管理 211 7.2 Linux进程控制编程 212 7.3 Linux守护进程 224 7.3.1 守护进程概述 224 7.3.2 编写守护进程 224 7.3.3 守护进程的出错处理 229 7.4 实验内容 232 7.4.1 编写...

    Linux内核学习

    内存管理虽难,但多达三章细致入微的说理,一定会让你茅斯顿开。而内容的组织更 是别具匠心,每章开始部分一般性原理的描述,打破知识的局限,将每个部分的全景展现在你面前。而针对 每个知识点,落到实处的独到分析...

    Linux多线程服务端编程:使用muduo C++网络库

    《Linux多线程服务端编程:使用muduo C++网络库》主要讲述采用现代C++在x86-64 Linux上编写多线程TCP网络服务程序的主流常规技术,重点讲解一种适应性较强的多线程服务器的编程模型,即one loop per thread。...

    毕设&课设&项目&实训-内存数据库课程实验设计思考、结合Orcale Database and Apex课程项目.zip

    包含前端、后端、移动开发、操作系统、人工智能、物联网、信息化管理、数据库、硬件开发、大数据、课程资源、音视频、网站开发等各种技术项目的源码。 包括STM32、ESP8266、PHP、QT、Linux、iOS、C++、Java、python...

    在 KVM 中按需分配内存和虚拟 CPU-研究论文

    我们提出的系统尝试在 KVM 内存管理和虚拟 CPU 分配方面进行两个正常的实现更改。 建议的系统包括 1) 根据需要在运行时为虚拟机分配二级内存。 2) 基于算法结果在运行时分配虚拟 CPU。 并在虚拟机中添加对称多处理...

    嵌入式课件

    9.2.3 内存分配伪指令 9.2.4 汇编控制伪指令 9.2.5 其他常用的伪指令 9.3 ARM的汇编语言结构 9.3.1 ARM汇编语言程序结构 9.3.2 ARM汇编语言的语句格式 9.3.3 基于Windows下ADS的汇编语言程序结构 9.3.4 基于Linux下...

    my-love:(都是脑图,建议使用xmind 8 :)工程师的自我修养->从linux,网络,MQ,Rpc,缓存,高可用架构,数据库,语言,全面成长,成为技术大神,优秀的工程师,自述文件,包括蚂蚁,头条,美团等面试思考(拿下要约)

    java /并发编程总结.pic_hd 质量管理体系如何快速整合团队架构-微服务 达博 IO多路收益系统编程和进度线程管理 未来发展信号和中断线程池的其他使用进度管理与调度算法 GC 管道与先进先出文件IO内存管理分散&& ...

    传智播客扫地僧视频讲义源码

    11_c的学习重理解到位_对初学者_传智扫地僧 12_直接通过内存标号操作内存空间_课堂答疑 13_中午课程回顾 14_内存四区基本原理_全局区案例理解 15_内存四区_堆栈案例理解 16_课堂答疑_理解指针的关键关键在内存 17_vs...

    自己动手写操作系统(含源代码).part2

    首先是操作系统的名字改变了,原因在于虽然我们的试验性 OS从前辈们那里借鉴了很多东西,但其各个部分的设计(比如文件系统和内存管理)往往有其独特之处,所以我将原先的 Tinix(本意为 TryMinix)改成了新名字...

    自己动手写操作系统(含源代码).part1

    首先是操作系统的名字改变了,原因在于虽然我们的试验性 OS从前辈们那里借鉴了很多东西,但其各个部分的设计(比如文件系统和内存管理)往往有其独特之处,所以我将原先的 Tinix(本意为 TryMinix)改成了新名字...

    fourinone-3.04.25

    淘宝Fourinone(中文名字“四不像”)是一个四合一分布式计算框架,在写这个框架之前,我对分布式计算进行了长时间的思考,也看了老外写的其他开源框架,当我们把复杂的hadoop当作一门学科学习时,似乎忘记了我们想...

    Fourinone分布式并行计算四合一框架

    Fourinone(中文名字“四不像”)是一个四合一分布式计算框架,在写这个框架之前,我对分布式计算进行了长时间的思考,也看了老外写的其他开源框架,当我们把复杂的hadoop当作一门学科学习时,似乎忘记了我们想解决问题...

    操作系统实验4-4实验报告.docx

    操作系统实验报告 实验4-4: Linux共享存储通信 实验目的 (1) 掌握Linux提供的共享存储区通信方式的使用方法。 (2) 了解共享存储区通信方法的特点。 (3) 了解实现进程间通信的不同方法之间的区别、特点和适用情况。 ...

Global site tag (gtag.js) - Google Analytics