40
LINUX LINUX 存存存存 存存存存

LINUX 存储管理

Embed Size (px)

DESCRIPTION

LINUX 存储管理. 地址空间. 地址空间( address space )是一段表示内存位置的地址范围。地址空间有两种: 物理地址空间 逻辑地址空间,也被称为虚拟地址空间 在逻辑地址和物理地址之间相互转换的工作是由内核和硬件内存管理单元( MMU — memory management unit )共同完成的。 MMU 是被集成进现代的 CPU 里的,它们都是同一块 CPU 芯片内的一个部分。内核告诉 MMU 如何为每个进程把某逻辑页面映射到某特定物理页面,而 MMU 在进程提出内存请求时完成实际的转换工作。. LINUX 的虚拟地址划分. - PowerPoint PPT Presentation

Citation preview

Page 1: LINUX 存储管理

LINUXLINUX 存储管理存储管理

Page 2: LINUX 存储管理

地址空间地址空间地址空间(地址空间( address spaceaddress space )是一段表示内存位置)是一段表示内存位置的地址范围。地址空间有两种:的地址范围。地址空间有两种:物理地址空间物理地址空间逻辑地址空间,也被称为虚拟地址空间逻辑地址空间,也被称为虚拟地址空间在逻辑地址和物理地址之间相互转换的工作是由内在逻辑地址和物理地址之间相互转换的工作是由内核和硬件内存管理单元(核和硬件内存管理单元( MMU—memory manageMMU—memory management unitment unit )共同完成的。)共同完成的。 MMUMMU 是被集成进现代的是被集成进现代的CPUCPU 里的,它们都是同一块里的,它们都是同一块 CPUCPU 芯片内的一个部芯片内的一个部分。内核告诉分。内核告诉 MMUMMU 如何为每个进程把某逻辑页面如何为每个进程把某逻辑页面映射到某特定物理页面,而映射到某特定物理页面,而 MMUMMU 在进程提出内存在进程提出内存请求时完成实际的转换工作。 请求时完成实际的转换工作。

Page 3: LINUX 存储管理

LINUXLINUX 的虚拟地址划分的虚拟地址划分• 每一个用户进程都可以访问每一个用户进程都可以访问 4GB4GB 的线性虚拟内存空间。的线性虚拟内存空间。• 从从 00 到到 3GB3GB 的虚拟内存地址是用户空间,用户进程可以的虚拟内存地址是用户空间,用户进程可以直接对其进行访问。直接对其进行访问。• 从从 3GB3GB 到到 4GB4GB 的虚拟内存地址为核心态空间,存放仅供的虚拟内存地址为核心态空间,存放仅供核心态访问的代码和数据,用户态进程不可访问。核心态访问的代码和数据,用户态进程不可访问。• 所有进程从所有进程从 3GB3GB 到到 4GB4GB 的虚拟空间都是一样的,有同样的虚拟空间都是一样的,有同样的页目录项,同样的页表,对应到同样的物理内存段。的页目录项,同样的页表,对应到同样的物理内存段。 LILI

NUXNUX 以此方式让内核态进程共享代码段和数据段。以此方式让内核态进程共享代码段和数据段。• 内核态虚拟空间从内核态虚拟空间从 3GB3GB 到到 3GB+4M3GB+4M 的一段(也就是进程的一段(也就是进程页目录第页目录第 768768 项所管辖的范围),被映射到物理空间项所管辖的范围),被映射到物理空间 00 到到

4M4M 段。因此,进程处于核心态时,只要通过访问虚拟空段。因此,进程处于核心态时,只要通过访问虚拟空间间 3GB3GB 到到 3GB+4M3GB+4M 段,偏移地址段,偏移地址 00 到到 4M4M ,即访问了物,即访问了物理空间理空间 00 到到 4M4M 段。段。

Page 4: LINUX 存储管理

虚拟地址转换虚拟地址转换

PGD PMD PTE Page Frame

页目录索引,页面中间目录、页表索引和偏移量虚拟内存和物理内存都分为大小固定的块,叫做页面。每一个页面有一个唯一的页面号,叫做 PFN(page frame number) 。

Page 5: LINUX 存储管理

