《深入理解Linux内核》笔记5:内存管理

本文介绍内核如何给自己分配物理内存并管理。对应《深入》第8章。

在《深入》第2章“内存寻址”(或者是我博客中的这篇文章,点这里)中,已经介绍了内核如何给自己分配1G的线性地址的。但是物理内存的分配及管理恐怕更复杂而且更有必要:内存分配和释放的速度(由内存管理的算法决定)影响内核的工作效率。

首先介绍概念:

页框:通俗的说就是物理内存上的单元。请注意与“页”的区别。页有两重意思,不过最多的用法是指线性地址的单元。所以一个是实际物理内存的单元,一个是线性地址/虚拟内存的单元。在大多数情况下,页框大小等于页的大小,为4KB,使得一个页框恰好可以容纳一个页的数据。

(1)为什么要进行内存管理?

内存管理的目的总体上说无非是两点:提高时间效率和提高空间效率。时间效率也就是尽量使寻找到空闲内存、分配和释放这块内存的时间更短。空间效率就是指尽量能找到合适大小的空间,并减少内存空间浪费。

关于空间效率,举个简单的例子:切蛋糕。当我们拿到一块完整的蛋糕的话,如果想每个人都吃到完整的一块,那么我们当然不能没有计划的切块。虽然总量是不变的,但是如果随便乱切,横七竖八,势必导致最后剩下的蛋糕都是碎块,那么后面吃蛋糕的同学必然只能把小块小块的蛋糕凑成一大块来吃。势必很不爽啊。。。

(2)关键数据结构:页描述符

如果需要对一个东西进行管理,那么必须要有负责管理的数据结构,这个数据结构中有各个字段,用来提供不同的管理功能。举例子:比如为了保护内核的内存不被用户进程使用,就必须使用一个标志位;用户进程在读写内存时,首先就要检查这个标志位,然后才能读写。

所以内核使用了“页描述符”这个数据结构,页描述符的类型是page,长度为32字节(是字节哦),所有的页描述符放在一个数组mem_map中。我个人觉得好像应该叫“页框描述符”比较好。

(3)为什么要使用内存管理区?

内存本来在物理上是一个实体,并不分区的。有人会问:这样的一个整体进行处理不是很简洁么?为什么要分区呢?

但是由于以下的两种约束,我们迫不得已给自己增加了负担,将内存分区来管理。

约束一:DMA。这个名词不再解释,请自行google。在进行DMA数据传输时,DMA控制器只能对16M的内存进行寻址,所以被迫无奈,只好将这16M的物理内存固定划分给DMA了。

约束二:线性地址有限,无法直接大的物理内存。所以,超出896M的物理内存必须被区别对待。

所以,最终,物理内存被分配成3个管理区:ZONE_DMA,ZONE_NORMAL,ZONE_HIGHMEM。

(4)为什么要使用伙伴系统(Buddy system)算法?

使用伙伴系统的直接目的就是为了防止物理内存“外碎片”的产生。关于外碎片,简而言之就是虽然我们一直分配或者释放连续的内存,但是结果就是我们的内存变得很不连续,充满了大大小小的碎片或者是洞,以至于我们无法再分配足够大的一块连续的内存。(回忆下我们刚才说过的蛋糕的例子)

下面举例说明。假设我们要分配一块256个连续页框的内存。

首先考虑一种不好的分配算法作为对比,例如:将所有的空闲连续页框链在一个链表中,我们在分配空间时选取遇到的第一个大于256个连续页框(这个可能很随机,可能是1024个页框,也可能是512个,也可能恰好是256个;而且我们不能奢望在链表的开头遇到大于256个的连续页框,如果链表很长。。。Orz)。假设我们遇到了空闲的1024个页框。这时候我们面临两个选择:

    (a)把这1024个页框都分配出去。这显然是一种巨大的浪费。

    (b)把这1024个页框切开,将256个连续页框脱离链表,然后链表上剩下了768个连续页框的块。这其实和外碎片没有什么区别(因为链表后面很可能有更适合256的连续页框,比如257个或者258个连续页框),最终会导致这个链表被分割的乱七八糟,以至于再也找不到一块合适的连续空间。

(5)伙伴系统

所以,Linux使用了著名的伙伴系统来处理这个问题。那么下面用实例说明伙伴系统是如何改进的。最后我们再总结一下伙伴系统的思想。

伙伴系统的基础是11个连续页框链表,第一个链表上只存储所有空闲的1个页框,第二个链表上只储存所有空闲的2个连续页框,以此类推。这11个链表将不同大小的连续内存块链在不同的链表上,这首先节省了遍历一个很长的链表的时间,可是使我们直奔最符合需求的连续内存。如果是需要256个连续页框,我们可以直接找到第9个链表,取出一个即可。但又出现了几个问题:(q1)如果我们需要254个连续页框呢?(q2)如果我们已经没有了256个的连续页框,即256个连续页框的链表已经空了呢?

