Linux内存管理实验

Linux内存管理实验
Linux内存管理实验

1

《unix 操作系统教程》课程实验报告

实验名称 Linux 内存管理实验

实验序号 5 姓 名

系院专业

班 级

学 号 实验日期 2012.11.28 指导教师

成 绩

一、实验目的

1. 通过在Linux 环境下对内存管理的基本操作,感性认识Linux 如何对内存进行管理。

2. 利用readelf 和objdump 观测 linux 下的内存地址映射过程以及进程的虚拟地址空间。

二、实验内容与要求

(1)按照实验内容完成实验操作步骤,学习内存管理中的一些常用命令 (2)理解linux 中逻辑地址、线性地址的概念。 (3)提交实验报告。

三、实验设备

地点: 实验实训中心A4-2 设备:计算机一台 linux 操作系统

2

四、实验步骤与测试

实验一

free 命令显示显示内存的使用情况(使用的和空闲的),包括物理内存、交换区内存、内核缓冲区内存。不包括共享内存。free 命令默认选项为-k 语法:

free [-bkmotV] [-s <间隔秒数>]选项介绍: -b: 以Byte 为单位显示内存使用情况; -k: 以KB 为单位显示内存使用情况; -m: 以MB 为单位显示内存使用情况; -o: 不显示缓冲区调节列;

-s<间隔秒数>: 每间隔指定时间执行一次free 命令; -t: 显示内存总和列;

-V: 显示版本信息;

(1)free -k: 以KB 为单位显示内存使用情况;

解释:total: 内存总量: 3355508(k) used: 已经使用的内存量: 490664(k) free: 空闲的内存量: 2864844(k)

shared: 当前已经废弃不用,总量是0(k) buffers: 25164(k)

Buffer Cache 内存量: 263480(k)

cached: Page Cache 内存量: 21436(k)

(2)free –m -s 5:以M 为单位,5秒显示以下内存信息

解释:以上为每隔5秒显示内存信息,由以上图可知:两次内存使用情况没有变化。 (3)free -o: 不显示缓冲区调节列;

解释:由以上可知Buffer Cache 这一列没有显示出来。 (4)free -t: 显示内存总和列;

解释:如上所示,内存总和是3355508(k),内存已使用为491408(k),内存空闲为2864100(k)。

(5)free -V: 显示版本信息

解释:版本号为3.2.7

2.swapon –s:显示交换区的使用状况

解释:交换区名为:/dev/sda3,类型为partition,大小为425712,已使用为0,优先级为-1。

3. vmstat是Virtual Meomory Statistics(虚拟内存统计)的缩写,可对操作系统的虚拟内存、进程、CPU活动进行监视。它是对系统的整体情况进行统计,不足之处是无法对某个进程进行深入分析。

解释:vmstat [-V] [-n] [delay [count]]

其中,-V表示打印出版本信息;-n表示在周期性循环输出时,输出的头部信息仅显示一次;delay是两次输出之间的延迟时间;count是指按照这个时间间隔统计的次数。对于vmstat输出各字段的含义,可运行man vmstat查看。

下面给出了各个参数的不同含义:

procs:

r-->在运行队列中等待的进程数

b-->在等待io的进程数

w-->可以进入运行队列但被替换的进程

memoy

swap-->现时可用的交换内存(k表示)

free-->空闲的内存(k表示)

buff-->被用来做为缓存的内存数,单位:KB

cache-->被用来做为文件读写缓存的内存数,单位:KB

swap

si-->从磁盘交换到内存的交换页数量,单位:KB/秒

so-->从内存交换到磁盘的交换页数量,单位:KB/秒

IO

bi-->磁盘块入

3

4

bo-->磁盘块出 System

in-->每秒的中断数,包括时钟中断 cs-->每秒的环境(上下文)切换次数 CPU

按 CPU 的总使用百分比来显示 us-->用户进程使用的时间 sy-->系统进程使用的时间 id-->cpu 空闲的时间 pages

re-->回收的页面

mf-->非严重错误的页面 pi-->进入页面数(k 表示) po-->出页面数(k 表示) fr-->空余的页面数(k 表示)

de-->提前读入的页面中的未命中数 sr-->通过时钟算法扫描的页面 disk 显示每秒的磁盘操作。 s 表示scsi 盘,0表示盘号 fault 显示每秒的中断数 in-->设备中断 sy-->系统中断 cy-->cpu 交换

实验二

1.搭建linux 实验平台,并在搭建好的平台中用vi 编辑器编写一个简单C 程序:

1. /*test.c */

2.

3. #include

4.

5. int global_data = 4;

6.

7. int global_data_2; 8.

9. int main(int argc, char **argv) 10. 11. { 12.

13. int local_data = 3; 14.

5

15. printf("HelloWorldn"); 16.

17. printf("global_data= %dn", global_data); 18.

19. printf("global_data_2= %dn", global_data_2); 20.

21. printf("local_data= %dn", local_data); 22.

23. return (0); 24. 25. }

