📄 024_mm_vmalloc_c.html
字号:
<html lang="zh-CN" xmlns:gdoc=""> <head> <meta content="text/html; charset=utf-8" http-equiv="Content-Type"> <style type="text/css">/* default css */table { font-size: 1em; line-height: inherit;}div, address, ol, ul, li, option, select { margin-top: 0px; margin-bottom: 0px;}p { margin: 0px;}body { margin: 0px; padding: 0px; font-family: Verdana, sans-serif; font-size: 10pt; background-color: #ffffff;}h6 { font-size: 10pt }h5 { font-size: 11pt }h4 { font-size: 12pt }h3 { font-size: 13pt }h2 { font-size: 14pt }h1 { font-size: 16pt }blockquote {padding: 10px; border: 1px #DDD dashed }a img {border: 0}div.google_header, div.google_footer { position: relative; margin-top: 1em; margin-bottom: 1em;}/* end default css */ /* default print css */ @media print { body { padding: 0; margin: 0; } div.google_header, div.google_footer { display: block; min-height: 0; border: none; } div.google_header { flow: static(header); } /* used to insert page numbers */ div.google_header::before, div.google_footer::before { position: absolute; top: 0; } div.google_footer { flow: static(footer); } /* always consider this element at the start of the doc */ div#google_footer { flow: static(footer, start); } span.google_pagenumber { content: counter(page); } span.google_pagecount { content: counter(pages); } } @page { @top { content: flow(header); } @bottom { content: flow(footer); } } /* end default print css */ /* custom css *//* end custom css */ /* ui edited css */ body { font-family: Verdana; font-size: 10.0pt; line-height: normal; background-color: #ffffff; } .documentBG { background-color: #ffffff; } /* end ui edited css */</style> </head> <body revision="dcbsxfpf_64dxmgrzfj:5"> <table align=center cellpadding=0 cellspacing=0 height=5716 width=768>
<tbody>
<tr>
<td height=5716 valign=top width=100%>
<pre>2006-8-10 <br>mm/vmalloc.c<br><br> 还是分析highmem的那张图,现在关注vmalloc使用的虚拟地址空间:<br>+------------------------------------------------------------------ <br><br>| 8K空洞<br><br>+------------------------------------------------------------------<br><br>| FIXADDR_TOP(0xffffe000UL) (include/asm-i386/fixmap.h)<br><br>| fixed map(每项4k虚存,见FIXADDR_SIZE) <br><br>| { //fix map 内容 (enum fixed_addresses)<br><br>| FIX_APIC_BASE, <br><br>| FIX_IO_APIC_BASE_0,<br><br>| FIX_IO_APIC_BASE_END = FIX_IO_APIC_BASE_0 + MAX_IO_APICS-1<br><br>| <br><br>| FIX_CO_CPU, /* Cobalt timer */<br><br>| FIX_CO_APIC, /* Cobalt APIC Redirection Table */ <br><br>| FIX_LI_PCIA, /* Lithium PCI Bridge A */<br><br>| FIX_LI_PCIB, /* Lithium PCI Bridge B */<br><br>+--------------<br><br>#ifdef CONFIG_HIGHMEM /*为fix KMAP预留每cpu 8k的虚存,读写各4k*/<br><br>| FIX_KMAP_BEGIN, /* 主要用于kmap_atomic*/<br><br>| FIX_KMAP_END = FIX_KMAP_BEGIN+(KM_TYPE_NR*NR_CPUS)-1,<br><br>#endif<br><br>+--------------<br><br>| __end_of_fixed_addresses<br><br>| }<br><br>| FIXADDR_START (FIXADDR_TOP - FIXADDR_SIZE)<br><br>+--------------------------------------------------------------------<br><br>| VMALLOC_END (FIXADDR_START) (include/asm-i386/pgtable.h)<br><br>| +------------------<br><br>| | xxxxx: kmap 和 vmalloc 相互重叠,2.6已经修正<br><br>| | kmap 使用的4M虚存 (asm/highmem.h,LAST_PKMAP)<br><br>| | PKMAP_BASE (0xfe000000UL) (距离4G 32M)<br><br>| +------------------<br><br>| vmalloc 映射区<br><br>| VMALLOC_START (((unsigned long) high_memory + 2*VMALLOC_OFFSET-1)<br><br>| & \~(VMALLOC_OFFSET-1)) /*down align 8M */<br><br>+--------------------------------------------------------------------<br><br>| 约 8M 空洞<br><br>+--------------------------------------------------------------------<br><br>| high_memory (见003___arch_i386_mm_ioremap.c 对此的分析) <br><br>| 内核已经映射了的物理页面 MAX 896M<br><br>| 3G<br><br>+--------------------------------------------------------------------<br><br>| resoved for app 0-3G<br><br>+--------------------------------------------------------------------<br><br><br> vmalloc使用的虚拟内存空间大概数值是百十来M.(详细计算略).分配给内核自己使用的大<br>的虚拟地址, ioremap和vmalloc使用相同的虚拟地址. 见arch/i386/ioremap.c的分析.<br> 管理vmalloc的虚拟内存的结构是vm_struct,而管理进程的虚拟空间使用的是vma,不一样的.<br>所有的vm_struct按顺序挂入<br> struct vm_struct * vmlist;<br> <br> 至于分配释放算法,实在没有什么跟多东西可讲.不要说我偷懒啊.ioremap.c中已经讲过释放<br>时候对vmalloc分配和ioremap映射的区别处理了.去看看吧. 就是函数:<br> void free_area_pte()<br>{<br> pte_t * pte;<br> unsigned long end;<br><br> if (pmd_none(*pmd))<br> return;<br> if (pmd_bad(*pmd)) {<br> pmd_ERROR(*pmd);<br> pmd_clear(pmd);<br> return;<br> }<br> pte = pte_offset(pmd, address);<br> address &= ~PMD_MASK;<br> end = address + size;<br> if (end > PMD_SIZE)<br> end = PMD_SIZE;<br> do {<br> pte_t page;<br> page = ptep_get_and_clear(pte);<br> address += PAGE_SIZE;<br> pte++;<br> if (pte_none(page))<br> continue;<br> if (pte_present(page)) {<br> struct page *ptpage = pte_page(page);<br> if (VALID_PAGE(ptpage) && (!PageReserved(ptpage)))<br> //VALID_PAGE 检查此区域是否分配了ram页面,ioremap可以影射vm_area为io内存<br> //如果是VALID_PAGE(pagenr<max_mapnr)<br> __free_page(ptpage);<br> continue;<br> }<br> printk(KERN_CRIT "Whee.. Swapped out page in kernel page table\n");<br> } while (address < end);<br>}<br><br> <br> <br> 另外vread,提供了内核内存读区功能,仅读取vmalloc部分的数据.get_vm_area中有一个<br>小小的bug?,见注释:<br>struct vm_struct * get_vm_area(unsigned long size, unsigned long flags)<br>{<br> unsigned long addr;<br> struct vm_struct **p, *tmp, *area;<br><br> area = (struct vm_struct *) kmalloc(sizeof(*area), GFP_KERNEL);<br> if (!area)<br> return NULL;<br> size += PAGE_SIZE; //空洞, 用于扑捉可能的越界<br> addr = VMALLOC_START;<br> write_lock(&vmlist_lock);<br> for (p = &vmlist; (tmp = *p) ; p = &tmp->next) {<br> if ((size + addr) < addr) {<br> write_unlock(&vmlist_lock);<br> kfree(area);<br> return NULL;<br> }<br> if (size + addr < (unsigned long) tmp->addr) //2 2.5 已经是<=了<br> break;<br> addr = tmp->size + (unsigned long) tmp->addr;<br> if (addr > VMALLOC_END-size) {<br> write_unlock(&vmlist_lock);<br> kfree(area);<br> return NULL;<br> }<br> }<br> area->flags = flags;<br> area->addr = (void *)addr;<br> area->size = size;<br> area->next = *p;<br> *p = area;<br> write_unlock(&vmlist_lock);<br> return area;<br>}<br><br> <br> vm_struct管理的虚拟地址所映射的页面,或者是内核使用的page,或者是reserve的page<br>或者干脆就不是内核的mem_map所能管理的了的(见ioremap).当然不会被swap. page的引用<br>计数应该是1.(fix me).<br><br></pre>
</td>
</tr>
</tbody>
</table></body></html>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -