暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

linux内存管理(一)开篇介绍

二进制人生 2019-08-30
647

开篇介绍

内存管理是linux内核比较重要的一个模块,其实也是任何操作系统里的一个核心专题。在实际的开发工作中,经常会遇到和内存牵扯的问题,比如内存泄露啊,内存越界等。如果你的技术仅仅只是停留于业务层面,对内核的东西一无所知,遇到这些问题往往是束手无策的。我们从事嵌入式linux开发的,应用程序跑在linux操作系统上,你总不能对程序的运行载体一无所知吧。网上有很多关于内存管理的博客,零零散散,对对错错,并不系统,我在阅读了大概上百篇博客之后,结合最新版本(5.2的内核源码,写了这个系列的文章。

我喜欢研究新的内核,都9102年了,还有人抱着0.11版本或者是2.6.0版本的内核进行研究,他们的出发点都是低版本的内核代码量少,简单易看,但我还是觉得就像手机,买新不买旧。由于内核代码开发人员比较多,还是会有一些垃圾代码存在的,开发人员会持续更新,垃圾代码也就会越来越少,比如以前没有设备树的概念,Linus Torvalds在2011年3月17日的ARM Linux邮件列表宣称“this whole ARM thing is a fucking pain in the ass”,有点脏就不翻译了,反正就是整个arm都是垃圾的意思,这句话引发了ARM Linux社区的地震,随后ARM社区进行了一系列的重大修正。在过去的ARM Linux中,arch/arm/plat-xxx和arch/arm/mach-xxx中充斥着大量的垃圾代码,相当多数的代码只是在描述板级细节,而这些板级细节对于内核来讲,不过是垃圾,如板上的platform设备、resource、i2c_board_info、spi_board_info以及各种硬件的platform_data。社区必须改变这种局面,于是PowerPC等其他体系架构下已经使用的Flattened Device Tree(FDT)进入ARM社区的视野。Device Tree是一种描述硬件的数据结构,它起源于OpenFirmware(OF)。在Linux2.6中,ARM架构的板极硬件细节过多地被硬编码在arch/arm/plat-xxx和arch/arm/mach-xxx,采用Device Tree后,许多硬件的细节可以直接透过它传递给Linux,而不再需要在kernel中进行大量的冗余编码。

 图 李纳斯

另外最新版本的内核相比以前做了许多技术上的革新,就算是基础机制比如内存管理也同样有在持续进步。

开篇撤了许多技术无关的东西,到此为止,我们进入主题。由于是第一篇,所以我想简单点,不讨论复杂的东西,就介绍一些基本概念。

基本概念

在学习内存管理前,你必须了解这些基本概念,才能继续往下看。物理地址和虚拟地址的操作,学过操作系统的人都是了解的。

物理地址:physical address),也叫实地址(real address)、二进制地址(binary address),它是在地址总线上,以电子形式存在的,使得数据总线可以访问主存的某个特定存储单元的内存地址。

虚拟地址:虚拟地址是相对于物理地址来说的。虚拟地址的提出,主要是为了解决在操作系统中,多进程内存地址重复,大进程在小内存运行等问题 。

Linux内核一般将进程的虚拟地址空间划分为两部分:底部较大的部分用于用户进程,顶部则用于内核,也就是经常听到的用户空间和内核空间。在IA-32(intel 32位架构)系统上,虚拟地址空间在用户进程和内核之间划分的典型比例是3:1arm亦是如此。现在的内核,该比例可以由用户进行配置,默认值仍旧是3:1

通常32位Linux内核地址空间划分0~3G为用户空间,3~4G为内核空间。注意下图是32位内核虚拟地址空间划分,64位内核地址空间划分是不同的。

 

 32位内核虚拟地址空间划分

内核需要管理所有的物理内存。为啥?因为你的应用程序通过malloc函数分配的虚拟内存都是由内核来分配的,而虚拟内存终究是要映射成实实在在的物理内存的。假设你电脑的物理内存是4G,那内核想要通过1G的虚拟内存来管理这4G的物理内存,很明显,简单的线性映射是无法做到的,因为空间不够。

上面的讨论提出了一个重要问题:

内核如何通过1G的虚拟内存,来管理大于1G的物理内存?即物理内存和虚拟内存的映射关系。这个问题贯穿了linux内存管理的始终。后续也会围绕这个问题层层铺开。



文章转载自二进制人生,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论