第二章 LINUX存储管理 LINUX的分页管理机制.

Slides:



Advertisements
Similar presentations
《微型计算机技术 及应用》 ( 第 4 版) —— 戴梅萼 史嘉权. 目标 深刻理解 牢固掌握 灵活应用.
Advertisements

基本概論 Basic concepts.
Foundations of Computer Science
Memory Pool ACM Yanqing Peng.
第一章 C语言概述 计算机公共教学部.
嵌入式图形显示.
第三章 鏈結串列 Linked List.
编译原理上机实习
Chapter 6 時序.
Linux File System Li-Shien Chen.
資料結構與C++程式設計進階 資料結構概論 講師:林業峻 CSIE, NTU 6/ 7, 2010.
性能测试培训 在组设置中可使用此模板作为演示培训材料的起始文件。 节
数据结构与算法 数据结构与算法实验
Linux Further.
Xen基础架构安全性分析 云朋
作業系統 第十三章 檔案系統實例.
Operating System Concepts 作業系統原理 Chapter 3 行程觀念 (Process Concept)
程式設計 博碩文化出版發行.
中国科学技术大学计算机系 陈香兰(0512- ) Spring 2011
补充内容 结构体 概述 定义结构体类型和定义结构体变量 结构体变量的引用 结构体变量的初始化 指针与结构体 用typedef定义类型的别名.
编译原理与技术 类型检查 2018/11/21 《编译原理与技术》-类型检查.
基于硬件辅助的内核漏洞挖掘框架 闫广禄.
CHAPTER 8 VIRTUAL MEMORY
第七章. 文件系统 (lab5).
C++语言程序设计 C++语言程序设计 第六章 指针和引用 第十一组 C++语言程序设计.
LINUX存储管理.
第12章 樹狀搜尋結構 (Search Trees)
Chapter 3 行程觀念 (Process Concept)
授课老师:龚涛 信息科学与技术学院 2018年3月 教材: 《Visual C++程序员成长攻略》 《C++ Builder程序员成长攻略》
CH.8 硬體管理.
Linux File System 文件系统 VFS VFS的作用 基于VFS的文件访问 VFS重要数据结构 文件系统的注册与安装
在專用的嵌入式板子運行 GNU/Linux 系統已經變得越來越流行。一個嵌入式 Linux 系統從軟體的角度看通常可以分為四個層次:
中国科学技术大学计算机系 陈香兰(0512- ) Autumn 2009
中国科学技术大学计算机系 陈香兰(0512- ) Spring 2011
第3章 堆栈和队列 堆栈 堆栈应用 队列 队列应用 优先级队列 主要知识点.
fp=fopen("CD2.dat","wb"); fwrite(&min,8,1,fp); fclose(fp);
嵌入式系统的Boot Loader技术 陈文智 浙江大学计算机学院 2009年5月.
第 六 章 鏈結串列(Link List) 課程名稱:資料結構 授課老師:________ 2019/1/2.
重點 資料結構之選定會影響演算法 選擇對的資料結構讓您上天堂 程式.
Ch9 Communicating with Hardware
Linux的文件系统 课程目标: 操作系统的运行级别 文件系统架构 设备管理.
第3章 認識處理元.
第五章 中断与异常 中断的基本知识 中断描述符表的初始化 中断处理 中断的下半部处理机制 中断的应用-时钟中断.
樹 2 Michael Tsai 2013/3/26.
Chapter 13 MMAP與DMA.
第2章 进程管理 2.1 进程概念 2.2 线程 2.3 进程管理 2.4 进程间通信 2.5 经典进程同步问题 2.6 管程
第1章 概述 本章要点: C语言程序结构和特点 C语言程序的基本符号与关键字 C语言程序的编辑及运行 学习方法建议:
運動競賽制度 授課教師:鄭俊傑副教授.
Holtek C Compiler V3--advanced
(第2版).
第9章 虛擬記憶體 (virtual memory)
作業系統 Operating System 第四單元 檔案系統
_08遍历物理网卡 本节课讲师——void* 视频提供:昆山爱达人信息技术有限公司 官网地址:
Chapter 7 掌控記憶體.
資料結構與C++程式設計進階 實作練習 講師:林業峻 CSIE, NTU 6/ 24, 2010.
计算机系统结构(2012年春) ----存储层次: Cache基本概念
第十四讲 直接存储器访问 DMA/EDMA BIT / TI 第十四讲 DMA/EDMA.
<编程达人入门课程> 本节内容 为什么要使用变量? 视频提供:昆山爱达人信息技术有限公司 官网地址: 联系QQ:
Chapter 7 掌控記憶體.
第六章 記憶體.
第二章 类型、对象、运算符和表达式.
#include <iostream.h>
实验二:添加Linux系统调用及熟悉常见系统调用
第十二章 位运算.
作業一: 安裝Linux於btrfs上 中正大學 作業系統實驗室 指導教授:羅習五
中国科学技术大学计算机系 陈香兰(0551- ) Spring 2009
獨孤派作業系統 main memory 中正大學 作業系統實驗室 指導教授:羅習五.
C语言程序设计 第13章 文件操作.
安排座位.
Presentation transcript:

第二章 LINUX存储管理 LINUX的分页管理机制

LINUX的地址划分 每一个用户进程都可以访问4GB的线性虚拟内存空间。 从3GB到4GB的虚拟内存地址为核心态空间,存放仅供核心态访问的代码和数据,用户态进程不可访问。 所有进程从3GB到4GB的虚拟空间都是一样的,有同样的页目录项,同样的页表,对应到同样的物理内存段。LINUX以此方式让内核态进程共享代码段和数据段。 内核态虚拟空间从3GB到3GB+4M的一段(也就是进程页目录第768项所管辖的范围),被映射到物理空间0到4M段。因此,进程处于核心态时,只要通过访问虚拟空间3GB到3GB+4M段,偏移地址0到4M,即访问了物理空间0到4M段。

虚拟地址转换

mm_struct (include/linux/sched.h) 203 struct mm_struct { 204 struct vm_area_struct * mmap; /* list of VMAs */ 205 struct vm_area_struct * mmap_avl; /* tree of VMAs */ 206 struct vm_area_struct * mmap_cache; /* last find_vma result */ 207 pgd_t * pgd; 208 atomic_t mm_users; /* How many users with user space? */ 209 atomic_t mm_count; /* How many 进程/线程 refer to "struct mm_struct" (users count as 1) */ 210 int map_count; /* number of VMAs */ 211 struct semaphore mmap_sem; /* 对mmap操作的信号量 */ 212 spinlock_t page_table_lock; 214 struct list_head mmlist; /* List of all active mm's */ 216 unsigned long start_code, end_code, start_data, end_data; 217 unsigned long start_brk, brk, start_stack; 218 unsigned long arg_start, arg_end, env_start, env_end; 219 unsigned long rss, total_vm, locked_vm; 220 unsigned long def_flags; 221 unsigned long cpu_vm_mask; 222 unsigned long swap_cnt; /* number of pages to swap on next pass */ 223 unsigned long swap_address; 226 mm_context_t context; /* Architecture-specific MM context */ 227 };

PCB对内存的控制(之一) struct mm_struct结构的成员 pgd_t * pgd; 表示进程页目录的起始地址。

PCB对内存的控制

第二章 LINUX存储管理 虚存段(vma)的组织和管理 (克服页表中空表项过烂问题)

vma段 (vitual memory area) 在这段虚存里的所有单元拥有相同的特征。例如:属于同一进程,相同的访问权限,同时被锁定(locked),同时受保护(protected),等等。

vm_area_struct (include/linux/mm.h) 41 struct vm_area_struct { 42 struct mm_struct * vm_mm; /* VM area parameters */ 43 unsigned long vm_start; 44 unsigned long vm_end; 47 struct vm_area_struct *vm_next; /* linked list of VM areas per task, sorted by address */ 49 pgprot_t vm_page_prot; 50 unsigned long vm_flags; 53 short vm_avl_height; /* AVL tree of VM areas per task, sorted by address */ 54 struct vm_area_struct * vm_avl_left; 55 struct vm_area_struct * vm_avl_right; 61 struct vm_area_struct *vm_next_share; 62 struct vm_area_struct **vm_pprev_share; 64 struct vm_operations_struct * vm_ops; 65 unsigned long vm_pgoff; /* offset in PAGE_SIZE units, *not* PAGE_CACHE_SIZE */ /* 如果vma段的内容是关于文件的,则vm_offset就是该段内容相对于文件起始位置的偏移量。 */ 66 struct file * vm_file; 67 unsigned long vm_raend; 68 void * vm_private_data; /* was vm_pte, 用于共享内存,含SHM_SWP_TYPE和共享内存段id号 */ 69 };

vma段的链表 进程通常占用几个vma段,分别用于代码段、数据段、堆栈段等。属于同一进程的vma段通过vm_next指针连接,组成链表。如图。 struct mm_struct结构的成员struct vm_area_struct * mmap 表示进程的vma链表的表头。

PCB对内存的控制(之二)