2. 编译: $gcc -o test test.c

A.查看ELF 的头。

刚生成的二进制就是我们要查看的目标。从ELF 的头开始吧: $readelf -h test 实验结果:

可执行文件是可以在Intel x86 32 bit 的体系的机器上运行的(从“machine”和“class”字段)。 当执行时,程序将从虚地址0x080482c0(看“Entry point address”)开始运行。这个地址不是指向我们常见的main()函数地址的,但是它指向是一个名为__start 的函数。__start 函数是被linker 创建的,它的目标是初始你的程序。

6

这个程序还有28个节区(section)和7个段(segment)

什么是节区(section)? Section 是在目标文件中的一个区,它包括一些信息(这些信息对连接过程有用):程序的代码、程序的数据(变量、数组、字符串),可重定向的信息和其它。所以,在每一个区,几种信息组合在一起,这里有一个明显地含义:代码区只有代码,数据区只是初始化的或是没有初始化的数据,等等。节区头部分列表(Section Header Table,SHT )精确地告诉我们:ELF 目标文件中有什么section 。至少从“Number of section headers”字段中知道“test”目标文件有28个section.

如果section 是一个二进制表示的,linux 内核不能用一种方式读懂它,linux 内核准备几个VMA (Virtual Memory Area ),它们包括虚拟地址连续的页面帧。在VMA 的内部,一个或多个section 被映射其中。在这个例子中每一个VMA 都代表一个ELF 的段(segment)。那内核是如何知道哪个section 去往哪个segment 呢?这是Program Header Table(PHT)的工作。

B.查看Section Header Table(SHT)

让我们看一个Section 在程序中的存在形式: $ readelf -S test 实验结果:

7

编译器把可执行代码保存到.text 节区中。那.text 节区被标记为可执行('X'在flag 字段)。在这个节区,你可以看到我们main()函数的机器代码。 $ objdump -d -j.text test 实验结果:

-d 选项告诉objdump 分解机器代码。-j 告诉objdump 只关心那个特定的节区(在本例中,是.text )。以下是执行命令后的部分内容。

.data 节区保存所有的初始化的变量,这些变量不在栈中。“Initialized”是指这些变量被赋于初始值,如”global_data”。那”local_data”呢?“local_data”的值不在此节区中,它们生活在进程的栈里。 以下是用objdump 查看.data 节区:

8

$ objdump -d -j.data test 实验结果:

C.查看 program Header Table(PHT)

段(segment)是一个OS“看懂”我们程序的方法。让我们看看我们程序是如何变成段的吧: $readelf -l test 实验结果:

实验结果解释:

映射很直观。例如段号2,这里有15个节区被映射到其中。.text 节区就映射到此段。它的标志是R,E 其含义分别是可读,可执行。W 就是可读的含义。

可以使用/proc//maps 文件也可以得看到它。是一个我们想要查看的进程的ID 。, test 进程运行的太快了,在进入/proc 这前,它就结束了。可以使用gdb 来解决此问题。

也可以在return 之前调用 sleep()来搞定这个问题。

9

在另一个控制台中: $ gdb test (gdb) b main

Breakpoint 1 at 0x8048376 (gdb) r

Breakpoint 1, 0x08048376 in main ()

在此保持(hold)住,打开另一个控制台,找到test 的PID 。如果你想图省事的话,就这样: $ cat /proc/`pgrep test`/maps 实验结果:

回到gdb ,输入: (gdb) q

10

于是,最后,我们看到了12个段(实际上是VMA )。重点关注第一个字段和最后一字段。第一字段显示了VMA 的地址范围,最后一个字段显示了背后的文件。你在看到VMA 的第8行与之前PHT 的第2行的类似点了吗?不同之处是SHT 说它自己于0x080484fc 结束,但在8号段中我们看到它的结束地址是0x08049000。在VMA9号与段3号之间也有同样的现象。SHT 显示3号段开始于0x080494fc 。而VMA 则显示开始于0x08049000。 有这么几个因素我们必须了解:

1.尽管VMA 开始于不同的地址,与之关联的节区仍然被映射到精确的虚拟地址上了。

2.内核分配内存是以4KB 的页为基本单位的,所以每一页的地址都是4KB 的整数倍。如0x1000,0x2000等。对于VMA 的9号,这个页的地址是0x08049000。或从技术角度讲,这个段的地址必须与页面的大小对齐。

最后,哪一个VMA 是栈呢?VMA11就是。一般地,内核动态地分配几个页面,并映射到用户空间可能的最高的虚拟地址,这就是栈的区域了。简单地讲,每一个进程的地址空间被分成两部分(前提是32位的CPU ):用户空间和内核空间。用户空间在0x00000000-0xc0000000 ,所以内核空间只能在0xc0000000以上了。

