⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 024_mm_vmalloc_c.html

📁 重读linux 2.4.2o所写的笔记
💻 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>|                  &amp; \~(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 &amp;= ~PMD_MASK;<br>	end = address + size;<br>	if (end &gt; 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) &amp;&amp; (!PageReserved(ptpage)))<br>				//VALID_PAGE 检查此区域是否分配了ram页面,ioremap可以影射vm_area为io内存<br>				//如果是VALID_PAGE(pagenr&lt;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 &lt; 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(&amp;vmlist_lock);<br>	for (p = &amp;vmlist; (tmp = *p) ; p = &amp;tmp-&gt;next) {<br>		if ((size + addr) &lt; addr) {<br>			write_unlock(&amp;vmlist_lock);<br>			kfree(area);<br>			return NULL;<br>		}<br>		if (size + addr &lt; (unsigned long) tmp-&gt;addr) //2 2.5 已经是&lt;=了<br>			break;<br>		addr = tmp-&gt;size + (unsigned long) tmp-&gt;addr;<br>		if (addr &gt; VMALLOC_END-size) {<br>			write_unlock(&amp;vmlist_lock);<br>			kfree(area);<br>			return NULL;<br>		}<br>	}<br>	area-&gt;flags = flags;<br>	area-&gt;addr = (void *)addr;<br>	area-&gt;size = size;<br>	area-&gt;next = *p;<br>	*p = area;<br>	write_unlock(&amp;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 + -