转换后备缓存(转换后备缓存( Translation Lookaside BufferTranslation Lookaside Bufferss :: TLBs)TLBs) 如果简单的执行从逻辑地址到物理地址的转换过如果简单的执行从逻辑地址到物理地址的转换过程,在跟踪指针链时将会需要几个内存引用。程,在跟踪指针链时将会需要几个内存引用。 RARAMM 虽然不像磁盘那么慢,但是仍然比虽然不像磁盘那么慢,但是仍然比 CPUCPU 要慢的要慢的多,这样就容易形成性能的瓶颈。为了减少这种多,这样就容易形成性能的瓶颈。为了减少这种开销,最近被执行过的地址转换结果将被存储在开销,最近被执行过的地址转换结果将被存储在MMUMMU 的转换后备缓存(的转换后备缓存( translation lookaside btranslation lookaside buffersuffers :: TLBsTLBs )内。)内。

虚拟地址转换虚拟地址转换

Page 6: LINUX 存储管理

虚存段虚存段 (VMA)(VMA) 的组织和管理的组织和管理VMA:vitual memory areaVMA:vitual memory area一个一个 vmavma 段是某个进程的一段连续的虚存空间;在这段虚存段是某个进程的一段连续的虚存空间;在这段虚存里的所有单元拥有相同的特征。例如:属于同一进程,相同里的所有单元拥有相同的特征。例如:属于同一进程,相同的访问权限,同时被锁定(的访问权限,同时被锁定( lockedlocked ),同时受保护(),同时受保护( protecteprotectedd ),等等。),等等。进程通常占用几个进程通常占用几个 vmavma 段,分别用于代码段、数据段、堆栈段,分别用于代码段、数据段、堆栈段等。属于同一进程的段等。属于同一进程的 vmavma 段通过段通过 vm_nextvm_next 指针连接,组成指针连接,组成链表。链表。对于一个给定的进程,两个对于一个给定的进程,两个 VMAsVMAs 决不会重叠,一个决不会重叠,一个地址最多被一个地址最多被一个 VMAVMA 所覆盖;进程从未访问过的的一个地址所覆盖;进程从未访问过的的一个地址将不会在任何一个将不会在任何一个 VMAVMA 中。 中。 struct mm_structstruct mm_struct 结构的成员结构的成员 struct vm_area_struct * mmap struct vm_area_struct * mmap 表表示进程的示进程的 vmavma 链表的表头。链表的表头。

Page 7: LINUX 存储管理
Page 8: LINUX 存储管理

当一个进程有多于当一个进程有多于 avl_min_map_countavl_min_map_count数目的数目的 VMAVMA 时,内核也会创建一个时,内核也会创建一个 AVLAVL 树树来存储它们,此时仍然是使用来存储它们,此时仍然是使用 VMAsVMAs 自己的自己的指针对该树进行管理。指针对该树进行管理。 AVLAVL 树是一个平衡二树是一个平衡二叉树结构,因此这种方法在叉树结构,因此这种方法在 VMAVMA 数量巨大数量巨大时查找效率十分高。 时查找效率十分高。

虚存段虚存段 (VMA)(VMA) 的组织和管理的组织和管理

Page 9: LINUX 存储管理

AVLAVL 树树 vm_area_struct

(1000, 2000) vm_avl_left vm_avl_right (500, 670)

vm_avl_left vm_avl_right

(2500, 3000) vm_avl_left vm_avl_right

(350, 450) vm_avl_left vm_avl_right

(800, 900) vm_avl_left vm_avl_right

Page 10: LINUX 存储管理

PCBPCB 对内存的控制对内存的控制 Task struct mm_struct _vm_area_struct vm_mm

pgd

mm

vm_operations_struct

vm_next

mmap vm_ops

pgd

vm_area_struct

pte pte

page

page

frame frame

vm_next

*open

Page 11: LINUX 存储管理

物理空间管理物理空间管理 物理空间的组织物理空间的组织 空闲物理内存管理空闲物理内存管理

• 空闲内存的组织空闲内存的组织• 分配分配•回收回收

Page 12: LINUX 存储管理

物理空间的组织物理空间的组织(include/linux/fs.h,struct page)(include/linux/fs.h,struct page)

物理内存以页帧物理内存以页帧 (page frame)(page frame) 为单位,页帧的长为单位,页帧的长度固定,等于页长,对度固定,等于页长,对 INTEL CPUINTEL CPU 缺省为缺省为 4K4K 字节。字节。 LINUXLINUX 对物理内存的管理通过对物理内存的管理通过 mem_mapmem_map 表描表描述述 (mm/memory.c)(mm/memory.c) 。。 mem_mapmem_map 在系统初始化时由在系统初始化时由 free_area_init()free_area_init() 函数函数创建创建 (mm/page_alloc.c)(mm/page_alloc.c) 。。 它本身是关于它本身是关于 struct page mem_map_t (linux/mm.struct page mem_map_t (linux/mm.

h)h) 的数组,每项的数组,每项 mem_map_tmem_map_t 对应一个关于核心态、对应一个关于核心态、用户态代码和数据等的页帧。用户态代码和数据等的页帧。

Page 13: LINUX 存储管理

mem_mapmem_map 在物理空间的位置在物理空间的位置 0X000000(0K) empty_Zero_Page 由 mem_init初始化 0X001000(4K) swapper_pg_dir 核心态访问空间的页目录 0X002000(8K) pg0 0X003000(12K) bad_pages 0X004000(16K) bad_pg_table 0X005000(20K) floppy_track_buffer 0X006000(24K) kernel_code+text FREE 0X0A0000(640K RESERVED 0X100000(1M) pg_tables(4K)

swap_cache mem_map

bitmap FREE

Page 14: LINUX 存储管理

struct pagestruct page134 typedef struct page {134 typedef struct page {135 struct list_head list;135 struct list_head list;136 struct address_space *mapping; 136 struct address_space *mapping; 137 unsigned long index; 137 unsigned long index; /* /* 若该页帧的内容是文件,则若该页帧的内容是文件,则 indexindex 指出文件的指出文件的 inoino

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

Page 15: LINUX 存储管理

空闲内存的组织空闲内存的组织

Page 16: LINUX 存储管理

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

Page 17: LINUX 存储管理

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

Page 18: LINUX 存储管理

free_areafree_area 数组数组 LINUXLINUX 用用 free_areafree_area 数组记录空闲的物理页帧。数组记录空闲的物理页帧。 free_areafree_area 数数组由组由 NR_MEM_LISTSNR_MEM_LISTS 个个 free_area_structfree_area_struct 结构类型的数组元素结构类型的数组元素构成,每个元素均作为一条空闲块链表的表头。构成,每个元素均作为一条空闲块链表的表头。 struct free_area_struct {struct free_area_struct { struct page *next;struct page *next; /* /* 此结构的此结构的 next,prevnext,prev 指针与指针与 struct pagestruct page匹配 匹配 */*/ struct page *prev;struct page *prev; unsigned int * map; /* unsigned int * map; /* 指向指向 bitmap */bitmap */ };}; static struct free_area_struct free_area[NR_MEM_LISTS];static struct free_area_struct free_area[NR_MEM_LISTS]; 所有单个空闲页帧组成的链表挂到所有单个空闲页帧组成的链表挂到 free_areafree_area 数组的第数组的第 00 项项后面。连续后面。连续 22 i i 个空闲页帧则被挂到个空闲页帧则被挂到 free_areafree_area 数组的第数组的第 ii 项后面。项后面。

Page 19: LINUX 存储管理

操作函数操作函数• 分配内存块由分配内存块由 __get_free_pages()__get_free_pages() 函数和宏函数和宏定义定义 __get_free_page()__get_free_page() 执行执行• 释放内存块可以调用释放内存块可以调用 free_pages()free_pages() 函数执行。函数执行。

Page 20: LINUX 存储管理

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

Page 21: LINUX 存储管理

释放算法释放算法 回收空闲块时,回收空闲块时, change_bit()change_bit()函数根据函数根据 bitmapbitmap表的对应组,判断回收块的前后邻居是否也为空。表的对应组,判断回收块的前后邻居是否也为空。 若空则合并,即修改若空则合并,即修改 bitmapbitmap 表中对应位,从表中对应位,从 ff

ree_arearee_area 的空闲链表中取下该相邻块。的空闲链表中取下该相邻块。 此判断是个递归过程,直至找不到空闲邻居此判断是个递归过程,直至找不到空闲邻居为止。为止。 将最后合并的最大块插入将最后合并的最大块插入 free_areafree_area 的相应链的相应链表中。表中。

Page 22: LINUX 存储管理

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

Page 23: LINUX 存储管理

交换空间的格式交换空间的格式• 前前 40964096 字节是一个以字符串 “字节是一个以字符串 “ SWAP_SPSWAP_SP

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

Page 24: LINUX 存储管理

启用交换空间启用交换空间 int sys_swapon(const char * swapfile, int swapflags);int sys_swapon(const char * swapfile, int swapflags);

• 第一个参数第一个参数 swapfileswapfile 是设备名或文件名,是设备名或文件名,• swapflagsswapflags 规定交换空间的优先数。该参数中,规定交换空间的优先数。该参数中,

SWAP_FLAG_PREFERSWAP_FLAG_PREFER (( 0X80000X8000 )必须置位,)必须置位,SWAP_FLAG_PRIO_MASK(0X7FFF)SWAP_FLAG_PRIO_MASK(0X7FFF) 指 定 一 个指 定 一 个正的优先数。如果没有指定优先数,正的优先数。如果没有指定优先数, swaponswapon 自自动给出一个负的优先数,负优先数的取值决定动给出一个负的优先数,负优先数的取值决定于于 swaponswapon 的调用次数。的调用次数。

Page 25: LINUX 存储管理

每注册一个交换空间,就在每注册一个交换空间,就在 swap_infoswap_info 表中填一项表中填一项 swap_infswap_info_structo_struct 结构结构

2525 struct struct swap_info_swap_info_structstruct swap_infoswap_info[[MAX_SWAPFILESMAX_SWAPFILES];]; 4949 struct struct swap_info_swap_info_structstruct { { 5050 unsigned int unsigned int flagsflags; ; /* /* 如果如果 SWP_USEDSWP_USED 位置位,则被占用。如果位置位,则被占用。如果 SWP_WRITEOKSWP_WRITEOK ,则该交换空间准备就绪。 ,则该交换空间准备就绪。

*/*/ 5151 kdevkdev_t_t swap_device; swap_device; /* /* 对于交换设备,对于交换设备, swap_deviceswap_device 属性表示交换设备的主、次设备号 属性表示交换设备的主、次设备号 */*/ 5252 spinlockspinlock_t_t sdev_lock; /* sdev_lock; /* 对于此设备的互斥锁对于此设备的互斥锁 */*/ 5353 struct struct dentrydentry * swap_file; * swap_file; /* /* 对于交换文件,对于交换文件, swap_fileswap_file 属性指向该文件的属性指向该文件的 inode */inode */ 5454 struct struct vfsmountvfsmount *swap_vfsmnt; *swap_vfsmnt; 5555 unsigned short * swap_map;/* unsigned short * swap_map;/* 指向一张表,其每一字节按顺序对应交换空间的一个页面,字节的值代表了引指向一张表,其每一字节按顺序对应交换空间的一个页面,字节的值代表了引用该页面的进程数 用该页面的进程数 */*/ 5656 unsigned int lowest_bit; /* unsigned int lowest_bit; /* 交换空间中的第一个没有被任何进程使用的交换页在交换空间中的第一个没有被任何进程使用的交换页在 swap_mapswap_map 数组中的下标数组中的下标 */*/ 5757 unsigned int highest_bit; /* unsigned int highest_bit; /* 交换空间中最后一个没被任何进程使用的交换页的下标交换空间中最后一个没被任何进程使用的交换页的下标 */*/ 5858 unsigned int cluster_next; /* unsigned int cluster_next; /* 上次从当前的上次从当前的 clustercluster 中成功分配的交换页面的后继页面在中成功分配的交换页面的后继页面在 swap_mapswap_map 数组中的下数组中的下标标 */*/ 5959 unsigned int cluster_nr; /* unsigned int cluster_nr; /* 当前当前 clustercluster 中可供使用的交换页面的个数中可供使用的交换页面的个数 */*/ 6060 int prio; int prio; /*/*交换空间的优先级。优先级越高,交换文件申请交换页面的时候越优先考虑 交换空间的优先级。优先级越高,交换文件申请交换页面的时候越优先考虑 */*/ 6161 int pages; /* int pages; /* 表示该交换空间尚有多少空闲空间可供保存进程换出的物理页表示该交换空间尚有多少空闲空间可供保存进程换出的物理页 */*/ 62 unsigned long max;62 unsigned long max; 63 int next; 63 int next; /*/* 指向下一项交换空间的的指针 指向下一项交换空间的的指针 */*/ 64 };64 };153 struct swap_list_t {153 struct swap_list_t {154 int head; /* head of priority-ordered swapfile list */154 int head; /* head of priority-ordered swapfile list */155 int next; /* swapfile to be used next */155 int next; /* swapfile to be used next */156 };156 };23 struct swap_list_t swap_list = {-1, -1};23 struct swap_list_t swap_list = {-1, -1};

Page 26: LINUX 存储管理

注销交换空间注销交换空间

int sys_swapoff(const char * swapfile);int sys_swapoff(const char * swapfile);

Page 27: LINUX 存储管理

交换空间的工作交换空间的工作 kswapd 进程换出页面时,调用 try_to_swap_out() 测试页面的年龄。如果某物理页面可以换出,则调用 get_swap_page向 swap_list.next 指示的交换空间申请空闲页面,得到一地址

entry 。该地址写入进程页表中那个原来描述换出物理页面的页表项,替换了其中的页帧地址。最后,调用 rw_swap_page(), 将换出的物理页面写到 entry 指定的交换空间某个页面中。

反过来,当缺页中断发生时,缺页中断服务程序可以根据产生缺页的地址(由 CR2寄存器给出),找到描述该页面的页表项。页表项的 Present 位应该为 0 ,最高 20 位指出该页面保存在哪个交换空间的哪个页面中。然后,经一系列函数调用后,读入该页面。

Page 28: LINUX 存储管理

kswapdkswapd• 当物理页面不够时,利用当物理页面不够时,利用 kswapdkswapd 释放部分物理页面,将释放部分物理页面,将它们的内容写到交换空间。它们的内容写到交换空间。• kswapdkswapd 是一特殊的进程,称内核态线程(是一特殊的进程,称内核态线程( kernel threakernel threa

dd )。)。• 注意,注意, kernel threadkernel thread 完全不同于通常意义上的线程。它完全不同于通常意义上的线程。它是没有虚拟存储空间的进程,它只运行在内核态,直接是没有虚拟存储空间的进程,它只运行在内核态,直接使用物理地址空间。同类型的进程还有使用物理地址空间。同类型的进程还有 bdflushbdflush 和和 initinit 。。• kswapdkswapd 的作用超越了字面上的描述。它不仅能将页面换的作用超越了字面上的描述。它不仅能将页面换出到交换空间(交换区或交换文件),它也保证系统中出到交换空间(交换区或交换文件),它也保证系统中有足够的空闲页面以保持存储系统高效地运行。有足够的空闲页面以保持存储系统高效地运行。

Page 29: LINUX 存储管理

请求调页请求调页一旦一个可执行镜像映射到了一个进程的虚拟内存中,它就可以开始执行了。因为开始时只有镜像开头的一小部分装入到了系统的物理内存中,所以不久进程就会存取一些不在物理内存中的虚拟内存页,这时处理器会通知 L i n u x 发生了页面错误。页面错误将会描述页面错误发生时的虚拟内存地址和存取内存操作的类型。

Page 30: LINUX 存储管理

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

Page 31: LINUX 存储管理

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

Page 32: LINUX 存储管理

中断服务流程中断服务流程根据控制寄存器 CR2传递的缺页地址,找到用来表示出现缺页的虚拟存储区的 vm_area_struct 结构。如果没有找到与缺页相对应的 vm_area_struct 结构,那么说明进程访问了一个非法存储区, LINUX向进程发送信号 SIGSEGV 。接着检测缺页时访问模式是否合法。如果进程对该页的访问超越权限,例如试图对只允许读操作的页面进行写操作,系统也将向该进程发送一个信号,通知进程的存储访问出错。如果 Linux认为此页面错误是合法的,它将处理此页面错误。Linux还必须区分页面是在交换文件中还是作为文件镜像的一部分存在于磁盘中。它靠检查出错页面的页面表来区分:如果页面表的入口是无效的,但非空,说明页面在交换文件中。最后, Linux调入所需的页面并更新进程的页面表。

Page 33: LINUX 存储管理

页面置换页面置换当一个进程需要把一个虚拟内存页面装入到物理内存而又没有空闲的物理内存时,操作系统必须将一个现在不用的页面从物理内存中扔掉以便为将要装入的虚拟内存页腾出空间。选择换出页对换出页的处理

Page 34: LINUX 存储管理

检查是否存在可以从缓冲区中回收的块检查是否存在可以从缓冲区中回收的块 若无,试图回收共享内存保留的页框若无,试图回收共享内存保留的页框 若无,用近似的若无,用近似的 LRU(LRU(全局的最近最少使全局的最近最少使用)替代算法找到换出页。用)替代算法找到换出页。

页面置换页面置换

Page 35: LINUX 存储管理

页面换出页面换出 如果将要扔掉的物理内存页一直没有被改写过,则操作系统将不保存此内存页,而只是简单地将它扔掉。如果再需要此内存页时,再从文件镜像中装入。 但是,如果此页面已经被修改过,操作系统就需要把页面的内容保存起来。这些页面称为“脏页面”( dirty page )。当它们从内存中移走时,将会被保存到一个特殊的交换文件中。

Page 36: LINUX 存储管理

内存管理中的高速缓存内存管理中的高速缓存 硬件高速缓存:硬件高速缓存:一个常用的硬件高速缓存是在处理器中,它一般保存着页表的入口。( TLB) 页面高速缓存页面高速缓存 ::它的作用是加快对磁盘中的文件的存取 交换高速缓存:交换高速缓存:它只保存那些被修改过的页面。只要在页面被写入到交换文件中后没有被修改过,那么此页面下一次从内存中交换出来时就不用再写入到交换文件中了,因为交换文件中已经有了该页面。这样,该页面就可以简单地扔掉,节省了大量的系统操作。 缓冲区高速缓存缓冲区高速缓存

Page 37: LINUX 存储管理

页面高速缓存页面高速缓存 对于已经作好了磁盘映射的文件, L i n u x每次读取一页,并将读取的页面存储到页面高速缓存中。 页面高速缓存由 page_hash_table 组成, page_hash_table 是一个包含指向mem_map_t 结构指针的数组。 每当从一个内存映射文件中读取一个页面时,页面都要从页面高速缓存中读取。如果页面在高速缓存中,则将一个指向mem_map_t 的指针返回给页面错误处理程序。否则,页面必须从磁盘上读入到内存中。 如果可能, L i n u x 系统将会提前读取文件中的下一个页面,这样,如果文件是顺序执行的,那么下一个页面就已经在内存中了。随着文件的读入和执行,页面高速缓存也将变得越来越大。不用的页面将被移出高速缓存。

Page 38: LINUX 存储管理
Page 39: LINUX 存储管理

缓冲区高速缓存缓冲区高速缓存 缓冲区高速缓存中包含了用于块设备驱动程序的缓冲区高速缓存中包含了用于块设备驱动程序的数据缓冲区。这些缓冲区大小固定(例如 数据缓冲区。这些缓冲区大小固定(例如 512 512 字字节),包括从块设备读出的数据或者要写到块设节),包括从块设备读出的数据或者要写到块设备的数据。块设备用设备标识符和要访问的数据备的数据。块设备用设备标识符和要访问的数据块编号作为索引,用来快速定位数据块。块编号作为索引,用来快速定位数据块。 块设备只能通过缓冲区高速缓存存取。如果数据块设备只能通过缓冲区高速缓存存取。如果数据可以在缓冲区高速缓存中找到,那就不需要从物可以在缓冲区高速缓存中找到,那就不需要从物理块设备如硬盘上读取,从而使访问加快。 理块设备如硬盘上读取,从而使访问加快。 参见 参见 fs/buffer.cfs/buffer.c

Page 40: LINUX 存储管理

内存管理的常用命令内存管理的常用命令