于是,分配给栈的地址是在0xc0000000边界附近的。结束地址是固定的,开始地址可以根据保存内容的多少而变化。

linux内核之内存管理

Linux内核之内存管理 作者:harvey wang 邮箱:harvey.perfect@https://www.360docs.net/doc/621729925.html, 新浪博客地址:https://www.360docs.net/doc/621729925.html,/harveyperfect,有关于减肥和学习英语相关的博文,欢迎交流 把linux内存管理分为下面四个层面 (一)硬件辅助的虚实地址转换 (二)内核管理的内存相关 (三)单个进程的内存管理 (四)malloc软件 (一)处理器硬件辅助的虚实地址转换(以x86为例) 在x86中虚实地址转换分为段式转换和页转换。段转换过程是由逻辑地址(或称为虚拟地址)转换为线性地址;页转换过程则是将线性地址转换为物理地址。段转换示意图如下 X86支持两种段,gdt和ldt(全局描述段表和局部描述符段表),在linux中只使用了4个全局描述符表,内核空间和用户空间分别两个gdt,分别对应各自的代码段和数据段。也可以认为在linux中变相地disable了x86的段式转换功能。 页转换示意图如下

在linux中x86 的cr3寄存器(页表基地址寄存器)保存在进程的上下文中,在进程切换时会保存或回复该寄存器的内容,这样每个进程都有自己的转换页表,从而保证了每个进程有自己的虚拟空间。 (二)内核管理的内存相关 从几个概念展开内存管理:node、zone、buddy、slab 1、Node SGI Altix3000系统的两个结点 如上图,NUMA系统的结点通常是由一组CPU(如,SGI Altix 3000是2个Itanium2 CPU)和本地内存组成。由于每个结点都有自己的本地内存,因此全系统的内存在物理上是分布的,每个结点访问本地内存和访问其它结点的远地内存的延迟是不同的,为了优化对NUMA 系统的支持,引进了Node 来将NUMA 物理内存进行划分为不同的Node。而操作系统也必须能感知硬件的拓扑结构,优化系统的访存。

linux内存管理子系统 笔记

4-4 linux内存管理子系统 4-4-1 linux内存管理(参考课件) 物理地址:cpu地址总线上寻址物理内存的地址信号,是地址变换的最终结果 逻辑地址:程序代码经过编译后,出现在汇编程序中的地址(程序设计时使用的地址) 线性地址:又名虚拟地址,32位cpu架构下4G地址空间 CPU要将一个逻辑地址转换为物理地址,需要两步: 1、首先CPU利用段式内存管理单元,将逻辑地址转换成线性地址; 2、再利用页式内存管理单元,把线性地址最终转换为物理地址 相关公式: 逻辑地址=段基地址+段内偏移量(段基地址寄存器+段偏移寄存器)(通用的) 16位CPU:逻辑地址=段基地址+段内偏移量(段基地址寄存器+段偏移寄存器) 线性地址=段寄存器的值×16+逻辑地址的偏移部分 物理地址=线性地址(没有页式管理) 32位CPU:逻辑地址=段基地址+段内偏移量(段基地址寄存器+段偏移寄存器) 线性地址=段寄存器的值+逻辑地址的偏移部分 物理地址<——>线性地址(mapping转换) ARM32位:逻辑地址=段基地址+段内偏移量(段基地址寄存器+段偏移寄存器) 逻辑地址=段内偏移量(段基地址为0) 线性地址=逻辑地址=段内偏移量(32位不用乘以32) 物理地址<——>线性地址(mapping转换) ************************!!以下都是x86模式下!!********************************* 一、段式管理 1.1、16位CPU:(没有页式管理) 1.1.1、段式管理的由来: 16位CPU内部有20位地址总线,可寻址2的20次方即1M的内存空间,但16位CPU 只有16位的寄存器,因此只能访问2的16次方即64K。因此就采用了内存分段的管理模式,在CPU内部加入了段寄存器,这样1M被分成若干个逻辑段,每个逻辑段的要求如下: 1、逻辑段的起始地址(段地址)必须是16的整数倍,即最后4个二进制位须全是0 (因此不必保存)。 2、逻辑段的最大容量为64K。 1.1.2、物理地址的形成方式: 段地址:将段寄存器中的数值左移4位补4个0(乘以16),得到实际的段地址。 段偏移:在段偏移寄存器中。 1)逻辑地址=段基地址+段内偏移量(段基地址寄存器+段偏移寄存器) 2)由逻辑地址得到物理地址的公式为:(因为没有页式管理,所以这一步就得到了物理地址)物理地址PA=段寄存器的值×16+逻辑地址的偏移部分(注意!!)(段与段可能会重叠)

《深入理解LINUX内存管理》学习笔记.

