Linux Kernel(2.6)の実装に関するメモ書き

ページ管理


物理ページ管理(Buddy System)


全物理ページの管理テーブル

	mem_map_t *mem_map <-- struct page *
	+-------------------+
	| 0   struct page   | Idx = physical_address >> 12
	|                   | (ページフレーム#がIndexとなる。1Page 4KByte)
	+-------------------+
	| 1                 |
	|                   |
	+-------------------+
		:
	+-------------------+
	| max_mapnr - 1     | zone:所属zoneへのポインタ
	|                   | virtual:該当ページの仮想アドレス(0xc0000000 + 物理アドレス)
	+-------------------+		free_area_init_coreで設定

Zone
	物理メモリを3種類(DMA,NORMAL,HIGHMEM)のZoneに分けて管理する。
	Zone内のページは物理的に連続ページとなる。
	各Zoneは2^n Pageの単位で物理Pageの割り当てを行う。
	各ページは必ずどれかのZoneに属する。

	contig_page_data
	+-----------------+ node_zones[]
	| ZONE_DMA        |
	|                 |
	|                 |
	|                 |
	+-----------------+
	| ZONE_NORMAL     | free_area[MAX_ORDER]:2^n PageSize毎にBitmapで使用状況を管理
	|                 | zone_mem_map:Zone先頭Pageの該当mem_mapへのポインタ
	|                 | zone_start_mapnr:Zone先頭Pageの該当mem_mapのindex
	|                 | zone_start_paddr:Zone先頭Pageの物理アドレス
	+-----------------+
	| ZONE_HIGHMEM    |    ^
	|                 |    |
	|                 |    |
	|                 |    |
	+-----------------+ node_zonelists[]
	| ZONE_DMA *      |    |
	+-----------------+    |
	| ZONE_NORMAL *   |----+
	+-----------------+
	| ZONE_HIGHMEM *  |
	+-----------------+
	| NULL            |
	+-----------------+
		:
		:

	free_area[] Example
					Page	bitmap size(exp. 4096Page)
	free_area[0].map		   1	255Byte
	free_area[1].map		   2	127Byte
	free_area[2].map		   4	63Byte
		:
	free_area[7].map		 128	1Byte
		:
	free_area[MAX_ORDER(10)].map	1024	0Byte
						Total 502Byte???


pg_data_t contig_page_data
	  後述



[初期化]
start_kernel()
	:
	setup_arch()
		:
		paging_init()
			pagetable_init()
				PTEを設定
					仮想アドレス0xc0000000〜__va(max_low_pfn*PAGE_SIZE)を
					物理アドレス0x00000000へストレートマッピング
					max_low_pfn:RAMの最後の物理ページ番号
					<-- e820hのBIOSコールで取得したメモリマップから計算される。
						メモリマップの内容は起動時にDmesgに出力されている。
			:
			free_area_init()
				free_area_init_core()
					全ページ分の管理テーブル用バッファを確保し、mem_mapに登録
					全ページReservedにする。
					ZoneListもここで初期化する。
					各ページの仮想アドレス(page->virtual)もここで設定


[ページの割り当て]
alloc_pages(gfp_mask, order)

	指定したZoneのfree listから 2^order Pageを取得する。
	Zoneはgfp_maskの種類によって選択される。

	取得したらZoneのfree_areaのBitmapを立てる。
	page->countも1にする。

	該当物理ページのmem_mapポインタを返す。


[メモリマップ例]
	BIOS-provided physical RAM map:
	 BIOS-e820: 0000000000000000 - 000000000009f800 (usable) <-- RAM領域
	 BIOS-e820: 000000000009f800 - 00000000000a0000 (reserved)
	 BIOS-e820: 00000000000e2800 - 0000000000100000 (reserved)
	 BIOS-e820: 0000000000100000 - 000000000bff0000 (usable) <-- RAM領域
	 BIOS-e820: 000000000bff0000 - 000000000bfff800 (ACPI data)
	 BIOS-e820: 000000000bfff800 - 000000000c000000 (ACPI NVS)
	 BIOS-e820: 00000000fff80000 - 0000000100000000 (reserved)
	On node 0 totalpages: 49136
	zone(0): 4096 pages.	<-- DMA     0x00000000 - 0x01000000
	zone(1): 45040 pages.	<-- NORMAL  0x01000000 - 0x0bff0000
	zone(2): 0 pages.	<-- HIGHMEM


[関連構造体]
typedef struct page {
        struct list_head list;          /* ->mapping has some page lists. */
        struct address_space *mapping;  /* The inode (or ...) we belong to. */
        unsigned long index;            /* Our offset within mapping. */
        struct page *next_hash;         /* Next page sharing our hash bucket in
                                           the pagecache hash table. */
        atomic_t count;                 /* Usage count, see below. */
        unsigned long flags;            /* atomic flags, some possibly
                                           updated asynchronously */
        struct list_head lru;           /* Pageout list, eg. active_list;
                                           protected by pagemap_lru_lock !! */
        wait_queue_head_t wait;         /* Page locked?  Stand in line... */
        struct page **pprev_hash;       /* Complement to *next_hash. */
        struct buffer_head * buffers;   /* Buffer maps us to a disk block. */
        void *virtual;                  /* Kernel virtual address (NULL if
                                           not kmapped, ie. highmem) */
        struct zone_struct *zone;       /* Memory zone we are in. */
} mem_map_t;

物理ページの管理構造体 (1Pageにつき1エントリ)
	index	mapping内でのオフセット(Page単位)
	virtual	該当物理ページに対応するカーネル仮想アドレスを示す
		(0xc0000000からストレートマップされた値)
		<-- Kernel2.6ではarchによってはなくなる
			virtualがない場合、page_address()は
			page - mem_mapからページフレーム#を求め物理アドレスを計算する。
			0xc0000000を加えてカーネル仮想アドレスを取得する。

			この作りからもstruct pageは起動時に作成されたmem_mapにしか
			存在しないことがわかる。
			(後から動的にstruct pageが確保されるようなことはない。)


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
         */
        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;

typedef struct pglist_data {
	zone_t node_zones[MAX_NR_ZONES];
	zonelist_t node_zonelists[GFP_ZONEMASK+1];
	int nr_zones;
	struct page *node_mem_map;
	unsigned long *valid_addr_bitmap;
	struct bootmem_data *bdata;
	unsigned long node_start_paddr;
	unsigned long node_start_mapnr;
	unsigned long node_size;
	int node_id;
	struct pglist_data *node_next;
} pg_data_t;

最終更新 2006/03/27 14:12:11 - kztomita
(2006/03/27 14:12:11 作成)


リンク
最近更新したページ
検索