内存管理基础

  • 格式:doc
  • 大小:92.00 KB
  • 文档页数:18

下载文档原格式

  / 18
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

系统对进程的虚拟内存管理:

mm{},vm_area_struct{}

系统对物理内存管理:page{}

每个进程都可用4G的虚拟地址空间 0~4G,

每个进程的页表不同(page table : 内存映射。Memory mapping)

几种内存地址:

物理地址(PA),

虚拟地址:内核空间: 3~4G共1G, 内核虚拟地址(其中包括896M的内核逻辑地址)

又划分为两部分:实际的物理地址直接映射到内核空间,

当实际物理内存>896M时,此时要做

映射,通过建立页表,只有前896M

存在这种映射关系

当实际物理内存<896M时,PA全部

映射到内核空间,此时内核VA –3G=

对应的物理PA,反之亦然。此部分地

址称为内核逻辑地址区域kernel

logical address

用户空间: 0~3G ,页表映射

高端内存: >896M的内存空间

以上4G虚拟地址空间分配见本子Figure-1。重点掌握kernel logical address

见课件

涉及到的内核结构体:

task-struct { mm_struct *mm ;}

mm_struct *mm {pgd_t pgd;}

vm_area_struct * mmap{ } /* emphasis Linux内核中对应进程内存区域的数据结构,一个进程有多个内存区域,所以有多个vma*/

cat /proc//map

内存映射的两层含义:1. 把VA 映射到对应的 PA 上(对VA的操作即对PA的操作)

2. 把一个文件的地址空间(文件打开后有缓存,即文件打开后存在于内存上,占用一定内存空间)映射到进程,让进程可以通过访问内存从而访问文件。

内存映射的基本单位都是VMA,如struct

file_operations{

int (*mmap) (struct file *, struct vm_area_struct *);

}

Linux内存管理中,4G的进程地址空间, 0-3G为用户空间,3-4G为内核空间,内核空间中小于896M的虚拟内存可以通过offset容易的映射到物理内存,大于896M的部分通过页表映射到物理内存,假如只有800M内存,会被内核空间完全映射,那用户空间的虚拟地址映射到物理内存哪里?

是不是内核空间虽然能够完全映射到物理内存,但是因为不会全部使用物理内存,所以当用户空间需要内存映射时,会从物理内存中空闲的部分进行映射?如果是这样,对于物理内存而言,同时存在着内核空间的映射和当前进程的用户空间的映射

Problems:

文件打开后被调入内存,称之为缓存

下载一个新的内核

叶框与页区别

页的状态

page cache, buffer cache

file inode

char tr = malloc(0);

把各个函数都用一下,把每个函数的返回值打印出来,看在哪个空间内。

8.1进程与内存

8.1.1进程如何使用内存(进程的内存映像)

毫无疑问所有进程(执行的程序)都必须占用一定数量的内存,它或是用来存放从磁盘载入的程序代码,或是存放取自用户输入的数据等等。不过进程对这些内存的管理方式因内存用途不一而不尽相同,有些内存是事先静态分配和统一回收的,而有些却是按需要动态分配和回收的。

对任何一个普通进程来讲,它都会涉及到5种不同的数据段。稍有编程知识的朋友都该能想到这几个数据段种包含有“程序代码段”、“程序数据段”、“程序堆栈段”等。不错,这几种数据段都在其中,但除了以上几种数据段之外,进程还另外包含两种数据段。下面我们来简单归纳一下进程对应的内存空间中所包含的5种不同的数据区(由vm_area_struct描述各个段)。

代码段:代码段是用来存放可执行文件的操作指令,也就是说是它是可执行程序在内存种的镜像。代码段需要防止在运行时被非法修改,所以只准许读取操作,而不允许写入(修改)操作——它是只读不可写的。

数据段:数据段用来存放可执行文件中已初始化全局变量,换句话说就是存放程序静态分配的变量和全局变量。可读可写

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

堆(heap):堆是用于存放进程运行中被动态分配的内存段,它大小并不固定,可动态扩张或缩减。当进程调用malloc等函数分配内存时,新分配的内存就被动态添加到堆上(堆被扩张);当利用free等函数释放内存时,被释放的内存从堆中被剔除(堆被缩减)

栈:栈是用户存放程序临时创建的局部变量,也就是说我们函数括弧“{}”中定义的变量(但不包括static声明的变量,static意味这在数据段中存放变量)。除此以外在函数被调用时,其参数也会被压入发起调用的进程栈中,并且待到调用结束后,函数的返回值也回被存放回栈中。由于栈的先进先出特点,所以栈特别方便用来保存/恢复调用现场。从这个意义上将我们可以把堆栈看成一个临时数据寄存、交换的内存区。

堆栈实际是在一个区域,看博客

8.1.2进程内存空间

Linux操作系统采用虚拟内存管理技术,使得每个进程都有各自互不干涉的进程地址空间。(页表)该空间是块大小为4G的线性虚拟空间,用户所看到和接触的都是该虚拟地址(驱动中也是,不能直接操作物理地址),无法看到实际的物理内存地址。利用这种虚拟地址不但能起到保护操作系统的效果(用户不能直接访问物理内存),而且更重要的是用户程序可使用比实际物理内存更大的地址空间(真正需要的放入内存中,不重要的放入缓存或磁盘)(具体的原因请看硬件基础部分)。

虚拟地址连续,物理地址不一定连续。(但由kmalloc()分配的虚拟内存和对应的物理内存是连续的)

在讨论进程空间细节前,请大家这里先要澄清下面几个问题。

●第一、4G的进程地址空间被人为的分为两个部分——用户空间与内核空

间。用户空间从0到3G(0xC0000000),内核空间占据3G到4G。用户进程通常情况下只能访问用户空间的虚拟地址,不能访问内核空间虚拟地址。例外情况只有用户进程进行系统调用(代表用户进程在内核态执行)等时刻可以访问到内核空间。

●第二、用户空间对应进程,所以每当进程切换,用户空间就会跟着变化(私

有的不公享的因为每个进程的页表不同);而内核空间不会跟着变化,是由内核负责映射,它并不会跟着进程改变,是固定的。内核空间地址有自己对应的页表(init_mm.pgd),用户进程各自有不同的页表。内核空间由所有进程共享。