引子 为什么要写这个笔记: 1,这本书的中文版翻译了太垃圾,没法阅读。阅读英文原版,可以很好的理解作者的思路。作此笔记备忘 2,一直以来学习LINUX kernel的知识缺乏系统化,借对这本书的学习,系统化的学习一下LINUX kernel。 3,自己一直在做一个too small,too simple的单进程,特权模式,64bit保护模式的称不上OS的OS,已经做完了bootloader, 构思kernel的实现的时候,困惑在内存管理的实现上,阅读这本书,希望能有利于自己的OS的编写。 4,克服惰性,多读书,希望一天能阅读5页,争取半年内阅读完这本原版700多页的巨著。 不足: 我不可能完全理解LINUX 内存管理的精髓,肯定有很多地方理解错误。希望大家能够指正,以便提高,谢谢。 学习方法: 可能您第一次阅读的时候很多地方都不理解,不用担心。那您可能需要阅读一些文件系统的知识。 或者阅读全部笔记后,再回头阅读,有些地方您就理解了。 言归正传: 一、概要 可用工具 CodeViz: 生成代码调用关系图的工具,这个工具我现在还没有去使用,有兴趣的可以自己试试去建立调用关系图。 http://www.csn.ul.ie/~mel/projects/codeviz/ Linux cross reference (LXR): 以web的方式阅读和查找LINUX内核源代码的工具。这个工具安装相当麻烦,我建议直接到它的官方网站直接读代码。 http://lxr.linux.no/linux+v2.6.24/ 模块 LINUX内存管理代码模块主要分为4个部分: 1.Out of memory 代码在mm/oom_kill.c 貌似用于杀进程的时候对内存的操作 2.虚拟内存的分配代码在mm/vmalloc.c

Linux内存管理实验

1 《unix 操作系统教程》课程实验报告 实验名称 Linux 内存管理实验 实验序号 5 姓 名 系院专业 班 级 学 号 实验日期 2012.11.28 指导教师 成 绩 一、实验目的 1. 通过在Linux 环境下对内存管理的基本操作,感性认识Linux 如何对内存进行管理。 2. 利用readelf 和objdump 观测 linux 下的内存地址映射过程以及进程的虚拟地址空间。 二、实验内容与要求 (1)按照实验内容完成实验操作步骤,学习内存管理中的一些常用命令 (2)理解linux 中逻辑地址、线性地址的概念。 (3)提交实验报告。 三、实验设备 地点: 实验实训中心A4-2 设备:计算机一台 linux 操作系统

2 四、实验步骤与测试 实验一 free 命令显示显示内存的使用情况(使用的和空闲的),包括物理内存、交换区内存、内核缓冲区内存。不包括共享内存。free 命令默认选项为-k 语法: free [-bkmotV] [-s <间隔秒数>]选项介绍: -b: 以Byte 为单位显示内存使用情况; -k: 以KB 为单位显示内存使用情况; -m: 以MB 为单位显示内存使用情况; -o: 不显示缓冲区调节列; -s<间隔秒数>: 每间隔指定时间执行一次free 命令; -t: 显示内存总和列; -V: 显示版本信息; (1)free -k: 以KB 为单位显示内存使用情况; 解释:total: 内存总量: 3355508(k) used: 已经使用的内存量: 490664(k) free: 空闲的内存量: 2864844(k) shared: 当前已经废弃不用,总量是0(k) buffers: 25164(k) Buffer Cache 内存量: 263480(k) cached: Page Cache 内存量: 21436(k) (2)free –m -s 5:以M 为单位,5秒显示以下内存信息 解释:以上为每隔5秒显示内存信息,由以上图可知:两次内存使用情况没有变化。 (3)free -o: 不显示缓冲区调节列; 解释:由以上可知Buffer Cache 这一列没有显示出来。 (4)free -t: 显示内存总和列;

Linux操作系统内存管理

Linux操作系统内存管理 摘要: Linux支持虚拟内存, 就是使用磁盘作为RAM的扩展,使可用内存相应地有效扩大。核心把当前不用的内存块存到硬盘,腾出内存给其他目的。当原来的内容又要使用时,再读回内存。这对用户全透明:运行于Linux的程序只看到大量的可用内存而不甘心哪部分在磁盘上。当然,读写硬盘比真的内存慢(慢千倍),所以程序运行较慢。用做虚拟内存的这部分硬盘叫对换空间。 Linux可以使用文件系统中的普通文件或单独的分区作为对换空间。对换分区更快,但对换文件更易于改变大小(无须对硬盘重分区)。如果知道要多少对换空间,应该用对换分区;如果不能确认,可以先用对换文件,用一段时间后再根据所需空间建立对换分区。 Linux允许同时使用多个对换分区和/或对换文件。即如果偶尔需要更多的对换空间,可以随时建立一个额外的对换文件。 Linux是一个遵循POSIX(Portable Operating System Interface)标准的操作系统,它继承了UNIX系统优秀的设计思想,拥有简练、容错强、高效而且稳定的内核。此外Linux还具备其他操作系统所不能比拟的优点。①:完全免费; ②:内核源代码完全公开。 Linux内核拥有一个功能完备的内存管理子系统,它增加了对NUMA(非均匀存储结构)体系结构的支持并且使用了基于区(ZONE)的物理内存管理方法,从而保持了物理上连续分布、而逻辑上统一的内存模式和传统的共享内存编程模型,使得系统的性能得以极大的扩展。这样Linux不仅能够满足传统的桌面应用,而且还能满足高端服务器市场的需要。目前,Linux不仅在Internet服务器上表现出色,而且还可以胜任大型数据库系统的服务器。 关键字:虚拟内存,物理内存管理,虚拟内存管理 一、Linux存储管理的基本框架 Linux内核采用虚拟页式存储管理,采用三次映射机制实现从线性地址到物理地址的映射。其中PGD为页面目录,PMD为中间目录,PT为页面表。具体的映射过程为: ⑴从CR3寄存器中找到PGD基地址; ⑵以线性地址的最高位段为下标,在PGD中找到指向PMD的指针;

