﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>C++博客-巢穴-随笔分类-linux内核</title><link>http://www.cppblog.com/ccl0326/category/16274.html</link><description>about:blank</description><language>zh-cn</language><lastBuildDate>Tue, 15 Mar 2011 12:14:21 GMT</lastBuildDate><pubDate>Tue, 15 Mar 2011 12:14:21 GMT</pubDate><ttl>60</ttl><item><title>linux内核情景分析笔记-存储管理</title><link>http://www.cppblog.com/ccl0326/archive/2011/03/15/141904.html</link><dc:creator>Vincent</dc:creator><author>Vincent</author><pubDate>Tue, 15 Mar 2011 09:47:00 GMT</pubDate><guid>http://www.cppblog.com/ccl0326/archive/2011/03/15/141904.html</guid><wfw:comment>http://www.cppblog.com/ccl0326/comments/141904.html</wfw:comment><comments>http://www.cppblog.com/ccl0326/archive/2011/03/15/141904.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/ccl0326/comments/commentRss/141904.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/ccl0326/services/trackbacks/141904.html</trackback:ping><description><![CDATA[<p>第2章 存储管理<br>LINUX页式管理<br>PGD&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; PMD&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; PT&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; PTE<br>页表目标&nbsp;&nbsp;&nbsp;&nbsp; 中间目录&nbsp;&nbsp;&nbsp;&nbsp; 页表&nbsp;&nbsp;&nbsp;&nbsp; 页表项</p>
<p>LINUX在32位地址下采取二层映射<br>#define PGDIR_SHIFT 22<br>#define PTRS_PER_PGD 1024</p>
<p>#define PMD_SHIFT 22<br>#define PTRS_PER_PMD 1</p>
<p>#define PTRS_PER_PTE 1024<br>根据以上宏定义,PMD被完美的架空了，而相当于采取了二层映射</p>
<p>其中PGD用了线性地址的最高10位 与&nbsp; MMU 对应<br>线性地址的中间10位是所对应的PTE在PT中的索引<br>剩下的最低12位则是页中的偏移量</p>
<p>虚拟地址 = 段基地址：段偏移量<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 16位&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 32位<br>更准确的讲是段选择子了吧<br><br></p>
<p>在LINUX中段基地址 = 0（下面的____KERNEL_CS等），所以可以认为线性地址与虚拟地址总是相等的，但其本质不是一个东西<br></p>
<p><br>0xC0000000-0xFFFFFFFF为内核占用<br>0x0-0xBFFFFFFF为用户控件 </p>
<p><br>内核的虚拟内存为简单的线性映射<br>#__PAGE_OFFSET (0xC0000000)<br>#define PAGE_OFFSET&nbsp; ((unsigned long) __PAGE_OFFSET)<br>#define __pa(x) ((unsigned long)(x) - PAGE_OFFSET)<br>#define __va(x)&nbsp;((void *)((unsigned long)(x) +PAGE_OFFSET)</p>
<p>__pa是从虚拟地址转换成物理地址<br>__va是从物理地址转换成虚拟地址</p>
<p><br>在GDT中有4个段描述符<br>其索引是2-5<br>分别是<br>__KERNEL_CS&nbsp;内核代码段<br>__KERNEL_DS&nbsp;内核数据段<br>__USER_CS&nbsp;用户代码段<br>__USER_DS&nbsp;用户数据段</p>
<p>#define start_thread(regs,new_eip,new_esp) do {\<br>&nbsp;__asm__("movl %0,%%fs;movl %0,%%gs"::"r"(0)); \<br>&nbsp;set_fs(USER_DS);<br>&nbsp;regs-&gt;xds = __USER_DS;&nbsp;\<br>&nbsp;regs-&gt;xes = __USER_DS; \<br>&nbsp;regs-&gt;xss = __USER_DS; \<br>&nbsp;regs-&gt;xcs = __USER_CS; \<br>&nbsp;regs-&gt;eip = new_eip;&nbsp;&nbsp; \<br>&nbsp;regs-&gt;esp = new_esp;&nbsp;&nbsp; \</p>
<p>}while(0)</p>
<p>通过这段宏可以看出，LINUX没用段式存储，虽然它也走了这个流程</p>
<p>&nbsp;</p>
<p>MMU的流程 MMU使用物理地址</p>
<p>页式映射<br>从REG CR3拿PGD的地址<br>找到页面目录，线性地址中的高10位为索引，找到页面目录项，从中拿高20位作为页面表的索引，页面表与4k字节边界对齐，CPU自动补充前12位为0得到页面表地址。</p>
<p>然后拿线性地址的中间10位，得到页面表中的索引，拿到页面表项，页面表项的高20位在低位补充12个0，再加上线性地址的低12位组成物理地址。</p>
<p><br>mm_struct 任务相关的虚拟内存<br>vm_area_struct 一段虚拟内存的抽象，也可以理解为段<br>mm_struct中拥有vm_area_struct的指针<br>在vm_area_struct多的时候使用avl树来存储<br>mem_map_t&nbsp; 物理页表<br>zone_struct 物理内存的区结构，zone_struct把物理内存分成了几个部分<br>ZONE_DMA 0&nbsp;供DMA使用<br>ZONE_NORMAL&nbsp;普通使用<br>ZONE_HIGHMEN&nbsp;高段内存，内核映射不到</p>
<p>物理内存之间区的划分并不是强制的，如果某一个区已经没有内存可用，是可以去别的区拿内存的</p>
<p>其实一直对内核的寻址有些疑问<br>不过刚刚似乎想通了<br>内核会做预映射，把PGD第768项以后的都做映射，也就是1G的空间<br>而这种映射应该是满足__pa()宏，即线性地址与物理地址是线性映射的。<br>所以最终__pa()宏被用作在内核代码中显性的获得某个线性地址所对应的物理地址<br>而MMU负责把一个线性地址隐式的转成了物理地址，而这已转换与内核代码无关。<br>不知这样理解是否正确？<br></p>
<p>今天只看到了这里<br>待续&#8230;&#8230;<br><br>说起来把这么个东西放到首页很不好意思，主要目的是希望有看到的人帮我指正一下我所认知的错误或者解惑。谢谢啦:)</p>
<img src ="http://www.cppblog.com/ccl0326/aggbug/141904.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/ccl0326/" target="_blank">Vincent</a> 2011-03-15 17:47 <a href="http://www.cppblog.com/ccl0326/archive/2011/03/15/141904.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>