我很久沒研究kernel,
這個文章是我幾年前吧,
隨意寫下的手扎,
是我直接看source code, 並且改kernel測試的.
2.6.xx(我忘了何時我寫的)...
供有興趣的人,
參考看看吧...
如下:
因為一開始先map 8MB,
所以若有大於8MB array,
立刻當
====
reserve_bootmem(phys_addr, size); ==> 若存取, 正常, 因為系統"早"有page對應
free_bootmem(phys_addr, size);
add_memory_region(0x100000, 0x1000000-0x100000, E820_RAM);
cat /proc/meminfo所得到記憶體大小是, 所有add_memory_region-_end-reserve_bootmem
copy_to_user
copy_from_user
pci_alloc_consistent
pci_free_consistent
*******************
*******************
struct task_struct
{
struct mm_struct *mm, *active_mm;
};
struct mm_struct
{
struct vm_area_struct *mmap;
};
struct vm_area_struct ==> 只跟user virtual space有關
{
unsigned long vm_start;
unsigned long vm_end;
struct vm_area_struct *vm_next;
};
get_unmapped_area ==> 取得可用的user virtual space
get_user_pages
*******************
*******************
對於user space已經被配置的記憶體空間,
是由很多個vm_area_struct一塊一塊組成.
*******************
*******************
對於kernel space已經被配置的記憶體空間,
是由很多個vm_struct一塊一塊組成.
*******************
=====================================
=====================================
=====================================
=====================================
=====================================
=====================================
=====================================
=====================================
=====================================
=====================================
=====================================
=====================================
=====================================
假設RAM共512MB
=====================================
<arch/i386/kernel/head.S>
startup_32:
裡面會設定cr3,只mapping 8MB的page table
start_kernel->setup_arch
{
XXX // 8MB
setup_memory_region();
/*
kernel會利用add_memory_region把一塊一塊BIOS偵測到的memory加入, 若memory region是
E820_RAM表示usable
*/
XXX
parse_cmdline_early
{
limit_regions(mem_size);
/*
若下mem=64M這個kernel command, 就會使用使用者定義的RAM size,
之前add_memory_region的記憶體區塊, 都一樣不變,
只是這個function會微微修改記憶體區塊, 變成64MB, 重要的是, 64MB以內跟之前BIOS給的都一樣!!
*/
}
XXX
setup_memory
{
XXX
start_pfn = PFN_UP(__pa(_end));
XXX
find_max_pfn();
/*
找add_memory_region加入的記憶體區塊, 最最高的address
*/
max_low_pfn = find_max_low_pfn();
XXX
bootmap_size = init_bootmem(start_pfn, max_low_pfn);
/*
設定全域性struct pglist_data *pgdat_list = &contig_page_data;
從0到max_low_pfn全部都reserve
contig_page_data.bdata->node_bootmem_map =
phys_to_virt(start_pfn << PAGE_SHIFT); ==> bootmem自定的page表,1byte表示8個
pages.
contig_page_data.bdata->node_boot_start = 0;
contig_page_data.bdata->node_low_pfn = max_low_pfn;
執行完後, 自定的表node_bootmem_map裡面紀錄, 所有page都被reserve!! ==>
0-512MB, 共512MB整, 都被reserve
*/
register_bootmem_low_pages(max_low_pfn);
/*
會把node_bootmem_map裡面, 不是E820_RAM的pages全部free_bootmem,
也就是現在所有max_low_pfn內的E820_RAM的pages都可以被自由alloc, 其餘所有pages都被
reserve,
簡單而言 ==> 已經完全把setup_memory_region(或limit_regions), 轉成變成
node_bootmem_map
*/
/* 從這裡開始, 就可以使用reserv_bootmem, 只會設定contig_page_data.bdata-
>node_bootmem_map這個bitmap, 其它事不做. */
/* kernel會用reserve_bootmem把vmlinux reserve起來, 從1MB到
virt_to_phys(_end) */
}
XXX // 8MB
paging_init()
{
pagetable_init(); /* mapping整個max_low_pfn, 當執行完後, 8MB變成512MB, 從
0xc0000000開始 */
XXX
zone_sizes_init
{
XXX
free_area_init(zones_size);
/*
contig_page_data.node_spanned_pages = 是指全部全部(DMA,
NORMAL, HIGHMEM)的pages總合
contig_page_data.node_mem_map是指node_spanned_pages個pages
==> kernel自定page table(struct page) ==> 跟pfn_to_page, page_to_pfn有關.
裡面會呼叫一些functions, 用SetPageReserved把
contig_page_data.node_mem_map全部都reserve
最後讓全域性struct page *mem_map =
contig_page_data.node_mem_map;
*/
}
}
XXX // 512MB
}
start_kernel->mem_init
{
XXX
high_memory = (void *) __va(max_low_pfn * PAGE_SIZE);
/* 在這裡仍可以使用reserve_bootmem */
totalram_pages += __free_all_bootmem();
/*
呼叫ClearPageReserved把可以alloc的page設定好
原理是把contig_page_data.bdata->node_bootmem_map轉成
contig_page_data.node_mem_map
最後讓contig_page_data.bdata->node_bootmem_map = NULL;
P.S HIGHMEM這塊zone整塊徹底還是被reserve
*/
/* 從此不能使用reserve_bootmem */
}
=====================================
=====================================
=====================================
=====================================
mem_map, contig_page_data.node_mem_map, pfn_to_page, page_to_pfn等等,
根據我非官方觀察,
只要跟struct page有關,
就是,
只跟RAM有關, 也就是從PAGE_OFFSET算, 大小是RAM size那塊!!
=====================================
=====================================
=====================================
=====================================
=====================================
=====================================
=====================================
=====================================
=====================================
=====================================
=====================================
=====================================
=====================================
=====================================
=====================================
=====================================
=====================================
=====================================
vmalloc運作原理
=====================================
get_vm_area
alloc_page
map_vm_area
=====================================
=====================================
=====================================
=====================================
=====================================
=====================================
=====================================
=====================================
=====================================
vfree運作原理
=====================================
remove_vm_area(這個function裡面會呼叫unmap_vm_area)
__free_page
=====================================
=====================================
=====================================
=====================================
=====================================
=====================================
=====================================
=====================================
=====================================
ioremap運作原理
=====================================
get_vm_area
remap_area_pages
=====================================
=====================================
=====================================
=====================================
=====================================
=====================================
=====================================
=====================================
=====================================
iounmap運作原理
=====================================
remove_vm_area(這個function裡面會呼叫unmap_vm_area)
=====================================
=====================================
=====================================
=====================================
=====================================
*****************************
*****************************
*****************************
*****************************
*****************************
*****************************
*****************************
*****************************
記住,
Linux有自己memory管理機制,
有自己free pages之類的list,
所以!!!!!
若是alloc_page或是__free_page等等的page,
其struct page也絕對不可能是reserve狀態!!!!!!!!!
*****************************
*****************************
*****************************
*****************************
*****************************
*****************************
*****************************
***************************************************************
GFP_USER - Allocate memory on behalf of user. May sleep.
GFP_KERNEL - Allocate normal kernel ram. May sleep.
GFP_ATOMIC - Allocation will not sleep. Use inside interrupt handlers.
Additionally, the GFP_DMA flag may be set to indicate the memory must
be suitable for DMA. This can mean different things on different
platforms. For example, on i386, it means that the memory must come
from the first 16MB.
***************************************************************
--
CIH
Software Magician