物理页面的使用和周转

来源:互联网 发布:dos编译两个java文件 编辑:程序博客网 时间:2024/03/29 15:50


交换设备(通常是磁盘,也可以是普通文件)的每个物理页面也要在内存中有个相应的数据结构(或者说“户口”),不过相对简单一些,实际只是一个计数,表示该页面是否也被分配使用。以及有几个用户在共享这个页面。对盘上页面的管理是按文件或磁盘设备来进行的。内核中定义一个swap_info_struct数据结构,用以描述和管理用于页面交换的文件和设备。



struct swap_info_struct {/** * 交换区标志 */unsigned int flags;/**  * 保护交换区的自旋锁。 */spinlock_t sdev_lock;/** * 指针,指向存放交换区的普通文件或设备文件的文件对象。 */struct file *swap_file;/** * 存放交换区的块设备描述符。 */struct block_device *bdev;/** * 指向交换区的子区链表的头部。 */struct list_head extent_list;/** * 组成交换区的子区数量。 */int nr_extents;/** * 指向最近使用的子区描述符的指针。 */struct swap_extent *curr_swap_extent;/** * 存放交换区的磁盘分区自然块大小。 */unsigned old_block_size;/** * 指向计数器数组的指针,交换区的每个页槽对应一个数组元素。 */unsigned short * swap_map;/** * 在搜索一个空闲页槽时要扫描的第一个页槽。 */unsigned int lowest_bit;/** * 在搜索一个空闲页槽时要扫描的最后一个页槽。 */unsigned int highest_bit;/** * 在搜索一个空闲页槽时要扫描的下一个页槽。 */unsigned int cluster_next;/** * 在从头重新开始扫描之前空闲页槽的分配次数? */unsigned int cluster_nr;/** * 交换区优先级。 */int prio;/* swap priority *//** * 可用页槽的个数。 */int pages;/** * 交换区的大小,以页为单位。 */unsigned long max;/** * 交换区内已用页槽数。 */unsigned long inuse_pages;/** * 指向下一个交换区描述符的指针。 */int next;/* next entry on swap list */};

除上文注释还要注意,swap_map[0]所代表的那个页面不用于页面交换的,它包含了该设备或文件本身的一些信息以及一个表明那些页面可供使用的位图。

Linux内核允许使用多个页面交换设备(或文件),所以在内核中建立了一个swap_info_struct结构数组swap_info ;

struct  swap_info_struct swap_info[MAX_SWAPFILES];

内核还设立队列swap_list,将各个可以分配物理页面的磁盘设备或文件的swap_info_struct结构按优先级高地连接在一起;


磁盘上也有类似于pte_t数据结构(页面表项,将物理内存页面与虚拟页面建立联系),就是swap_entry_t数据结构;

swap_entry_t结构实际只是32为无符号整数,但是分为了三部分;高24位(offset)表示页面在一个磁盘设备或文件中的位置,也就是文件中的逻辑页面号;而(bit1-bit7)type则是指该页面在哪一个文件中,是一个序号。bit0永远为0;当为1代表的是pte_t;


只有映射到用户空间的页面才会被换出,内核空间不可以,内核可以访问所有的物理页面。

按页面的内容和性质,用户空间的页面有以下几种:

1)普通的用户空间页面,包括进程的代码段、数据段、堆栈段,以及动态分配的“堆存储”。其中有些页面从用户程序即进程的角度看是静态的(如代码段),但从系统的角度看仍是动态分配的。

2)通过系统调用mmap()映射到用户空间的已打开文件的内容。

3)进程间的共享内存区

==================================================================================================内核代码和内核全区量所占的内存页面既不需要经过分配也不会释放。

此外内核中使用的内存页面也要经过动态分配,但永远都保存在内存中,不会被交换出去。此类常驻内存根据其内容的性质可以分成两类;

(1)一类时一旦使用完毕便无保存价值,所以立即便可释放、回收。

(2)另一类时虽然使用完毕了,但是其内容仍有保存的价值。只要条件允许,几把这些页面“养起来”也许可以提高以后的操作效率。这类页面(或数据结构)在"释放"之后要放入一个LRU队列,经过一段时间的缓冲让其“老化”;如果在此期间又要用到其内容,便直接将页面内容分配给“用户”,否则便继续老化,直到条件不再允许时才加以回收。

=================================================================================================================================

页面交换最简单的是每当缺页异常便分配一个内存页面,并把磁盘上的页面读入到分配的内存页面上。而没有空闲页面可供分配时,将设法将一个或几个内存页面换出到磁盘上。从而腾出一些内存页面。这种方式比较消极,在系统忙碌的时候会没有调度的余地;积极地方式是采用定期,相对空闲时预先腾出一些内存页面(LRU,最近最少使用页面);但也可能导致页面抖动;

防止此情况,可以将页面的换出和页面的释放分两步进行;

当系统挑选若干页面准备换出的时候,将这些页面的内容写入相应的磁盘页面中,并将页面表项的标志位P改为0(表示不在内存中)。然后将page页面留在暂存(cache)队列中(缓冲队列),【将“现役”转为“预备役”】。再次受到访问,建立映射就好,不需要读入盘中内容。

在内核中设置了active_list和inactive_dirty_list两个LRU队列,在每个页面管理区设置了一个inactive_clean_list;

内核采用“拖延战术”,如果自从最近一次换入该页面以后从未写过这个页面,那么这个页面是“干净”,不用写出去;其次,即使是“脏”的页面,也不立即写出,而先断开页面映射表,经过一段时间的“冷却”或“老化”后写出去,从而变成“干净”页面,至于干净页面可以在继续缓冲到真有必要时再回收,回收一个“干净”页面花费很小。







阅读全文
0 0
原创粉丝点击