下面介绍如何妥善处理剩余部分,也就是解决问题q1。我们只需要254个连续页框时,我们把这个256个连续页框从链表上切除,但是只分配出去254个页框,剩余的两个连续页框链入属于它的链表,也就是存储所有两个连续页框的链表。这样我们看到,我们一个页框都没有浪费。

有人可能会问,如果需要258个连续页框怎么办(258>256)?这个问题其实与q1等价,但是此时最符合需求的是512个连续页框,但是剩下的部分只是要切割多次。但我们无需证明最后一个页框都不会浪费(因为至少最后都会链到1个页框的链表里)。q2其实与这种情况很类似,仍然要去更大的一级链表中寻找。

那么伙伴系统与开始介绍的那种不好的算法到底有什么本质区别呢?

简而言之,伙伴系统直奔最符合需求的连续内存,然后它妥善的处理了剩余部分。首先我们使用了空间换时间的算法:维护这11个块链表的开销,相对于一个好的内存分配算法根本算不上什么。其次,伙伴系统是类似“贪心”的。它寻找当前认为最好的。最后,它把分配后剩余的部分妥善的移动到它们最应该去的地方。

(6)使用的函数

分配:alloc_pages()/alloc_page()/__alloc_pages()

释放:__free_pages()/free_pages()/free_page()

==============================

下面插入两个概念,内存区(memory area)与内碎片。内存区这个词很容易让人产生误会,它不是指整个内存,而是指连续的任意长度的物理内存区。而内碎片是相对于外碎片讲的,外碎片是以页框为单位的,在页框之外;而内碎片就是在页框内部的碎片。产生内碎片的原因其实与外碎片一致:虽然我们所有的分配和释放都是连续的,但最后结果却是不连续的物理内存。

===============================

(7)为什么要使用slab分配器?

我们先不管slab是什么,先考虑为什么要使用它:它的出现就是为了解决内碎片的问题。

当然,有人肯定会想,使用伙伴系统解决内碎片不是一样么?只不过把单位从页框改为字节。

早期Linux确实是这么做的。但是遇到了一些问题(详见《深入》p.324),以我的理解就是:当分配和释放的粒度变细时,被迫需要考虑更多的因素,比如说需要考虑到数据类型。所以伙伴系统在处理内碎片时效率并不是最好的。

于是采用了具有面向对象思想(考虑到数据类型,就已经是一种面向对象的思想了)的slab系统。

(8)slab系统的思想的。。。呃 猜测

这里,限于篇幅和个人能力有限,就不详细介绍slab系统了。我的理解是:slab系统提供了一种快速查找并分配特定类型的数据(面向对象)的细粒度连续内存空间的方法。因为它使用了下图所示的这种层级结构,让我不由得联想到了数据结构中的B树(B树也是用来快速查找,减少树的层数的,当然也付出了一定的空间复杂度;当然我还不知道我这种联想合理不合理)。

c4a7ab3e06c638ca55e723f3.jpg

(9)slab所使用的函数

分配和释放slab:kmem_cache_alloc()/kmem_cache_free()

分配和释放对象:kmalloc()/kfree()。

======================================

参考资料:

这里有一篇IBM关于slab的技术文章:Linux slab 分配器剖析


转载于:https://www.cnblogs.com/microgrape/archive/2011/05/12/2043909.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/405288.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Objective-C设计模式——单例Singleton(对象创建)

单例 和其它语言的单例产不多,可以说是最简单的一种设计模式了。但是有几个点需要注意下,单例就是一个类只有一个实例。 所以我们要想办法阻止该类产生别的实例,一般语言中都会将构造函数写为private。但是OC中的函数并没有限定符&#xff0c…

基于SSM在线协同过滤汽车推荐销售系统

SSM毕设分享 基于SSM在线协同过滤汽车推荐销售系统 1 项目简介 Hi,各位同学好,这里是郑师兄! 今天向大家分享一个毕业设计项目作品【】 师兄根据实现的难度和等级对项目进行评分(最低0分,满分5分) 难度系数:3分 工作…

Keil中的Code,RO,RW,ZI分别表示什么?

在使用keil开发STM32应用程序时,点击Build后在Build Output窗口中经常会有如下信息:以前一直好奇这几个参数和实际使用的STM32芯片中Flash和SRAM的对应关系,于是上网搜了一圈,做如下总结:这些参数的单位是Byte图中几个…

JTAG、SWD接口定义

