﻿<?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++博客-天衣有缝</title><link>http://www.cppblog.com/jinglexy/</link><description>冠盖满京华，斯人独憔悴～</description><language>zh-cn</language><lastBuildDate>Fri, 05 Sep 2008 05:15:19 GMT</lastBuildDate><pubDate>Fri, 05 Sep 2008 05:15:19 GMT</pubDate><ttl>60</ttl><item><title>博客迁移：http://jinglexy.cublog.cn</title><link>http://www.cppblog.com/jinglexy/archive/2008/05/25/51024.html</link><dc:creator>天衣有缝</dc:creator><author>天衣有缝</author><pubDate>Sun, 25 May 2008 04:48:00 GMT</pubDate><guid>http://www.cppblog.com/jinglexy/archive/2008/05/25/51024.html</guid><wfw:comment>http://www.cppblog.com/jinglexy/comments/51024.html</wfw:comment><comments>http://www.cppblog.com/jinglexy/archive/2008/05/25/51024.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/jinglexy/comments/commentRss/51024.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/jinglexy/services/trackbacks/51024.html</trackback:ping><description><![CDATA[订阅rss的朋友请更换到http://jinglexy.cublog.cn吧<br>cu职业程序员较多，这里大多是学生，也没有linux&amp;开源气氛。<br>感谢cppblog<br><br><img src ="http://www.cppblog.com/jinglexy/aggbug/51024.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/jinglexy/" target="_blank">天衣有缝</a> 2008-05-25 12:48 <a href="http://www.cppblog.com/jinglexy/archive/2008/05/25/51024.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>c++普通成员函数转换成c函数指针的执行（原创）</title><link>http://www.cppblog.com/jinglexy/archive/2008/05/16/50087.html</link><dc:creator>天衣有缝</dc:creator><author>天衣有缝</author><pubDate>Fri, 16 May 2008 12:37:00 GMT</pubDate><guid>http://www.cppblog.com/jinglexy/archive/2008/05/16/50087.html</guid><wfw:comment>http://www.cppblog.com/jinglexy/comments/50087.html</wfw:comment><comments>http://www.cppblog.com/jinglexy/archive/2008/05/16/50087.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/jinglexy/comments/commentRss/50087.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/jinglexy/services/trackbacks/50087.html</trackback:ping><description><![CDATA[<br>&nbsp; 1 #include &lt;unistd.h&gt;<br>&nbsp; 2 #include &lt;stdlib.h&gt;<br>&nbsp; 3 #include &lt;stdio.h&gt;<br>&nbsp; 4 #include &lt;string.h&gt;<br>&nbsp; 5 <br>&nbsp; 6 typedef void (*func_type)(void * obj, int num);<br>&nbsp; 7 class test_t<br>&nbsp; 8 {<br>&nbsp; 9 public:<br>&nbsp;10&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; void test_func(int num)<br>&nbsp;11&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br>&nbsp;12&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; printf("num is %d\n", num);<br>&nbsp;13&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;14 <br>&nbsp;15&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int a;<br>&nbsp;16&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int b;<br>&nbsp;17 <br>&nbsp;18 };<br>&nbsp;19 <br>&nbsp;20 <br>&nbsp;21 int main(int argc, char* argv[])<br>&nbsp;22 {<br>&nbsp;23&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; test_t obj;<br>&nbsp;24&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; func_type p = &amp;test_t::test_func;<br>&nbsp;25&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for(int i = 100; i &lt; 104; i++)<br>&nbsp;26&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; p(&amp;obj, i);<br>&nbsp;27 <br>&nbsp;28&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return 0;<br>&nbsp;29 }<br>&nbsp;30 <br><br>程序比较简单，注意它的编译参数：<br>g++&nbsp; -Wno-pmf-conversions&nbsp;&nbsp; -O hello.cpp &amp;&amp; ./a.out<br>否则编译不能通过。<br><br><br><img src ="http://www.cppblog.com/jinglexy/aggbug/50087.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/jinglexy/" target="_blank">天衣有缝</a> 2008-05-16 20:37 <a href="http://www.cppblog.com/jinglexy/archive/2008/05/16/50087.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>执行c++构造函数（原创）</title><link>http://www.cppblog.com/jinglexy/archive/2008/05/14/49845.html</link><dc:creator>天衣有缝</dc:creator><author>天衣有缝</author><pubDate>Wed, 14 May 2008 10:00:00 GMT</pubDate><guid>http://www.cppblog.com/jinglexy/archive/2008/05/14/49845.html</guid><wfw:comment>http://www.cppblog.com/jinglexy/comments/49845.html</wfw:comment><comments>http://www.cppblog.com/jinglexy/archive/2008/05/14/49845.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/jinglexy/comments/commentRss/49845.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/jinglexy/services/trackbacks/49845.html</trackback:ping><description><![CDATA[对于全局对象，特殊情况下构造函数不会执行。如c++写的os。<br><br>链接器把构造函数放在start_ctors和end_ctors之间，所以我们可以这样做：<br>&nbsp;&nbsp;&nbsp; for (i = &amp;start_ctors; i &lt; &amp;end_ctors; i++) {<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; foo = (CONSTRUCTOR_FUNC)*i;<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; foo();&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; /* 构造函数不能用 cout对象，这个时候控制台还没有初始化 */<br>&nbsp;&nbsp;&nbsp; }<br><br>引出一个特殊需求，全局对象按顺序构造，我们显然无法预知start_ctors表顺序。<br>一个可行的方法使用重载new，并用模板函数封装其执行：<br><br>#include &lt;unistd.h&gt;<br>#include &lt;stdlib.h&gt;<br>#include &lt;stdio.h&gt;<br>#include &lt;string.h&gt;<br><br>struct test_t<br>{<br>public:<br>&nbsp;&nbsp;&nbsp; test_t()<br>&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; printf("construct of test_t()\n");<br>&nbsp;&nbsp;&nbsp; }<br><br>&nbsp;&nbsp;&nbsp; int a;<br>&nbsp;&nbsp;&nbsp; int b;<br><br>};<br><br><br>void * operator new (size_t size, void * place)<br>{<br>&nbsp;&nbsp;&nbsp; return place;<br>}<br><br>/* call the default constructor */<br>template &lt;class object_t&gt; void construct(object_t * ptr)<br>{<br>&nbsp;&nbsp;&nbsp; new (ptr) object_t();<br>}<br><br><br>test_t t;<br>int main(int argc, char* argv[])<br>{<br>&nbsp;&nbsp;&nbsp; construct(&amp;t);<br><br>&nbsp;&nbsp;&nbsp; return 0;<br>}<br><br><br><br><br><img src ="http://www.cppblog.com/jinglexy/aggbug/49845.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/jinglexy/" target="_blank">天衣有缝</a> 2008-05-14 18:00 <a href="http://www.cppblog.com/jinglexy/archive/2008/05/14/49845.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>一款好用的pim工具：essentialpim（原创）</title><link>http://www.cppblog.com/jinglexy/archive/2008/05/07/49132.html</link><dc:creator>天衣有缝</dc:creator><author>天衣有缝</author><pubDate>Wed, 07 May 2008 07:50:00 GMT</pubDate><guid>http://www.cppblog.com/jinglexy/archive/2008/05/07/49132.html</guid><wfw:comment>http://www.cppblog.com/jinglexy/comments/49132.html</wfw:comment><comments>http://www.cppblog.com/jinglexy/archive/2008/05/07/49132.html#Feedback</comments><slash:comments>3</slash:comments><wfw:commentRss>http://www.cppblog.com/jinglexy/comments/commentRss/49132.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/jinglexy/services/trackbacks/49132.html</trackback:ping><description><![CDATA[ms-project2002实在是太大了，一点也不轻量级。<br>一直都在找一款好用的pim(personal info manager)/gtd(get things done)工具，<br>测试了10几个之后，锁定到essentialpim-2.50了。<br>（个人任务最好用最强大的是am-notebook了，网上有人号称自己pj了，<br>下载下来一看，只是从pro版切换到lite版，反正我是没）<br>发个图看看吧，呵呵：<br>要是有更好用的pim/gtd软件，欢迎大家提出<br><br><img alt=""  src="http://www.cppblog.com/images/cppblog_com/jinglexy/4600/o_essentialpim.PNG" height="770" width="990"><br><img src ="http://www.cppblog.com/jinglexy/aggbug/49132.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/jinglexy/" target="_blank">天衣有缝</a> 2008-05-07 15:50 <a href="http://www.cppblog.com/jinglexy/archive/2008/05/07/49132.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>how to read file in kernel(原创)</title><link>http://www.cppblog.com/jinglexy/archive/2008/05/04/48822.html</link><dc:creator>天衣有缝</dc:creator><author>天衣有缝</author><pubDate>Sun, 04 May 2008 13:21:00 GMT</pubDate><guid>http://www.cppblog.com/jinglexy/archive/2008/05/04/48822.html</guid><wfw:comment>http://www.cppblog.com/jinglexy/comments/48822.html</wfw:comment><comments>http://www.cppblog.com/jinglexy/archive/2008/05/04/48822.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/jinglexy/comments/commentRss/48822.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/jinglexy/services/trackbacks/48822.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: simple example of vfs call&nbsp;&nbsp;<a href='http://www.cppblog.com/jinglexy/archive/2008/05/04/48822.html'>阅读全文</a><img src ="http://www.cppblog.com/jinglexy/aggbug/48822.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/jinglexy/" target="_blank">天衣有缝</a> 2008-05-04 21:21 <a href="http://www.cppblog.com/jinglexy/archive/2008/05/04/48822.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>mm(use slab arithmetic)  for jinix-1.2.1（原创）</title><link>http://www.cppblog.com/jinglexy/archive/2007/11/21/37103.html</link><dc:creator>天衣有缝</dc:creator><author>天衣有缝</author><pubDate>Wed, 21 Nov 2007 12:23:00 GMT</pubDate><guid>http://www.cppblog.com/jinglexy/archive/2007/11/21/37103.html</guid><wfw:comment>http://www.cppblog.com/jinglexy/comments/37103.html</wfw:comment><comments>http://www.cppblog.com/jinglexy/archive/2007/11/21/37103.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/jinglexy/comments/commentRss/37103.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/jinglexy/services/trackbacks/37103.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: jinix-1.2.1 will be a useful os later, written by c++. now memory finished, with buddy and slab arithmetic.&nbsp;&nbsp;<a href='http://www.cppblog.com/jinglexy/archive/2007/11/21/37103.html'>阅读全文</a><img src ="http://www.cppblog.com/jinglexy/aggbug/37103.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/jinglexy/" target="_blank">天衣有缝</a> 2007-11-21 20:23 <a href="http://www.cppblog.com/jinglexy/archive/2007/11/21/37103.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>jinix内核项目：http://jinix.sourceforge.net（原创）</title><link>http://www.cppblog.com/jinglexy/archive/2007/07/24/28723.html</link><dc:creator>天衣有缝</dc:creator><author>天衣有缝</author><pubDate>Tue, 24 Jul 2007 12:52:00 GMT</pubDate><guid>http://www.cppblog.com/jinglexy/archive/2007/07/24/28723.html</guid><wfw:comment>http://www.cppblog.com/jinglexy/comments/28723.html</wfw:comment><comments>http://www.cppblog.com/jinglexy/archive/2007/07/24/28723.html#Feedback</comments><slash:comments>16</slash:comments><wfw:commentRss>http://www.cppblog.com/jinglexy/comments/commentRss/28723.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/jinglexy/services/trackbacks/28723.html</trackback:ping><description><![CDATA[上周四在sf申请的project，周一晚上就批下来了。现在亢哧亢哧的做着，结果究竟如何是个不知数，闲着找点事做吧，免得自己慢慢失去了动力。花了一晚上看sf管理站点方法，顺便做了个简单web，挺丑的。试了好几款sftp工具，可能是内网firewall原因，只有ws_ftp可以联上。<br><br>大致介绍一下：linux环境，gcc编译器，c++语言，混合式内核（现在还只是单内核），目前目标平台i386/arm。刚刚完成了MM部分，都是移的linux算法（buddy，slab等），整个MM就一个类，彻底荤菜，呵呵。如果找些人讨论讨论c++倒是好事（当然不是那种无里头的，得先看书），但是我c++超菜鸟，又不善组织，希望冥冥中得遇大老指点一二。<br><br>不知道sf大家访问有没有问题，贴一些主要内容：<br>
版本历史：<br>
<font color="red">3.1.1版：代号：</font><br>
<font color="#3366ff">总体目标/功能：xx</font><br><br>
<font color="red">3.0.0版：代号：</font><br>
<font color="#3366ff">总体目标/功能：（发布稳定系统）</font><br><br>
<font color="red">2.1.1版：代号：</font><br>
<font color="#3366ff">总体目标/功能：单元测试，bug修复</font><br><br>
<font color="red">2.0.0版：代号：</font><br>
<font color="#3366ff">总体目标/功能：（完成系统核心，封锁版本）</font><br><br>
<font color="red">1.7.1版：代号：</font><br>
<font color="#3366ff">总体目标/功能：完成计划的第8章节</font><br><br>
<font color="red">1.6.1版：代号：xx（</font><font color="green">2008-02-05 ~ 2008-05-05</font><font color="red">）</font><br>
<font color="#3366ff">总体目标/功能：完成计划的第7章节（tcp/ip）</font><br><br>
<font color="red">1.5.1版：代号：xx（</font><font color="green">2008-01-01 ~ 2008-02-04</font><font color="red">）</font><br>
<font color="#3366ff">总体目标/功能：完成计划的第6章节（文件系统）</font><br><br>
<font color="red">1.4.1版：代号：xx（</font><font color="green">2007-10-25 ~ 2007-12-24</font><font color="red">）</font><br>
<font color="#3366ff">总体目标/功能：完成计划的第5章节（设备驱动）</font><br><br>
<font color="red">1.3.1版：代号：xx（</font><font color="green">2007-10-10 ~ 2007-10-24</font><font color="red">）</font><br>
<font color="#3366ff">总体目标/功能：单元测试，bug修复</font><br><br>
<font color="red">1.2.1版：代号：一帘忧梦（</font><font color="green">2007-07-01 ~ 2007-09-24</font><font color="red">正在进行中）</font><br>
<font color="#3366ff">总体目标/功能：完成计划的第1，2，3，4章节</font><br>
(4).jinix-1.2.1.2007-07-19_09.18.22.tar.bz2<br>
&nbsp;&nbsp;&nbsp;&nbsp;完成slab算法调研及编写<br>
&nbsp;&nbsp;&nbsp;&nbsp;内核初始化流程完善，及相关部分接口/框架<br><br>
(3).jinix-1.2.1.2007-07-15_16.36.41.tar<br>
&nbsp;&nbsp;&nbsp;&nbsp;textio类重载&lt;&lt;运算符以支持cout &lt;&lt; __func__;<br>
&nbsp;&nbsp;&nbsp;&nbsp;内存管理初始化及buddy算法完成, 内核对象完善（启动流程）<br><br>
(2).jinix-1.2.1.2007-07-12_18.49.44.tar.bz2<br>
&nbsp;&nbsp;&nbsp;&nbsp;内核对象编写，boot.S-&gt;head.S，初始化汇编文件中全局变量移入bootdata.cpp中<br>
&nbsp;&nbsp;&nbsp;&nbsp;内存管理类接口编写，以及使用到的相关数据结构从linux中移植<br><br>
(1).jinix-1.2.1.2007-07-03_21.07.57.tar.bz2<br>
&nbsp;&nbsp;&nbsp;&nbsp;某些初始化过的全局变量被编译到bss节去了，被boot.S文件清空，<br>
&nbsp;&nbsp;&nbsp;&nbsp;调整到新Makefile, 和unixlite相似<br>
&nbsp;&nbsp;&nbsp;&nbsp;使用__attribute__((section(...强制链接到.data<br><br>
(0).jinix-1.2.1.2007-06-30_17.50.21.tar.bz2<br>
&nbsp;&nbsp;&nbsp;&nbsp;控制台显示部分调试完成, textio和ostream调试完成<br><br><br>
<table class="thin" border="0" cellpadding="0" cellspacing="1">
    <tbody>
        <tr>
            <td colspan="3" align="center" valign="top" width="572">1.系统初始化</td>
        </tr>
        <tr>
            <td valign="top" width="52">&nbsp;</td>
            <td valign="top" width="330">内核启动</td>
            <td valign="top" width="190">完成</td>
        </tr>
        <tr>
            <td valign="top" width="52">&nbsp;</td>
            <td valign="top" width="330">i86硬件初始化（分页）</td>
            <td valign="top" width="190">完成</td>
        </tr>
        <tr>
            <td valign="top" width="52">&nbsp;</td>
            <td valign="top" width="330">时钟初始化</td>
            <td valign="top" width="190">完成</td>
        </tr>
        <tr>
            <td valign="top" width="52">&nbsp;</td>
            <td valign="top" width="330">中断及异常初始化</td>
            <td valign="top" width="190">完成</td>
        </tr>
        <tr>
            <td valign="top" width="52">&nbsp;</td>
            <td valign="top" width="330">reboot/halt/poweroff</td>
            <td valign="top" width="190">完成</td>
        </tr>
        <tr>
            <td valign="top" width="52">&nbsp;</td>
            <td valign="top" width="330">acpi/apm</td>
            <td valign="top" width="190"><strong><em>未完成</em></strong></td>
        </tr>
        <tr>
            <td valign="top" width="52">&nbsp;</td>
            <td valign="top" width="330">fpu/mmx/sse/sse2</td>
            <td valign="top" width="190"><strong><em>未完成</em></strong></td>
        </tr>
    </tbody>
</table>
<br>
<table class="thin" border="0" cellpadding="0" cellspacing="1">
    <tbody>
        <tr>
            <td colspan="3" align="center" valign="top" width="568">2.支撑型数据结构和算法</td>
        </tr>
        <tr>
            <td valign="top" width="55">&nbsp;</td>
            <td valign="top" width="324">hash</td>
            <td valign="top" width="189">完成</td>
        </tr>
        <tr>
            <td valign="top" width="55">&nbsp;</td>
            <td valign="top" width="324">队列</td>
            <td valign="top" width="189">完成</td>
        </tr>
        <tr>
            <td valign="top" width="55">&nbsp;</td>
            <td valign="top" width="324">链表</td>
            <td valign="top" width="189">完成</td>
        </tr>
        <tr>
            <td valign="top" width="55">&nbsp;</td>
            <td valign="top" width="324">fifo/lifo</td>
            <td valign="top" width="189">完成</td>
        </tr>
    </tbody>
</table>
<br>
<table class="thin" border="0" cellpadding="0" cellspacing="1">
    <tbody>
        <tr>
            <td colspan="3" align="center" valign="top" width="568">3.内存管理子系统</td>
        </tr>
        <tr>
            <td valign="top" width="55">&nbsp;</td>
            <td valign="top" width="324">buddy算法</td>
            <td valign="top" width="189">完成</td>
        </tr>
        <tr>
            <td valign="top" width="55">&nbsp;</td>
            <td valign="top" width="324">slab分配器</td>
            <td valign="top" width="189">完成</td>
        </tr>
        <tr>
            <td valign="top" width="55">&nbsp;</td>
            <td valign="top" width="324">页异常处理</td>
            <td valign="top" width="189">完成</td>
        </tr>
        <tr>
            <td valign="top" width="55">&nbsp;</td>
            <td valign="top" width="324">cow（copy on write）</td>
            <td valign="top" width="189"><strong><em>未完成</em></strong></td>
        </tr>
        <tr>
            <td valign="top" width="55">&nbsp;</td>
            <td valign="top" width="324">demand paging</td>
            <td valign="top" width="189"><strong><em>未完成</em></strong></td>
        </tr>
        <tr>
            <td valign="top" width="55">&nbsp;</td>
            <td valign="top" width="324">守护线程（swap，页面冲洗）</td>
            <td valign="top" width="189"><strong><em>未完成</em></strong></td>
        </tr>
    </tbody>
</table>
<br>
<table class="thin" border="0" cellpadding="0" cellspacing="1">
    <tbody>
        <tr>
            <td colspan="3" align="center" valign="top" width="568">4.进程及任务调度</td>
        </tr>
        <tr>
            <td valign="top" width="55">&nbsp;</td>
            <td valign="top" width="324">任务切换</td>
            <td valign="top" width="189"><strong><em>未完成</em></strong></td>
        </tr>
        <tr>
            <td valign="top" width="55">&nbsp;</td>
            <td valign="top" width="324">fork()</td>
            <td valign="top" width="189"><strong><em>未完成</em></strong></td>
        </tr>
        <tr>
            <td valign="top" width="55">&nbsp;</td>
            <td valign="top" width="324">调度算法</td>
            <td valign="top" width="189"><strong><em>未完成</em></strong></td>
        </tr>
        <tr>
            <td valign="top" width="55">&nbsp;</td>
            <td valign="top" width="324">内核线程</td>
            <td valign="top" width="189"><strong><em>未完成</em></strong></td>
        </tr>
        <tr>
            <td valign="top" width="55">&nbsp;</td>
            <td valign="top" width="324">idle线程</td>
            <td valign="top" width="189"><strong><em>未完成</em></strong></td>
        </tr>
        <tr>
            <td valign="top" width="55">&nbsp;</td>
            <td valign="top" width="324">用户线程</td>
            <td valign="top" width="189"><strong><em>未完成</em></strong></td>
        </tr>
        <tr>
            <td valign="top" width="55">&nbsp;</td>
            <td valign="top" width="324">同步机制：内核锁和原子操作</td>
            <td valign="top" width="189"><strong><em>未完成</em></strong></td>
        </tr>
    </tbody>
</table>
<br>
<table class="thin" border="0" cellpadding="0" cellspacing="1">
    <tbody>
        <tr>
            <td colspan="3" align="center" valign="top" width="568">5.设备驱动</td>
        </tr>
        <tr>
            <td valign="top" width="55">&nbsp;</td>
            <td valign="top" width="324">中断机制</td>
            <td valign="top" width="189"><strong><em>未完成</em></strong></td>
        </tr>
        <tr>
            <td valign="top" width="55">&nbsp;</td>
            <td valign="top" width="324">驱动框架及对外接口考虑</td>
            <td valign="top" width="189"><strong><em>未完成</em></strong></td>
        </tr>
        <tr>
            <td valign="top" width="55">&nbsp;</td>
            <td valign="top" width="324">字符设备驱动框架</td>
            <td valign="top" width="189"><strong><em>未完成</em></strong></td>
        </tr>
        <tr>
            <td valign="top" width="55">&nbsp;</td>
            <td valign="top" width="324">块设备驱动框架</td>
            <td valign="top" width="189"><strong><em>未完成</em></strong></td>
        </tr>
        <tr>
            <td valign="top" width="55">&nbsp;</td>
            <td valign="top" width="324">网络设备驱动框架</td>
            <td valign="top" width="189"><strong><em>未完成</em></strong></td>
        </tr>
        <tr>
            <td valign="top" width="55">&nbsp;</td>
            <td valign="top" width="324">控制台驱动（显卡，键盘，鼠标）</td>
            <td valign="top" width="189"><strong><em>未完成</em></strong></td>
        </tr>
        <tr>
            <td valign="top" width="55">&nbsp;</td>
            <td valign="top" width="324">dma驱动</td>
            <td valign="top" width="189"><strong><em>未完成</em></strong></td>
        </tr>
        <tr>
            <td valign="top" width="55">&nbsp;</td>
            <td valign="top" width="324">pci驱动</td>
            <td valign="top" width="189"><strong><em>未完成</em></strong></td>
        </tr>
        <tr>
            <td valign="top" width="55">&nbsp;</td>
            <td valign="top" width="324">8029/8139, ne2000网卡驱动</td>
            <td valign="top" width="189"><strong><em>未完成</em></strong></td>
        </tr>
        <tr>
            <td valign="top" width="55">&nbsp;</td>
            <td valign="top" width="324">usb驱动</td>
            <td valign="top" width="189"><strong><em>未完成</em></strong></td>
        </tr>
    </tbody>
</table>
<br>
<table class="thin" border="0" cellpadding="0" cellspacing="1">
    <tbody>
        <tr>
            <td colspan="3" align="center" valign="top" width="568">6.文件系统</td>
        </tr>
        <tr>
            <td valign="top" width="55">&nbsp;</td>
            <td valign="top" width="324">proc</td>
            <td valign="top" width="189"><strong><em>未完成</em></strong></td>
        </tr>
        <tr>
            <td valign="top" width="55">&nbsp;</td>
            <td valign="top" width="324">ramdisk</td>
            <td valign="top" width="189"><strong><em>未完成</em></strong></td>
        </tr>
        <tr>
            <td valign="top" width="55">&nbsp;</td>
            <td valign="top" width="324">ext2</td>
            <td valign="top" width="189"><strong><em>未完成</em></strong></td>
        </tr>
        <tr>
            <td valign="top" width="55">&nbsp;</td>
            <td valign="top" width="324">ext3</td>
            <td valign="top" width="189"><strong><em>未完成</em></strong></td>
        </tr>
        <tr>
            <td valign="top" width="55">&nbsp;</td>
            <td valign="top" width="324">vfat</td>
            <td valign="top" width="189"><strong><em>未完成</em></strong></td>
        </tr>
        <tr>
            <td valign="top" width="55">&nbsp;</td>
            <td valign="top" width="324">可执行文件elf加载</td>
            <td valign="top" width="189"><strong><em>未完成</em></strong></td>
        </tr>
        <tr>
            <td valign="top" width="55">&nbsp;</td>
            <td valign="top" width="324">动态链接库和内核模块</td>
            <td valign="top" width="189"><strong><em>未完成</em></strong></td>
        </tr>
    </tbody>
</table>
<br>
<table class="thin" border="0" cellpadding="0" cellspacing="1">
    <tbody>
        <tr>
            <td colspan="3" align="center" valign="top" width="568">7.TCP/IP网络模块</td>
        </tr>
        <tr>
            <td valign="top" width="55">&nbsp;</td>
            <td valign="top" width="324">数据链路层（Layer 2）</td>
            <td valign="top" width="189"><strong><em>未完成</em></strong></td>
        </tr>
        <tr>
            <td valign="top" width="55">&nbsp;</td>
            <td valign="top" width="324">IP层（Layer 3）</td>
            <td valign="top" width="189"><strong><em>未完成</em></strong></td>
        </tr>
        <tr>
            <td valign="top" width="55">&nbsp;</td>
            <td valign="top" width="324">icmp, arp, ip, 路由协议</td>
            <td valign="top" width="189"><strong><em>未完成</em></strong></td>
        </tr>
        <tr>
            <td valign="top" width="55">&nbsp;</td>
            <td valign="top" width="324">tcp, udp</td>
            <td valign="top" width="189"><strong><em>未完成</em></strong></td>
        </tr>
        <tr>
            <td valign="top" width="55">&nbsp;</td>
            <td valign="top" width="324">socket接口</td>
            <td valign="top" width="189"><strong><em>未完成</em></strong></td>
        </tr>
    </tbody>
</table>
<br>
<table class="thin" border="0" cellpadding="0" cellspacing="1">
    <tbody>
        <tr>
            <td colspan="3" align="center" valign="top" width="568">8.进程间通信IPC</td>
        </tr>
        <tr>
            <td valign="top" width="55">&nbsp;</td>
            <td valign="top" width="324">共享内存</td>
            <td valign="top" width="189"><strong><em>未完成</em></strong></td>
        </tr>
        <tr>
            <td valign="top" width="55">&nbsp;</td>
            <td valign="top" width="324">信号量</td>
            <td valign="top" width="189"><strong><em>未完成</em></strong></td>
        </tr>
        <tr>
            <td valign="top" width="55">&nbsp;</td>
            <td valign="top" width="324">消息队列</td>
            <td valign="top" width="189"><strong><em>未完成</em></strong></td>
        </tr>
    </tbody>
</table>
<br>
<table class="thin" border="0" cellpadding="0" cellspacing="1">
    <tbody>
        <tr>
            <td colspan="3" align="center" valign="top" width="568">9.posix支持及其他</td>
        </tr>
        <tr>
            <td valign="top" width="55">&nbsp;</td>
            <td valign="top" width="324">susv3调研</td>
            <td valign="top" width="189"><strong><em>未完成</em></strong></td>
        </tr>
        <tr>
            <td valign="top" width="55">&nbsp;</td>
            <td valign="top" width="324">lsb调研</td>
            <td valign="top" width="189"><strong><em>未完成</em></strong></td>
        </tr>
        <tr>
            <td valign="top" width="55">&nbsp;</td>
            <td valign="top" width="324">posix兼容及测试</td>
            <td valign="top" width="189"><strong><em>未完成</em></strong></td>
        </tr>
        <tr>
            <td valign="top" width="55">&nbsp;</td>
            <td valign="top" width="324">linux-abi兼容</td>
            <td valign="top" width="189"><strong><em>未完成</em></strong></td>
        </tr>
        <tr>
            <td valign="top" width="55">&nbsp;</td>
            <td valign="top" width="324">shell及常用application</td>
            <td valign="top" width="189"><strong><em>未完成</em></strong></td>
        </tr>
        <tr>
            <td valign="top" width="55">&nbsp;</td>
            <td valign="top" width="324">arm体系架构调研</td>
            <td valign="top" width="189"><strong><em>未完成</em></strong></td>
        </tr>
    </tbody>
</table>
<br>
<table class="thin" border="0" cellpadding="0" cellspacing="1">
    <tbody>
        <tr>
            <td colspan="3" align="center" valign="top" width="568">10.保留</td>
        </tr>
        <tr>
            <td valign="top" width="55">&nbsp;</td>
            <td valign="top" width="324">&nbsp;</td>
            <td valign="top" width="189">&nbsp;</td>
        </tr>
    </tbody>
</table>
<br><img src ="http://www.cppblog.com/jinglexy/aggbug/28723.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/jinglexy/" target="_blank">天衣有缝</a> 2007-07-24 20:52 <a href="http://www.cppblog.com/jinglexy/archive/2007/07/24/28723.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>流程图绘制软件dia介绍（原创）</title><link>http://www.cppblog.com/jinglexy/archive/2007/07/17/28186.html</link><dc:creator>天衣有缝</dc:creator><author>天衣有缝</author><pubDate>Tue, 17 Jul 2007 05:03:00 GMT</pubDate><guid>http://www.cppblog.com/jinglexy/archive/2007/07/17/28186.html</guid><wfw:comment>http://www.cppblog.com/jinglexy/comments/28186.html</wfw:comment><comments>http://www.cppblog.com/jinglexy/archive/2007/07/17/28186.html#Feedback</comments><slash:comments>3</slash:comments><wfw:commentRss>http://www.cppblog.com/jinglexy/comments/commentRss/28186.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/jinglexy/services/trackbacks/28186.html</trackback:ping><description><![CDATA[<p class="MsoNormal"><span lang="EN-US">Dia</span><span style="font-family: 宋体;">是一个用于绘制各类图表的工具软件，它从</span><span lang="EN-US">Windows Visio</span><span style="font-family: 宋体;">中借鉴了不少特性。对于各类流程图，网络布局，</span><span lang="EN-US">UML</span><span style="font-family: 宋体;">图等，表现非常良好。以前使用的如</span><span lang="EN-US">Ration Rose</span><span style="font-family: 宋体;">，</span><span lang="EN-US">Windows Visio</span><span style="font-family: 宋体;">，</span><span lang="EN-US">SmartDraw</span><span style="font-family: 宋体;">，</span><span lang="EN-US">DD</span><span style="font-family: 宋体;">等，一直都不顺手，用了一段时间</span><span lang="EN-US">dia</span><span style="font-family: 宋体;">后觉得很不错。这是个跨平台开源的软件，在</span><span lang="EN-US">Win/Linux</span><span style="font-family: 宋体;">上都可以使用。最新的版本是</span><span lang="EN-US">0.96.1</span><span style="font-family: 宋体;">。</span></p>
<p class="MsoNormal"><span style="font-family: 宋体;">可以在</span><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US"><a href="http://www.gnome.org/projects/dia/">http://www.gnome.org/projects/dia</a></span><span style="font-size: 12pt; font-family: 宋体;">上找到它的下载和<span lang="EN-US">screenshot</span>。<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal"><span style="font-size: 12pt; font-family: 宋体;">这个软件基本上不需要学习，使用界面非常简单。<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US"><o:p>&nbsp;</o:p></span></p>
<p class="MsoNormal"><span style="font-family: 宋体;">下面是示例图：</span></p>
<img alt="" src="http://www.cppblog.com/images/cppblog_com/jinglexy/4600/o_dia.PNG">
<p class="MsoNormal"><span lang="EN-US"><br></span></p>
<p class="MsoNormal"><span lang="EN-US">Dia</span><span style="font-family: 宋体;">对各类图形的支持是插件形式提供，很容易扩展。如果支持图形间超级链接就更好了。不过程序发生异常的情况较多，最严重的是有时候异常了原来的图形文件打不开。等到</span><span lang="EN-US">1.x</span><span style="font-family: 宋体;">版本出来的时候可能会好些吧。</span></p>
<p class="MsoNormal"><span style="font-family: 宋体;"><br></span></p><img src ="http://www.cppblog.com/jinglexy/aggbug/28186.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/jinglexy/" target="_blank">天衣有缝</a> 2007-07-17 13:03 <a href="http://www.cppblog.com/jinglexy/archive/2007/07/17/28186.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>jinix内核虚拟控制台实现（原创）</title><link>http://www.cppblog.com/jinglexy/archive/2007/07/10/27828.html</link><dc:creator>天衣有缝</dc:creator><author>天衣有缝</author><pubDate>Tue, 10 Jul 2007 12:15:00 GMT</pubDate><guid>http://www.cppblog.com/jinglexy/archive/2007/07/10/27828.html</guid><wfw:comment>http://www.cppblog.com/jinglexy/comments/27828.html</wfw:comment><comments>http://www.cppblog.com/jinglexy/archive/2007/07/10/27828.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.cppblog.com/jinglexy/comments/commentRss/27828.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/jinglexy/services/trackbacks/27828.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: jinix是小弟正在实现的一个c++kernel，因为调试缘故，所以早早的把控制台部分调出来了，以便于后来的调试。代码使用c++写的，如果使用c写内核也很容易移植过去。转载请保留原 创：http://www.cppblog.com/jinglexy，mail &amp; msn: jinglexy at yahoo dot com dot cn。这部分代码是在内存管理之前实现的，所以没有做到任...&nbsp;&nbsp;<a href='http://www.cppblog.com/jinglexy/archive/2007/07/10/27828.html'>阅读全文</a><img src ="http://www.cppblog.com/jinglexy/aggbug/27828.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/jinglexy/" target="_blank">天衣有缝</a> 2007-07-10 20:15 <a href="http://www.cppblog.com/jinglexy/archive/2007/07/10/27828.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>OS调试相关的工具（附图，原创）</title><link>http://www.cppblog.com/jinglexy/archive/2007/06/28/27133.html</link><dc:creator>天衣有缝</dc:creator><author>天衣有缝</author><pubDate>Thu, 28 Jun 2007 03:02:00 GMT</pubDate><guid>http://www.cppblog.com/jinglexy/archive/2007/06/28/27133.html</guid><wfw:comment>http://www.cppblog.com/jinglexy/comments/27133.html</wfw:comment><comments>http://www.cppblog.com/jinglexy/archive/2007/06/28/27133.html#Feedback</comments><slash:comments>6</slash:comments><wfw:commentRss>http://www.cppblog.com/jinglexy/comments/commentRss/27133.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/jinglexy/services/trackbacks/27133.html</trackback:ping><description><![CDATA[部分观点可能过于激进，读者自行取舍。尽管我认为程序是写出来的，不是调出来的（和市场上的观点正好相反），优质的程序应该在模块设计和实现时应保证不出现什么bug。这当然只是理想情况，还得取决于个人水平。程序应在实现阶段得到最大保证，而不是过度依赖调试器。一个彻底的反调试派，据说真正的高手会在cpu旁放一颗爆米花：）转载请保留原创：http://www.cppblog.com/jinglexy，MSN &amp; Email：jinglexy at yahoo dot com dot cn<br><br>如果系统处于仿真的初期节点，例如操作系统的初始化，调试还是很有必要的。这里是我在linux环境调试操作系统的相关工具，os开发者可参考，欢迎指正：）<br>（1）工具安装：<br>linux安装：bochs-2.3，insight-6.6，gcc-3.4（使用g++和as（binutils包中））<br>windows安装：Xmanager Enterprise2.1<br>因为网管没有lotus和clearcase在linux系统下的支持，所以只好用两个操作系统了。这样也比较好，一个用于program，一个用于调试，毕竟bochs挺耗cpu的，就让她干活好了。<br>bochs安装：./configure --with-all-libs --enable-vbe --enable-gdb-stub &amp;&amp; make &amp;&amp; make install<br>insight-6.6安装：包含了tck/tk，gdb-6.6，bfd等工具，使用insight时最好这样设置环境变量：<br>export LC_ALL=en_US<br>否则运行时可能会报错：<br>Tcl_Init failed: can't read "env(TCL_LIBRARY)": no such variable<br>配置xserver用于远程访问Linux图形界面，这样可以在windows上通过ssh执行linux的图形界面程序。<br><br><br>（2）相关文件：<br>bochs配置文件添加如下节：<br>gdbstub: enabled=1, port=1234, text_base=0, data_base=0, bss_base=0<br><br>gdb调试脚本：<br>gdb的命令集可以写入到一个文件中去，这样避免了在启动时输入一大堆命令，100%鼠标操作？faint<br>保存所有命令到一个文件，每行一个命令，如下：<br>file ./vmjinix<br>target remote 127.0.0.1:1234<br>dir&nbsp; ./arch/i386<br>dir&nbsp; ./init<br>dir&nbsp; ./kernel<br>dir&nbsp; ./drivers<br>dir&nbsp; ./drivers/video<br>dir&nbsp; ./drivers/video/console<br>show dir<br>break start_kernel<br>continue<br>list 0<br>gdb和gdb前端执行如下：<br>gdb -q -x gdb.command<br>insight -q -x gdb.command<br><br>其他脚本（磁盘自动创建分区，自动安装grub，拷贝内核，及Makefile脚本），这些贴出来太长，花了好几个小时写好的，需要可以和我联系（MSN &amp; Email：jinglexy at yahoo dot com dot cn）<br><br>（3）调试方法<br>将内核（jinix-1.2.1是我正在编写的一个C++ 开源OS，欢迎参与）拷贝到linux主机，配置samba共享，这样可以在windows上开发（推荐使用slickedit 2007，哪位有linux上的2007版本可否发一个给我）。<br>使用xshell（ssh方式）登录到linux主机上，编译和调试都在这里了。<br>在ssh上执行bochs -f bochsrc.txt.linux，<br>在ssh上执行insight -q -x gdb.command<br>截图如下：<br><img alt="" src="http://www.cppblog.com/images/cppblog_com/jinglexy/4600/o_insight.png" height="768" width="1024"><br><br><br>汇编语言节点也可用使用bochs＋gdb调试，在gdb断点时候执行：<br>disassemble $pc $pc+100（从当前断点处反汇编100字节）<br>需要注意的是，在os的汇编初始化的前期阶段，分页机制往往未开启，符号和地址不能一一对应，<br>这个时候不能进行源码级汇编调试，只能用最即便的反汇编调试了。<br>bochs-2.3中好像有个bug没有解决，nexti执行和stepi在call的时候居然一样，如果要断点到指定行，可以使用物理地址断点。<br><br>（4）文章会不断更新，如有什么好的想法可以在原博客讨论：<br>http://www.cppblog.com/jinglexy<br><br>（5）整理的一份常用gdb指令<br>x&nbsp; /4wx ds:0x1234&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; x是线性地址空间<br>xp /4wx 0x1234&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; xp是物理地址空间<br>backtrace<br>print&nbsp; variable&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; 打印变量值<br>print&nbsp; variable@10&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; 打印变量后面的10个整数值<br>set&nbsp;&nbsp;&nbsp; variable=2&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; 赋值<br>whatis variable&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; 显示变量类型<br>ptype&nbsp; variable&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; 显示数据结构（变量类型加强版）<br><br>断点类型：<br>break init_kernel.cpp:start_kernel&nbsp;&nbsp;&nbsp; 断点在文件的函数<br>break init_kernel.cpp:101&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; 断点在文件的101行<br>break init_kernel.cpp:101 if var==100&nbsp;&nbsp;&nbsp; 条件断点<br>break *0xc0102030<br>info break&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; 查看所有断点<br>delete breakpoint 3<br>delete breakpoint&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; 删除所有断点<br>isable breakpoint 2<br>enable breakpoint 2<br><br><br>search string1&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; 搜索字符串，从list结束行开始<br>reverse-search string1&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; 方向搜索<br>set history expansion on&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; 使用历史命令<br>clear&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; 删除刚才停止处的断点<br>continue&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; 从断点开始继续执行<br>info break&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; 显示当前断点清单，包括到达断点处的次数等<br>info files&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; 显示被调试文件的详细信息<br>info func&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; 显示所有的函数名称<br>info local&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; 显示当函数中的局部变量信息<br>info prog&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; 显示被调试程序的执行状态<br>info var&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; 显示所有的全局和静态变量名称<br>info all<br>run<br>continue<br>step, next, stepi, nexti&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; i后缀表示执行一条汇编指令<br><br>/*********************************************************************************<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;&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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /<br>/*********************************************************************************<br>x&nbsp; /nuf addr检查位于线性地址addr处的内存内容，若addr不指定，则默认为下一个单元地址。<br>xp /nuf addr检查位于物理地址addr处的内存内容。<br>其中的可选参数n、u和f的分别可为：<br>n欲显示内存单元的计数值，默认值为1。<br>u表示单元大小，默认选择为'w'：<br>b （Bytes）1字节；<br>h （Halfwords）2字节；<br>w （Words）4字节；<br>g （Giantwords）8字节。<br>注意：这些缩略符与Intel的不同，主要是为了与GDB调试器的表示法一致。<br>f显示格式，默认选择为'x'：<br>x （hex）显示为十六进制数（默认选择）；<br>d （decimal）显示为十进制数；<br>u （unsigned）显示成无符号十进制数；<br>o （octal）显示成八进制数；<br>t （binary）显示成二进制数。<br>c （char）显示字节代码对应的字符。若不是可显示字符代码，就直接显示代码。<br>*********************************************************************************/<br><br>说明一下：bochs 和 insight本身单个执行就非常慢，而且insight是通过ssh方式链接远程xserver执行，所以速度巨慢，本文所述完全可以全部在linux上操作，不限于平台。<br><br><br> <img src ="http://www.cppblog.com/jinglexy/aggbug/27133.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/jinglexy/" target="_blank">天衣有缝</a> 2007-06-28 11:02 <a href="http://www.cppblog.com/jinglexy/archive/2007/06/28/27133.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>C++写内核需要注意的一些事情（原创）</title><link>http://www.cppblog.com/jinglexy/archive/2007/06/25/26940.html</link><dc:creator>天衣有缝</dc:creator><author>天衣有缝</author><pubDate>Mon, 25 Jun 2007 13:19:00 GMT</pubDate><guid>http://www.cppblog.com/jinglexy/archive/2007/06/25/26940.html</guid><wfw:comment>http://www.cppblog.com/jinglexy/comments/26940.html</wfw:comment><comments>http://www.cppblog.com/jinglexy/archive/2007/06/25/26940.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cppblog.com/jinglexy/comments/commentRss/26940.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/jinglexy/services/trackbacks/26940.html</trackback:ping><description><![CDATA[内核当然可用用c++来些，但是相对c来说有许多要注意的地方，我们不得不关掉一些特性。这里只提一些gcc相关的内容，Microsoft VC我没有尝试。转载请注明原创：天衣有缝（http://www.cppblog.com/jinglexy），MSN: jinglexy at yahoo dot com dot cn<br><br>1)g++选项-nostartfiles：用户环境的在main之前调用的代码，当然不能使用了<br>2)全局对象：每种类型都有自己的构造函数，如果不自己编写代码调用，它们不会执行。<br>这包括所有全局对象和局部static对象，建议的做法是在内核栈建立后，c++运行代码执行之前<br>调用构造函数，如果构造函数没有运行（假设里面有分配内存之类的操作），后果很严重：）<br>我们可以这样做：<br>先修改gnu-ld链接脚本<br>.data : { <br>&nbsp;&nbsp;&nbsp; start_ctors = .;<br>&nbsp;&nbsp;&nbsp; *(.ctor*)<br>&nbsp;&nbsp;&nbsp; end_ctors = .;<br>&nbsp;&nbsp;&nbsp; start_dtors = .;<br>&nbsp;&nbsp;&nbsp; *(.dtor*)<br>&nbsp;&nbsp;&nbsp; end_dtors = .;<br><br>&nbsp;&nbsp;&nbsp; *(.data)<br>}<br>这样构造函数的指针就都保存在start_ctors 和end_ctors之间的内存中了，构造函数其实就是void foo(void);形式的函数，编写一个for循环<br><br>调用它即可；析构函数也是一样的。当每个构造函数调用完后，gcc会自动调用一个函数：<br>int __cxa_atexit(void (* f)(void *), void *p, void *d);<br>当内核退出时，会执行一个函数：<br>void __cxa_finalize(void *d);<br>这两个函数必须按上面格式定义，g++是这样规定的。看看下面的代码就明白了：<br>extern "C"<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int __cxa_atexit(void (*f)(void *), void *p, void *d);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; void __cxa_finalize(void *d);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; };<br><br>void *__dso_handle; /*only the address of this symbol is taken by gcc*/<br><br>struct object<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; void (*f)(void*);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; void *p;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; void *d;<br>} object[32] = {0};<br>unsigned int iObject = 0;<br><br>int __cxa_atexit(void (*f)(void *), void *p, void *d)<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (iObject &gt;= 32) return -1;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; object[iObject].f = f;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; object[iObject].p = p;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; object[iObject].d = d;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ++iObject;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return 0;<br>}<br><br>/* This currently destroys all objects */<br>void __cxa_finalize(void *d)<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; unsigned int i = iObject;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for (; i &gt; 0; --i)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; --iObject;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; object[iObject].f(object[iObject].p);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>}<br><br>3)new和delete：在完成内存管理后，重载类的new和delete函数<br>4)-nostdlib：把标准库禁用掉，最近有了移植stl到内核的想法<br>5)RTTI：最好是禁止它，这样不能用typeid 和 dynamic_cast了<br>6)禁用异常：-fno-exceptions，这个和操作系统太紧密了<br>7)纯虚函数，如果子类没有实现父类中的纯虚函数，链接到下面默认例程：<br>extern "C" void __cxa_pure_virtual()<br>{<br>&nbsp;&nbsp;&nbsp; // print error message<br>}<br>虽然不是为了定义纯虚类的对象，但是链接时编译器会抱怨，所以定义上面函数使编译通过。<br>8)如果一定要使用异常，rtti，new/delete，gcc中提供了静态库：libgcc/libsupc++，<br>还得写这个库的一些基础函数，觉得它应该是在上层抽象出接口，将底层实现空出来给用户实现。<br>而且代码本身非常复杂，网络上也没有任何中文资料。<br>指令：<br>readelf -a `gcc -print-libgcc-file-name`<br>里面定义了很多的函数。<br><br>   <img src ="http://www.cppblog.com/jinglexy/aggbug/26940.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/jinglexy/" target="_blank">天衣有缝</a> 2007-06-25 21:19 <a href="http://www.cppblog.com/jinglexy/archive/2007/06/25/26940.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>自己动手写内核（pdf，chm，source下载）（20070711修订版，原创）</title><link>http://www.cppblog.com/jinglexy/archive/2007/06/11/26021.html</link><dc:creator>天衣有缝</dc:creator><author>天衣有缝</author><pubDate>Mon, 11 Jun 2007 02:00:00 GMT</pubDate><guid>http://www.cppblog.com/jinglexy/archive/2007/06/11/26021.html</guid><wfw:comment>http://www.cppblog.com/jinglexy/comments/26021.html</wfw:comment><comments>http://www.cppblog.com/jinglexy/archive/2007/06/11/26021.html#Feedback</comments><slash:comments>14</slash:comments><wfw:commentRss>http://www.cppblog.com/jinglexy/comments/commentRss/26021.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/jinglexy/services/trackbacks/26021.html</trackback:ping><description><![CDATA[以前一系列的文章整理在下面包中，chm格式和pdf格式，及所有源程序：<br>http://blogimg.chinaunix.net/blog/upfile2/080524213721.rar<br><br>
目录：<br>
自己动手写内核（序）......................... 3<br>
第0 课：环境需求............................. 4<br>
第1 课：引导程序............................. 5<br>
第2 课：保护模式............................. 8<br>
第3 课：辅助函数............................. 17<br>
第4 课：中断和异常1.......................... 25<br>
第5 课：中断和异常2.......................... 39<br>
第6 课：多任务............................... 45<br>
第7 课：文件系统............................. 56<br>
第8 课：内存管理............................. 70<br>
第9 课：系统调用和可执行程序................. 76<br>
一份免责声明................................. 81<br><br><br>    <img src ="http://www.cppblog.com/jinglexy/aggbug/26021.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/jinglexy/" target="_blank">天衣有缝</a> 2007-06-11 10:00 <a href="http://www.cppblog.com/jinglexy/archive/2007/06/11/26021.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>自己动手写内核（第9课：系统调用和可执行程序）（原创）</title><link>http://www.cppblog.com/jinglexy/archive/2007/06/08/25854.html</link><dc:creator>天衣有缝</dc:creator><author>天衣有缝</author><pubDate>Fri, 08 Jun 2007 15:21:00 GMT</pubDate><guid>http://www.cppblog.com/jinglexy/archive/2007/06/08/25854.html</guid><wfw:comment>http://www.cppblog.com/jinglexy/comments/25854.html</wfw:comment><comments>http://www.cppblog.com/jinglexy/archive/2007/06/08/25854.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.cppblog.com/jinglexy/comments/commentRss/25854.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/jinglexy/services/trackbacks/25854.html</trackback:ping><description><![CDATA[<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan" align=left><span lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">&nbsp; <o:p></o:p></span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan" align=left><span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">第<span lang=EN-US>9</span>课：系统调用和可执行程序<span lang=EN-US>&nbsp;&nbsp;&nbsp;&nbsp;<a href="http://skelix.org/download/09.rar" target=_blank><span lang=EN-US><span lang=EN-US><u><font color=#0000ff>下载源代码</font></u></span></span></a><o:p></o:p></span></span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan" align=left><span lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体"><o:p>&nbsp;</o:p></span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; LINE-HEIGHT: 150%; TEXT-ALIGN: left; mso-pagination: widow-orphan; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto" align=left><span style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">声明：转载请保留：<span lang=EN-US><o:p></o:p></span></span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; LINE-HEIGHT: 150%; TEXT-ALIGN: left; mso-pagination: widow-orphan; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto" align=left><span style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">译者：<span lang=EN-US>http://www.cppblog.com/jinglexy<o:p></o:p></span></span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; LINE-HEIGHT: 150%; TEXT-ALIGN: left; mso-pagination: widow-orphan; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto" align=left><span style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">原作者：<span lang=EN-US>xiaoming.mo at skelix dot org<o:p></o:p></span></span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; LINE-HEIGHT: 150%; TEXT-ALIGN: left; mso-pagination: widow-orphan; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto" align=left><span lang=EN-US style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">MSN &amp; Email: jinglexy at yahoo dot com dot cn<o:p></o:p></span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan" align=left><span lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体"><o:p>&nbsp;</o:p></span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan" align=left><span style="FONT-SIZE: 12pt; COLOR: blue; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">目标</span><span lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体"><o:p></o:p></span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan" align=left><span lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">&nbsp;<o:p></o:p></span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan" align=left><span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">这一节中，我们来实现从磁盘加载应用程序并执行它，以及给这个应用程序系统调用的能力。<span lang=EN-US><o:p></o:p></span></span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan" align=left><span lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体"><br></span><span style="FONT-SIZE: 12pt; COLOR: blue; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">系统调用</span><span lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体"><o:p></o:p></span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan" align=left><span lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体"><br></span><span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">经过前面一系列的课程，我们基本上建立了一个<span lang=EN-US>OS</span>的各个简单组件，确实非常简单，没有什么复杂的算法和架构。现在再来实现一个简单的<span lang=EN-US>shell</span>控制，一般的<span lang=EN-US>shell</span>处理流程是：<span lang=EN-US>getty()</span>打印登录提示符，等待用户<span lang=EN-US>login</span>，然后执行<span lang=EN-US>bash</span>。这里，我当然不想实现一个<span lang=EN-US>shell</span>，也不想写什么<span lang=EN-US>getty</span>。这一节中，<span lang=EN-US>skelix</span>将从磁盘加载一个可执行程序并执行它，就像常用的<span lang=EN-US>*nix OS</span>一样。<span lang=EN-US><o:p></o:p></span></span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan" align=left><span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">由于<span lang=EN-US>slelix</span>的虚拟内存管理部分还没有做好，所有的任务共享同一个地址空间。我们采取一个简单的方法，程序从磁盘中加载到地址<span lang=EN-US>0x100000</span>，放到<span lang=EN-US>"/"</span>根目录下面。<span lang=EN-US><o:p></o:p></span></span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan" align=left><span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">要注意的是，用户任务不能访问内核地址空间，所以一些函数如<span lang=EN-US>kprintf, print_c</span>等也不能再使用了（实际上是可以的，因为我们没有实现虚拟内存管理，这里先假定不能使用它们）。大多数的操作系统都提供了一些<span lang=EN-US>API</span>或系统调用来执行这些函数。现在先添加一个系统调用：<span lang=EN-US><br><br><span style="COLOR: red">09/isr.s</span><o:p></o:p></span></span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan" align=left><span lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">sys_print:<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; pushl&nbsp;&nbsp;&nbsp; %esi&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; #&nbsp;</span><span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">背景颜色<span lang=EN-US><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pushl&nbsp;&nbsp;&nbsp; %edi&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; #&nbsp;</span>前景颜色<span lang=EN-US><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pushl&nbsp;&nbsp;&nbsp; %ebx&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; #&nbsp;</span>要打印的字符<span lang=EN-US><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cli&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; # </span>中断门会字节关掉<span lang=EN-US>EFLAGS </span>的<span lang=EN-US>IF</span>位，系统调用却不行<span lang=EN-US><o:p></o:p></span></span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan" align=left><span lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; call&nbsp;&nbsp;&nbsp; <span style="COLOR: blue">print_c</span><br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; sti<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; addl&nbsp;&nbsp;&nbsp; $12,&nbsp;&nbsp;&nbsp; %esp<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; ret<o:p></o:p></span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan" align=left><span lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">&nbsp;<o:p></o:p></span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan" align=left><span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">恨简单，不是吗？上面系统调用有三个参数，<span lang=EN-US>esi</span>是背景颜色，<span lang=EN-US>edi</span>是前景颜色，<span lang=EN-US>ebx</span>是要打印的字符。这个系统调用只打印一个字符，起始就是用户程序对内核<span lang=EN-US>print_c</span>函数的一个<span lang=EN-US>wrapper</span>。<span lang=EN-US><o:p></o:p></span></span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan" align=left><span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">理论上说，用户任务不能直接使用<span lang=EN-US>print_c</span>函数，也不应当知道有这个函数存在。唯一的方法就是使用系统调用，以此提供给用户一个可用的接口。<span lang=EN-US>DOS </span>操作系统提供了<span lang=EN-US>int 0x21</span>作为系统服务，<span lang=EN-US>linux </span>提供<span lang=EN-US>int 0x80</span>系统调用，本节中模仿<span lang=EN-US>linux</span>在<span lang=EN-US>IDT </span>中添加一个号码<span lang=EN-US>0x80 </span>的系统调用。<span lang=EN-US><br></span>现在我们只用到了<span lang=EN-US>IDT </span>中断的<span lang=EN-US>34</span>项，所以其余的项都可以拿来使用，但是我们只需要<span lang=EN-US>0x80</span>已足够。在<span lang=EN-US>IDT</span>中建立一个<span lang=EN-US>386 </span>的陷阱门就行了，陷阱门和中断门非常类似，只是<span lang=EN-US>E </span>位的类型用<span lang=EN-US>8</span>替代，并且<span lang=EN-US>DPL </span>特权级设置为<span lang=EN-US>3</span>。<span lang=EN-US><br><br><span style="COLOR: red">09/init.c</span><o:p></o:p></span></span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan" align=left><span lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">static void<br>sys_call_install(void) {<br>&nbsp;&nbsp;&nbsp; unsigned long long sys_call_entry = 0x0000ef0000080000ULL<o:p></o:p></span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan" align=left><span lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">&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;&nbsp;&nbsp;| ((unsigned long long)CODE_SEL&lt;&lt;16);<br>&nbsp;&nbsp;&nbsp; sys_call_entry |= ((unsigned long long)<span style="COLOR: blue">sys_call</span>&lt;&lt;32)<o:p></o:p></span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan" align=left><span lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">&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;&nbsp;&nbsp;&amp; 0xffff000000000000ULL;<br>&nbsp;&nbsp;&nbsp; sys_call_entry |= ((unsigned long long)<span style="COLOR: blue">sys_call</span>) &amp; 0xffff;<br>&nbsp;&nbsp;&nbsp; idt[<span style="COLOR: blue">SYS_CALL</span>] = sys_call_entry;<br>}<o:p></o:p></span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan" align=left><span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">宏<span lang=EN-US>SYS_CALL </span>值为<span lang=EN-US>0x80</span>。<span lang=EN-US><o:p></o:p></span></span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan" align=left><span lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">&nbsp;<o:p></o:p></span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan" align=left><span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">现在我们来看下<span lang=EN-US>0x80</span>的陷阱门处理例程：<span lang=EN-US><br><span style="COLOR: red">09/isr.s</span><o:p></o:p></span></span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan" align=left><span lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">sys_call:<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; cmpl&nbsp;&nbsp;&nbsp; $1,&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; %eax<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; jb&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <st1:chmetcnv w:st="on" TCSC="0" NumberType="1" Negative="False" HasSpace="False" SourceValue="1" UnitName="F">1f</st1:chmetcnv><br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; iret<br>1:<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; pushal<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; call&nbsp;&nbsp;&nbsp; *<span style="COLOR: blue">sys_call_table</span>(, %eax, 4)<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; popal<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; iret<o:p></o:p></span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan" align=left><span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">我尽量做到简单，虽然很多东西没有考虑周全，这样做可以降低学习成本。该例程判断系统调用号，即存储在<span lang=EN-US>eax</span>中的值，然后查找函数表：<span lang=EN-US>sys_call_table</span>。<span lang=EN-US><o:p></o:p></span></span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan" align=left><span lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">&nbsp;<o:p></o:p></span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan" align=left><span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">函数表定义如下：<span lang=EN-US><br><span style="COLOR: red">09/syscall.c</span><o:p></o:p></span></span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan" align=left><span lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">void (*sys_call_table[VALID_SYSCALL])(void) = {sys_print};<o:p></o:p></span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan" align=left><span lang=EN-US style="FONT-SIZE: 12pt; COLOR: blue; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">VALID_SYSCALL</span><span lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体"> </span><span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">宏定义为<span lang=EN-US>1, of course<br><br></span><span style="COLOR: blue">系统调用测试函数</span><span lang=EN-US><br></span>现在我们来做一个用户任务的系统调用测试函数：<span lang=EN-US><br><span style="COLOR: red">09/color.c</span><o:p></o:p></span></span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan" align=left><span lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">void<br>color(void) {<br>&nbsp;&nbsp;&nbsp; int i, j;<br>&nbsp;&nbsp;&nbsp; for (i=0; i&lt;16; ++i)<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; for (j=0; j&lt;16; ++j)<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; __asm__ ("int&nbsp;&nbsp;&nbsp; $0x80"::"S"(i),"D"(j),"b"('X'),"a"(0));<br>&nbsp;&nbsp;&nbsp; for (;;)<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; ;<br>}<o:p></o:p></span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan" align=left><span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">按例，最简单实现。这个函数打印一些<span lang=EN-US>&#8220;X&#8221;</span>字符，以不同的前景和背景颜色。还有一个问题，怎样把它存储在磁盘上呢，在没有<span lang=EN-US>shell</span>的情况下（否则可以用<span lang=EN-US>cp</span>来拷贝了）。解决的方法是另外写一个程序把程序直接写到磁盘上：实现一个<span lang=EN-US>ghex.c</span>程序来把<span lang=EN-US>color</span>可执行程序的内容打印出来，在内核里面再把可执行文件写到磁盘上。<span lang=EN-US><o:p></o:p></span></span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan" align=left><span lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">Makefile</span><span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">也得修改一下：<span lang=EN-US><br><span style="COLOR: red">09/Makefile</span><o:p></o:p></span></span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan" align=left><span lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">all: final.img color<br><br>color: color.o<br>&nbsp;&nbsp;&nbsp; ${LD} --oformat binary -N -e color -Ttext 0x100000 -o color $&lt;<o:p></o:p></span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan" align=left><span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">上面的命令把<span lang=EN-US>color.o</span>文件生成一个二进制可执行文件，入口点在<span lang=EN-US>color</span>函数，代码段逻辑地址从<span lang=EN-US>0x100000</span>开始。<span lang=EN-US><o:p></o:p></span></span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan" align=left><span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">（<span lang=EN-US>color.c</span>由主机上的<span lang=EN-US>gcc</span>编译器编译，<span lang=EN-US>ld</span>链接）<span lang=EN-US><o:p></o:p></span></span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan" align=left><span lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">&nbsp;<o:p></o:p></span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan" align=left><span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">现在把这些二进制数据（显示命令是：<span lang=EN-US>./ghex ../color</span>）写到磁盘上：<span lang=EN-US><br><span style="COLOR: red">09/fs.c</span><o:p></o:p></span></span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan" align=left><span lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">void<br>install_color(void) {<br>&nbsp;&nbsp;&nbsp; struct SUPER_BLOCK sb;<br>&nbsp;&nbsp;&nbsp; char sect[512] = {0};<br>&nbsp;&nbsp;&nbsp; struct DIR_ENTRY *de = NULL;<br>&nbsp;&nbsp;&nbsp; int inode = -1;<br>&nbsp;&nbsp;&nbsp; struct INODE clnode;<br>&nbsp;&nbsp;&nbsp; unsigned int blk = 0;<br>&nbsp;&nbsp;&nbsp; unsigned char color[] = <br>{0x57,0x56,0x53,0x83,0xec,0x08,0xc7,0x44,0x24,0x04,0x00,0x00,<br>&nbsp;0x00,0x00,0x83,0x<st1:chmetcnv w:st="on" TCSC="0" NumberType="1" Negative="False" HasSpace="False" SourceValue="7" UnitName="C">7c</st1:chmetcnv>,0x24,0x04,0x<st1:chmetcnv w:st="on" TCSC="0" NumberType="1" Negative="False" HasSpace="False" SourceValue="0" UnitName="F">0f</st1:chmetcnv>,0x<st1:chmetcnv w:st="on" TCSC="0" NumberType="1" Negative="False" HasSpace="False" SourceValue="7" UnitName="F">7f</st1:chmetcnv>,0x2e,0xc7,0x04,0x24,<br>&nbsp;0x00,0x00,0x00,0x00,0x83,0x<st1:chmetcnv w:st="on" TCSC="0" NumberType="1" Negative="False" HasSpace="False" SourceValue="3" UnitName="C">3c</st1:chmetcnv>,0x24,0x<st1:chmetcnv w:st="on" TCSC="0" NumberType="1" Negative="False" HasSpace="False" SourceValue="0" UnitName="F">0f</st1:chmetcnv>,0x<st1:chmetcnv w:st="on" TCSC="0" NumberType="1" Negative="False" HasSpace="False" SourceValue="7" UnitName="F">7f</st1:chmetcnv>,0x19,0x8b,0x74,<br>&nbsp;0x24,0x04,0x8b,0x<st1:chmetcnv w:st="on" TCSC="0" NumberType="1" Negative="False" HasSpace="False" SourceValue="3" UnitName="C">3c</st1:chmetcnv>,0x24,0xbb,0x58,0x00,0x00,0x00,0xb8,0x00,<br>&nbsp;0x00,0x00,0x00,0xcd,0x80,0x89,0xe0,0xff,0x00,0xeb,0xe1,0x8d,<br>&nbsp;0x44,0x24,0x04,0xff,0x00,0xeb,0xcb,0xeb,0xfe};<br><br>&nbsp;&nbsp;&nbsp; sb.sb_start = *(unsigned int *)(HD0_ADDR);<br>&nbsp;&nbsp;&nbsp; hd_rw(ABS_SUPER_BLK(sb), HD_READ, 1, sect);<br>&nbsp;&nbsp;&nbsp; memcpy(&amp;sb, sect, sizeof(struct SUPER_BLOCK));<br><br>&nbsp;&nbsp;&nbsp; inode = alloc_inode(&amp;sb);<br>&nbsp;&nbsp;&nbsp; assert(inode &gt; 0);<br>&nbsp;&nbsp;&nbsp; blk = alloc_blk(&amp;sb);<br>&nbsp;&nbsp;&nbsp; assert(blk != 0);<br>&nbsp;&nbsp;&nbsp; clnode.i_block[0] = blk;<br>&nbsp;&nbsp;&nbsp; hd_rw(blk, HD_WRITE, 1, color);<br>&nbsp;&nbsp;&nbsp; clnode.i_mode = FT_NML;<br>&nbsp;&nbsp;&nbsp; clnode.i_size = sizeof color;<br>&nbsp;&nbsp;&nbsp; iput(&amp;sb, &amp;clnode, inode);<o:p></o:p></span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan" align=left><span lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">&nbsp;&nbsp;&nbsp; // </span><span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">为<span lang=EN-US>color</span>程序分配新的<span lang=EN-US>inode</span>节点和块<span lang=EN-US><br><br>&nbsp;&nbsp;&nbsp; hd_rw(iroot.i_block[0], HD_READ, 1, sect);<br>&nbsp;&nbsp;&nbsp; de = &amp;((struct DIR_ENTRY *)sect)[2];<br>&nbsp;&nbsp;&nbsp; strcpy(de-&gt;de_name, "color");<br>&nbsp;&nbsp;&nbsp; de-&gt;de_inode = inode;<br>&nbsp;&nbsp;&nbsp; hd_rw(iroot.i_block[0], HD_WRITE, 1, sect);<o:p></o:p></span></span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan" align=left><span lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">&nbsp;&nbsp;&nbsp; // </span><span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">把<span lang=EN-US>color</span>程序放到根目录<span lang=EN-US>"/"</span>下面<span lang=EN-US><o:p></o:p></span></span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan" align=left><span lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体"><br><br>&nbsp;&nbsp;&nbsp; iget(&amp;sb, &amp;iroot, 0);<br>&nbsp;&nbsp;&nbsp; iroot.i_size = 3*sizeof(struct DIR_ENTRY);<br>&nbsp;&nbsp;&nbsp; iput(&amp;sb, &amp;iroot, 0);<br>&nbsp;&nbsp;&nbsp; // </span><span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">搞定<span lang=EN-US><br>}<o:p></o:p></span></span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan" align=left><span lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">&nbsp;<o:p></o:p></span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan" align=left><span lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">// color</span><span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">程序已经写到磁盘上了，再把它加载到内存地址<span lang=EN-US>0x100000<br><span style="COLOR: red">09/fs.c</span><o:p></o:p></span></span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan" align=left><span lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">void<br>load_color(void) {<br>&nbsp;&nbsp;&nbsp; struct INODE inode;<br>&nbsp;&nbsp;&nbsp; struct SUPER_BLOCK sb;<br>&nbsp;&nbsp;&nbsp; char sect[512] = {0};<br><br>&nbsp;&nbsp;&nbsp; sb.sb_start = *(unsigned int *)(HD0_ADDR);<br>&nbsp;&nbsp;&nbsp; hd_rw(ABS_SUPER_BLK(sb), HD_READ, 1, sect);<br>&nbsp;&nbsp;&nbsp; memcpy(&amp;sb, sect, sizeof(struct SUPER_BLOCK));<br>&nbsp;&nbsp;&nbsp; iget(&amp;sb, &amp;inode, 1);<br><br>&nbsp;&nbsp;&nbsp; /* </span><span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">只是简单的把<span lang=EN-US>color</span>加载到虚拟地址<span lang=EN-US>0x100000</span>（也是物理地址<span lang=EN-US>0x100000</span>）<span lang=EN-US> */<br>&nbsp;&nbsp;&nbsp; hd_rw(inode.i_block[0], HD_READ, 1, (void *)0x100000);<br>}<o:p></o:p></span></span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan" align=left><span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">还记得以前运行的<span lang=EN-US>task1_run </span>和<span lang=EN-US>task2_run</span>这两个任务吗，它们只是做一些轮流在屏幕上打印字符的无聊工作。我们把<span lang=EN-US>task1</span>换成执行磁盘中的<span lang=EN-US>color</span>程序：<span lang=EN-US><br><span style="COLOR: red">09/init.c</span><o:p></o:p></span></span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan" align=left><span lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">void<br>do_task1(void) {<br>&nbsp;&nbsp;&nbsp; __asm__ ("incb 0xb8000+160*24+2");<br>&nbsp;&nbsp;&nbsp; load_color();<br>&nbsp;&nbsp;&nbsp; __asm__ ("jmp 0x100000");<br>}<o:p></o:p></span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan" align=left><span lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体"><br></span><span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">最后在<span lang=EN-US>check_root()</span>函数中添加一些安装函数：<span lang=EN-US><br>09/fs.c<o:p></o:p></span></span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan" align=left><span lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">&nbsp;&nbsp;&nbsp; if (! testb(sect, 0)) {<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; kprintf(KPL_DUMP, "/ has not been created, creating....\t\t\t\t\t&nbsp; ");<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if (alloc_inode(&amp;sb) != 0) {<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; kprintf(KPL_PANIC, "\n/ must be inode 0!!!\n");<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; halt();<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; iroot.i_block[0] = alloc_blk(&amp;sb);<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; iput(&amp;sb, &amp;iroot, 0);<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; hd_rw(iroot.i_block[0], HD_READ, 1, sect);<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; de = (struct DIR_ENTRY *)sect;<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; strcpy(de-&gt;de_name, ".");<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; de-&gt;de_inode = 0;<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; ++de;<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; strcpy(de-&gt;de_name, "..");<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; de-&gt;de_inode = -1;<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; hd_rw(iroot.i_block[0], HD_WRITE, 1, sect);<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; kprintf(KPL_DUMP, "[DONE]");<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if (iroot.i_size == 2*sizeof(struct DIR_ENTRY))<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="COLOR: red">install_color</span>();<br>&nbsp;&nbsp;&nbsp; }<o:p></o:p></span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan" align=left><span lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">&nbsp;<o:p></o:p></span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan" align=left><span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">编译，运行一下。如果一起正常的话，应该是<span lang=EN-US>color</span>任务打印一系列的彩色字符。很有成就感吧：）<span lang=EN-US><o:p></o:p></span></span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan" align=left><span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">到此为止，这一系列的课程就结束了，大家可以继续深入下去，<span lang=EN-US>linux</span>内核是一个值得学习的好<span lang=EN-US>kernel</span>，<span lang=EN-US><o:p></o:p></span></span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan" align=left><span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">而且也有一些较好的书籍，如情景分析，<span lang=EN-US>ULK2</span>，<span lang=EN-US>In A Nut Shell</span>等。<span lang=EN-US><o:p></o:p></span></span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan" align=left><span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">学习是一件愉快的事情，当然也少不了挫折和煎熬。态度才是第一位，祝大家进步：）<span lang=EN-US><o:p></o:p></span></span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan" align=left><span lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">&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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">丁亥年四月廿四<span lang=EN-US>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>于上海体育馆<span lang=EN-US><o:p></o:p></span></span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan" align=left><span lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">&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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;http://www.cppblog.com/jinglexy<o:p></o:p></span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan" align=left><span lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">&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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">天衣有缝<span lang=EN-US><o:p></o:p></span></span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan" align=left><span lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">&nbsp;<o:p></o:p></span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><o:p>&nbsp;</o:p></span></p>
<p>&nbsp;</p>
<img src ="http://www.cppblog.com/jinglexy/aggbug/25854.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/jinglexy/" target="_blank">天衣有缝</a> 2007-06-08 23:21 <a href="http://www.cppblog.com/jinglexy/archive/2007/06/08/25854.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>自己动手写内核（第8课：内存管理）（原创）</title><link>http://www.cppblog.com/jinglexy/archive/2007/06/08/25801.html</link><dc:creator>天衣有缝</dc:creator><author>天衣有缝</author><pubDate>Fri, 08 Jun 2007 00:44:00 GMT</pubDate><guid>http://www.cppblog.com/jinglexy/archive/2007/06/08/25801.html</guid><wfw:comment>http://www.cppblog.com/jinglexy/comments/25801.html</wfw:comment><comments>http://www.cppblog.com/jinglexy/archive/2007/06/08/25801.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cppblog.com/jinglexy/comments/commentRss/25801.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/jinglexy/services/trackbacks/25801.html</trackback:ping><description><![CDATA[<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">&nbsp; <o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">第<span lang="EN-US">8</span>课：内存管理<span lang="EN-US">&nbsp;&nbsp;&nbsp;&nbsp;<a  href="http://skelix.org/download/08.rar" target="_blank"><span lang="EN-US"><span lang="EN-US">下载源代码</span></span></a><o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US"><o:p>&nbsp;</o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">声明：转载请保留：<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">译者：<span lang="EN-US">http://www.cppblog.com/jinglexy<o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">原作者：<span lang="EN-US">xiaoming.mo at skelix dot org<o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">MSN &amp; Email: jinglexy at yahoo dot com dot cn<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US"><o:p>&nbsp;</o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">&nbsp;<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体; color: blue;">目标</span><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">&nbsp;<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">抱歉，其实还没有实现。在任务分配独立的<span lang="EN-US">4G</span>地址空间上调试失败了，现在只使能了分页机制，页异常。大量的工作未实现，有兴趣的同学可以搜索<span lang="EN-US">buddy</span>和<span lang="EN-US">slab</span>的相关资料，经典的内存管理算法。<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US"><br>
</span><span style="font-size: 12pt; font-family: 宋体; color: blue;">分页</span><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">&nbsp;<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">386</span><span style="font-size: 12pt; font-family: 宋体;">处理器的内存管理单元可以实现任务独立地址空间，任务间内存保护。每个任务可以拥有独立的<span lang="EN-US">4G</span>虚拟地址空间。内存映射是内存管理很重要的一步，可以分为两部分：分段和分页。前面的课程中已经讨论过分段机制了，通过分段可以隔开不同的代码，数据，堆栈等；分页单元把虚拟地址映射成物理地址，还可以用来实现虚拟内存（和硬盘分区进行交换），现在我们来了解一下它。<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">&nbsp;<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">对于每个任务，我们无法分配<span lang="EN-US">4G</span>的物理内存，所以使用了一些机制来管理内存：及虚拟内存机制。该机制有处理器的分页部分来实现，首先我们将内存分成一些块，每个块大小为<span lang="EN-US">4k</span>，通常我们称之为一个页帧。操作系统通过页目录和页表来管理这些页帧。页目录是相当于第一级页表，其中的每一项再管理一个下级页表。（更详细过程请参考<span lang="EN-US">intel</span>的<span lang="EN-US">IA 32/64</span>手册）<span lang="EN-US"><br>
<br>
</span>当分页机制开启时，处理器把任务中的虚拟地址转换成物理地址，步骤如下：<span lang="EN-US"><br>
1.</span>查找段选择子在<span lang="EN-US">GDT </span>或<span lang="EN-US"> LDT </span>中的描述符，做一些权限检查，看看能否访问<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">2.</span><span style="font-size: 12pt; font-family: 宋体;">以描述符中的基址相加页目录基址得到一个线性地址<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">3.</span><span style="font-size: 12pt; font-family: 宋体;">在页表中索引虚拟地址所对应的页表项，得到页地址<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">4.</span><span style="font-size: 12pt; font-family: 宋体;">查找偏移得到实际物理地址。<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">如果实际物理页不存在（可能交换到硬盘中去了），则引发异常，可以在这个异常里面做想要做的事情（加载硬盘中的交换页，或者<span lang="EN-US">kill</span>这个程序：<span lang="EN-US">Segment Fault</span>，等等）<span lang="EN-US"><br>
<br>
</span>处理器使用的页目录或者页表，都是由<span lang="EN-US">32 </span>位的项组成：<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体; color: blue;">页目录项：</span><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">&nbsp;31&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;12&nbsp;&nbsp;&nbsp;
11&nbsp;&nbsp;&nbsp;&nbsp;9&nbsp;&nbsp;&nbsp; 876&nbsp;&nbsp; 5&nbsp;&nbsp;
43&nbsp;&nbsp;&nbsp; 2&nbsp;&nbsp;&nbsp;&nbsp; 1&nbsp;&nbsp;&nbsp;&nbsp; 0<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">┃&nbsp;&nbsp; </span><span style="font-size: 12pt; font-family: 宋体;">指向页表的物理地址<span lang="EN-US">&nbsp; ┃ </span>用户定义<span lang="EN-US"> ┃&nbsp; X&nbsp; ┃&nbsp;A┃
X&nbsp;┃ U/S┃ R/W┃ P&nbsp;┃<o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">&nbsp;<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体; color: blue;">页表项：</span><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">&nbsp;31&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;12&nbsp;&nbsp;&nbsp;
11&nbsp;&nbsp;&nbsp;&nbsp;9&nbsp;&nbsp;&nbsp;87&nbsp; 6&nbsp; 5&nbsp;&nbsp;
43&nbsp;&nbsp;&nbsp; 2&nbsp;&nbsp;&nbsp;&nbsp; 1&nbsp;&nbsp;&nbsp;&nbsp; 0<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">┃&nbsp;&nbsp; </span><span style="font-size: 12pt; font-family: 宋体;">指向页帧的物理地址<span lang="EN-US">&nbsp; ┃ </span>用户定义<span lang="EN-US"> ┃&nbsp;X┃D┃&nbsp;A┃ X&nbsp;┃
U/S┃ R/W┃ P&nbsp;┃<o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">&nbsp;<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">从上面可以知道，页目录项和页表项的结构很类似，下面逐个说明一下其中的域：<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US"><o:p>&nbsp;</o:p></span></p>
<table class="MsoNormalTable" style="width: 79.58%;" border="1" cellpadding="0" width="79%">
    <tbody>
        <tr>
            <td style="padding: 1.5pt; width: 84.75pt;" valign="top" width="113">
            <p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">Bit&nbsp; 0<o:p></o:p></span></p>
            </td>
            <td style="padding: 1.5pt; width: 63pt;" valign="top" width="84">
            <p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">P<o:p></o:p></span></p>
            </td>
            <td style="padding: 1.5pt; width: 393.75pt;" valign="top" width="525">
            <p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">存在位（<span lang="EN-US">present</span>），为<span lang="EN-US">0 </span>表示该页帧或页表不在内存中。如果访问该项将发生异常。<span lang="EN-US"><o:p></o:p></span></span></p>
            </td>
        </tr>
        <tr>
            <td style="padding: 1.5pt; width: 84.75pt;" valign="top" width="113">
            <p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">Bit&nbsp; 1<o:p></o:p></span></p>
            </td>
            <td style="padding: 1.5pt; width: 63pt;" valign="top" width="84">
            <p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">R/W<o:p></o:p></span></p>
            </td>
            <td style="padding: 1.5pt; width: 393.75pt;" valign="top" width="525">
            <p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">表示页表或页帧指向的内存只读（＝<span lang="EN-US">0</span>），或可写（＝<span lang="EN-US">1</span>）<span lang="EN-US"><o:p></o:p></span></span></p>
            </td>
        </tr>
        <tr>
            <td style="padding: 1.5pt; width: 84.75pt;" valign="top" width="113">
            <p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">Bit&nbsp; 2<o:p></o:p></span></p>
            </td>
            <td style="padding: 1.5pt; width: 63pt;" valign="top" width="84">
            <p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">U/S<o:p></o:p></span></p>
            </td>
            <td style="padding: 1.5pt; width: 393.75pt;" valign="top" width="525">
            <p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">表示页表或页帧的权限，当特权级为<span lang="EN-US">0</span>时，只有<span lang="EN-US">ring0</span>到<span lang="EN-US">2</span>的特权级可以访问它，否则所有的<span lang="EN-US">ring3</span>任务都可以访问。这个域非常重要。<span lang="EN-US"><o:p></o:p></span></span></p>
            </td>
        </tr>
        <tr>
            <td style="padding: 1.5pt; width: 84.75pt;" valign="top" width="113">
            <p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">Bits 3, 4, (6), 7, 8<o:p></o:p></span></p>
            </td>
            <td style="padding: 1.5pt; width: 63pt;" valign="top" width="84">
            <p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">X<o:p></o:p></span></p>
            </td>
            <td style="padding: 1.5pt; width: 393.75pt;" valign="top" width="525">
            <p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">Intel </span><span style="font-size: 12pt; font-family: 宋体;">保留位，设置为<span lang="EN-US">0</span>就行了<span lang="EN-US"><o:p></o:p></span></span></p>
            </td>
        </tr>
        <tr>
            <td style="padding: 1.5pt; width: 84.75pt;" valign="top" width="113">
            <p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">Bit&nbsp; 5<o:p></o:p></span></p>
            </td>
            <td style="padding: 1.5pt; width: 63pt;" valign="top" width="84">
            <p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">A<o:p></o:p></span></p>
            </td>
            <td style="padding: 1.5pt; width: 393.75pt;" valign="top" width="525">
            <p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">该页是否已访问<span lang="EN-US"><o:p></o:p></span></span></p>
            </td>
        </tr>
        <tr>
            <td style="padding: 1.5pt; width: 84.75pt;" valign="top" width="113">
            <p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">Bits 9-11<o:p></o:p></span></p>
            </td>
            <td style="padding: 1.5pt; width: 63pt;" valign="top" width="84">
            <p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">用户定义<span lang="EN-US"><o:p></o:p></span></span></p>
            </td>
            <td style="padding: 1.5pt; width: 393.75pt;" valign="top" width="525">
            <p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">我们使用第<span lang="EN-US">11</span>位，表示该页帧是否被交互到硬盘上了<span lang="EN-US"><o:p></o:p></span></span></p>
            </td>
        </tr>
    </tbody>
</table>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">&nbsp;<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">页目录的每一项：即页表的物理地址，它的高<span lang="EN-US">20 </span>位地址表示有个页帧的起始地址，正好和<span lang="EN-US">4k</span>对齐。<span lang="EN-US">2^20</span>可以表示<span lang="EN-US">1M</span>范围，每个页帧大小是<span lang="EN-US">4k</span>，所以可以索引<span lang="EN-US">1M * 4K</span>地址空间。页目录项中还有一个<span lang="EN-US">D </span>位，它用来表示一个页帧是否已修改，<span lang="EN-US">linux</span>用它来表示一个页面释放是脏页面，这个位非常有用，当一个页帧交换到硬盘上后，如果该页帧还没有被修改，而且是已经从硬盘交换出来的，则简单取消以后的交换。<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">&nbsp;<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">为了将逻辑地址转换成物理地址，逻辑地址被分成<span lang="EN-US">3 </span>部分：<span lang="EN-US"><o:p></o:p></span></span></p>
<table class="MsoNormalTable" style="width: 79.58%;" border="1" cellpadding="0" width="79%">
    <tbody>
        <tr>
            <td style="padding: 1.5pt; width: 101.25pt;" valign="top" width="135">
            <p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">Bits 31-22<o:p></o:p></span></p>
            </td>
            <td style="padding: 1.5pt; width: 437.25pt;" valign="top" width="583">
            <p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">页目录项的索引下标，由它可以得到页表的物理地址<span lang="EN-US"><o:p></o:p></span></span></p>
            </td>
        </tr>
        <tr>
            <td style="padding: 1.5pt; width: 101.25pt;" valign="top" width="135">
            <p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">Bits 21-12<o:p></o:p></span></p>
            </td>
            <td style="padding: 1.5pt; width: 437.25pt;" valign="top" width="583">
            <p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">页表项的索引下标，由它可以得到页帧的物理地址<span lang="EN-US"><o:p></o:p></span></span></p>
            </td>
        </tr>
        <tr>
            <td style="padding: 1.5pt; width: 101.25pt;" valign="top" width="135">
            <p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">Bits 11-0<o:p></o:p></span></p>
            </td>
            <td style="padding: 1.5pt; width: 437.25pt;" valign="top" width="583">
            <p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">相对页帧起始地址的偏移<span lang="EN-US"><o:p></o:p></span></span></p>
            </td>
        </tr>
    </tbody>
</table>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">&nbsp;<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">举例来说，我们有一个逻辑地址：<span lang="EN-US">0x3E837B0A</span>。前提条件：<span lang="EN-US">CR3</span>寄存器指向的页目录地址是<span lang="EN-US"> 0x0005C000</span>，这个寄存器存储了当前页目录所使用的页帧的物理地址，通常也叫做<span lang="EN-US">
PDBR</span>。<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">&nbsp;<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">先取它的高<span lang="EN-US">10</span>位， 就是<span lang="EN-US">0x0FA</span>，由它可以索引到页目录的第<span lang="EN-US">0x0FA</span>项，我们取得这一项的值，假设得到的地址值是<span lang="EN-US">0x0003F000</span>。然后我们取虚拟地址的中间<span lang="EN-US">10</span>位，就是<span lang="EN-US">0x037</span>，再取出<span lang="EN-US">0x0003F000</span>指向页帧的第<span lang="EN-US">0x037</span>项的值，假设是<span lang="EN-US">0x0001B000</span>。这个地址就是我们要找的虚拟地址对应的物理地址的页帧的起始地址，最后加上偏移值（低<span lang="EN-US">12</span>位），即<span lang="EN-US">0xB0A</span>，得到实际的物理地址是：<span lang="EN-US">0x0001BB0A</span>。<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">相关的知识可以参考<span lang="EN-US"> Intel </span>的<span lang="EN-US">IA 32/64</span>手册。<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">CR3</span><span style="font-size: 12pt; font-family: 宋体;">寄存器必须在分页机制开启前就装载好，可以使用<span lang="EN-US">MOV </span>指令或者在任务切换时使用<span lang="EN-US">TSS</span>中的<span lang="EN-US">CR3</span>域的值。当处理器访问不存在的页帧时，发生一个异常，<span lang="EN-US">CR2 </span>寄存器存引发异常的逻辑地址，同时错误码也会压入到堆栈中，错误码格式如下：<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">&nbsp;31&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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
3&nbsp;&nbsp; 2&nbsp;&nbsp;&nbsp;&nbsp; 1&nbsp;&nbsp;&nbsp;&nbsp; 0<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">┃&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp; </span><span style="font-size: 12pt; font-family: 宋体;">未使用<span lang="EN-US">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
┃ U/S┃ R/W┃ P&nbsp;┃<o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">&nbsp;<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">异常处理例程通常采取如下的步骤：<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">查找一个空闲的页帧或从硬盘中将页帧交换出来，重新设置正确的页目录项或页表项的值，刷新<span lang="EN-US">TLB</span>。处理器通常保存最近最多访问的页目录或页表项到一个<span lang="EN-US">cache</span>中，以避免每次都进行虚拟地址到物理地址的转换，这个<span lang="EN-US">cache</span>就叫做<span lang="EN-US">TLB</span>。只有我们改动了页目录或页表项，就应当刷新<span lang="EN-US">TLB</span>。方法很简单，就是重新加载<span lang="EN-US">CR3 </span>寄存器。<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US"><br>
</span><span style="font-size: 12pt; font-family: 宋体;">现在我们来看看代码段，内存管理通常少不了大量的宏定义：<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体; color: red;" lang="EN-US">08/include/kernel.h</span><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">#define PAGE_DIR&nbsp;&nbsp;&nbsp;
((HD0_ADDR+HD0_SIZE+(4*1024)-1) &amp; 0xfffff000)<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">物理内存安排：<span lang="EN-US">IDT</span>（在<span lang="EN-US">0x40000</span>），接下来是<span lang="EN-US">GDT</span>，接下来是<span lang="EN-US">HD0</span>使用，然后才是页目录，<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">所以这个宏看起来有点长。<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US"><br>
<span style="color: red;">08/include/mm.h</span><br>
#define PAGE_SIZE&nbsp;&nbsp;&nbsp;
(4*1024)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/*
</span><span style="font-size: 12pt; font-family: 宋体;">页帧粒度<span lang="EN-US"> */<br>
#define PAGE_TABLE&nbsp;&nbsp;&nbsp; (PAGE_DIR+PAGE_SIZE)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/*
</span>页表物理地址<span lang="EN-US"> */<br>
#define MEMORY_RANGE (4*1024)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
/* skelix</span>只管理<span lang="EN-US">4M </span>内存暂时<span lang="EN-US"> */<o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US"><br>
<span style="color: red;">08/mm.c</span><o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">/* </span><span style="font-size: 12pt; font-family: 宋体;">物理内存使用情况的位图表<span lang="EN-US"> */<o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">static char mmap[MEMORY_RANGE/PAGE_SIZE] = {PG_REVERSED,
};<br>
<br>
void<br>
mm_install(void) {<br>
&nbsp;&nbsp;&nbsp; unsigned int *page_dir = ((unsigned int *)PAGE_DIR);<br>
&nbsp;&nbsp;&nbsp; unsigned int *page_table = ((unsigned int *)PAGE_TABLE);<br>
&nbsp;&nbsp;&nbsp; unsigned int address = 0;<br>
&nbsp;&nbsp;&nbsp; int i;<br>
&nbsp;&nbsp;&nbsp; for(i=0; i&lt;MEMORY_RANGE/PAGE_SIZE; ++i) {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; /* </span><span style="font-size: 12pt; font-family: 宋体;">页表项属性设置为<span lang="EN-US">: kernel, r/w, present */<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; page_table[i] = address|7;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; address += PAGE_SIZE;<br>
&nbsp;&nbsp;&nbsp; };<o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">&nbsp;&nbsp;&nbsp;&nbsp;// </span><span style="font-size: 12pt; font-family: 宋体;">上面循环初始化了<span lang="EN-US">0~4M</span>对应的所有页表项<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US"><br>
&nbsp;&nbsp;&nbsp; page_dir[0] = (PAGE_TABLE|7);<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">&nbsp;&nbsp;&nbsp;&nbsp;// </span><span style="font-size: 12pt; font-family: 宋体;">页目录项只需要第一个就可以了，因为只有<span lang="EN-US">4M</span>内存<span lang="EN-US"><br>
<br>
&nbsp;&nbsp;&nbsp; for (i=1; i&lt;1024; ++i)<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; page_dir[i] = 6;<o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">&nbsp;&nbsp;&nbsp;&nbsp;// </span><span style="font-size: 12pt; font-family: 宋体;">其他的<span lang="EN-US">1023</span>个页目录项设置为空，如果这<span lang="EN-US">1024</span>项都设置，可访问<span lang="EN-US">4G</span>内存空间<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">&nbsp;&nbsp;&nbsp;&nbsp;// </span><span style="font-size: 12pt; font-family: 宋体;">设置<span lang="EN-US">0</span>～<span lang="EN-US">1M</span>内存为已使用。<span lang="EN-US"><br>
&nbsp;&nbsp;&nbsp; for (i=(1*1024*1024)/PAGE_SIZE-1; i&gt;=0; --i)<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; mmap[i] = PG_REVERSED;<o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">&nbsp;&nbsp;&nbsp;&nbsp;// </span><span style="font-size: 12pt; font-family: 宋体;">因为内核只用到了低于<span lang="EN-US">1M</span>的内存，所以保留它们，这样就不会被交换出去了<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US"><br>
<br>
&nbsp;&nbsp;&nbsp; __asm__ (<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; "movl&nbsp;&nbsp;&nbsp;
%%eax,&nbsp;&nbsp;&nbsp;
%%cr3\n\t"&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// </span><span style="font-size: 12pt; font-family: 宋体;">加载页目录基址到寄存器<span lang="EN-US"><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "movl&nbsp;&nbsp;&nbsp;
%%cr0,&nbsp;&nbsp;&nbsp; %%eax\n\t"<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; "orl&nbsp;&nbsp;&nbsp; $0x80000000,&nbsp;&nbsp;&nbsp;
%%eax\n\t"<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; "movl&nbsp;&nbsp;&nbsp;
%%eax,&nbsp;&nbsp;&nbsp;
%%cr0"::"a"(PAGE_DIR));&nbsp;&nbsp;&nbsp;&nbsp;// </span>开启分页机制，<span lang="EN-US">CR0</span>的最高位<span lang="EN-US"><br>
}<o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">&nbsp;<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">通过<span lang="EN-US">mmap</span>位图，我们可以清楚的知道内存的使用情况，这样就可以分配空闲页帧了，如下：<span lang="EN-US"><br>
<span style="color: red;">08/mm.c</span><o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">unsigned int<br>
alloc_page(int type) {<br>
&nbsp;&nbsp;&nbsp; int i;<br>
<br>
&nbsp;&nbsp;&nbsp; for (i=(sizeof mmap)-1; i&gt;=0 &amp;&amp; mmap[i]; --i)<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; ;<br>
<br>
&nbsp;&nbsp;&nbsp; if (i &lt; 0) {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; kprintf(KPL_PANIC, "NO MEMORY
LEFT");<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; halt();<br>
&nbsp;&nbsp;&nbsp; }<br>
&nbsp;&nbsp;&nbsp; mmap[i] = type;<br>
&nbsp;&nbsp;&nbsp; return
i;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// </span><span style="font-size: 12pt; font-family: 宋体;">返回页帧号<span lang="EN-US"><br>
}<br>
<br>
void *<br>
page2mem(unsigned int nr)
{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// </span>转换为虚拟地址<span lang="EN-US"><br>
&nbsp;&nbsp;&nbsp; return (void *)(nr * PAGE_SIZE);<br>
}<br>
<br>
void<br>
do_page_fault(enum KP_LEVEL kl,<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; unsigned int
ret_ip, unsigned int ss, unsigned int gs,<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; unsigned int
fs, unsigned int es, unsigned int ds, <br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; unsigned int
edi, unsigned int esi, unsigned int ebp,<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; unsigned int
esp, unsigned int ebx, unsigned int edx, <br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; unsigned int
ecx, unsigned int eax, unsigned int isr_nr, <br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; unsigned int
err, unsigned int eip, unsigned int cs, <br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; unsigned int
eflags,unsigned int old_esp, unsigned int old_ss) {<br>
&nbsp;&nbsp;&nbsp; unsigned int cr2, cr3;<br>
&nbsp;&nbsp;&nbsp; (void)ret_ip; (void)ss; (void)gs; (void)fs; (void)es; <br>
&nbsp;&nbsp;&nbsp; (void)ds; (void)edi; (void)esi; (void)ebp; (void)esp; <br>
&nbsp;&nbsp;&nbsp; (void) ebx; (void)edx; (void)ecx; (void)eax; <br>
&nbsp;&nbsp;&nbsp; (void)isr_nr; (void)eip; (void)cs; (void)eflags; <br>
&nbsp;&nbsp;&nbsp; (void)old_esp; (void)old_ss; (void)kl;<br>
&nbsp;&nbsp;&nbsp; __asm__ ("movl %%cr2, %%eax":"=a"(cr2));<br>
&nbsp;&nbsp;&nbsp; __asm__ ("movl %%cr3, %%eax":"=a"(cr3));<br>
&nbsp;&nbsp;&nbsp; kprintf(KPL_PANIC, "\n&nbsp; The fault at %x cr3:%x was
caused by a %s. "<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; "The accessing
cause of the fault was a %s, when the "<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; "processor was
executing in %s mode, page %x is free\n", <br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; cr2, cr3,<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
(err&amp;0x1)?"page-level protection voilation":"not-present
page", <br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
(err&amp;0x2)?"write":"read", <br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
(err&amp;0x4)?"user":"supervisor",<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: red;">alloc_page</span>(PG_NORMAL));<br>
}<o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">页异常函数，它什么也没有做，知识显示一些错误信息。<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">现在我们来动态的分配一些内存，我们修改一下任务函数：<span lang="EN-US"><br>
<span style="color: red;">08/init.c</span><o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">static void<br>
new_task(unsigned int eip) {<br>
&nbsp;&nbsp;&nbsp; struct TASK_STRUCT *task = <span style="color: red;">page2mem</span>(alloc_page(PG_TASK));<br>
&nbsp;&nbsp;&nbsp; memcpy(&amp;(task-&gt;tss), &amp;(TASK0.tss), sizeof(struct
TSS_STRUCT));<br>
<br>
&nbsp;&nbsp;&nbsp; task-&gt;tss.esp0 = (unsigned int)task + PAGE_SIZE;<br>
&nbsp;&nbsp;&nbsp; task-&gt;tss.eip = eip;<br>
&nbsp;&nbsp;&nbsp; task-&gt;tss.eflags = 0x3202;<br>
&nbsp;&nbsp;&nbsp; task-&gt;tss.esp = (unsigned int)<span style="color: red;">page2mem</span>(alloc_page(PG_TASK))+PAGE_SIZE;<br>
&nbsp;&nbsp;&nbsp; task-&gt;tss.cr3 = PAGE_DIR;<br>
&nbsp;&nbsp;&nbsp; task-&gt;priority = INITIAL_PRIO;<br>
&nbsp;&nbsp;&nbsp; task-&gt;ldt[0] = DEFAULT_LDT_CODE;<br>
&nbsp;&nbsp;&nbsp; task-&gt;ldt[1] = DEFAULT_LDT_DATA;<br>
<br>
&nbsp;&nbsp;&nbsp; task-&gt;next = current-&gt;next;<br>
&nbsp;&nbsp;&nbsp; current-&gt;next = task;<br>
&nbsp;&nbsp;&nbsp; task-&gt;state = TS_RUNABLE;<br>
}<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">自己分配的任务数据结构和任务堆栈，是不是很有成就感：）<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">&nbsp;<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">&nbsp;<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">最后在<span lang="EN-US">init.c</span>中添加初始化代码：<span lang="EN-US"><br>
<span style="color: red;">08/init.c</span><o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">void <br>
init(void) {<br>
&nbsp;&nbsp;&nbsp; char wheel[] = {'\\', '|', '/', '-'};<br>
&nbsp;&nbsp;&nbsp; int i = 0;<br>
<br>
&nbsp;&nbsp;&nbsp; idt_install();<br>
&nbsp;&nbsp;&nbsp; pic_install();<br>
&nbsp;&nbsp;&nbsp; mm_install();&nbsp;&nbsp; &nbsp;&nbsp; /*&nbsp;</span><span style="font-size: 12pt; font-family: 宋体;">初始化函数调用<span lang="EN-US"> */<br>
&nbsp;&nbsp;&nbsp; kb_install();<br>
&nbsp;&nbsp;&nbsp; timer_install(100);<br>
&nbsp;&nbsp;&nbsp; set_tss((unsigned long long)&amp;TASK0.tss);<br>
&nbsp;&nbsp;&nbsp; set_ldt((unsigned long long)&amp;TASK0.ldt);<br>
&nbsp;&nbsp;&nbsp; __asm__ ("ltrw&nbsp;&nbsp;&nbsp;
%%ax\n\t"::"a"(TSS_SEL));<br>
&nbsp;&nbsp;&nbsp; __asm__ ("lldt&nbsp;&nbsp;&nbsp;
%%ax\n\t"::"a"(LDT_SEL));<br>
<br>
&nbsp;&nbsp;&nbsp; kprintf(KPL_DUMP, "Verifing disk partition
table....\n");<br>
&nbsp;&nbsp;&nbsp; verify_DPT();<br>
&nbsp;&nbsp;&nbsp; kprintf(KPL_DUMP, "Verifing file systes....\n");<br>
&nbsp;&nbsp;&nbsp; verify_fs();<br>
&nbsp;&nbsp;&nbsp; kprintf(KPL_DUMP, "Checking / directory....\n");<br>
&nbsp;&nbsp;&nbsp; verify_dir();<br>
<br>
&nbsp;&nbsp;&nbsp; sti();<br>
&nbsp;&nbsp;&nbsp; new_task((unsigned int)task1_run);<br>
&nbsp;&nbsp;&nbsp; new_task((unsigned int)task2_run);<br>
&nbsp;&nbsp;&nbsp; __asm__ ("movl %%esp,%%eax\n\t" \<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;"pushl %%ecx\n\t"
\<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;"pushl
%%eax\n\t" \<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;"pushfl\n\t" \<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;"pushl
%%ebx\n\t" \<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;"pushl
$1f\n\t" \<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;"iret\n" \<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;"1:\tmovw
%%cx,%%ds\n\t" \<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;"movw
%%cx,%%es\n\t" \<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;"movw %%cx,%%fs\n\t"
\<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;"movw
%%cx,%%gs" \<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;::"b"(USER_CODE_SEL),"c"(USER_DATA_SEL));<br>
&nbsp;&nbsp;&nbsp; __asm__ ("incb 0xeeffeeff");&nbsp;&nbsp;
&nbsp;&nbsp; &nbsp;&nbsp; /*&nbsp;</span><span style="color: r