linux内存管理浅析

【虚拟内存管理】

每个进程对应一个task结构,它指向一个mm结构,这就是该进程的内存管理器。mm->pdg指向容纳页表的内存,每个进程都有自己的mm,每个mm都有自己的页表。用户程序对内存的操作(分配、回收、映射等)都是对mm的操作,具体来说是对mm上的vma(虚拟内存空间)的操作。这些vma代表这进程的各个区域,比如堆、栈、代码区、数据区、各种映射区等等。用户程序对内存的操作并不会直接影响页表,更不会直接影响物理内存。比如malloc成功,仅仅是改变了某个vma,页表不会变,物理内存的分配也不会变。

假设用户分配了内存,然后访问这块内存。由于页表里面并没有记录相关的映射,CPU产生一次缺页异常,内核捕捉异常,检查产生异常的地址是不是一个合法的vma中。如果不是,则给进程一个段错误,让其崩溃;如果是,则分配屋里也,并为之建立映射。

【物理内存管理】

物理内存是如何分配的呢?

首先,linux支持NUMA,物理内存管理的第一个层次就是介质的管理。pg_data_t结构就描述了介质。一般而言,我们的内存管理介质只有内存,并且它是均匀的,所以可以简单的认为系统中只有pg_data_t对象。每一种介质下有若干zone。一般是三个:DMA、NORMAL和HIG。

DMA:因为有些硬件系统的DMA总线比系统总线窄,所以只有一部分地址空间能够用作DMA,这部分地址被管理在DMA区域

HIGH:高端内存。在32位系统中,地址空间是4G,其中内核规定3-4G的范围内是内核空间,0-3G是用户空间。内核的地址映射是写死的,这是指地址空间3-4G对应的页表是写死的,它映射到了物理地址的0-1G(实际上没有映射1G,只映射了896M.剩下的空间留下来映射大于1G的物理地址,而这部分显然是没有写死的)。所以,大于896M的物理地址是没有写死的页表来对应的,内核不能直接访问它们(必须建立映射),称它们为高端内存。

在zone之上的zone_list代表了分配策略,即内存分配时的zone优先级。一种内存分配往往不是只能在一个zone里进行分配的,比如分配一个页给内核使用时,最优先是从NORMAL里分配的,不行的话就在DMA里面(HIGH就不行,因为还没有建立映射),这就是一种分配策略。

每个内存介质维护一个mem_map,为介质中的每一个物理页面建立了一个page结构,以便管理物理内存。每个zone记录着它在mem_map上的起始位置。并且通过free_area串连这个zone上空闲的page。物理内存的分配就是从这里来的,从free_area上把page摘下,就算分配了。

【建立地址映射】

内核需要物理内存时,很多情况是整页分配的,这在上面的mem_map中摘一个page下来就好。比如前面说到内核捕获缺页异常,然后就需要分配一个page建立映射。说到这里,会有一个疑问,内核在分配page、建立映射的过程中,使用的虚拟地址还是物理地址呢?首先,内核代码所访问的地址都是虚拟地址,因为CPU指令接收的就是虚拟地址。但是,建立地址映射时,内核在页表里填写的内容却是物理地址,因为地址映射的目标就是物理地址。那么内核怎么得到这个物理地址呢?其实,上面也提到了,mem_map中的page就是根据物理内存来建立的,每个page就对应一个物理页。于是我们可以说,虚拟地址的映射是靠这里的page完成的,是他们给出了最终的物理地址。然后page结构显然是通过虚拟地址来管理的。那么page结构实现了别人的虚拟地址映射,谁又来实现page结构自己的虚拟地址映射呢?没有人。这就引出了前面提到的一个问题,内核空间的页表项是写死的。在内核初始化时,内核的地址空间就已经把地址映射写死了。由于内核空间的页表项是写死的,又引出另一个问题,NORMAL区域的内存可能被同时映射到内核空间和用户空间。被映射到内核空间是显然的,因为这个映射已经写死。而这些页面也可能被用户空间映射,在前面提到的缺页夜场的场景中就有这样的可能。但是,NORMAL区域内存被同时映射到内核空间和用户空间并没有问题,因为如果某个页面正在被内核使用,对应的page应该从free_area摘下来,于是缺页异常处理代码不会再将该页映射到用户空间。

【内核空间管理】

除了对内存整页的使用,有些时候内核也需要想用户程序使用malloc一样,分配任意大小的空间,这个功能由slab系统来实现。

slab相当于为内核中常用的一些结构体对象建立了对象池,比如task结构池、mm结构池等等。而slab也维护有通用的对象池,比如‘32字节大小’的对象池、‘64字节大小’的对象池等等。内核常用的kmalloc就是在这些通用的对象池分配的。


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值