欢迎来到乐乐文库,课件爱好者! | 帮助中心 精品ppt课件,ppt课件精品!
乐乐文库,课件爱好者
首页 乐乐文库,课件爱好者 > 资源分类 > PPT文档下载

05 存储管理.ppt

  • 资源大小:828.50KB        全文页数:73页
  • 资源格式: PPT        下载权限:游客/注册会员/VIP会员    下载费用:15金币 【人民币15元】
游客快捷下载 游客一键下载
会员登录下载
下载资源需要15金币 【人民币15元】

邮箱/手机:
温馨提示:

支付成功后,系统会根据您填写的邮箱或者手机号作为您下次登录的用户名和密码(如填写的是手机,那登陆用户名和密码就是手机号),方便下次登录下载和查询订单;
特别说明:
请自助下载,系统不会自动发送文件的哦;
支付方式: 支付宝   
验证码:   换一换

 
友情提示
2、本站资源不支持迅雷下载,请使用浏览器直接下载(不支持QQ浏览器)
3、本站资源下载后的文档和图纸-无水印,预览文档经过压缩,下载后原文更清晰   

05 存储管理.ppt

Linux存储管理,,,Linux虚拟内存的实现,需要几种不同的机制来实现 地址映射机制 内存的分配与回收 请页机制 交换机制 内存共享机制,x86的虚拟存储系统支持,x86具有两种存储器管理模式 实地址模式--实模式 受保护的虚地址模式--保护模式 在保护模式下,x86提供了实现虚拟存储器的硬件机制。 x86的地址转换机制 x86中地址总线为32位,物理内存空间最大为4G字节。 x86指令系统提供的的逻辑地址为48位,由它确定的虚拟地址空间可达64T字节。,虚地址到实地址转换,进程虚存空间,,内核空间(1GB),进程1的用户空间3GB,进程2的用户空间3GB,,进程n的用户空间3GB,,虚拟地址空 间,虚拟内存、内核空间和用户空间,虚拟内存-共4G字节,分为内核空间(最高的1G字节)和用户空间(较低的3G字节)两部分,每个进程最大拥有3G字节私有虚存空间 地址转换-通过页表把虚存空间的一个地址转换为物理空间中的实际地址。,虚拟内存、内核空间和用户空间,内核空间到物理内存的映射,内核空间由所有进程共享,其中存放的是内核代码和数据,即内核映象 进程的用户空间中存放的是用户程序的代码和数据 内核空间映射到物理内存总是从最低地址(0x00000000)开始,使之在内核空间与物理内存之间建立简单的线性映射关系。,Linux虚拟内存的实现需要多种机制的支持 地址映射机制 请页机制 内存分配和回收机制 交换机制 缓存和刷新机制,虚拟内存实现机制,,地址映射,虚拟内存实现机制及之间的关系,虚拟内存实现机制及之间的关系,每个进程经编译、链接后形成的二进制映像文件有一个代码段和数据段 进程运行时须有独占的堆栈空间,,,,,,堆栈段,空洞,数据段,代码段,进程的用户空间(3G),进程用户空间的管理,Linux把进程的用户空间划分为一个个区间,便于管理 一个进程的用户地址空间主要由mm_struct结构和vm_area_structs结构来描述。 mm_struct结构它对进程整个用户空间进行描述 vm_area_structs结构对用户空间中各个区间简称虚存区进行描述 mm_struct结构首地址在task_struct成员项mm中 struct mm_struct *mm;,进程用户空间,mm_struct结构,mm_struct结构定义在/include/linux/sched.h中。 struct mm_struct { struct vm_area_struct * mmap;/* list of VMAs */ rb_root_t mm_rb;//Pointer to the root of the red-black tree struct vm_area_struct * mmap_cache;/* last find_vma result */ pgd_t * pgd; //进程页目录指针 atomic_t mm_users;/* How many users with user space */ atomic_t mm_count; /* How many references to struct mm_struct users count as 1 */ int map_count;/* number of VMAs */ struct rw_semaphore mmap_sem; spinlock_t page_table_lock;/* Protects task page tables and mm-rss */ struct list_head mmlist;/* List of all active mms. These are globally strung *together off init_mm.mmlist, and are protected by mmlist_lock */ unsigned long start_code, end_code, start_data, end_data; unsigned long start_brk, brk, start_stack; unsigned long arg_start, arg_end, env_start, env_end; unsigned long rss, total_vm, locked_vm;//驻留内存页框总数,VMA总数及被锁VMA总数 unsigned long def_flags; unsigned long cpu_vm_mask; unsigned long swap_address; unsigned dumpable1; /* Architecture-specific MM context */ mm_context_t context; };,VM_AREA_STRUCT 结构,vm_area_struct结构是虚存空间中一个连续的区域,在这个区域中的信息具有相同的操作和访问特性。 各区间互不重叠,按线性地址的高低次序链接在一起。当区间的数目较多时,将建立AVL树以保证搜索速度。 vm_area_struct结构定义在include/linux/mm.h中,vm_area_struct,struct vm_area_struct { struct mm_struct * vm_mm;/* The address space we belong to. */ unsigned long vm_start;/* Our start address within vm_mm. */ unsigned long vm_end;/* The first byte after our end address within vm_mm. */ /* linked list of VM areas per task, sorted by address */ struct vm_area_struct *vm_next; pgprot_t vm_page_prot;/* Access permissions of this VMA. */ unsigned long vm_flags;/* Flags, listed below. */ struct rb_node vm_rb; /** For areas with an address space and backing store,one of the address_space-i_mmap{,shared} lists, for shm areas, the list of attaches, otherwise unused. */ struct list_head shared; /* Function pointers to deal with this struct. */ struct vm_operations_struct * vm_ops; /* Information about our backing store */ unsigned long vm_pgoff; /* Offset within vm_file in PAGE_SIZE units, *not* PAGE_CACHE_SIZE */ struct file * vm_file;/* File we map to can be NULL. */ void * vm_private_data;/* was vm_pte shared mem */ };,VMA,vm_mm指针指向进程的mm_struct结构体。 vm_start和vm_end 虚拟区域的开始和终止地址。 vm_flags指出了虚存区域的操作特性 VM_READ 虚存区域允许读取 VM_WRITE 虚存区域允许写入 VM_EXEC 虚存区域允许执行 VM_SHARED 虚存区域允许多个进程共享 VM_GROWSDOWN 虚存区域可以向下延伸 VM_GROWSUP 虚存区域可以向上延伸 VM_SHM 虚存区域是共享存储器的一部分 VM_LOCKED 虚存区域可以加锁 VM_STACK_FLAGS 虚存区域做为堆栈使用 vm_page_prot 虚存区域的页面的保护特性。,VMA,所有vm_area_struct结构体按地址递增链接成一个单向链表,vm_next指向下一个vm_area_struct结构体。链表的首地址由mm_struct中成员项mmap指出。 vm_ops是指向vm_operations_struct结构体的指针。该结构体中包含着指向各种操作的函数的指针。 vm_next_share和vm_prev_share,把有关的vm_area_struct 结合成一个共享内存时使用的双向链表。,红黑树,所有vm_area_struct结构体组成一个红黑树(AVL树)。 AVL树是一种具有平衡结构的二叉树。 include/linux/rbtree.h struct rb_node { struct rb_node *rb_parent; int rb_color; defineRB_RED0 defineRB_BLACK1 struct rb_node *rb_right; struct rb_node *rb_left; }; struct rb_root { struct rb_node *rb_node; };,红黑树,Every node must be either red or black. The root of the tree must be black. The children of a red node must be black. Every path from a node to a descendant leaf must contain the same number of black nodes . When counting the number of black nodes, null pointers are counted as black nodes。,,虚存段的建立,Linux使用do_mmap函数完成可执行映像向虚存段的映射,由它建立有关的虚存段。 do_mmap函数定义在include/linux/mm.h文件中 unsigned long do_mmapstruct file * file, unsigned long addr, unsigned long len,unsigned long prot, unsigned long flags, unsigned long off,虚存段的建立,addr虚存段在虚拟内存空间的开始地址。 len是这个虚存段的长度。 file是指向该文件结构体的指针,若file为NULL,称为匿名映射anonymous mapping。 off是相对于文件起始位置的偏移量。 prot指定了虚存段的访问特性 PROT_READ 0x1 对虚存段允许读取 PROT_WEITE 0x2 对虚存段允许写入 PROT_EXEC 0x4 虚存段(代码)允许执行 PROT_NONE 0x0 不允许访问该虚存段 flag指定了虚存段的属性 MAP_FIXED 指定虚存段固定在addr的位置上。 MAP_SHARED 指定对虚存段的操作是作用在共享页面上 MAP_PRIVATE指定了对虚存段的写入操作将引起页面拷贝。,fork系统调用在创建新进程时也为该进程创建完整的用户空间 具体而言,是通过拷贝或共享父进程的用户空间来实现的,即内核调用copy_mm 函数,为新进程建立所有页表和mm_struct结构 Linux利用“写时复制”技术来快速创建进程,创建进程用户空间,执行一个进程时,其可执行映像必须装入进程的用户地址空间 虚存文件映射即把文件从磁盘映射到进程的用户空间,对文件的访问转化为对虚存区的访问 有共享的、私有的虚存映射和匿名映射 当可执行映像映射到进程的用户空间时,将产生一组 vm_area_struct 结构来描述各虚拟区间的起始点和终止点,虚存映射,例exam.c int main { printf“virtual area test”; },,,exam进程的虚存区,进程的虚存区举例,Linux的分页存储管理机制,一、Linux的页表机制 Linux总是假定处理器支持三级页表结构。Linux在64位体系结构上采用三级页表机制。对于以i386体系结构的32位机器,则采用二级也表机制,页中间目录层实际不起作用。 三级分页管理把虚拟地址分成四个位段 页目录、页中间目录、页表、页内偏移。 系统设置三级页表系列 页目录PGD(Page Directory) 页中间目录PMD(Page Middle Directory) 页表PTE(Page Table),Linux三级页表结构,三级分页结构是Linux提供的与硬件无关的分页管理方式。 当Linux运行在某种机器上时,需要利用该种机器硬件的存储管理机制来实现分页存储。 Linux内核中对不同的机器配备了不同的分页结构的转换方法。 对i386,提供了把三级分页管理转换成两级分页机制的方法。 其中一个重要的方面就是把PGD与PMD合二为一,使所有关于PMD的操作变为对PGD的操作。,二、地址映射,,以i386体系结构为例。i386系列既支持分段机制,也支持分页机制,Linux主要采用了分页机制, 页面可以映射到任一物理页帧。i386下进程的线性地址为32位,分为以下三个部分 页目录p1置于高10位,记录在页目录中的索引。 页表p2占据中间的10位,记录在页表中的索引。 偏移d占据低12位,用来表示在4KB的页帧中的偏移。,页目录项和页表项,页表或页帧的物理地址,第31位至第12位,D,31,6,5,12,A,,,U/S,R/W,P,2,1,0,P1 当前物理页存在;P0则当前物理页不再内存,R/W1则该页可写,可读,且可执行;R/W0则该页可读,可执行,但不可写,U/S1则该页可在任何特权级下访问; U/S0则该页只能在特权级0、1和2下访问,A访问位,D已写标志位,MMU地址映射过程,每个进程都有一个页目录,当进程运行时,寄存器CR3指向该页目录的基址。 1从CR3取得页目录的基地址。页目录用一个物理页帧存储,用来保存页表的基址。 2以逻辑地址的页目录段为索引,在页目录中找到页表的基址。页表也是用一个物理页帧存储, 用来保存物理页帧号。 3以逻辑地址的页表段为索引, 在页表中找相应的物理页帧号。 4物理页帧号加上逻辑地址的偏移段即得到了对应的物理地址。,页面异常的处理,导致页面异常的原因有 1编程错误。可分为内核程序错误和用户 程序错误。 2操作系统故意引发的异常。操作系统合理利用硬件机制,在适当时间触发异常, 使得该异常的处理程序被调用,以达到预期目的。,,,,,否,是,是,是,否,否,缺页异常处理程序,,否,否,否,否,否,否,否,否,否,是,是,是,是,是,是,是,是,是,缺页异常处理流程图,,页面异常的处理程序是do_page_fault 函数,该函数有两个参数 一个是指针,指向异常发生时寄存器值存放的地址。 另一个错误码,由三位二进制信息组成 第0位访问的物理页帧是否存在; 第1位写错误还是读错误或执行错误; 第2位程序运行在核心态还是用户态。,do_page_fault ,do_page_fault函数的执行过程如下 首先得到导致异常发生的线性地址,对于X86该地址放在CR2寄存器中。 检查异常是否发生在中断或内核线程中,如是,则进行出错处理。 检查该线性地址属于进程的某个vm_area_ struct区间。如果不属于任何一个区间,则需要进一步检查该地址是否属于栈的合理可扩展区间。一但是用户态产生异常的线性地址正好位于栈区间的vm_start前面的合理位置,则调用expand_stack 函数扩展该区间,通常是扩充一个页面,但此时还未分配物理页帧。 至此,线性地址必属于某个区间。,do_page_fault ,根据错误码的值确定下一个步骤 如果错误码的值表示为写错误,则检查该区间是否允许写,不允许则进行出错处理。如果允许就是属于前面提到的写时拷贝COW。如果错误码的值表示为页面不存在,这就是所谓的按需调页demand paging。 写时拷贝的处理过程 首先改写对应页表项的访问标志位,表明其刚被访问过,这样在页面调度时该页面就不会被优先考虑。 如果该页帧目前只为一个进程单独使用,则只需把页表项置为可写。 如果该页帧为多个进程共享,则申请一个新的物理页面并标记为可写,复制原来物理页面的内容,更改当前进程相应的页表项,同时原来的物理页帧的共享计数减一。,do_page_fault ,按需调页的处理过程 第一种情况页面从未被进程访问,这种情况页表项的值全为0。 1如果所属区间的vm_ops-nopage不为空,表示该区间映射到一个文件,并且vm_ops-nopage指向装入页面的函数,此时调用该函数装入该页面。 2如果vm_ops或vm_ops-nopage为空,则该调用do_anonymous_page 申请一个页面; 另一种情况是该页面被进程访问过,但是目前已被写到交换分区, 页表项的存在标志位为0,但其他位被用来记录该页面在交换分区中的信息。调用do_swap_page 函数从交换分区调入该页面。,do_page_fault ,换页,Linux使用最近最少使用(LRU)页面衰老算法来公平地选择将要从系统中抛弃的页面。 这种策略为系统中的每个页面设置一个年龄,它随页面访问次数而变化。页面被访问的次数越多则页面年龄越年轻;相反则越衰老。年龄较老的页面是待交换页面的最佳侯选者。,当物理内存不足时,Linux通过某种机制选出内存中的某些页面换到磁盘上,以便留出空闲区来调入需要使用的页面 交换的基本原理当空闲内存数量小于一个固定的极限值时,就执行换出操作(包括把进程的整个地址空间拷贝到磁盘上)。反之,当调度算法选择一个进程运行时,整个进程又被从磁盘中交换进来,交换机制,在Linux中,进行交换的单位是页面而不是进程 在页面交换中,页面置换算法是影响交换性能的关键性指标,其复杂性主要与换出有关 哪种页面要换出 如何在交换区中存放页面 如何选择被交换出的页面,页面交换,只有与用户空间建立了映射关系的物理页面才会被换出,内核空间中内核所占的页面则常驻内存 进程映像所占的页面 ,其代码段、数据段可被换入换出,但堆栈段一般不换出 通过系统调用mmap把文件内容映射到用户空间时,页面所使用的交换区就是被映射的文件本身 进程间共享内存区其页面的换入换出比较复杂 映射到内核空间中的页面都不会被换出 内核在执行过程中使用的页面要经过动态分配,但永驻内存,选择被换出的页面策略,在交换区中存放页面,交换区也被划分为块,每个块的大小恰好等于一页,一块叫做一个页插槽 换出时,内核尽可能把换出的页放在相邻的插槽中,从而减少访问交换区时磁盘的寻道时间 若系统使用了多个交换区,快速交换区可以获得比较高的优先级 当查找一个空闲插槽时,要从优先级最高的交换区中开始搜索 如果优先级最高的交换区不止一个,应该循环选择相同优先级的交换区,策略1需要时才交换 策略2系统空闲时交换 策略3换出但并不立即释放 策略4把页面换出推迟到不能再推迟为止,页面交换策略,页面换入/换出及回收的基本思想,释放页面。如果一个页面变为空闲可用,就把该页面的page结构链入某个空闲队列free_area,同时页面的使用计数count减1。 分配页面。调用___get_free_page从某个空闲队列分配内存页面,并将其页面的使用计数count置为1。 活跃状态。已分配的页面处于活跃状态,该页面的数据结构page通过其队列头结构lru链入活跃页面队列active_list,并且在进程地址空间中至少有一个页与该页面之间建立了映射关系。 不活跃“脏”状态。处于该状态的页面其page结构通过其队列头结构lru链入不活跃“脏”页面队列inactive_dirty_list,并且原则是任何进程的页面表项不再指向该页面,也就是说,断开页面的映射,同时把页面的使用计数count减1。 将不活跃“脏”页面的内容写入交换区,并将该页面的page结构从不活跃“脏”页面队列inactive_dirty_list转移到不活跃“干净”页面队列,准备被回收。 不活跃“干净”状态。页面page结构通过其队列头结构lru链入某个不活跃“干净”页面队列。 如果在转入不活跃状态以后的一段时间内,页面又受到访问,则又转入活跃状态并恢复映射。 当需要时,就从“干净”页面队列中回收页面,也就是说或者把页面链入到空闲队列,或者直接进行分配。,Linux内核利用守护进程kswapd定期地检查系统内的空闲页面数是否小于预定义的极限,一旦发现空闲页面数太少,就预先将若干页面换出 kswapd相当于一个进程,它有自己的进程控制块task_struct结构,与其它进程一样受内核调度,但没有独立的地址空间,页面交换守护进程kswapd,物理内存的管理,内存用途 存储内核映像; 其他内核子系统的内存需求; 进程的需求; 缓冲需求。 功能要求 快速响应请求; 尽可能地利用内存同时减少内存碎片。 解决方案 基于区的伙伴系统及slab分配器。,,页帧与区域,页帧物理内存是以页帧page frame为基本单位,页帧的大小固定,i386默认为4KB。 结点访问速度相同的一个内存区域称为一个结点(Node)。 区每个结点的物理内存因为用途不同又分成不同的区zone。例如x86,分成如下三个区 DMA ZONE 低于16MB的内存,是DMA方式能够访问的物理内存。在内存分配时,尽可能保留这部分内存以供DMA方式使用。 NORMAL ZONE 介于16MB与896MB之间,直接被内核映射。 HIGHMEM ZONE 高端内存,超过896MB以上的部分,不能被内核直接映射。 区的划分没有任何物理意义,是内核内核为了管理页帧而采取逻辑上的分组。include/linux/mmzone.h定义了区结构 Linux对不同zone的内存使用单独的伙伴系统buddy system管理,而且独立地监控空闲页帧。,页帧与区域,Linux设置了一个mem_map[]数组管理内存页帧。 mem_map[]在系统初始化时由free_area_init函数创建,它存放在物理内存的底部(低地址部分) mem_map[]数组的元素是一个个的page结构体,每一个page结构体它对应一个物理页帧。 page结构进一步被定义为mem_map_t类型,其定义在include/linux/mm.h中2.4 kernel,物理页帧,typedef struct page { struct page *next, *prev; /* 把page结构链接成一个双向循环链表。 */ struct inode *inode; /* 若该页帧的内容是文件,则inode和offset unsigned long offset; /* 指出文件的inode和偏移位置 */ struct page *next_hash; /*把有关page结构体连成一个哈希表*/ atomic_t count; /* 访问此页帧的进程记数,大于1表示由多个进程共享 */ unsigned flags; /*页帧标志 */ unsigned dirty16, /*页帧修改标志 */ age8; /*页帧的年龄,越小越先换出 */ struct wait_queue *wait; /*是等待该页帧资源的进程等待队列的指针*/ struct page *prev_hash; struct buffer_head * buffers; /* 若该页帧作为缓冲区,则指示地址 */ unsigned long swap_unlock_entry; unsigned long map_nr;/*页帧在mem_map表中的下标,也就是物理页帧的页帧号*/ } mem_map_t; mem_map_t * mem_map NULL; /* 页帧描述表的首地址 */,flag,符号常量 意 义 PG_locked 页帧处于闭锁状态,正在装入该页帧 PG_error 页帧装入时发生错误 PG_referenced 页帧已装入,可以访问 PG_uptodate 页帧内容更新过 PG_free_after 关于页帧的I/O过程结束,页帧被释放 PG_decr_after 关于页帧的I/O过程结束,页帧计数减少 PG_swap_unlock_after 读出交换页帧后,页帧解除闭锁 PG_DMA 页帧可以用于DMA传送 PG_reserved 页帧被保留以后使用,当前禁止使用,伙伴算法,Linux对内存空闲空间的管理采用Buddy算法。 Buddy算法是把内存中的所有页帧按照2n划分,其中n0~10。对内存空间按1个页帧、2个页帧、4个页帧、8个页帧、16个页帧、32个页帧、 、1024个页帧进行划分。 划分后形成了大小不等的存储块,称为页帧块,简称页块。包含1个页帧的页块称为1页块,包含2个页帧的称为2页块,依此类推。 Linux把物理内存划分成了1、2、4、8、、1024共十一种页块。,伙伴算法,Linux把空闲的页帧按照页块大小分组进行管理,数组free_area[]来管理各个空闲页块组。 struct free_area_struct { struct page *next; /* 此结构的next,prev指针与struct page匹配 */ struct page *prev; unsigned int * map; /* 指向bitmap */ }; static struct free_area_struct free_area[NR_MEM_LISTS];,Buddy算法,bitmap,bitmap表在物理内存低端,紧跟mem_map表的bitmap表以位示图方式记录了所有物理内存的空闲状况。与mem_map一样,bitmap在系统初始化时由free_area_init函数创建mm/page_alloc.c。 Linux对内存页帧块的每种划分都对应一个位图map(bitmap),free_area[]各个元素中的指针map指向相应页帧块的位图,free_area[0]中的map指向内存按照1个页帧划分时的位图, free_area[1]中的map指向内存按照2个页帧划分时的位图。,bitmap,位图中每一位(bit)表示页帧的使用情况。当bit所指物理页帧块都是空闲时,该位置0;全部或部分占用时, 对应的位置1。 free_area[]数组指向的10个位图, 放在内存mem_map的上方bitmap区域内。 用来记录页块组使用情况的位图的长度不同,页块越小位图越长。当内存区域的开始地址为start_mem,结束地址为end_mem,页帧尺寸为PAGE_SIZE时, 每种页块组的位图的长度计算公式为 end_mem-start_mem/PAGE_SIZE/2i3(字节) 其中i0~1024,分别对应1~1024十一种页块组的map长度。,Buddy算法,系统按照Buddy关系把具有相同大小的空闲页帧块组成页块组,即1页块组、2页块组1024页块组。 每个页块组用一个双向循环链表进行管理,共有11个链表,分别为1、2、4、8、、1024页块的链表。 这些链表是由空闲页帧的page结构体双向连接而成,分别挂到free_area[] 数组上。 free_area[0]的指针指向1页帧块的链表, free_area[1]的指针指向2页帧块的链表, , free_area[10]的指针指向1024页帧块的链表。 在页块组链表中的page结构体通过prev和next相互链接。,Buddy系统的内存分配,在请求内存分配时,系统按照Buddy算法,根据请求的页帧数在free_area[]对应的空闲页块组中搜索。 若请求的页帧数不是2的整数次幂,则按照稍大于请求数的2的整数次幂的值搜索相应的页帧块组。 当相应的页块组中没有可使用的空闲页帧块时就查询更大一些的页块组,在找到可利用的空闲页帧块后,分配所需的页帧。 当某一空闲页帧块被分配后,若仍有剩余的空闲页帧, 则根据剩余页帧的大小把它们加入到相应的页块组中。 例8、9、10、页帧分配后图,8、9、10、页帧分配后图,,内存回收,在内存页帧释放时,系统将做为空闲页帧看待。 然后检查是否存在与这些页帧相邻的其它空闲页块, 若存在,则合为一个连续的空闲区按Buddy算法重新分组。 内存回收需要一定时间,13页帧回收后图,,,Buddy算法,两组连续页帧被认为是一对“伙伴”必须满足如下条件 1大小相同,比如说都有b 个页帧; 2物理空间上连续; 3位于后面那个块的最后页帧号必须是2b 的倍数。 伙伴系统的操作 申请空间的函数为__alloc_pages ; 释放函数为__free_pages ; 当在申请内存发现页面短缺时,还会唤醒kswapd内核线程运行,该线程会腾出一些空间以满足要求。,函数__alloc_pages ;用于分配物理页 该函数所做的工作如下 检查所请求的页块大小是否能够被满足 检查系统中空闲物理页的总数是否已低于允许的下界 正常分配。从free_area数组的第order项开始,这是一个mem_map_t链表。 换页。通过下列语句调用函数try_to_free_pages(),启动换页进程,物理页面的分配,物理页面的分配,1如果该链表中有满足要求的页块,则 将其从链表中摘下;将free_area数组的位图中该页块所对应的位取反,表示页块已用;修改全局变量nr_free_pages(减去分配出去的页数);根据该页块在mem_map数组中的位置,算出其起始物理地址,返回。 2 如果该链表中没有满足要求的页块,则在free_area数组中顺序向上查找。其结果有二 a整个free_area数组中都没有满足要求的页块,此次无法分配,返回。 b 找到一个满足要求的页块,则 将其从链表中摘下;将free_area数组的位图中该页块所对应的位取反,表示页块已用;修改全局变量nr_free_pages(减去分配出去的页数);因为页块比申请的页块要大,所以要将它分成适当大小的块。因为所有的页块都由2的幂次的页数组成,所以这个分割的过程比较简单,只需要将它平分就可以 I.将其平分为两个伙伴,将小伙伴加入free_area数组中相应的链表,修改位图中相应的位; II.如果大伙伴仍比申请的页块大,则转I,继续划分; III.大伙伴的大小正是所要的大小,修改位图中相应的位,根据其在mem_map数组中的位置,算出它的起始物理地址,返回。,函数__free_pages用于页块的回收 该函数所做的工作如下 根据页块的首地址addr算出该页块的第一页在mem_map数组的索引; 如果该页是保留的(内核在使用),则不允许回收; 将页块第一页对应的mem_map_t结构中的count域减1,表示引用该页的进程数减了1个。若count域的值不为0,有别的进程在使用该页块,不能回收,仅简单返回 清除页块第一页对应的mem_map_t结构中flags域的PG_referenced位,表示该页块不再被引用; 将全局变量nr_free_pages的值加上回收的物理页数 将页块加入到数组free_area的相应链表中,物理页面的回收,slab分配器,伙伴系统是以页帧为基本分配单位, 因而对于小对象容易造成内部碎片。 不同的数据类型用不同的方法分配内存可能提高效率。比如需要初始化的数据结构,释放后可以暂存着,再分配时就不必初始化了。内核的函数常常重复地使用同一类型的内存区,缓存最近释放的对象可以加速分配和释放。 解决办法基于伙伴系统的slab分配器。 slab分配器的基本思想为经常使用的小对象建立缓冲,小对象的申请与释放都通过slab 分配器来管理。slab 分配器再与伙伴系统打交道。 好处其一是充分利用了空间,减小了内部碎片;其二是管理局部化,尽可能少地与伙伴系统打交道,从而提高了效率。,slab分配器的构成,为不同的常用对象生成不同的缓冲,每个缓冲存储相同类型的对象。 每个slab又由一个或多个连续的物理页帧组成,包含了若干同种类型的对象。 slab对象用结构slab_t来描述,某种特定对象建立的slab队列都有个队头。kmem_cache_t 系统有一个总的slab队列,其对象是其他对象的队头,其队头也是一个kmem_cache_t结构,叫cache_cache。,除了上面讨论的特定对象的缓冲外, Linux还提供了13种通用的缓冲区,其存储对象的单位大小分别为32B, 64B, 128B, 256B, 512B, 1KB, 2KB, 4KB, 8KB, 16KB, 32KB, 64KB和128KB。这些缓冲区用来满足特定对象之外的普通内存需求。单位大小级数增长保证了内部碎片率不超过50。,slab分配器的相关操作 1kmem_cache_create 该函数创建一种特定对象的kmem_cache_t结构,并加入cache_cache 所管理的队列。如下代码创建了inode_cache kmem_cache_createinode_cache, sizeofstructinode, 0, SLAB_HWCACHE_ALIGN, init_once,NULL; kmem_cache_create 函数一开始分配一个kmem_cache_t结构,然后进行一系列运算,以确定最佳的slab 构成。包括每个slab由几个页面组成,可包含几个对象;slab的控制结构应该在slab 外面集中存放还是放在每个slab的尾部。,2kmem_cache_alloc 与kmem_cache_free 当需要分配一个拥有专用slab队列的对象时,应该通过kmem_cache_alloc 函数,相反的动作则是kmem_cache_free 函数。 分配的对象来自slab缓冲,释放的对象归还slab缓冲,通过某种标识表明对象是可用还是已被占用。,3kmem_cache_grow 与kmem_cache_reap kmem_cache_create 函数只是建立了所需的专用缓冲区队列的基础设施,所形成的slab队列是个空队列。 而具体slab的创建则要等需要分配缓冲区时,却发现队列中并无空闲的缓冲区可供分配时,再通过kmem_cache_grow 来进行, kmem_cache_ grow 再向伙伴系统申请空间。 kswapd会定时调用kmem_cache_reap 来“收割”缓冲区队列。 4kmalloc 函数与kfree 函数 从通用的缓冲区队列中申请和释放空间。,

注意事项

本文(05 存储管理.ppt)为本站会员(w89153)主动上传,乐乐文库,课件爱好者仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知乐乐文库,课件爱好者(发送邮件至1748365562@qq.com或直接QQ联系客服),我们立即给予删除!

温馨提示:如果因为网速或其他原因下载失败请重新下载,重复下载不扣分。

关于我们 - 网站声明 - 网站地图 - 资源地图 - 友情链接 - 网站客服客服 - 联系我们

站长联系QQ:1748365562
工信部备案号: 鄂ICP备17024083号                 公安局备案号:42118102000213

收起
展开