读核笔记(6) - 虚拟存储

本来想看完pagefault的处理的,不过实验室有事情了,只能先把这一半放上来了。

页面的分配与回收使用了一个叫做buddy allocator的机制,kernelnewbies上的解释
The memory allocation scheme used in the kernel. A vector of lists of free pages is kept, ordered by the size of the chunk (in powers of two). When a chunk is allocated, it is removed from the relevant list. When a chunk is freed back to the free pages pool, it is placed in the relevant list, starting from the top. If it is physically contiguous with a present chunk, they are merged and placed in the list above (i.e. where the chunks are twice the size), and this operation percolates up the vector. As regions are merged whenever possible, this design helps to reduce memory fragmentation.

首先在zone_struct{} 中保存了一个free_area_t数组,这个数组记录了各种大小的空闲内存块的信息。
include/linux/mmzone.h:


/**/ /*
 * On machines where it is needed (eg PCs) we divide physical memory
 * into multiple physical zones. On a PC we have 3 zones:
 *
 * ZONE_DMA      < 16 MB    ISA DMA capable memory
 * ZONE_NORMAL    16-896 MB    direct mapped by the kernel
 * ZONE_HIGHMEM     > 896 MB    only page cache and user processes
 
*/

typedef 
struct  zone_struct  {
    
/**/ /*
     * Commonly accessed fields:
     
*/

    spinlock_t        
lock ;
    unsigned 
long         free_pages;
    unsigned 
long         pages_min, pages_low, pages_high;
    
int             need_balance;

    
/**/ /*
     * free areas of different sizes
     
*/

    
//  数组中每个元素依次维护1个pagesize,2个pagesize,4个pagesize……的空闲块的链表
    free_area_t        free_area[MAX_ORDER];  

    
/**/ /*
     * Discontig memory support fields.
     
*/

    
struct  pglist_data     * zone_pgdat;
    
struct  page         * zone_mem_map;
    unsigned 
long         zone_start_paddr;
    unsigned 
long         zone_start_mapnr;

    
/**/ /*
     * rarely used fields:
     
*/

    
char              * name;
    unsigned 
long         size;
}
 zone_t;

free_area_struct {}

typedef struct free_area_struct {
    
struct list_head    free_list;
    unsigned 
long        *map;       // 某个特定大小的页面块分配情况的位图
}
 free_area_t;

页面分配时,找到适合大小的free_area_struct{},然后从free_list中找有没有空闲的内存块,如果没有就找更大的free_area_struct{},因为大小都是2^n,很容易把大块内存拆开,一块分配给请求,剩下的保存到对应大小的队列中。
页面回收时主要的问题是如何解决过多的内存碎片。当页面块被释放时,先检查是否有相同大小的相邻空闲块存在,如果有的话就结合起来(递归过程)。

你可能感兴趣的:(读核笔记(6) - 虚拟存储)