PCB对内存的控制(之三) LINUX同时维护了一个AVL(Adelson-Velskii and Landis)树。 在树中,所有vma段均有左指针vm_avl_left指向相邻的低地址虚存段,右指针vm_avl_right指向相邻的高地址虚存段。 struct mm_struct结构的成员struct vm_area_struct * mmap_avl表示进程的AVL树的根,vm_avl_height表示AVL树的高度。 对vma段可以进行加锁、加保护等操作。

AVL树

第二章 LINUX存储管理 物理空间管理

物理空间的组织 (include/linux/fs.h,struct page) 物理内存以页帧(page frame)为单位,页帧的长度固定,等于页长,对INTEL CPU缺省为4K字节。 LINUX对物理内存的管理通过mem_map表描述(mm/memory.c)。 mem_map在系统初始化时由free_area_init()函数创建(mm/page_alloc.c)。 它本身是关于struct page mem_map_t (linux/mm.h)的数组,每项mem_map_t对应一个关于核心态、用户态代码和数据等的页帧。

mem_map在物理空间的位置

struct page 134 typedef struct page { 135 struct list_head list; 136 struct address_space *mapping; /* 见书中解释 */ 137 unsigned long index; /* 若该页帧的内容是文件,则index指出文件的inode和偏移位置 */ 138 struct page *next_hash; 139 atomic_t count; /* 指明目前使用该页面的用户数。count==0意味着此页空闲 */ 140 unsigned long flags; /* atomic flags, some possibly updated asynchronously */ 141 struct list_head lru; 142 unsigned long age; /* 页帧的年龄,越小越先换出 */ 143 wait_queue_head_t wait; 144 struct page **pprev_hash; 145 struct buffer_head * buffers; /* 若该页帧作为缓冲区,则指示地址 */ 146 void *virtual; /* non-NULL if kmapped */ 147 struct zone_struct *zone; 148 } mem_map_t;

(Buddy System Impelmentation Codes) 第二章 LINUX存储管理 空闲物理内存管理 (Buddy System Impelmentation Codes)

空闲内存的组织

bitmap 表 在物理内存低端,紧跟mem_map表的bitmap表以位图方式记录了所有物理内存的空闲状况。 与mem_map一样,bitmap表在系统初始化时由free_area_init()函数创建(mm/page_alloc.c)。 与一般性位图不同的是,bitmap表分割成NR_MEM_LISTS组(缺省值6)。

bitmap 表 首先是第0组,初始化时设定了长度为(end_mem-start_mem) / PAGE_SIZE/20+3,每位表示20个页帧的空闲状况,置位表示已被占用。 接着是第1组,初始化时设定了长度为: (end_mem-start_mem) / PAGE_SIZE/21+3 ,每位表示连续21个页帧的空闲状况,置位表示其中1页或2页已被占用。 类似地,对第i组,初始化时设定了长度为: (end_mem-start_mem) / PAGE_SIZE / 2i+3 ,每位表示连续2i个页帧的空闲状况,置位表示其中1页或几页已被占用。 例如对第5组,某个bit所对应的连续32页帧中只要有一个被占用,此位即置1,只有当所有32页帧全部回收后才清0。

free_area数组 LINUX用free_area数组记录空闲的物理页帧。free_area数组由NR_MEM_LISTS个free_area_struct结构类型的数组元素构成,每个元素均作为一条空闲块链表的表头。 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]; 所有单个空闲页帧组成的链表挂到free_area数组的第0项后面。连续2 i个空闲页帧则被挂到free_area数组的第i项后面。

操作函数 分配内存块由__get_free_pages()函数和宏定义__get_free_page()执行

分配算法 LINUX采用buddy算法分配空闲块,块长可以是2i个 (0<= i< NR_MEM_LISTS) 页帧。 当分配长度是2i页帧的块时,从free_area数组的第i条链表开始搜索,找不到再搜索第i+1条链表,余此类推。 若找到的空闲块长正好等于需求的块长,则直接将它从free_area删除,返回首地址。 若找到的空闲块长大于需求的块长,则将空闲块一分为二,前半部分插入free_area中前一条链表,取后半部分。 若还大,则继续对半分,留一半取一半,直至相等。 bitmap表也相应调整。每分配一个2i页帧长的块,都要将bitmap表从第i组到第NR_MEM_LISTS组的对应的bit置1。

释放算法 回收空闲块时,change_bit()函数根据bitmap表的对应组,判断回收块的前后邻居是否也为空。 若空则合并,即修改bitmap表中对应位,从free_area的空闲链表中取下该相邻块。 此判断是个递归过程,直至找不到空闲邻居为止。 将最后合并的最大块插入free_area的相应链表中。

第二章 LINUX存储管理 SLAB

第二章 LINUX存储管理 核心态内存的申请与释放