LINUX系统基本的内存管理知识讲解

内存是Linux内核所管理的最重要的资源之一。内存管理系统是操作系统中最为重要的部分,因为系统的物理内存总是少于系统所需要的内存数量。虚拟内存就是为了克服这个矛盾而采用的策略。系统的虚拟内存通过在各个进程之间共享内存而使系统看起来有多于实际内存的内存容量。Linux支持虚拟内存, 就是使用磁盘作为RAM的扩展,使可用内存相应地有效扩大。核心把当前不用的内存块存到硬盘,腾出内存给其他目的。当原来的内容又要使用时,再读回内存。 一、内存使用情况监测 (1)实时监控内存使用情况 在命令行使用Free命令可以监控内存使用情况 代码如下: #free total used free shared buffers cached Mem: 256024 192284 63740 0 10676 101004 -/+ buffers/cache: 80604 175420 Swap: 522072 0 522072 上面给出了一个256兆的RAM和512兆交换空间的系统情况。第三行输出(Mem:)显示物理内存。total列不显示核心使用的物理内存(通常大约1MB)。used列显示被使用的内存总额(第二行不计缓冲)。 free列显示全部没使用的内存。Shared列显示多个进程共享的内存总额。Buffers列显示磁盘缓存的当前大小。第五行(Swap:)对对换空间,显示的信息类似上面。如果这行为全0,那么没使用对换空间。在缺省的状态下,free命令以千字节(也就是1024字节为单位)来显示内存使用情况。可以使用—h参数以字节为单位显示内存使用情况,或者可以使用—m参数以兆字节为单位显示内存使用情况。还可以通过—s 参数使用命令来不间断地监视内存使用情况: #free –b –s2 这个命令将会在终端窗口中连续不断地报告内存的使用情况,每2秒钟更新一次。 (2)组合watch與 free命令用来实时监控内存使用情况: 代码如下: #watch -n 2 -d free

linux内存管理实验报告

操作系统实验报告 院别:XXXXXX 班级:XXXXXX 学号:XXXXXX 姓名:稻草人

实验题目:内存管理实验 一、实验目的 1、通过本次试验体会操作系统中内存的分配模式; 2、掌握内存分配的方法(FF,BF,WF); 3、学会进程的建立,当一个进程被终止时内存是如何处理被 释放块,并当内存不满足进程申请时是如何使用内存紧 凑; 4、掌握内存回收过程及实现方法; 5、学会进行内存的申请释放和管理; 二、实验内容 附源代码: /*宏定义*/ #include #include #include #define PROCESS_NAME_LEN 32 /*进程名称的最大长度*/ #define MIN_SLICE 10 /*最小碎片的大小*/ #define DEFAULT_MEM_SIZE 1024 /*默认内存的大小*/ #define DEFAULT_MEM_START 0 /*默认内存的起始位置*/ /* 内存分配算法 */ #define MA_FF 1 #define MA_BF 2 #define MA_WF 3 int mem_size=DEFAULT_MEM_SIZE; /*内存大小*/ int ma_algorithm = MA_FF; /*当前分配算法*/ int flag = 0; /*设置内存大小标志*/ static int pid = 0; /*初始pid*/ int algorithm;

