Linux Kernel读书笔记(二)---内存管理

2. Memory Management
(1) Linux内核从线性地址到实际物理地址转换设计为3层映射模型,所以一个线性地址从逻辑上分为四个位段,PGD下标,PMD下标,PT下标,和页内偏移量下标.
(2) 32位机器上,一般2层映射用的较多,所以在实现代码时需将PMD直接映射至自身.
(3) 32位机器上,寻址空间为4G,线性地址管理上一般会将3G-4G(0xC000000~0xFFFFFFFF)用做内核空间,而将其余部分作为用户空间.当然,在内核中这个值是可以通过CONFIG_PAGE_OFFSET配置的.实际上用户空间的大小通常也不会有3G这么大,还需要减去共享库或者专门用于vmalloc的区域,具体大小在内核代码中通过TASK_SIZE确定。
(4) 对于内核来说,其线性地址到物理地址的转换是直接映射的.即知道在内核空间中VA到PA之间的差为PAGE_OFFSET.
(5) 在进程切换时实际上只需将新进程的PGD基地址(注意,这里需要是物理地址)写入到PGD基地址寄存器即可。重要的实现函数switch_mm
(6) 64位机器上,pte_t数组的类型会是long long型。
(7) 由于pte_t都是按页面对齐的,所以低12位(4K)全部是0,这12位用来存储页面状态信息和访问权限。可以通过这12位来确定此虚拟页面是否已经进行了映射,或者映射后是否被交换至交换设备以及其他一些特性。
(8) 对于每个物理页面,内核会为其建立一个page结构体,记录其重要信息,所有的page会组成一个数组。管理这个数组时内核会将其分为三个区域(ZONE_NORMAL,ZONE_DMA,ZONE_HIGHMEM),用数据结构zone_struct表示,每个zone_struct维护着一组空闲空间队列free_area_t,每个队列维护着一个2的幂大小的空闲空间队列。在NUMA(非一致性内存)情况下,对每个单独的内存设备(又称之为一个内存节点),用数组结构pglist_data来表示。
(9) 每个进程的虚拟内存分布是以段为单位的,段内地址连续,但段和段之间是非连续的,之间存在“空洞”。每个段用结构体vm_area_struct表示。虚拟内存页面不一定会在物理内存中,有可能会被交换至交换设备。另外,一个文件可以通过mmap调用映射至进程的用户空间中。每个进程的虚拟内存用结构体mm_struct来表示,每个进程只拥有一个mm_struct,但多个进程实际上是可以共享同一个mm_struct的(例如vfork),每个mm_struct包含着一系列的vma,一个PGD(意味着拥有自己独立的映射),标记着代码段,数据段,堆栈段的起始和结束,是进程的核心数据结构。
(10) 缺页异常(do_page_fault)发生在如下几个情况
a) 相应的页表项为空,即还没有为这该虚拟地址进行到物理地址的映射
b) 相应的物理页面被交换至交换设备
c) 权限访问失败
其中,对c情况,会直接终止进程的运行(段错误)。b情况会进行交换设备和内存设备的页面交换(do_swap_page)。a情况比较复杂,首先第一种情况为find_vma失败,即越界访问,访问了超出用户空间的高地址;第二种情况为在两个vma中间,而且并不是在堆栈区的下方,则也是越界访问,常出现在mmap的区域撤销了以后继续访问;第三种情况在两个vma中间,但是在堆栈区的下方,则在符合的情况下(如此地址在当然堆栈以下32字节内)尝试进行堆栈扩展。第四种情况,find_vma成功,则分配新的物理页面(alloc_pages),创建新的页面项进行映射。
(11) 在实时系统上,由于页面交换时间的不确定性,通常会关闭交换设备
(12) 交换设备用数据结构swap_info_struct表示,数据结构其中的swap_map表示着交换设备中页面的集合数组,swap_map[0]即第一个页面不用于页面交换,其包含着交换设备的信息。
(13) 内核在管理内存页面和交换设备页面时,内存物理页面是用count成员表示,交换设备页面是用swap的offset表示使用情况,为0时即为空闲页面
(14) 内核的页面是常驻在内存的,不可能被交换至交换设备.用户空间页面包括堆栈段,动态分配malloc段,代码段,数据段,mmap映射的文件段,共享内存段都是可以被交换的.
(15) 内存页面的周转有两方面的意思,第一是页面的分配,使用和回收;第二是内存和交换设备的交换。
(16) 内核空间的代码和全局变量常驻在内存中,被认为是静态的内存,但内核也可以动态管理页面,即所谓的“堆”分配空间,分配的函数包括alloc_pages,kmalloc,vmalloc,还有一种专用于小内存分配的slab分配器。
(17) 用户空间的代码和全局变量虽然从进程的角度来看是静态的,但是从系统的角度来看依然是动态的,即都是可以被分配,释放,或交换至交换设备。
(18) 内存和交换设备的交换策略要求是:既要尽可能多的交换出空闲页面来保证内存页面充足,又要避免频繁的换入换出导致抖动现象。
(19) 为了防止抖动的产生,内核将内存页面的换出和释放分为两步去做。当内存页面换出时,并不立即将此内存页面释放,而是将其链入一个inactive list中。如果进程发生缺页异常,则首先去检查页面是否在inactive list中,如果在,则直接恢复映射.
(20) 为了减少实际的交换此数,当一个页面换出时也并不立即将其写入交换设备,首先先判断此页面是否为”clean”的页面,如为clean的页面,则无需写入;若为“dirty”的页面,也只是先从页面映射表断开,经过一段时间后,才将其写入交换设备,变成一个“clean”的页面,此“clean”的页面还会继续缓存一段时间,从而最大程度的减少了抖动和交换设备IO。
(21) 内存和文件的IO发生在两个情况,第一是内存和交换设备的交换,第二是内存作为文件的缓存。
(22) alloc_pages会根据参数GFP_MASK决定分配的策略,这个策略指优先分配的区域。比较典型的如GFP_HIGHMEM,GFP_NORMAL,GFP_DMA。
(23) 分配物理内存时,首先先从各个管理区(zone)的空闲队列上去找。如果空闲区紧张,即物理内存紧张时,如果只需要一个空闲页面,可以从内核管理的inactive clean list里面去回收。另外,会唤醒内核守护线程kswapd,试图回收一些内存页面。
(24) 由于内存碎片的问题,有时候实际内存页面总量是空余的,但是没有连续的内存空间了,此时,就会尝试回收inactive list中的页面(clean页面可以直接回收,dirty页面需要先换出),试图拼凑成一个较大的内存块。
(25) Kswapd每秒至少会执行一次。每次执行首先会检查物理页面是否短缺,如短缺,则开始寻找适当的页面从页面表断开,将其放入inactive list,为页面的换出做准备;然后第二部分是每次都会执行的,将目前的inactive dirty页面写入交换设备,使其变成inactive clean list,以及进一步讲inactive clean list进行回收。
(26) 缺页异常发生时,首先通过pte_present检查物理页面是否在内存中,如不在内存中,则通过pte_none判断表项是否为空,如果不为空,则证明此物理页面在交换设备中,开始进行换入。换入时首先需要判断页面是否在inactive list中,如果在,则无需从交换设备上读页面;如果页面不在内存中,则先分配一个空闲页面,在从交换设备上读入内容。
(27) 为了管理频繁分配和使用的数据结构,内核提供了slab机制。使用kmem_cache_create创建一个专用缓冲区,用kmem_cache_alloc从缓冲区中分配所需的内存。
(28) 如果无需从专用缓冲区分配空间,且所需空间较小,则使用kmalloc函数;如果所需空间接近或超过一个页面大小,则使用alloc_pages进行分配。如果在内核中需要分配一大块连续内存而很难满足时,可以使用vmalloc函数。
(29) slab对象一般会使用高速缓存行(cache line)对齐方式,另外在同一个slab队列上不同slab对象区的起始地址会尽量错开(通过着色区实现),以尽量避免cache的“抖动”。
(30) ioremap函数完成外设物理地址到内核虚拟地址的映射;内核专用的mm结构体为init_mm,映射时会在init_mm的表项中遍历。另外,由于init_mm不关联task_struct,所以永远不会被换出。
(31) brk系统调用的作用为移动进程的堆空间指针。不仅可以扩大堆空间,也可能缩小堆空间,需要注意的是当缩小堆空间时,需要通过do_munmap解除缩小部分的映射。
(32) mmap系统调用的作用为将一个已打开文件的内容映射至进程空间。在内核的实现为do_mmap_pgoff,这个实现不仅可以映射打开的文件,还可以创建共享内存区。当然,实现exec系统调用时也会使用到此函数,将可执行文件映射到内存中去。
(33) 内核实现mmap时同样使用了“lazy computation”的技术,只是寻找到一个vma给进程使用,进程在实际访问到某页面时,如果发现尚未被映射,则发生缺页中断,分配实际物理内存页面并从
对应文件读出相应内容;如对此页面修改后,只是置此页面为“dirty”,并不立即将其回写至文件,而是由内核线程定期将其写入;或等待至页面长时间无人访问,准备被换出时,才会真正写入。当然,也可以使用msync系统调用显示同步数据。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值