核心态内存 核心态内存是用来存放LINUX核心系统数据结构的内存区域,处于进程虚拟空间的3G至4G(精确地说应该是3G+high_memory,其中high_memory是系统在启动阶段测得的物理内存的实际容量)范围内。 核心态内存的分配和释放以块(block)为单位。

核心态空闲内存的组织

blocksize表 blocksize表规定申请内存块时可供选择的块长度: static const unsigned int blocksize[] = { 32, 64, 128, 252, 508, 1020, 2040, 4096 – 16, 8192 – 16, 16384 – 16, 32768 – 16, 65536 – 16, 131072 – 16, 0 /* 表示blocksize表的结束 */ }; 它们近似等于2的次幂。

sizes表 sizes表管理那些从物理空间free_area申请得到的用于核心态内存空间分配的空闲块。 sizes表的元素类型是struct size_descriptor, 每个表项实质上就是两个由等长空闲块所组成链表的表头,一是DMA可访问的,一是一般性的。

char *kmalloc (unsigned long size, int priority); 核心内存的申请和释放 核心内存申请 char *kmalloc (unsigned long size, int priority); 核心内存释放 kfree(char * addr); 参见文件“kmalloc.doc”

kmalloc cache

第二章 LINUX存储管理 用户态内存的申请与释放

用户态内存 由vmalloc()分配的存储空间在进程的虚拟空间是连续的,但它对应的物理内存仍需经缺页中断后,由缺页中断服务程序分配。所分配的物理页帧也不是连续的。这些特征与访问用户态内存相似,所以不妨把vmalloc()和vfree()称作用户态内存的申请与释放界面。 注意,malloc()、free()与vmalloc()、vfree()不是一回事,gcc并不是利用vmalloc、vfree实现malloc、free的。

用户态内存的位置 可分配的虚拟空间在3G+high_memory+HOLE_8M以上高端,由vmlist链表管理。 3G是核心态赖以访问物理内存的始址,high_memory是安装在计算机中实际可用的物理内存的最高地址,因此3G+high_memory也就是(从虚拟空间中看到的)物理内存的上界。HOLE_8M则是长度为8M的“隔离带”,起到越界保护作用。 尽管vmalloc返回高于任何物理地址的高端地址,但因为vmalloc同时更改了页表甚至页目录,处理器仍能正确地访问这些高端连续地址(页目录和页表把高端虚拟地址映射到实际的物理地址)。内核态程序与进程用户态程序共享同一个页目录,同一组页表,因而内核态程序也能正常访问。

管理用户态内存的结构

操作函数 申请 void * vmalloc(unsigned long size); 释放 void vfree(void * addr); 参见文件vmalloc.doc

kmalloc与vmalloc的比较 vmalloc返回的地址空间不能绕过CPU的页表机构直接使用。当操作系统某些管理模块(如DMA部件)需要直接使用实际物理地址时,vmalloc不合适,必须用kmalloc。 向vmalloc申请小块内存(如1页左右)也不合适,因为无论是内存的分配还是使用,都涉及到内存和页表两方面因素。。 比较合适的情形可能是申请大块缓冲区。此时,尽管大缓冲区占用了大段虚拟地址,但实际占用的物理地址不大,因为当前不用的内容不会调入物理内存中。相反,如果用kmalloc申请大缓冲区,那么,将实实在在占用这么大的一块物理内存。何况,缺省情况下,kmalloc可分配的最大内存块只有131054字节。

第二章 LINUX存储管理 交换空间

两种交换空间 一种用整个块设备,如硬盘的一个分区,称作交换设备,效率较高; 另一种用文件系统中固定长度的文件,称作交换文件,效率较低。 LINUX允许并行管理MAX_SWAPFILES个交换空间(MAX_SWAPFILES的缺省值为8)。

交换空间的格式 前4096字节是一个以字符串 “SWAP_SPACE”结尾的位图。位图的每一位(bit)对应一个交换空间的页面,置位表示对应的页面可用于换页操作。 第4096字节之后则是真正存放换出页面的空间。 这样,每个交换空间最多可容纳 (4096-10)* 8 – 1 = 32687个页面。

启用交换空间 int sys_swapon(const char * swapfile, int swapflags); swapflags规定交换空间的优先数。该参数中,SWAP_FLAG_PREFER(0X8000)必须置位,SWAP_FLAG_PRIO_MASK(0X7FFF)指定一个正的优先数。如果没有指定优先数,swapon自动给出一个负的优先数,负优先数的取值决定于swapon的调用次数。