版权声明:本文为博主原创文章,转载请注明。 博客已转到 http://blog.csdn.net/upc_xbt https://blog.csdn.net/u014124220/article/details/50829713Jlink仿真器接口仿真器端口连接目标板备注1. VCCMCU电源VCCVCC2. VCCMCU电源VCCVCC3. TRSTTRSTTest ReS…

Drainage Ditches - poj 1273(网络流模板)

题意:1是源点,m是汇点,求出来最大流量,没什么好说的就是练习最大流的模板题 ************************************************************** 先用Edmonds-Karp的算法做一下试试吧重边贡献了 1W,要加上所有的重边才算…

linux RTC 驱动模型分析

linux RTC 驱动模型分析RTC(real time clock)实时时钟,主要作用是给Linux系统提供时间。RTC因为是电池供电的,所以掉电后时间不丢失。Linux内核把RTC用作“离线”的时间与日期维护器。当Linux内核启动时,它从RTC中读取时间与日期,…

Install Docker Mac OS X

检查 Mac OS version 要求必须是 OS X 10.6 Snow Leopard or newer to run Boot2Docker安装 Boot2Docker 列表内容下载地址:https://github.com/boot2docker/osx-installer/releases/download/v1.7.0/Boot2Docker-1.7.0.pkg 下载后点击安装,就是按照提示…

linq to sql报错,

以上是由于我把关联表中的string类型写成int类型所导致的,记一下,备用。转载于:https://www.cnblogs.com/server126/archive/2011/05/25/2057416.html

[VC6] RadioBox使用入门

基于对话框的应用程序,界面如下: 。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。 具体请参考代码: 关键代码: // del2Dlg.cpp : implementation file //#include "stdaf…

树莓派使用STEP1:装系统

1、windows安装SD卡格式化软件:SDFormatter.exe 2、windows安装系统烧录软件Win32DiskImager.exe 3、下载镜像:https://www.raspberrypi.org/downloads/raspbian/ 并解压缩 4、用Win32DiskImager将下载的镜像文件烧录进SD卡。 5、插上SD到树莓派&…

树莓派使用STEP2:设置网络

安装好系统并开机,插入鼠标键盘和显示器,登陆系统,打开终端。按以下操作。 1、sudo raspi-config 进入配置,打开SSH功能。 Interfacing Options -> SSH 2、扩展系统内存。 Advanced options -> Expand Filesystem 3、设置…

linux3.0-内核自带led驱动移植

********************************************************************************************************************************************************************************** cpu : s3c2440(arm9) linux内核:linux-3.0 开发板 &am…

树莓派使用STEP3:更换镜像源

更换国内镜像源,这里使用中科大的源,软件下载和更新速度更快。 1、sudo nano /etc/apt/sources.list 2、sudo nano /etc/apt/sources.list.d/raspi.list 3、sudo apt-get update && apt-get upgrade

树莓派使用STEP4:安装vim

系统原装的vi操作对新手和学习者不友好,可以用nano编辑器,因为我比较熟悉vi和vim,这里推荐使用vim。首先需要删除原装的vi,然后重新安装新的vim,过程比较简单。 1、卸载预装的vi sudo apt-get remove vim-common 2、…

手机测试pc端网页

在这个问题上徘徊了 一个钟头了,终于被我找到方法了,就赶紧记下来,以后好查阅!! 主要问题在防火墙,防火墙阻当了80端口,所以怎么用手机访问都是访问不了的。把防火墙关闭就好了! 贴上…

树莓派使用STEP5:安装samba文件共享服务器

samba服务器可以在多平台多操作系统搭建文件服务器,用于共享文件。为了方便windows和树莓派交换文件,将samba服务器的搭建过程记录如下。 1、安装samba服务器。 sudo apt-get install samba samba-common-bin 出现以下提示:Modify smb.conf…

ETH—Lwip以太网通信

第39章 ETH—Lwip以太网通信 全套200集视频教程和1000页PDF教程请到秉火论坛下载:www.firebbs.cn 野火视频教程优酷观看网址:http://i.youku.com/firege 互联网技术对人类社会的影响不言而喻。当今大部分电子设备都能以不同的方式接入互联网(Inter…

计算从A地出发到各个地方的路径及距离

数据库环境:SQL SERVER 2005 如题,现有bus表数据如下,dstart是起点,dend是终点,distance是两地的距离。 求从A地出发到各个地方的距离。 有经验的人一看,就知道题目关于树形查询的。SQL SERVER 2005数据库…

树莓派使用STEP6:安装git

git用于创建和管理代码仓,是一个很优秀的版本控制工具。linux/树莓派安装非常简单。 1、sudo apt-get install git-core

cJSON 使用笔记

缘 起 最近在stm32f103上做一个智能家居的项目,其中选择的实时操作系统是 rt_thread OS v1.2.2稳定版本,其中涉及到C和java(android)端数据…