/*描述每一个空闲块的数据结构*/ struct free_block_type{ int size; int start_addr; struct free_block_type *next; }; /*指向内存中空闲块链表的首指针*/ struct free_block_type *free_block; /*每个进程分配到的内存块的描述*/ struct allocated_block{ int pid; int size; int start_addr; char process_name[PROCESS_NAME_LEN]; struct allocated_block *next; }; /*进程分配内存块链表的首指针*/ struct allocated_block *allocated_block_head = NULL; struct allocated_block *find_process(int id) { struct allocated_block *p; p=allocated_block_head; while(p!=NULL) { if (p->pid==id) return p; } return NULL; } void swap(int *p,int *q) { int temp; temp = *p; *p = *q; *q = temp; return;

Linux 内存管理导读

Linux 内存管理导读 1. 存储层次结构和x86存储管理硬件(MMU) 1.1存储层次 高速缓存(cache) à主存(main memory) à磁盘(disk) 理解存储层次结构的根源:CPU速度和存储器速度的差距。 层次结构可行的原因:局部性原理。 LINUX的任务: l减小footprint,提高cache命中率,充分利用局部性。 l实现虚拟存储以满足进程的需求,有效地管理内存分配,力求最合理地利用有限的资源。 1.2 MMU的作用 辅助操作系统进行内存管理,提供虚实地址转换等硬件支持。 1.3 x86的地址 逻辑地址:出现在机器指令中,用来制定操作数的地址。段:偏移 线性地址:逻辑地址经过分段单元处理后(如将段地址左移四位与偏移量)得到线性地址,这是一个32位的无符号整数,可用于定位4G个存储单元。 物理地址:线性地址经过页表查找后得出物理地址,这个地址将被送到地址总线上指示所要访问的物理内存单元。 LINUX: 尽量避免使用段功能以提高可移植性。如通过使用基址为0的段, 使逻辑地址==线性地址。 1.4 x86的段与Linux下的段比较 x86保护模式下的段:表索引+描述符项。不仅仅是一个基地址的原因是为了提供更多的信息:保护、长度限制、类型等。描述符项存放在一张表中(GDT或LDT),表索引就是表的索引。段寄存器中存放的是表索引,在段寄存器装入的同时,描述符中的数据被装入一个不可见的寄存器以便cpu快速访问。 专用寄存器:GDTR(包含全局描述附表的首地址), LDTR(当前进程的段描述附表首地址), TSR(指向当前进程的任务状态段) LINUX使用的四种段: __KERNEL_CS:内核代码段。范围0-4G。可读、执行。DPL=0。 __KERNEL_DS:内核代码段。范围0-4G。可读、写。DPL=0。 __USER_CS:内核代码段。范围0-4G。可读、执行。DPL=3。 __USER_DS:内核代码段。范围0-4G。可读、写。DPL=3。 TSS(任务状态段):存储进程的硬件上下文,进程切换时使用。(因为x86硬件对TSS有一定支持,所有有这个特殊的段和相应的专用寄存器。) __USER_CS和__USER_DS段都是被所有在用户态下的进程共享的。但这种段的共享和进程空间的共享是有区别的:虽然各个进程使用同一个(种)段,但通过使

Linux内存管理初始化

Linux内存管理初始化 内存管理子系统是linux内核最核心最重要的一部分,内核的其他部分都需要在内存管理子系统的基础上运行。而对其初始化是了解整个内存管理子系统的基础。对相关数据结构的初始化是从全局启动例程start_kernel开始的。本文详细描述了从bootloader跳转到linux 内核内存管理子系统初始化期间所做的操作,从而来加深对内存管理子系统知识的理解和掌握。 内核的入口是stext,这是在arch/arm/kernel/vmlinux.lds.S中指定的。而符号stext是在arch/arm/kernel/head.S中定义的。整个初始化分为两个阶段,首先是在head.S中用汇编代码执行一些平台相关的初始化,完成后跳转到start_kernel函数用C语言代码执行剩余的通用初始化部分。整个初始化流程图如下图所示: 一、启动条件 通常从系统上电到运行到linux kenel这部分的任务是由bootloader来完成。Boot loader在跳转到kernel之前要完成一些限制条件: 1、CPU必须处于SVC(supervisor)模式,并且IRQ和FIQ中断必须是禁止的;

2、MMU(内存管理单元)必须是关闭的, 此时虚拟地址对应物理地址; 3、数据cache(Data cache)必须是关闭的; 4、指令cache(Instructioncache)没有强制要求; 5、CPU通用寄存器0(r0)必须是0; 6、CPU通用寄存器1(r1)必须是ARM Linuxmachine type; 7、CPU通用寄存器2(r2)必须是kernelparameter list的物理地址; 二、汇编代码初始化部分 汇编代码部分主要完成的工作如下所示,下文只是概述head.S中各个函数完成的主要 功能,具体的技术细节,本文不再赘述。 ? 确定processortype ? 确定machinetype ? 创建页表 ? 调用平台特定的__cpu_flush函数 ? 开启mmu ? 切换数据 ? 最终跳转到start_kernel 三、C语言代码初始化部分 C语言代码初始化部分主要负责建立结点和内存域的数据结构、初始化页表、初始化用 于内存管理的伙伴系统。在启动过程中,尽管内存管理模块尚未初始化完成,但内核仍然需要分配内存以创建各种数据结构。bootmem分配器用于在启动阶段分配内存。所有涉及的实现都是在start_kernel函数中实现的,其中涉及到内存初始化的函数如下: 1、build_all_zonelist用于结点和内存域的初始化。

Linux操作系统内存管理

Linux 操 作 系 统 内 存 管 理 学院:信息工程 姓名:张卫莉 班级:信管二班 学号:100301238

摘要: Linux支持虚拟内存, 就是使用磁盘作为RAM的扩展,使可用内存相应地有效扩大。核心把当前不用的内存块存到硬盘,腾出内存给其他目的。当原来的内容又要使用时,再读回内存。这对用户全透明:运行于Linux的程序只看到大量的可用内存而不甘心哪部分在磁盘上。当然,读写硬盘比真的内存慢(慢千倍),所以程序运行较慢。用做虚拟内存的这部分硬盘叫对换空间。 Linux可以使用文件系统中的普通文件或单独的分区作为对换空间。对换分区更快,但对换文件更易于改变大小(无须对硬盘重分区)。如果知道要多少对换空间,应该用对换分区;如果不能确认,可以先用对换文件,用一段时间后再根据所需空间建立对换分区。 Linux允许同时使用多个对换分区和/或对换文件。即如果偶尔需要更多的对换空间,可以随时建立一个额外的对换文件。 Linux是一个遵循POSIX(Portable Operating System Interface)标准的操作系统,它继承了UNIX系统优秀的设计思想,拥有简练、容错强、高效而且稳定的内核。此外Linux还具备其他操作系统所不能比拟的优点。①:完全免费;②:内核源代码完全公开。 Linux内核拥有一个功能完备的内存管理子系统,它增加了对NUMA(非均匀存储结构)体系结构的支持并且使用了基于区(ZONE) 的物理内存管理方法,从而保持了物理上连续分布、而逻辑上统一的内存模式和传统的共享内存编程模型,使得系统的性能得以极大的扩展。这样Linux不仅能够满足传统的桌面应用,而且还能满足高端服务器市场的需要。目前,Linux不仅在Internet服务器上表现出色,而且还可以胜任大型数据库系统的服务器。

Linux内存管理

Linux内存管理:页表、页式内存管理机制 一. CPU的页式内存管理(硬件) CPU的页式内存管理单元,负责把一个线性地址,最终翻译为一个物理地址。从管理和效率的角度出发,线性地址被分为以固定长度为单位的组,称为页(page),例如一个32位的机器,线性地址最大可为4G,可以用4KB为一个页来划分,这页,整个线性地址就被划分为一个tatol_page[2^20]的大数组,共有2的20个次方个页。这个大数组我们称之为页目录。目录中的每一个目录项,就是一个地址——对应的页的地址。(虚拟内存地址) 另一类“页”,我们称之为物理页,或者是页框、页桢的。是分页单元把所有的物理内存也划分为固定长度的管理单位,它的长度一般与内存页是一一对应的。(物理内存管理) 这里注意到,这个total_page数组有2^20个成员,每个成员是一个地址(32位机,一个地址也就是4字节),那么要单单要表示这么一个数组,就要占去4MB的内存空间。为了节省空间,引入了一个二级管理模式的机器来组织分页单元。文字描述太累,看图直观一些: 如上图, 1、分页单元中,页目录是唯一的,它的地址放在CPU的cr3寄存器中,是进行地址转换的开始点。万里长征就从此长始了。 2、每一个活动的进程,因为都有其独立的对应的虚似内存(页目录也是唯一的),那么它也对应了一个独立的页目录地址。——运行一个进程,需要将它的页目录地址放到cr3寄存器中,将别个的保存下来。 3、每一个32位的线性地址被划分为三部份,面目录索引(10位):页表索引(10位):偏移(12位) 依据以下步骤进行转换: 1、从cr3中取出进程的页目录地址(操作系统负责在调度进程的时候,把这个地址装入对应寄存器); 2、根据线性地址前十位,在数组中,找到对应的索引项,因为引入了二级管理模式,页目录中的项,不再是页的地址,而是一个页表的地址。(又引入了一个数组),页的地址被放到页表中去了。 3、根据线性地址的中间十位,在页表(也是数组)中找到页的起始地址; 4、将页的起始地址与线性地址中最后12位相加,得到最终我们想要的葫芦; 这个转换过程,应该说还是非常简单地。全部由硬件完成,虽然多了一道手续,但是节约了大量的内存,还是值得的。那么再简单地验证一下: 1、这样的二级模式是否仍能够表示4G的地址; 页目录共有:2^10项,也就是说有这么多个页表

Linux物理内存管理概述

在内核态申请内存比在用户态申请内存要更为直接,它没有采用用户态那种延迟分配内存技术。内核认为一旦有内核函数申请内存,那么就必须立刻满足该申请内存的请求,并且这个请求一定是正确合理的。相反,对于用户态申请内存的请求,内核总是尽量延后分配物理内存,用户进程总是先获得一个虚拟内存区的使用权,最终通过缺页异常获得一块真正的物理内存。 1.物理内存的内核映射 IA32架构中内核虚拟地址空间只有1GB大小(从3GB到4GB),因此可以直接将1GB大小的物理内存(即常规内存)映射到内核地址空间,但超出1GB大小的 物理内存(即高端内存)就不能映射到内核空间。为此,内核采取了下面的方法使得内核可以使用所有的物理内存。 1.高端内存不能全部映射到内核空间,也就是说这些物理内存没有对应的线性地址。不过,内核为每个物理页框都分配了对应的页框描述符,所有的页框描述符都保存在mem_map数组中,因此每个页框描述符的线性地址都是固定存在的。内核此时可以使用alloc_pages()和alloc_page()来分配高端内存,因为这些函数返回页框描述符的线性地址。 2.内核地址空间的后128MB专门用于映射高端内存,否则,没有线性地址的高端内存不能被内核所访问。这些高端内存的内核映射显然是暂时映射的,否则也只能映射128MB的高端内存。当内核需要访问高端内存时就临时在这个区域进行地址映射,使用完毕之后再用来进行其他高端内存的映射。 由于要进行高端内存的内核映射,因此直接能够映射的物理内存大小只有 896MB,该值保存在high_memory中。内核地址空间的线性地址区间如下图所示:

从图中可以看出,内核采用了三种机制将高端内存映射到内核空间:永久内核映射,固定映射和vmalloc机制。 2.物理内存管理机制 基于物理内存在内核空间中的映射原理,物理内存的管理方式也有所不同。内核中物理内存的管理机制主要有伙伴算法,slab高速缓存和vmalloc机制。其中伙伴算法和slab高速缓存都在物理内存映射区分配物理内存,而vmalloc机制则在高端内存映射区分配物理内存。 伙伴算法 伙伴算法负责大块连续物理内存的分配和释放,以页框为基本单位。该机制可以避免外部碎片。 per-CPU页框高速缓存 内核经常请求和释放单个页框,该缓存包含预先分配的页框,用于满足本地CPU 发出的单一页框请求。 slab缓存 slab缓存负责小块物理内存的分配,并且它也作为高速缓存,主要针对内核中经常分配并释放的对象。 vmalloc机制

Linux内存管理中的Slab分配机制

现 代计算机!总第二三五期" MODERNCOMPUTER2006.5 实践与经验 1Linux内存管理体系 在Intel80x86体系结构中,Linux内核的内存管 理采用了分页管理方式,真正实现了虚拟存储器管理,其虚拟内存管理的实现结构如图1所示。 图1 内存映射模块负责把磁盘文件的逻辑地址映射到虚拟地址,把虚拟地址映射到物理地址;交换模块负责控制内存内容的换入和换出;核心管理模块负责核心内存管理功能,即对页的分配、 回收、释放及请页处理等;结构特定的模块负责给各种硬件提供通用接口,这个模块通过执行命令来改变硬件MMU的虚拟地址映射。 Linux虚拟内存的实现机制为:内存管理程序通过映射机制把用户程序的逻辑地址映射到物理地址,在用户程序运行时如果发现程序中要用到的虚地址没有对应的物理内存时,就发出了请页要求;如果有空闲的内存可供分配,就请求分配内存,并把正在使 用的物理页纪录在页缓存中。如果没有足够的内存可供分配,那么就调用交换机制,腾出一部分内存。另外,在地址映射中要通过TLB来寻找物理页,交换机制中也要用到交换缓存,并且把物理页内容交换到交换文件后也要修改页表来映射文件地址。 2Slab分配机制概述 Slab分配机制用来对内存区域中内核空间进行 分配和回收。Slab使用对象来组织内存区域,对象就是指存放一组数据结构的内存区。Slab根据内存区的使用频率对内存区域进行划分。对于预期频繁使用的内存区,Slab创建一组特定大小的专用缓冲区进行处理,以避免内碎片的产生;对于较少使用的内存区, Slab创建一组通用缓冲区来处理,即使这种处理模式产生碎片,对整个系统的性能影响也不大。 Slab分配模式把对象分组放进缓冲区,Slab缓冲区并非由各个对象直接构成,而是由一连串的Slab构成,而每个大块中则包括了若干个同种类型的对象。 高速缓存、Slab及对象之间的关系如图2所示。 图2 Linux内存管理中的Slab分配机制 赵鲲鹏1 , 苏葆光2 (1.长安大学,西安710061;2.浙江万里学院,宁波315101) 摘 要:早期Linux的内存分配机制采用伙伴算法,当请求分配的内存大小为几十个字节或几百个 字节时会产生内存碎片,严重消耗系统资源。现今采用Slab机制可以缓存物理空间的申请和回收,杜绝外部碎片的产生,降低内部碎片量。本文分析了Slab内存分配机制及其数据结构和接口函数,然后给出了Slab机制的实现。 关键词:Slab;内存管理;Linux;分配机制 ! "

相关主题
相关文档
最新文档