每注册一个交换空间,就在swap_info表中填一项swap_info_struct结构 25 struct swap_info_struct swap_info[MAX_SWAPFILES]; 49 struct swap_info_struct { 50 unsigned int flags; /* 如果SWP_USED位置位,则被占用。如果SWP_WRITEOK,则该交换空间准备就绪。 */ 51 kdev_t swap_device; /* 对于交换设备,swap_device属性表示交换设备的主、次设备号 */ 52 spinlock_t sdev_lock; /* 对于此设备的互斥锁 */ 53 struct dentry * swap_file; /* 对于交换文件,swap_file属性指向该文件的inode */ 54 struct vfsmount *swap_vfsmnt; 55 unsigned short * swap_map;/* 指向一张表,其每一字节按顺序对应交换空间的一个页面,字节的值代表了引用该页面的进程数 */ 56 unsigned int lowest_bit; /*交换空间中的第一个没有被任何进程使用的交换页在swap_map数组中的下标 */ 57 unsigned int highest_bit; /* 交换空间中最后一个没被任何进程使用的交换页的下标 */ 58 unsigned int cluster_next; /*上次从当前的cluster中成功分配的交换页面的后继页面在swap_map数组中的下标 */ 59 unsigned int cluster_nr; /* 当前cluster中可供使用的交换页面的个数 */ 60 int prio; /*交换空间的优先级。优先级越高,交换文件申请交换页面的时候越优先考虑 */ 61 int pages; /* 表示该交换空间尚有多少空闲空间可供保存进程换出的物理页 */ 62 unsigned long max; 63 int next; /*指向下一项交换空间的的指针 */ 64 }; 153 struct swap_list_t { 154 int head; /* head of priority-ordered swapfile list */ 155 int next; /* swapfile to be used next */ 156 }; 23 struct swap_list_t swap_list = {-1, -1};

int sys_swapoff(const char * swapfile); 注销交换空间 int sys_swapoff(const char * swapfile);

交换空间的工作 kswapd进程换出页面时,调用try_to_swap_out() 测试页面的年龄。如果某物理页面可以换出,则调用get_swap_page向swap_list.next指示的交换空间申请空闲页面,得到一地址entry。该地址写入进程页表中那个原来描述换出物理页面的页表项,替换了其中的页帧地址。最后,调用rw_swap_page(),将换出的物理页面写到entry指定的交换空间某个页面中。 反过来,当缺页中断发生时,缺页中断服务程序可以根据产生缺页的地址(由CR2寄存器给出),找到描述该页面的页表项。页表项的Present位应该为0,最高20位指出该页面保存在哪个交换空间的哪个页面中。然后,经一系列函数调用后,读入该页面。

第二章 LINUX存储管理 页交换进程和页面换出

kswapd 当物理页面不够时,利用kswapd释放部分物理页面,将它们的内容写到交换空间。 kswapd是一特殊的进程,称内核态线程(kernel thread)。 注意,kernel thread完全不同于通常意义上的线程。它是没有虚拟存储空间的进程,它只运行在内核态,直接使用物理地址空间。同类型的进程还有bdflush和init。 kswapd的作用超越了字面上的描述。它不仅能将页面换出到交换空间(交换区或交换文件),它也保证系统中有足够的空闲页面以保持存储系统高效地运行。

由于只有该映像区的开始部分调入内存,因此,进程迟早会执行到那些尚未调入内存的代码。 第二章 LINUX存储管理 缺页中断和页面换入 由于只有该映像区的开始部分调入内存,因此,进程迟早会执行到那些尚未调入内存的代码。

产生缺页中断 当一个进程访问了一个还没有有效页表项的虚拟地址时(即页表项的P位为0),处理器将产生缺页中断,通知操作系统,并将出现缺页的虚存地址(在CR2寄存器中)和缺页时访问虚存的模式一并传递给LINUX的缺页中断服务程序。

缺页中断服务程序为do_page_fault() set_trap_gate(14, &page_fault); /* arch/i386/kernel/trap.c */ ENTRY(page_fault) /* arch/i386/kernel/entry.S */ pushl $SYMBOL_NAME(do_page_fault) jmp error_code /* 异常中断服务程序的统一入口 */

中断服务流程 根据控制寄存器CR2传递的缺页地址,找到用来表示出现缺页的虚拟存储区的vm_area_struct结构。 如果没有找到与缺页相对应的vm_area_struct结构,那么说明进程访问了一个非法存储区,LINUX向进程发送信号SIGSEGV。 接着检测缺页时访问模式是否合法。如果进程对该页的访问超越权限,例如试图对只允许读操作的页面进行写操作,系统也将向该进程发送一个信号,通知进程的存储访问出错。 主要流程参见文件pagefault.doc