<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2enclosuresfull.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss xmlns:atom="http://www.w3.org/2005/Atom" xmlns:openSearch="http://a9.com/-/spec/opensearch/1.1/" xmlns:georss="http://www.georss.org/georss" xmlns:gd="http://schemas.google.com/g/2005" xmlns:thr="http://purl.org/syndication/thread/1.0" xmlns:media="http://search.yahoo.com/mrss/" xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0"><channel><atom:id>tag:blogger.com,1999:blog-3931381955158939823</atom:id><lastBuildDate>Fri, 25 Nov 2011 12:59:29 +0000</lastBuildDate><category>Life</category><category>3D</category><category>Java</category><category>BSD</category><category>Linux</category><category>C/C++</category><title>Wei</title><description /><link>http://wei-hu-tw.blogspot.com/</link><managingEditor>noreply@blogger.com (Wei)</managingEditor><generator>Blogger</generator><openSearch:totalResults>25</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/wei-hu-tw" /><feedburner:info uri="wei-hu-tw" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><itunes:owner><itunes:email>noreply@blogger.com</itunes:email></itunes:owner><itunes:explicit>no</itunes:explicit><itunes:subtitle></itunes:subtitle><item><guid isPermaLink="false">tag:blogger.com,1999:blog-3931381955158939823.post-3547690233732209018</guid><pubDate>Mon, 11 Jul 2011 10:30:00 +0000</pubDate><atom:updated>2011-07-12T09:46:43.763+08:00</atom:updated><title>My simple Excel gantt chart template</title><description>For doing task management well, I found that vertex42 does make a good &lt;a href="http://www.vertex42.com/ExcelTemplates/excel-gantt-chart.html"&gt;Excel gantt chart template&lt;/a&gt;. However, I can not modify that template due to I don't know the unprotect password. Hence, I make a similar one, and add some features useful to me. My simple Excel gantt chart template can be downloaded from &lt;a href="https://docs.google.com/leaf?id=0B7EcbVKeXCFlMDI3YzM3MTMtOWViOS00NWM0LWJhNWQtNjhhYTg4ZDI3NDY2&amp;hl=en_US"&gt;Here&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-re-WMPO27bo/ThunfshG1fI/AAAAAAAABPI/seyihFCZS_4/s1600/z11111111111111111111111.gif" imageanchor="1" style="clear:left; float:left;margin-right:1em; margin-bottom:1em"&gt;&lt;img border="0" height="206" width="400" src="http://2.bp.blogspot.com/-re-WMPO27bo/ThunfshG1fI/AAAAAAAABPI/seyihFCZS_4/s400/z11111111111111111111111.gif" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3931381955158939823-3547690233732209018?l=wei-hu-tw.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/wei-hu-tw/~4/yRjHNTsJEUQ" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/wei-hu-tw/~3/yRjHNTsJEUQ/my-simple-excel-gantt-chart-template.html</link><author>noreply@blogger.com (Wei)</author><media:thumbnail url="http://2.bp.blogspot.com/-re-WMPO27bo/ThunfshG1fI/AAAAAAAABPI/seyihFCZS_4/s72-c/z11111111111111111111111.gif" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://wei-hu-tw.blogspot.com/2011/07/my-simple-excel-gantt-chart-template.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-3931381955158939823.post-1859113423497675707</guid><pubDate>Mon, 27 Jun 2011 08:52:00 +0000</pubDate><atom:updated>2011-06-27T16:52:46.587+08:00</atom:updated><title>X 工</title><description>大陸習慣簡稱工程師為 X 工, 比方說 "陳工程師" 就叫 "陳工".&lt;br /&gt;
一日, 我旁邊的同事打電話給客戶...&lt;br /&gt;
&lt;br /&gt;
"喂, 請問是蔣工嗎"&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3931381955158939823-1859113423497675707?l=wei-hu-tw.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/wei-hu-tw/~4/HGe2HAxY6lU" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/wei-hu-tw/~3/HGe2HAxY6lU/x.html</link><author>noreply@blogger.com (Wei)</author><thr:total>0</thr:total><feedburner:origLink>http://wei-hu-tw.blogspot.com/2011/06/x.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-3931381955158939823.post-5014072644963247008</guid><pubDate>Mon, 06 Apr 2009 14:00:00 +0000</pubDate><atom:updated>2009-04-06T22:02:39.271+08:00</atom:updated><title>昨天公司樓下的便利商店舉辦杜老爺冰棒買一送一特惠活動</title><description>我就買了兩根卡布奇諾口味的, 結果晚上就失眠了...!@#$%&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3931381955158939823-5014072644963247008?l=wei-hu-tw.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/wei-hu-tw/~4/V9urrMSQdak" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/wei-hu-tw/~3/V9urrMSQdak/blog-post.html</link><author>noreply@blogger.com (Wei)</author><thr:total>0</thr:total><feedburner:origLink>http://wei-hu-tw.blogspot.com/2009/04/blog-post.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-3931381955158939823.post-6356773999489239051</guid><pubDate>Mon, 24 Mar 2008 14:03:00 +0000</pubDate><atom:updated>2008-03-24T22:05:29.809+08:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Life</category><title>什麼叫做多此一舉</title><description>就是看到一個人很好心的放棄了排的很前面的位置，然後跑到上風處去抽香菸。。。&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3931381955158939823-6356773999489239051?l=wei-hu-tw.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/wei-hu-tw/~4/mda26uH-IvY" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/wei-hu-tw/~3/mda26uH-IvY/blog-post.html</link><author>noreply@blogger.com (Wei)</author><thr:total>0</thr:total><feedburner:origLink>http://wei-hu-tw.blogspot.com/2008/03/blog-post.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-3931381955158939823.post-121553926048877718</guid><pubDate>Thu, 21 Feb 2008 11:03:00 +0000</pubDate><atom:updated>2008-12-10T06:59:45.524+08:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">C/C++</category><title>"Shared library" + "C++" + "static" is evil</title><description>Shared library 在 Microsoft windows 上通常是以 .dll 作為檔名結尾，而在 UNIX like 系統上則是以 .so 作為結束。為什麼會有這麼大的差異呢？這是因為 shared library 並沒有一個跨 OS 的 standard 可以遵循，所以在撰寫 C/C++ 程式時就會碰到很多麻煩。&lt;br /&gt;&lt;br /&gt;基本上，只要使用到 shared library，這個程式就不 portable 了。所有用來處理 shared library 的機制都不 portable。 Windows 有他自己的一套，UNIX 有它自己的另一套。當 C++ 程式裡面使用到 static 時更是嚴重，如果再加上 template 的話，那基本上就很難去切割的很模組化了。&lt;br /&gt;&lt;br /&gt;舉例來說，下面是 dll 的 .h 檔：&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_e5w2gEy9U-Q/R77KamdV8YI/AAAAAAAAASw/GbT9yoJJbt8/s1600-h/1.PNG"&gt;&lt;img style="cursor: pointer;" src="http://4.bp.blogspot.com/_e5w2gEy9U-Q/R77KamdV8YI/AAAAAAAAASw/GbT9yoJJbt8/s400/1.PNG" alt="" id="BLOGGER_PHOTO_ID_5169791980616937858" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;再來看 exe 的 .c 檔：&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_e5w2gEy9U-Q/R77KbGdV8bI/AAAAAAAAATI/5ByvGIm65MY/s1600-h/4.PNG"&gt;&lt;img style="cursor: pointer;" src="http://2.bp.blogspot.com/_e5w2gEy9U-Q/R77KbGdV8bI/AAAAAAAAATI/5ByvGIm65MY/s400/4.PNG" alt="" id="BLOGGER_PHOTO_ID_5169791989206872498" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;為求完整，附上 dll 的 .c 檔：&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_e5w2gEy9U-Q/R77Ka2dV8aI/AAAAAAAAATA/G3cvzfONxn8/s1600-h/3.PNG"&gt;&lt;img style="cursor: pointer;" src="http://1.bp.blogspot.com/_e5w2gEy9U-Q/R77Ka2dV8aI/AAAAAAAAATA/G3cvzfONxn8/s400/3.PNG" alt="" id="BLOGGER_PHOTO_ID_5169791984911905186" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;這樣子經過 Visual C++ 2008 express edition 編譯後，執行時會發現在 .exe 跟 .dll 內部都會存在一份 static member 的 memory space。所以執行後的結果會得到 .exe 跟 .dll 看到的是不一樣的值：&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_e5w2gEy9U-Q/R77KbWdV8cI/AAAAAAAAATQ/yew1lxnWDgc/s1600-h/5.PNG"&gt;&lt;img style="cursor: pointer;" src="http://3.bp.blogspot.com/_e5w2gEy9U-Q/R77KbWdV8cI/AAAAAAAAATQ/yew1lxnWDgc/s400/5.PNG" alt="" id="BLOGGER_PHOTO_ID_5169791993501839810" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;這是因為在 Visual C++ 中的 default 設定是 .exe 或 .dll 內的 symbol 都不會被 export 出去，如果沒有特別設定的話，都預設是專屬於該 .exe 或 .dll 內部的，也就是說外面是看不到的。所以如果外面也要能夠存取到的話，那麼 Visual C++ 提供一個 keyword，也就是 __declspec(dllimport) 跟 __declspec(dllexport)，可以做到這件事情。透過這兩個 keyword 的使用，就可以讓 .exe 檔也能存取 .dll 內的 static member，而不會產生不一致的現象了。所以新的 .dll 的 .h 檔會像是如下所示：&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_e5w2gEy9U-Q/R77Ka2dV8ZI/AAAAAAAAAS4/brhYhXPwg6Q/s1600-h/2.PNG"&gt;&lt;img style="cursor: pointer;" src="http://1.bp.blogspot.com/_e5w2gEy9U-Q/R77Ka2dV8ZI/AAAAAAAAAS4/brhYhXPwg6Q/s400/2.PNG" alt="" id="BLOGGER_PHOTO_ID_5169791984911905170" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_e5w2gEy9U-Q/R77Lk2dV8dI/AAAAAAAAATY/kPqG0p6lAPo/s1600-h/6.PNG"&gt;&lt;img style="cursor: pointer;" src="http://1.bp.blogspot.com/_e5w2gEy9U-Q/R77Lk2dV8dI/AAAAAAAAATY/kPqG0p6lAPo/s400/6.PNG" alt="" id="BLOGGER_PHOTO_ID_5169793256222224850" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;我在 mingw gcc 4.2.3 上做試驗，也得到一樣的結果，一定要加上 __declspec(dllimport) 以及 __declspec(dllexport) 這樣的關鍵字才有用。&lt;br /&gt;&lt;br /&gt;&lt;不負責猜想&gt; 我沒有在 linux 版上的 gcc 做試驗，不過我記得 gcc 的 default 行為是 export module 內所有的 symbol，所以我想 linux 版的 gcc 應該是不用加任何 keyword 就應該是 .exe 跟 .so 都只會看到同一份 static member data 才對。&lt;/不負責猜想&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3931381955158939823-121553926048877718?l=wei-hu-tw.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/wei-hu-tw/~4/TEaLQvzHgRU" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/wei-hu-tw/~3/TEaLQvzHgRU/shared-library-c-static-is-evil.html</link><author>noreply@blogger.com (Wei)</author><media:thumbnail url="http://4.bp.blogspot.com/_e5w2gEy9U-Q/R77KamdV8YI/AAAAAAAAASw/GbT9yoJJbt8/s72-c/1.PNG" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://wei-hu-tw.blogspot.com/2008/02/shared-library-c-static-is-evil.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-3931381955158939823.post-2987500290296190068</guid><pubDate>Fri, 15 Feb 2008 16:40:00 +0000</pubDate><atom:updated>2008-02-16T00:42:10.816+08:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Life</category><title>什麼時候晚上用時速 40 公里的龜速開沒路燈的蘇花高還會緊張個半死？</title><description>就是當自己是第一台車，而後面跟著一屁股車的時候。。。&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3931381955158939823-2987500290296190068?l=wei-hu-tw.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/wei-hu-tw/~4/dT0J0M2i7hU" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/wei-hu-tw/~3/dT0J0M2i7hU/40.html</link><author>noreply@blogger.com (Wei)</author><thr:total>0</thr:total><feedburner:origLink>http://wei-hu-tw.blogspot.com/2008/02/40.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-3931381955158939823.post-2262896460168293667</guid><pubDate>Sun, 20 Jan 2008 09:21:00 +0000</pubDate><atom:updated>2008-01-20T18:54:43.676+08:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">3D</category><title>Open source 的 scene graph library 的選擇</title><description>3D scene graph 在很多地方都見得到，例如 Java 的 JSR-184 (a.k.a m3g)，3D studio max 裡面也有自己的一套 (要用 3dsmax sdk 或更高一層的 3DXI 才存取得到)。談到 open source 的 3D scene graph library，常見到的幾乎就是下列三套：&lt;br /&gt;&lt;ol&gt;&lt;li&gt;&lt;a href="http://www.openscenegraph.org/"&gt;Open Scene Graph&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.opensg.org"&gt;OpenSG&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.coin3d.org"&gt;Coin3D&lt;/a&gt;&lt;/li&gt;&lt;/ol&gt;其中的 Coin3D 是 GPL license，所以如果你的 project 不是 GPL license, 那麼就不用考慮他了。OpenSG 採用的是 LGPL，而 Open Scene Graph 採用的也是類似 LGPL，但卻是更寬鬆的 license，他容許 static linking 以及直接 embedded 到 application 中。所以就 license 而言，Open Scene Graph 是最有彈性的。&lt;br /&gt;&lt;br /&gt;另外就使用者及社群的活躍性而言，以&lt;a href="http://www.openscenegraph.org/projects/osg/wiki/Community/CommunityActivity"&gt;這個網頁&lt;/a&gt;的資料來看，Open Scene Graph 不論是在使用者以及社群活躍度上，都比另外兩個 project 來的蓬勃。OpenSG 次之，Coin3D 敬陪末座。&lt;br /&gt;&lt;br /&gt;在架構上，Open Scene Graph 跟 OpenSG 類似，都是採用 Application-driven 的方式，也就是在 application 的執行期間內，會一直不斷的進行 render 的動作，所以適合用在遊戲以及模擬類的程式中 (比方說飛行模擬)。而 Coin3D 只會在 scene 的內容有變的時候，才會 render，比方說 view point 改變等等。&lt;br /&gt;&lt;br /&gt;Coin3D 是基於 SGI 的 OpenInventor 這套 API 而來，所以他跟 OpenInventor 是 API 相容的。雖然他跟 SGI 的 OpenInventor 相容，但也加入了不少自己的一些 extension。而且 SGI OpenInventor 上次的 source release 是在 2003 年，跟一直在進行更新的 Coin3D 相比，似乎活躍度差了那麼一點。&lt;br /&gt;&lt;br /&gt;另外，就網路上查到的資料，同樣的一個 3D scene，用這三套 library 來撰寫，結果似乎以 OpenSG 撰寫所得到的 performance 最好，Open Scene Graph 次之，Coin3D 最末。&lt;br /&gt;&lt;br /&gt;所以看來要選一套 open source 的 scene graph library 來用的話，不外乎就是挑 OpenSG 或 Open Scene Graph 了。雖然 OpenSG 似乎有個比較好的 performance 表現，但以社群的活躍度以及所得或的支援來說，Open Scene Graph 看來是 open source scene graph 中最好的選擇了。&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3931381955158939823-2262896460168293667?l=wei-hu-tw.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/wei-hu-tw/~4/baFWPQiaJlE" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/wei-hu-tw/~3/baFWPQiaJlE/3d-scene-graph-java-jsr-184.html</link><author>noreply@blogger.com (Wei)</author><thr:total>0</thr:total><feedburner:origLink>http://wei-hu-tw.blogspot.com/2008/01/3d-scene-graph-java-jsr-184.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-3931381955158939823.post-378863054137665726</guid><pubDate>Thu, 03 Jan 2008 14:55:00 +0000</pubDate><atom:updated>2008-01-05T12:56:59.242+08:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Life</category><title>像我這種樂天知命的人</title><description>怎麼會有好幾根白頭髮呢~&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3931381955158939823-378863054137665726?l=wei-hu-tw.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/wei-hu-tw/~4/qeSxxTu3AD8" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/wei-hu-tw/~3/qeSxxTu3AD8/blog-post_03.html</link><author>noreply@blogger.com (Wei)</author><thr:total>0</thr:total><feedburner:origLink>http://wei-hu-tw.blogspot.com/2008/01/blog-post_03.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-3931381955158939823.post-7115077456965412279</guid><pubDate>Mon, 31 Dec 2007 19:24:00 +0000</pubDate><atom:updated>2008-01-01T15:32:44.774+08:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Life</category><title>新年理當新氣象</title><description>果真第一次在公司加班跨年就發生在今年&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3931381955158939823-7115077456965412279?l=wei-hu-tw.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/wei-hu-tw/~4/Xi6SnwyE7Es" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/wei-hu-tw/~3/Xi6SnwyE7Es/blog-post.html</link><author>noreply@blogger.com (Wei)</author><thr:total>1</thr:total><feedburner:origLink>http://wei-hu-tw.blogspot.com/2008/01/blog-post.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-3931381955158939823.post-1077723240813632856</guid><pubDate>Fri, 28 Dec 2007 13:20:00 +0000</pubDate><atom:updated>2008-01-01T03:24:23.880+08:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Life</category><title>RD有兩種</title><description>RD 有兩種，一種是 Research &amp;amp; Design，另一種是 Revise &amp;amp; Debug...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3931381955158939823-1077723240813632856?l=wei-hu-tw.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/wei-hu-tw/~4/NFuH_sxRPkM" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/wei-hu-tw/~3/NFuH_sxRPkM/rd-research-design-revise-debug.html</link><author>noreply@blogger.com (Wei)</author><thr:total>0</thr:total><feedburner:origLink>http://wei-hu-tw.blogspot.com/2007/12/rd-research-design-revise-debug.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-3931381955158939823.post-6983242475318194085</guid><pubDate>Thu, 27 Dec 2007 16:00:00 +0000</pubDate><atom:updated>2007-12-28T00:03:51.024+08:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Life</category><title>苦命工程師</title><description>有人說我這種好與人為善的彌勒佛個性，不適合當主管。&lt;br /&gt;...&lt;br /&gt;看來我天生就是苦命工程師唉。&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3931381955158939823-6983242475318194085?l=wei-hu-tw.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/wei-hu-tw/~4/fkQQgwAqbis" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/wei-hu-tw/~3/fkQQgwAqbis/blog-post.html</link><author>noreply@blogger.com (Wei)</author><thr:total>0</thr:total><feedburner:origLink>http://wei-hu-tw.blogspot.com/2007/12/blog-post.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-3931381955158939823.post-467833666415624954</guid><pubDate>Thu, 15 Nov 2007 13:16:00 +0000</pubDate><atom:updated>2007-11-15T21:17:09.738+08:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Life</category><title>添購新的沐浴乳卻沒有仔細看標籤的後果</title><description>&lt;span id="ctl00_MainContentPlaceholder_ctl01_ctl00_lblEntry"&gt;就是在強烈冷氣團來襲的晚上, 用清爽的薄荷口味沐浴乳讓自己稍微動一下就 "涼"~ 到不行...&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3931381955158939823-467833666415624954?l=wei-hu-tw.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/wei-hu-tw/~4/4V8TWaVM3wU" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/wei-hu-tw/~3/4V8TWaVM3wU/blog-post_1652.html</link><author>noreply@blogger.com (Wei)</author><thr:total>0</thr:total><feedburner:origLink>http://wei-hu-tw.blogspot.com/2007/11/blog-post_1652.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-3931381955158939823.post-3266432328657554585</guid><pubDate>Thu, 15 Nov 2007 13:16:00 +0000</pubDate><atom:updated>2007-11-15T21:16:36.814+08:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Life</category><title>平常太貪吃的後果</title><description>&lt;span id="ctl00_MainContentPlaceholder_ctl01_ctl00_lblEntry"&gt;對於同事一看到有新的餅乾口味就馬上來通知我的心態覺得有深入研究的必要性&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3931381955158939823-3266432328657554585?l=wei-hu-tw.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/wei-hu-tw/~4/DQiJKT5cBzc" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/wei-hu-tw/~3/DQiJKT5cBzc/blog-post_9942.html</link><author>noreply@blogger.com (Wei)</author><thr:total>0</thr:total><feedburner:origLink>http://wei-hu-tw.blogspot.com/2007/11/blog-post_9942.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-3931381955158939823.post-3023022732802670768</guid><pubDate>Thu, 15 Nov 2007 13:15:00 +0000</pubDate><atom:updated>2007-11-15T21:15:43.551+08:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Life</category><title>過敏源</title><description>&lt;span id="ctl00_MainContentPlaceholder_ctl01_ctl00_lblEntry"&gt;&lt;div&gt;從小我就對灰塵還有冷空氣過敏&lt;/div&gt; &lt;div&gt; &lt;/div&gt; &lt;div&gt;雖然長大了好很多&lt;/div&gt; &lt;div&gt; &lt;/div&gt; &lt;div&gt;但爾偶還是會這麼來個折磨一下&lt;/div&gt; &lt;div&gt; &lt;/div&gt; &lt;div&gt;今天晚上吃晚餐的時候&lt;/div&gt; &lt;div&gt; &lt;/div&gt; &lt;div&gt;大概是為了邊吃飯, 邊跟同事聊天&lt;/div&gt; &lt;div&gt; &lt;/div&gt; &lt;div&gt;所以不小心把飯吃到鼻子裡去&lt;/div&gt; &lt;div&gt; &lt;/div&gt; &lt;div&gt;沒想到晚上就開始過敏了&lt;/div&gt; &lt;div&gt; &lt;/div&gt; &lt;div&gt;邊加班邊過敏的感覺, 怎個讚字了得&lt;/div&gt; &lt;div&gt; &lt;/div&gt; &lt;div&gt;好不容易撐到事情做的差不多&lt;/div&gt; &lt;div&gt; &lt;/div&gt; &lt;div&gt;回家洗個熱水澡就好多了&lt;/div&gt; &lt;div&gt; &lt;/div&gt; &lt;div&gt;所以我的過敏源除了灰塵跟冷空氣&lt;/div&gt; &lt;div&gt; &lt;/div&gt; &lt;div&gt;還有今天晚餐的... 一粒米&lt;/div&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3931381955158939823-3023022732802670768?l=wei-hu-tw.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/wei-hu-tw/~4/FF1VbCGxrfk" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/wei-hu-tw/~3/FF1VbCGxrfk/blog-post_9298.html</link><author>noreply@blogger.com (Wei)</author><thr:total>0</thr:total><feedburner:origLink>http://wei-hu-tw.blogspot.com/2007/11/blog-post_9298.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-3931381955158939823.post-658860694117507391</guid><pubDate>Thu, 15 Nov 2007 13:14:00 +0000</pubDate><atom:updated>2007-11-15T21:14:54.525+08:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Life</category><title>什麼叫做質疑的眼神</title><description>&lt;span id="ctl00_MainContentPlaceholder_ctl01_ctl00_lblEntry"&gt;&lt;/span&gt;&lt;span id="ctl00_MainContentPlaceholder_ctl01_ctl00_lblEntry"&gt;就是當我晚上 10:30 看到同事正在吃大碗公泡麵而跟他說這樣會變胖的時候, 他看著我嘴巴裏面塞了滿滿滿~餅乾時的眼神...&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3931381955158939823-658860694117507391?l=wei-hu-tw.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/wei-hu-tw/~4/EySnJstxsT8" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/wei-hu-tw/~3/EySnJstxsT8/blog-post_1611.html</link><author>noreply@blogger.com (Wei)</author><thr:total>0</thr:total><feedburner:origLink>http://wei-hu-tw.blogspot.com/2007/11/blog-post_1611.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-3931381955158939823.post-9031899777048367129</guid><pubDate>Thu, 15 Nov 2007 13:08:00 +0000</pubDate><atom:updated>2007-11-15T21:08:48.316+08:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Life</category><title>上禮拜參加本大樓舉辦的旅遊</title><description>當在遊覽車上面聽到鄧麗君專輯從頭到尾唱過一遍以及我家前面有小河時，就知道本車年齡層的分布了&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3931381955158939823-9031899777048367129?l=wei-hu-tw.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/wei-hu-tw/~4/O21A1eAPVzg" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/wei-hu-tw/~3/O21A1eAPVzg/blog-post_452.html</link><author>noreply@blogger.com (Wei)</author><thr:total>0</thr:total><feedburner:origLink>http://wei-hu-tw.blogspot.com/2007/11/blog-post_452.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-3931381955158939823.post-7508604588786311250</guid><pubDate>Thu, 15 Nov 2007 13:08:00 +0000</pubDate><atom:updated>2007-11-15T21:08:22.237+08:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Life</category><title>我就說我很年輕嘛</title><description>這是我今天去參加母親那邊的囍宴時，看到上去唱卡拉 OK 的男生都是老男人的時候的感想。&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3931381955158939823-7508604588786311250?l=wei-hu-tw.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/wei-hu-tw/~4/cvdYeFVet-c" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/wei-hu-tw/~3/cvdYeFVet-c/blog-post_7167.html</link><author>noreply@blogger.com (Wei)</author><thr:total>0</thr:total><feedburner:origLink>http://wei-hu-tw.blogspot.com/2007/11/blog-post_7167.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-3931381955158939823.post-2274651283298063902</guid><pubDate>Thu, 15 Nov 2007 13:07:00 +0000</pubDate><atom:updated>2007-11-15T21:07:56.626+08:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Life</category><title>母女的對話</title><description>在孔廟聽到的一段母女間的對話&lt;br /&gt;&lt;br /&gt;女孩：媽~ 為什麼孔子這麼聰明？&lt;br /&gt;媽媽：因為他很善良&lt;br /&gt;&lt;br /&gt;嘖~ 奇怪，我也很善良呀...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3931381955158939823-2274651283298063902?l=wei-hu-tw.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/wei-hu-tw/~4/Y0F4wsrbTn4" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/wei-hu-tw/~3/Y0F4wsrbTn4/blog-post_15.html</link><author>noreply@blogger.com (Wei)</author><thr:total>0</thr:total><feedburner:origLink>http://wei-hu-tw.blogspot.com/2007/11/blog-post_15.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-3931381955158939823.post-4735463175269713020</guid><pubDate>Thu, 15 Nov 2007 13:06:00 +0000</pubDate><atom:updated>2007-11-15T21:07:29.676+08:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Life</category><title>墾丁的佳樂水</title><description>琪：接下來要去佳樂水嗎？&lt;br /&gt;我：大熱天的加什麼熱水，我 prefer 加冷水...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3931381955158939823-4735463175269713020?l=wei-hu-tw.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/wei-hu-tw/~4/nxWyF6FpKTg" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/wei-hu-tw/~3/nxWyF6FpKTg/blog-post.html</link><author>noreply@blogger.com (Wei)</author><thr:total>0</thr:total><feedburner:origLink>http://wei-hu-tw.blogspot.com/2007/11/blog-post.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-3931381955158939823.post-4294207586067971278</guid><pubDate>Wed, 14 Nov 2007 15:28:00 +0000</pubDate><atom:updated>2008-12-10T06:59:45.800+08:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">C/C++</category><title>C 語言中如何保護跨檔案的 exported symbol</title><description>有時候我們想把一個 module 分成好幾個 source/header 檔案, 因為這樣比較好管理, 也比較好看, 每個檔案也比較小, refactoring (re-compile) 的時間也比較短.  不過這樣的缺點是, 勢必有若干個原本是在一個 .c 檔裡的 static global variable 或 static function 會變成 global 的 variable 或 function.  這會增加別的 module (programmer) 誤用的風險, 在此提供一個保護這些你不願意讓其他 module 使用, 但卻可以在自己數個 .c 檔裡共用 variable (或 function) 的方法.&lt;br /&gt;&lt;br /&gt;其實方法很簡單, 就是在 C 裡面借用 C++ 的 name mangling.&lt;br /&gt;&lt;br /&gt;例如有一個 module A. 我用下面的 macro 來替每個希望只能用在 module 內部的 global variable (或 function) 加上一段文字:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://lh3.google.com/wei.hu.tw/RzsUjW461II/AAAAAAAAAC8/m9jbDTLGzb8/ggg_1.jpg"&gt;&lt;img style="cursor: pointer;" src="http://lh3.google.com/wei.hu.tw/RzsUjW461II/AAAAAAAAAC8/m9jbDTLGzb8/ggg_1.jpg" alt="" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;在這邊用 "__this_(data | function)_should_not_be_(accessed | called)_outside_module_A" 這個字串來讓其他 programmer 很清楚的知道他不應該呼叫或存取這個 data (或 function), 但我又擔心這樣的防護還是不夠, 所以又加了一個 compiler predefined 的 macro, _INTEGRAL_MAX_BITS, 來增加使用的難度. 這個 _INTEGRAL_MAX_BITS 是由 Microsoft Visual C/C++ compiler 所定義的, 有可能會隨著不同版本的 VC++ 而不同, 也很有可能其他家的 compiler 不支援, 比方說 gcc, ARM CC 等等. 基本上, 這個 compiler predefined 的 macro 是看你所用的 compiler 而自由定義的.&lt;br /&gt;&lt;br /&gt;=============================================================&lt;br /&gt;註:&lt;br /&gt;&lt;br /&gt;在一般的 VC 2005 使用上, _INTEGRAL_MAX_BITS 會被展開成為 32 這個數字.&lt;br /&gt;=============================================================&lt;br /&gt;&lt;br /&gt;=============================================================&lt;br /&gt;註:&lt;br /&gt;&lt;br /&gt;為了使用 _INTEGRAL_MAX_BITS 這種 compiler predefined 的 macro, 必須多使用一層 macro expansion, 這是因為 C preprocessor 的 ## (string concatenation) 會阻擋&lt;br /&gt;preprocessor 的 prescan 的動作.&lt;br /&gt;=============================================================&lt;br /&gt;&lt;br /&gt;例如:&lt;br /&gt;&lt;br /&gt;當有一個叫做 global_data 的 global variable 希望只有在 module A 內使用, 而不希望其他的 module 使用的話, 可以如下宣告:&lt;br /&gt;&lt;br /&gt;int MODULE_A_INTERNAL_DATA(global_data);&lt;br /&gt;&lt;br /&gt;經過 macro expansion 會變成:&lt;br /&gt;&lt;br /&gt;int global_data__this_data_should_not_be_accessed_outside_module_A32;&lt;br /&gt;&lt;br /&gt;而要存取他的話, 也很簡單, 就用&lt;br /&gt;&lt;br /&gt;MODULE_A_INTERNAL_DATA(global_data) = 3;&lt;br /&gt;&lt;br /&gt;就可以了.&lt;br /&gt;&lt;br /&gt;function 的例子也是一樣.&lt;br /&gt;&lt;br /&gt;當有一個叫做 global_func 的 global function 希望只有在 module A 內使用, 而不希望其他的 module 使用的話, 可以如下宣告 (定義也是一樣):&lt;br /&gt;&lt;br /&gt;void MODULE_A_INTERNAL_FUNCTION(global_func)(int a)&lt;br /&gt;{&lt;br /&gt;\\...&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;呼叫這個 function 也很簡單:&lt;br /&gt;&lt;br /&gt;MODULE_A_INTERNAL_FUNCTION(global_func)(3);&lt;br /&gt;&lt;br /&gt;如此一來, 就可以約略的保住 module 內部的 internal data 及 function.&lt;br /&gt;&lt;br /&gt;不過, 假如有其他的 module 也 include 了定義 MODULE_A_INTERNAL_(DATA | API) 的 header file 的話, 那不就破功了嗎? 所以最後, 我們要保護上面的這段特殊 macro, 否則其他的 module 只要 include 了這個 header file, 就可以透過這樣的&lt;br /&gt;macro 來存取我的 global data 了, 所以在這個 header file 的最前面加上這段話:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://lh3.google.com/wei.hu.tw/RzsWEW461JI/AAAAAAAAADU/NbRvtGe-yiM/ggg_2.jpg"&gt;&lt;img style="cursor:pointer;" src="http://lh3.google.com/wei.hu.tw/RzsWEW461JI/AAAAAAAAADU/NbRvtGe-yiM/ggg_2.jpg" border="0" alt="" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;並且在 module A 的所有 source files (.c) 的最前面加上下面這句話:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_e5w2gEy9U-Q/RzsWY2461KI/AAAAAAAAADc/2hYxxleucV0/s1600-h/ggg_3.jpg"&gt;&lt;img style="cursor: pointer;" src="http://3.bp.blogspot.com/_e5w2gEy9U-Q/RzsWY2461KI/AAAAAAAAADc/2hYxxleucV0/s400/ggg_3.jpg" alt="" id="BLOGGER_PHOTO_ID_5132720816625734818" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;=============================================================&lt;br /&gt;Note: 只能在 module A 的 .c 檔裡面加 #define THIS_FILE_IS_BELONG_TO_..., 不能在 module A 的任何一個 .h 檔裡面定義, 否則別的 module include 那隻 .h 檔就破功了.&lt;br /&gt;=============================================================&lt;br /&gt;&lt;br /&gt;這樣的話, 當有你不認識的人想要 include 你的 header file, compiler 就會馬上列印出一句大家都看得懂的話:&lt;br /&gt;&lt;br /&gt;You should _NOT_ include this file directly.&lt;br /&gt;&lt;br /&gt;所以, 不管是從哪條路上走, 都再再的告知其他 module 不可以來用我的 internal global variable or internal global function. 不是跟他說你不可以 include 這個 header file, 就是跟他說這個 variable, function 不可以被你存取或呼叫.&lt;br /&gt;&lt;br /&gt;而且最棒的是, 上面的這些機制都是純 compile time 的, 也就是說完全沒有任何 runtime 的 overhead.&lt;br /&gt;&lt;br /&gt;基本上, 我想應該可以達到為了模組化切割成多個檔案. 但又保護住自己 internal data 的好處.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3931381955158939823-4294207586067971278?l=wei-hu-tw.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/wei-hu-tw/~4/8T9CWzygp1M" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/wei-hu-tw/~3/8T9CWzygp1M/c-exported-symbol.html</link><author>noreply@blogger.com (Wei)</author><media:thumbnail url="http://3.bp.blogspot.com/_e5w2gEy9U-Q/RzsWY2461KI/AAAAAAAAADc/2hYxxleucV0/s72-c/ggg_3.jpg" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://wei-hu-tw.blogspot.com/2007/11/c-exported-symbol.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-3931381955158939823.post-7278728161009195580</guid><pubDate>Tue, 13 Nov 2007 16:19:00 +0000</pubDate><atom:updated>2007-11-15T00:22:22.704+08:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Linux</category><title>使 linux 隱藏於 MS windows 中的一個 kernel patch</title><description>我發現到有很多人的電腦裡只安裝了 Microsoft 的作業系統, 並且往往一安裝就是佔據了整個硬碟的儲存空間. 這造成如果有一天, 該名使用者突然想試試看 Linux 作業系統, 但又不想重新 fdisk, format 硬碟內的寶貴資料 (因為只是想試試看而已), 所以常常就這樣放棄了使用 Linux 的大好契機.&lt;br /&gt;&lt;br /&gt;這對於推廣 Linux 的使用與佔有率有一定程度的影響, 所以我小小修改了 Linux kernel 的開機啟動流程, 使得這一經過修改的 Linux kernel 可以在不重新 fdisk, format 硬碟的情況下來使用 Linux. (i.e. 整顆硬碟都還是保持 Microsoft windows 作業系統), 經由特別為此 kernel 製作的 bootable 安裝光碟安裝完後, 可以經由硬碟 (i.e. 安裝完後就不再需要光碟了) 來啟動一個完整的 Linux 作業系統.&lt;br /&gt;&lt;br /&gt;我所 focus 的 Linux kernel 版本編號為 2.2.16, 基本上, 2.2.x 的版本應該都可以使用, 2.0.x 或 2.4.x 就沒有試驗過了.&lt;br /&gt;&lt;br /&gt;我所修改的效果為：&lt;br /&gt;&lt;br /&gt;當 lilo (或其他可以達到 multiboot 效果的 boot loader) 啟動 Linux kernel 時, kernel 會去 "第一顆" 硬碟的 "第一個分割區" 內 (i.e. /dev/hda1) 的 root directory 尋找一個名為 linux 的檔案, (i.e. windows 系統下的 C:\linux) (i.e. 檔名全為小寫, 因為是寫死在 source code 內)&lt;br /&gt;&lt;br /&gt;這個 C:\linux 檔案就是 Linux 系統的 root file system (可用 loopback device 製作出來), 當 kernel 找到 C:\linux 檔案後, 會自動將其 dump 到 ramdisk 內, 而後就以該存在 ramdisk 內的 root file system 來進行整個 Linux 系統的運作. 這樣作法的好處是, 縱使該名使用者因不熟悉 Linux 的使用而破壞了 root file system 的架構, 因其破壞的只是存在 memory 內的 root file system copy, 所以當下次重新開機時, root file system 依舊保持一開始的良好狀態.&lt;br /&gt;&lt;br /&gt;雖然 root file system 的如此實作會讓使用者沒有辦法儲存自己的資料, 但可在硬碟內放置另一個利用 loopback device 製作出來的 file, 當 kernel 完成 mount root file system 後, 就可以經由一般的簡單程序來 mount 該 loopback file 到 root directory 下的某個 entry directory (i.e. /usr)&lt;br /&gt;&lt;br /&gt;我希望這個簡單的 kernel patch 可以為 Linux 的推廣貢獻一點心力.&lt;br /&gt;&lt;br /&gt;下載這個 kernel patch: &lt;a href="http://www.csie.ntu.edu.tw/~r88052/kernel_patch_1/download/mango_kernel.patch"&gt;mango_kernel.patch&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3931381955158939823-7278728161009195580?l=wei-hu-tw.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/wei-hu-tw/~4/71KobJiPy94" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/wei-hu-tw/~3/71KobJiPy94/linux-ms-windows-kernel-patch.html</link><author>noreply@blogger.com (Wei)</author><thr:total>1</thr:total><feedburner:origLink>http://wei-hu-tw.blogspot.com/2007/11/linux-ms-windows-kernel-patch.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-3931381955158939823.post-1983691125511077524</guid><pubDate>Mon, 12 Nov 2007 16:27:00 +0000</pubDate><atom:updated>2008-01-20T18:48:59.589+08:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">BSD</category><title>BSD 與 Embedded BSD簡介</title><description>&lt;p&gt; 在類 Unix 系統的家族中，目前最為人所知的大概就算是 Linux 系統了。然而，還有另一支跟 Linux 系統很像，但又有點不太一樣的類 Unix 系統叫做 BSD 系統，也常被拿來使用。最近一個蠻有名的例子是 Apple 公司的 Mac OS X 作業系統，其底層所用的 Darwin 核心就是拿FreeBSD 的核心來做修改而來的。 &lt;/p&gt; &lt;a name="history"&gt;&lt;span style="color:red;"&gt;BSD 系統的歷史&lt;/span&gt;&lt;/a&gt; &lt;p&gt;一開始的時候，加州大學柏客萊分校的電腦科學研究團隊 (CSRG，Computer Systems Research Group) 對貝爾實驗室 (Bell Labs) 所開發的 Unix 系統不太滿意，因此自行對它做了一些修改。後來越改越多，漸漸的跟原本 Bell Labs 的 Unix 系統越來越不一樣，因此後來這個由 CSRG 所開發的類 Unix 系統另外又稱做是 BSD (Berkeley Software Distribution) 系統。&lt;br /&gt;&lt;br /&gt;後來 CSRG 解散了，原本他們所維護的 BSD 系統程式碼被 386BSD 計畫拿去移植並使用在 Intel 的 i386 系統上。過了幾年，這個 386BSD 計畫也終止了，但他們所維護的 386BSD 程式碼被 FreeBSD 跟 NetBSD 這兩個計畫拿去繼續發展。稍後由於 NetBSD 內部的意見分歧，有些人就從 NetBSD 內部獨立出來成立另一個 OpenBSD 計畫。 &lt;/p&gt; &lt;a name="distribution"&gt;&lt;span style="color:red;"&gt;主流的 BSD 系統&lt;/span&gt;&lt;/a&gt; &lt;p&gt; 因此目前主流的 BSD 系統大致有下列三種：&lt;br /&gt;&lt;br /&gt;&lt;span style="color:red;"&gt;FreeBSD&lt;/span&gt;&lt;br /&gt;&lt;a href="http://www.freebsd.org/"&gt;http://www.freebsd.org/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;img src="http://www.csie.ntu.edu.tw/%7Er88052/MyArticles/Embedded_BSD/Pictures/FreeBSD.jpg" /&gt;&lt;br /&gt;圖：用來代表 FreeBSD 的小惡魔&lt;br /&gt;&lt;br /&gt;原本專注於 i386 平台上的開發，後來也慢慢的加入了對 Alpha，Sparc 等其他平台的支援。FreeBSD 最主要的目標是成為Intel/AMD 平台上一個穩定並且經過最佳化後的 BSD 系統。&lt;br /&gt;&lt;br /&gt;&lt;span style="color:red;"&gt;NetBSD&lt;/span&gt;&lt;br /&gt;&lt;a href="http://www.netbsd.org/"&gt;http://www.netbsd.org/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.csie.ntu.edu.tw/%7Er88052/MyArticles/Embedded_BSD/Pictures/NetBSD.jpg"&gt;&lt;img src="http://www.csie.ntu.edu.tw/%7Er88052/MyArticles/Embedded_BSD/Pictures/NetBSD_small.jpg" /&gt; (按一下放大) &lt;/a&gt;&lt;br /&gt;圖：舊的 NetBSD 圖示&lt;br /&gt;&lt;br /&gt;立志要成為一個能夠在最多平台上運行的作業系統，到目前為止 NetBSD 可以在 50 多個硬體平台上執行，例如 Macintosh，Atari ST，Amiga，Intel，Playstation2，Sega Dreamcast 等等。時到今日，NetBSD 最主要的成就在於其高度的可移植性，以及成為學術上的研究目標。 很多學校的教授及學生都在 NetBSD 上面實做新的功能，以及驗證新理論的可行性。而某些確實有用的新功能最後也將被移植到其他的作業系統上，比方說 FreeBSD，OpenBSD 等等。&lt;br /&gt;&lt;br /&gt;&lt;span style="color:red;"&gt;OpenBSD&lt;/span&gt;&lt;br /&gt;&lt;a href="http://www.openbsd.org/"&gt;http://www.openbsd.org/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;img src="http://www.csie.ntu.edu.tw/%7Er88052/MyArticles/Embedded_BSD/Pictures/OpenBSD.jpg" /&gt;&lt;br /&gt;圖：代表 OpenBSD 的河豚&lt;br /&gt;&lt;br /&gt;特別專注在與安全相關的作業系統議題上。OpenBSD 的目標在於成為一個最安全的 BSD 系統。OpenBSD 的開發小組檢視過整個 OpenBSD 系統上的每一行程式碼，試圖找出不安全的部份並進行適當的修改。由於 OpenBSD 計畫是從 NetBSD 計畫中衍生出來的，因此 OpenBSD 也具有不錯的移植性，雖然沒有像 NetBSD 一樣號稱可在 50 多個平台上使用，但 OpenBSD 一樣支援目前一些主流的平台，例如 i386，PowerPC，m68k，Alpha等。並且，在 OpenBSD 上所進行的一些關於安全性的改良成果，最後也將會被移植到其他的 BSD 系統上，比方說 FreeBSD，NetBSD 等。 &lt;/p&gt; &lt;p&gt; &lt;a name="license"&gt;&lt;span style="color:red;"&gt;BSD 的版權宣告&lt;/span&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;BSD 的開發者往往使用的是 BSD 版權宣告來為他們所寫的軟體定義後續使用者應盡的權利與義務，而這個 BSD 版權宣告跟另一個 GPL 版權宣告常常拿來做一些比較。其實他們一個最明顯的不同點在於使用 BSD License 的軟體可以不用公開原始碼，而使用 GPL License 的軟體不管經過多少的修改都必須要公開修改過後的原始碼。因此在某些情況下，使用 BSD License 可能比較適合。例如商業性的軟體，商業公司不希望公開內部的機密或設計的方法等等。另一個情況是當一個標準 (standard) 的參考實做 (Reference Implementation) 如果使用 BSD License 的話將可以比較容易達到較高的推廣率。&lt;br /&gt;&lt;br /&gt;然而，有些商業公司在將其產品開放原始碼的時候，反而比較喜歡採用 GPL，因為這樣可以確保競爭對手在對該程式碼做出修改後，還可以回饋給原來的公司。&lt;br /&gt;&lt;br /&gt;&lt;table&gt; &lt;tbody&gt;&lt;tr&gt;    &lt;td&gt;&lt;br /&gt;&lt;/td&gt;    &lt;td&gt;BSD&lt;/td&gt;    &lt;td&gt;GPL&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt;    &lt;td&gt;是否可使用在商業軟體中&lt;/td&gt;    &lt;td&gt;可以&lt;/td&gt;    &lt;td&gt;不行&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt;    &lt;td&gt;散播原軟體的限制&lt;/td&gt;    &lt;td&gt;無&lt;/td&gt;    &lt;td&gt;必須同樣使用 GPL 才可散播該軟體&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt;    &lt;td&gt;對程式碼做出修改後的限制&lt;/td&gt;    &lt;td&gt;無&lt;/td&gt;    &lt;td&gt;修改後的程式碼也必須要以 GPL 來進行散播&lt;/td&gt; &lt;/tr&gt; &lt;/tbody&gt;&lt;/table&gt; 表：BDS License 跟 GPL License 的比較 &lt;/p&gt;  &lt;p&gt; &lt;span style="color:red;"&gt;核心 (Kernel)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;各家不同 BSD 系統 (FreeBSD，NetBSD，OpenBSD 等等) 的核心幾乎都提供了分時排程 (Time-shared scheduling)，不同配置演算法的需求分頁 (Demand paging)，以及一個虛擬的檔案系統來簡化開發新檔案系統的流程。基本上，各家的 BSD 的核心很多部份都很類似，並且也會互相的截長補短，更慎者，縱使是拿各家的 BSD 核心來跟 Linux 核心相比，也都有很多部份幾乎一樣。&lt;br /&gt;&lt;br /&gt;在 FreeBSD 5.3 的核心內，排程的基本單位是一個 thread，並且總共分為 255 個優先級，此外較低的優先權數字代表較高的優先權，這點跟 Linux 2.6 核心相同，但跟 Solaris 核心則相反。FreeBSD 5.3 核心支援 POSIX 定義的 SCHED_FIFO，SCHED_RR 及 SCHED_OTHER 三種排程。&lt;br /&gt;&lt;br /&gt;在檔案系統中，FreeBSD 5.3 核心內類似 Linux 2.6 核心的 inode 資料結構是所謂的 vnode (virtual node) 資料結構。然而，FreeBSD 不像 Linux 一般，將檔案的處理分為 file operations 跟 inode operations，而是直接合併成一個 vnode operations。&lt;br /&gt;&lt;br /&gt;而在一個完整的作業系統內，不可能只包含一個核心而已，也必須包含其他在執行時所必須的軟體元件，某些元件是執行時所一定需要的，某些則否。那些在執行時一定需要的軟體元件，在 BSD 的世界裡，就被合併起來稱為『基礎系統』。 &lt;/p&gt;  &lt;p&gt; &lt;span style="color:red;"&gt;基礎系統 (Base System)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;基礎系統 (Base System) 是由一群用來啟動系統時所需的基本軟體套件所組合而成，這包括了 BSD 的 kernel，BSD 的 ls 以及 BSD 的 libc 等軟體套件，而這些套件被組合在一起開發來獲得最佳的整合性，並且在安裝的時候也必須要一起安裝，無法切割出來。比方說以基礎系統內的 OpenSSH 套件來說，使用者沒有辦法單獨升級 OpenSSH 套件，而必須要升級整個基礎系統才可以。&lt;br /&gt;&lt;br /&gt;註：為什麼要特別指名是 BSD 的 ls 跟 libc 呢，這是因為一般在 Linux 系統上所使用的是 GNU 組織所發行的 ls 及 libc，但在 BSD 上則是直接拿 CSRG 所發展的 BSD 系統上的對應套件來修改使用。&lt;br /&gt;&lt;br /&gt;不同的 BSD 系統，比方說 FreeBSD，NetBSD，OpenBSD 系統之間，對於基礎系統內應該包括哪些軟體套件的標準不太一樣，所以在這些不同的 BSD 系統之間，他們的基礎系統內所包含的內容也就會有所不同。比方說在 NetBSD 及 OpenBSD 系統內，X Window 視窗系統就被包含在基礎系統內，但在 FreeBSD 系統下，X Window 視窗系統是必須另外安裝的。&lt;br /&gt;&lt;br /&gt;然而，縱使是在同一個系統內，也會隨著時間的不同，刪除或擴充其基礎系統的內容。比方說，由於 SSH Server 及 SSH Client的使用越來越廣泛，所以在 FreeBSD 的基礎系統內就涵蓋了 OpenSSH 這個高品質的SSH Server/Client 實作。&lt;br /&gt;&lt;br /&gt;當然，由於軟體的一直發展與進步，因此在安裝完 BSD 系統之後，一定會有需要進行基礎系統的升級與更新。由於整個 BSD 的基礎系統是整合在一起開發的，所以也必須要一起安裝，這將會是個冗長的動作。然而，BSD 系統通常都會簡化這樣的步驟，使用者可以很輕鬆的透過抓取基礎系統的原始碼，並且在原始碼的根目錄下執行一些簡單的命令就可以完成整個基礎系統的編譯以及 升級。基本上，FreeBSD 基礎系統的升級流程類似上述的動作，然而 NetBSD 採用了一個比較不一樣的機制，OpenBSD 則是需要幾乎重新安裝整個作業系統才能完成基礎系統的升級。 &lt;/p&gt; &lt;p&gt; &lt;span style="color:red;"&gt;Ports 系統 (Ports System)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;而除了基礎系統之外，其他在 BSD 系統下的所有軟體套件都可以在所謂的 ports 系統下找到。所有可以在 BSD 下執行的軟體原始碼都被集中在一個大型的原始碼樹下，每一個軟體都是這個原始碼樹下的一個目錄，這麼做的原因是因為管理比較方便，除了把軟體蒐集並集中在 一起之外，在經過了或多或少的修改之後，使得所有軟體都能夠適合並緊密的整合到 BSD 系統中。&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.csie.ntu.edu.tw/%7Er88052/MyArticles/Embedded_BSD/Pictures/FreeBSD_Ports_Tree.jpg"&gt;&lt;img src="http://www.csie.ntu.edu.tw/%7Er88052/MyArticles/Embedded_BSD/Pictures/FreeBSD_Ports_Tree_small.jpg" /&gt; (按一下放大) &lt;/a&gt;&lt;br /&gt;圖：FreeBSD 的 Ports 系統原始碼樹&lt;br /&gt;&lt;br /&gt;註：為什麼叫做 Ports 系統？由於很多軟體必須經過或多或少的修改才可以在 BSD 系統上執行，因此用來蒐集並管理這些經過移植 (porting) 後的軟體的系統就稱做是 ports 系統。&lt;br /&gt;&lt;br /&gt;基本上，如果要從 ports 系統安裝軟件，使用者必須先從 ports 系統下載軟體的原始碼，然後經過編譯與安裝的流程就可以在 BSD 上使用該軟體。當然這跟 Linux 系統的 rpm 或 deb 套件管理系統有些差異，rpm 或 deb 是以安裝二進位檔 (Binary file) 的角度來設計的，之後才設計出額外的從原始碼編譯軟體的機制。然而，ports 系統是以從原始碼編譯的角度來設計，之後才發展出直接拿事先編譯好的二進位檔來安裝的方便功能。如果讀者有使用過 Linux 世界裡的 gentoo 系統 (&lt;a href="http://www.gentoo.org/"&gt;http://www.gentoo.org/&lt;/a&gt;) 的話，就會發現 gentoo 的 portage 套件管理系統就是模仿 BSD 的 ports 系統，可以讓使用者便利的從每一個軟體套件的原始碼開始自行編譯並且安裝系統。&lt;br /&gt;&lt;br /&gt;&lt;table&gt; &lt;tbody&gt;&lt;tr&gt;    &lt;td&gt;&lt;br /&gt;&lt;/td&gt;    &lt;td&gt;類 ports 系統&lt;/td&gt;    &lt;td&gt;類 rpm 或 deb 系統&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt;    &lt;td&gt;硬碟空間使用量&lt;/td&gt;    &lt;td&gt;由於需從原始碼開始編譯，所以需要較多的硬碟空間&lt;/td&gt;    &lt;td&gt;由於直接安裝編譯好的二進位檔，所以只需較少的硬碟空間&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt;    &lt;td&gt;安裝所需的時間&lt;/td&gt;    &lt;td&gt;需要花費大量的時間在編譯原始碼上&lt;/td&gt;    &lt;td&gt;只需要些許的時間就可完成安裝的動作&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt;    &lt;td&gt;對套件的掌握度&lt;/td&gt;    &lt;td&gt;極高，因為可以自行設定編譯時期的選項&lt;/td&gt;    &lt;td&gt;較低，只能遵循套件管理者的設定&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt;    &lt;td&gt;不同函式庫版本之間的衝突性&lt;/td&gt;    &lt;td&gt;極低，因為套件是自行編譯的，所以可以針對當時所使用的函式庫版本來製作出對應的套件出來&lt;/td&gt;    &lt;td&gt;較高，假如所使用的函式庫版本與套件管理者預先設定的版本不相容，則軟體在安裝或執行上就會有或多或少的問題&lt;/td&gt; &lt;/tr&gt; &lt;/tbody&gt;&lt;/table&gt; 表：不同套件管理系統間的優缺點 &lt;/p&gt; &lt;p&gt; &lt;span style="color:red;"&gt;FreeBSD 的版本編號命名法則&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;由於目前常用的 BSD 系統應該要算是 FreeBSD 了，而 FreeBSD 系統的每個版本間的命名法則有些複雜，因此筆者在這邊來做個說明。基本上 FreeBSD 的開發主要分成兩個主軸，其中一個發展主軸叫做 CURRENT，另外一個發展主軸叫做 STABLE。而 STABLE 的發展重點放在修正程式或安全性的錯誤，因此 STABLE 的變動性不大，所以 STABLE 的意思不是說整個系統執行起來很穩定，而是說 STABLE 這條發展主軸的變動性不大。而所有變動性大的修改，比方說架構上的更新，新功能的增加等等，都會實做在 CURRENT 這條發展線上。而在某些時間點，當開發小組覺得目前的發展狀態到了某種穩定度的時候，就會把當時的發展成果標記成 RELEASE。他們的關係可用下圖來做說明：&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.csie.ntu.edu.tw/%7Er88052/MyArticles/Embedded_BSD/Pictures/FreeBSD_Version.jpg"&gt;&lt;img src="http://www.csie.ntu.edu.tw/%7Er88052/MyArticles/Embedded_BSD/Pictures/FreeBSD_Version_small.jpg" /&gt; (按一下放大) &lt;/a&gt;&lt;br /&gt;圖：FreeBSD 的開發軸線&lt;br /&gt;&lt;br /&gt;FreeBSD 的版本編號主要還是依照一般開放原始碼的習慣，以數個英文字母來代表，比方說 2.3-STABLE。其中的 2 代表主要的版本編號，而 3 則代表次要的版本編號，-STABLE代表的則是 STABLE 的發展軸線，也就是說變動不會太大的意思。大版本編號的增加是當某些重大的架構變動或新功能加入到 FreeBSD 裡面後，就有可能會因此增加大版本編號。但通常在新版本的第二或第三個次要版本發展出來之後，該新的版本才會從 CURRENT 軸線放到 STABLE 軸線中。這整個流程可用下圖來做說明：&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.csie.ntu.edu.tw/%7Er88052/MyArticles/Embedded_BSD/Pictures/FreeBSD_Version_major.jpg"&gt;&lt;img src="http://www.csie.ntu.edu.tw/%7Er88052/MyArticles/Embedded_BSD/Pictures/FreeBSD_Version_major_small.jpg" /&gt; (按一下放大) &lt;/a&gt;&lt;br /&gt;圖：FreeBSD 的版本編號演變流程&lt;br /&gt;&lt;br /&gt;基本上，這個版本命名法則是以 FreeBSD 為中心，但 NetBSD 其實也有類似的情況。 &lt;/p&gt; &lt;p&gt; &lt;a name="development"&gt;&lt;span style="color:red;"&gt;BSD 系統上軟體的開發&lt;/span&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;一般說來，一個軟體只要所使用的作業系統功能是定義在標準內的，比方說該軟體都使用 POSIX 介面來與作業系統溝通。那麼這個軟體就幾乎確定可以在 BSD 系統上執行。然而，由於 Linux 系統的普及性，因此某些軟體使用到了專屬於 Linux 系統內的專屬功能，那麼這個時候，該軟體就必須要經過移植跟修改，才能夠在 BSD 系統下執行。&lt;br /&gt;&lt;br /&gt;然而，並不是每個使用到專屬 Linux 系統功能的軟體都可以取得原始碼來進行修改。因此在 BSD 系統下，幾乎都提供了一個模擬 Linux 系統的模擬器，來讓上層那些特殊的軟體能夠順利的在 BSD 系統上執行。因此這些軟體的能否順利執行與否，就端視這一層模擬層能否提供所需的執行環境。 &lt;/p&gt; &lt;p&gt; &lt;a name="appliance"&gt;&lt;span style="color:red;"&gt;目前 BSD 在嵌入式系統上的應用&lt;/span&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;雖然很少為人所知，但目前的確已經有許多嵌入式計畫或裝置上面使用 BSD 作業系統。&lt;br /&gt;&lt;br /&gt;&lt;span style="color:red;"&gt;PicoBSD&lt;/span&gt;&lt;br /&gt;&lt;a href="http://people.freebsd.org/%7Epicobsd/picobsd.html"&gt;http://people.freebsd.org/~picobsd/picobsd.html&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;PicoBSD 是 FreeBSD 官方的一個計畫，這個計畫的目的是把一個相對完整的 FreeBSD 系統給放置到一張容量為 1.44MB 的軟碟片上。這個計畫的最新版本是 0.42 版。它宣稱可以在一台 386SX 並配有 8MB 記憶體的機器上運作順利。&lt;br /&gt;&lt;br /&gt;使用 PicoBSD 並搭配一台只有網路卡跟軟碟機的簡單電腦，就可以完成一個簡單的防火牆 (firewall) 設備了。&lt;br /&gt;&lt;br /&gt;&lt;span style="color:red;"&gt;Wasabi Systems&lt;/span&gt;&lt;br /&gt;&lt;a href="http://www.wasabisystems.com/"&gt;http://www.wasabisystems.com/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;img src="http://www.csie.ntu.edu.tw/%7Er88052/MyArticles/Embedded_BSD/Pictures/wasabi.jpg" /&gt;&lt;br /&gt;圖：Wasabi 公司的標誌&lt;br /&gt;&lt;br /&gt;Wasabi 公司是由一群 NetBSD 的開發者所成立的公司，這裡面包含了 NetBSD 的核心開發小組。他們專注於將 NetBSD 移植到嵌入式裝置或網路裝置上，並且進行開發的工作。&lt;br /&gt;&lt;br /&gt;&lt;span style="color:red;"&gt;Soekris&lt;/span&gt;&lt;br /&gt;&lt;a href="http://www.soekris.com/"&gt;http://www.soekris.com/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;img src="http://www.csie.ntu.edu.tw/%7Er88052/MyArticles/Embedded_BSD/Pictures/Soekris.jpg" /&gt;&lt;br /&gt;圖：Soekris 的公司標誌&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.csie.ntu.edu.tw/%7Er88052/MyArticles/Embedded_BSD/Pictures/net4801.jpg"&gt;&lt;img src="http://www.csie.ntu.edu.tw/%7Er88052/MyArticles/Embedded_BSD/Pictures/net4801_small.jpg" /&gt; (按一下放大) &lt;/a&gt;&lt;br /&gt;圖：Soekris 公司設計的 Net4801 開發版&lt;br /&gt;&lt;br /&gt;Soekris 是一家專門設計嵌入式電腦跟通訊設備的公司。他們最新的產品 Net4801 開發版上面就明確支援了 FreeBSD，NetBSD 以及 OpenBSD。&lt;br /&gt;&lt;br /&gt;在 Net4801 開發版上，裝載了一顆 266 Mhz 的中央處理器，以及 128MB 的隨機存取記憶體。可以使用一般的硬碟來當主要的儲存裝置，也可以使用 Compact Flash 卡。如果要在 net4801 開發版上面安裝 BSD 系統的話，可以參考下面的計畫成果。&lt;br /&gt;&lt;br /&gt;&lt;span style="color:red;"&gt;OpenSoekris 計畫&lt;/span&gt;&lt;br /&gt;&lt;a href="http://opensoekris.sourceforge.net/"&gt;http://opensoekris.sourceforge.net/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;這個計畫的成果是一些 script 檔案，透過執行這些 script 檔案，使用者可以為 Soekris 公司的產品製作出一個可開機的 OpenBSD 映像檔。最新的版本是 1.0.12 版。&lt;br /&gt;&lt;br /&gt;&lt;span style="color:red;"&gt;CompactBSD 計畫&lt;/span&gt;&lt;br /&gt;&lt;a href="http://sourceforge.net/projects/compactbsd"&gt;http://sourceforge.net/projects/compactbsd&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;CompactBSD 計畫可以讓使用者製作出一個小型的 OpenBSD 系統，並且把它放到 Compact flash 卡中。目前的最新版本是 0.1.0 版。&lt;br /&gt;&lt;br /&gt;&lt;span style="color:red;"&gt;Apple Mac Mini&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.csie.ntu.edu.tw/%7Er88052/MyArticles/Embedded_BSD/Pictures/Mac_Mini.jpg"&gt;&lt;img src="http://www.csie.ntu.edu.tw/%7Er88052/MyArticles/Embedded_BSD/Pictures/Mac_Mini_small.jpg" /&gt; (按一下放大) &lt;/a&gt;&lt;br /&gt;圖：Apple 出的 Mac Mini&lt;br /&gt;&lt;br /&gt;在 Mac Mini 一出廠的時候，內部安裝的是 Mac OS X。所以如果我們想把 BSD 裝在上面的話，得先把硬碟重新分割。不過 Mac OS X 內建的分割工具非常陽春 (比方說 Disk Utility)，幾乎只能夠重新分割硬碟而已，因此除非使用第三方軟體，否則就只能夠重灌 Mac OS X 了。&lt;br /&gt;&lt;br /&gt;針對硬體支援部份，目前的 BSD 系統沒有辦法支援 Mac Mini 上的 Airport Extreme 卡以及內建的  modem。然而，顯示卡及音效卡這兩個部份都可以順利的運作，因此 X Window 也可以正常的啟動。&lt;br /&gt;&lt;br /&gt;如果你想要在 Mac Mini 上開發程式的話，BSD 系統幾乎都採用 GNU Compiler Collection，因此開發軟體也就不是一件困難的事情了。&lt;br /&gt;&lt;br /&gt;&lt;a name="build"&gt;&lt;span style="color:red;"&gt;自行製作一個 Embedded BSD 系統&lt;/span&gt;&lt;br /&gt;&lt;/a&gt;&lt;br /&gt;由於 BSD 所採用的 BSD License 對商業公司來說或許比較適當，所以在嵌入式系統上，不難見到 BSD 的蹤跡。因此我們現在來看看要如何製作出一個 Embedded 的 BSD 系統。&lt;br /&gt;&lt;br /&gt;&lt;span style="color:red;"&gt;製作 Kernel&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;首先我們得製作出一個符合目標系統所使用的核心 (kernel) 出來。製作 kernel 的方法非常簡單，根據你平台的硬體配置來包含相關的驅動程式，如果你有編譯過 BSD 的核心或 Linux 的核心，那麼這一個步驟將會很容易的。&lt;br /&gt;&lt;br /&gt;&lt;span style="color:red;"&gt;製作 /sbin/init 執行檔&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;/sbin/init 執行檔也就是當 kernel 起來後所呼叫的第一個使用者程式。所以使用者可以自行撰寫一個 init 程式，然後把所有需要執行的功能都放到 init 內，這種方法適合用在目標平台在開機後就只需要執行一項事先定義好的任務，而不需要動態的啟動新的任務起來。&lt;br /&gt;&lt;br /&gt;另一種方法是使用一般的 init 程式，也就是一般我們使用在 BSD 系統內的 init，並且搭配一個 shell 來動態的啟動我們所需要的服務。這個方法的好處是比自行撰寫一個 init 程式來的簡單，而且假如日後要加入新的功能的話，也僅僅只需要把新的執行檔放到目標平台上即可。&lt;br /&gt;&lt;br /&gt;&lt;span style="color:red;"&gt;製作其他所需軟體&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;除了 kernel 之外的軟體基本上都可以透過在一般的電腦系統上進行跨平台編譯 (Cross-compile) 後放置到目標平台上。如果需要小型化的軟體的話，可以參考 busybox 或者是自行採用Crunchgen 這類的工具來從許多的程式中組合出一個較小的執行檔出來。&lt;br /&gt;&lt;br /&gt;＠附註：Crunchgen 的運作原理：由於在某些版本的 BSD 系統上許多的程式都是使用 static link 的方式 (比方說 NetBSD)，所以相同的函式庫空間可能會在好幾個執行檔裡面出現，這樣也就浪費了記憶空間 (記憶體或硬碟)，而 Crunchgen 這類的工具程式就是用來把這些 static link 的函式庫&lt;br /&gt;&lt;br /&gt;&lt;span style="color:red;"&gt;製作目標平台的檔案系統 (File System)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;在準備好核心 (kernel)，以及其他所需的軟體之後，我們就可以開始來製作目標平台上的檔案系統了。在這個檔案系統裡應該要有 /dev 目錄，/sbin/init 執行檔，如果需要 shell 的話，它應該會位於 /bin/sh，而其他所需的軟體也應該照著正確的目錄來擺近這個檔案系統內。&lt;br /&gt;&lt;br /&gt;&lt;span style="color:red;"&gt;製作出最後的映像檔 (Image file)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;接下來，我們可以使用 makefs 這個工具程式來把我們剛剛製作出來的檔案系統目錄組合成一個單一的映像檔。而在產生這個映像檔之後，我們還可以使用 mdsetimage 這個工具程式來把它與 kernel 連結在一起。而當目標平台上的開機啟動程式 (boot loader) 啟動這個 kernel 的時候，它就會自動執行 /sbin/init，以及使用者所設定的開機程序。&lt;br /&gt;&lt;br /&gt;&lt;span style="color:red;"&gt;結語&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;由於 BSD 系統擁有穩定的核心及優良的 TCP/IP 協議實作，因此在很多網路設備上，例如 router 跟無線網路裝置上都可以看到 BSD 系統的蹤影。筆者認為不論是 BSD 還是 Linux 都很適合使用在嵌入式設備上，但最後到底要使用哪一種系統端視比較喜歡 BSD License 還是 GPL License。如果選定使用 BSD License 的話，那麼就可以選擇 FreeBSD，OpenBSD 或者是 NetBSD 來當作嵌入式設備的作業系統；反之，如果選定採用 GPL License 的話，那麼就可以使用 Linux。由於 BSD 跟 Linux 在整個系統架構上都很相近，所以 Embedded BSD 的開發跟 Embedded Linux 的極為類似。因此相信在未來，一定會有更多的嵌入式系統中使用 BSD，不論是 FreeBSD，NetBSD，還是 OpenBSD，相信都會在嵌入式裝置上佔有一席之地的。&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3931381955158939823-1983691125511077524?l=wei-hu-tw.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/wei-hu-tw/~4/fUcundtiTxs" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/wei-hu-tw/~3/fUcundtiTxs/bsd-embedded-bsd.html</link><author>noreply@blogger.com (Wei)</author><thr:total>0</thr:total><feedburner:origLink>http://wei-hu-tw.blogspot.com/2007/11/bsd-embedded-bsd.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-3931381955158939823.post-488236312401444083</guid><pubDate>Mon, 12 Nov 2007 16:26:00 +0000</pubDate><atom:updated>2008-01-20T18:49:44.967+08:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Linux</category><title>Embedded Linux簡介</title><description>&lt;p&gt; 在近幾年的電腦發展趨勢裡面，Linux已經從伺服器或桌上型市場跨足到嵌入式（embedded）的環境。而這些所謂的嵌入式裝置，在大部分的情況下， 其運算能力及可用資源都沒有伺服器以及桌上電腦那麼的強大。然而，Linux在最近幾年的發展及進步，已經可以讓它勝任某部份嵌入式系統所應用的範圍。因 此在本文內，筆者將簡單的介紹嵌入式Linux，包括它的發展現況以及開發流程。 &lt;/p&gt; &lt;a name="brief"&gt;&lt;span style="color:red;"&gt;嵌入式Linux簡介&lt;/span&gt;&lt;/a&gt; &lt;p&gt;對於嵌入式Linux（Embedded Linux）的定義，各家說法或有不同。簡單來說，只要不是在個人電腦或伺服器上面運作的Linux，就是所謂的是嵌入式Linux。所謂的「嵌入式」， 說穿了就是將精簡過的Linux系統寫入至Flash Rom，而日後可以藉由刷新韌體，來做功能的增加及系統的修補。而嵌入式Linux的應用其實相當廣泛，大到伺服器，小到家電，都可以看到嵌入式 Linux的影子。 只要硬體本身不故障的情況下，機器本身所內嵌的Linux，是不會遭受到任何的毀損，因此不需費心去考慮「重灌」的問題。 目前在embedded linux界有數家廠商合作起來成立一個名叫CELF的組織，透過這個組織來推動linux在家電市場的應用。&lt;br /&gt;&lt;br /&gt;&lt;img src="http://www.csie.ntu.edu.tw/%7Er88052/MyArticles/Embedded_Linux/Pictures/celf_logo.jpg" /&gt;&lt;br /&gt;圖：CELF是一個將焦點放在如何使linux應用於消費性電子產品上面的組織(取自CELF網站) &lt;/p&gt;  &lt;span style="color:red;"&gt;常見的核心版本&lt;/span&gt; &lt;p&gt; 而在嵌入式Linux的執行環境中，核心佔了相當重要的地位。一般而言，常見的Embedded Linux核心版本大概有下列數種：  &lt;/p&gt;&lt;ol&gt;&lt;li&gt;由Linux之父：Linus Torvalds所維護的「正宗Linux 核心版本」。&lt;/li&gt;&lt;li&gt;知名的MontaVista公司所修改的版本。&lt;/li&gt;&lt;li&gt;專門使用在便宜且不具備記憶體管理單元（Memory-Management Unit，MMU）硬體的uCLinux。&lt;/li&gt;&lt;li&gt;專門應用在即時（Real-Time）系統中的RTAI以及RTLinux（RTLinux/Pro）。&lt;/li&gt;&lt;/ol&gt;  當然以Linux「Open Source」的特性，說不定在網路上還有其他可供用來開發嵌入式Linux的核心，如果有興趣的話，可以去網路上找找，說不定還有意想不到的發現。   &lt;span style="color:red;"&gt;C語言函式庫的支援&lt;/span&gt; &lt;p&gt; 除了核心之外，嵌入式Linux系統還需要很多其他的軟體元件，這些元件包括了標準的C語言函式庫。雖然GNU有發展過一套C語言函式庫可供開發時使用，但這套函式庫對嵌入式環境來說還是過於肥大，所以有很多縮小化或重新撰寫的版本被開發出來。&lt;br /&gt;&lt;br /&gt;&lt;table&gt; &lt;tbody&gt;&lt;tr&gt;    &lt;td&gt;uCLibc&lt;/td&gt;    &lt;td&gt;&lt;a href="http://www.uclinux.org/"&gt;http://www.uclinux.org&lt;/a&gt;（最為常見）&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt;    &lt;td&gt;Diet libc&lt;/td&gt;    &lt;td&gt;&lt;a href="http://www.fefe.de/dietlibc"&gt;http://www.fefe.de/dietlibc&lt;/a&gt;&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt;    &lt;td&gt;newlib&lt;/td&gt;    &lt;td&gt;&lt;a href="http://sources.redhat.com/newlib"&gt;http://sources.redhat.com/newlib&lt;/a&gt;&lt;/td&gt; &lt;/tr&gt; &lt;/tbody&gt;&lt;/table&gt; 表：嵌入式Linux常用的C語言函式庫 &lt;/p&gt;  &lt;p&gt; &lt;span style="color:red;"&gt;小型GUI系統&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;使用者可以自行在嵌入式系統內設計出一個圖形使用者介面(GUI)，讓嵌入式Linux看起來較為「友善」一些，然而目前在Linux系統上的X -Window，可不是嵌入式Linux消受的起，因此就有很多小型的GUI系統（像是Qt/Embedded、OpenGUI等）被開發出來。&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.csie.ntu.edu.tw/%7Er88052/MyArticles/Embedded_Linux/Pictures/opengui.jpg"&gt;&lt;img src="http://www.csie.ntu.edu.tw/%7Er88052/MyArticles/Embedded_Linux/Pictures/opengui_small.jpg" /&gt; (按一下放大) &lt;/a&gt;&lt;br /&gt;圖：OpenGUI的執行畫面(取自OpenGUI網站) &lt;/p&gt;  &lt;p&gt; &lt;span style="color:red;"&gt;Java的應用&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;除了先前提到的C語言函式庫之外，Java的應用也日益廣泛，使用者可以在嵌入式平台上使用Java程式語言來開發應用程式，舉個例子來說，目前 有不少手機是以嵌入式Linux作為作業系統，而使用者可以在這些手機上安裝一些以Java寫成的小遊戲或者是應用程式就是一個最好的例子。&lt;br /&gt;&lt;br /&gt;而這些用來執行Java程式的Java虛擬機器(Java Virtual Machine)，也必須儘量的精簡，如此才能夠在嵌入式的硬體平台上流暢地執行，而目前較常被使用在嵌入式平台的Java虛擬機器有昇陽（SUN）的 J2ME以及免費的Kaffe兩種，而J2ME又可分為用於手機上的KVM，以及可能會使用在數位電視上的CVM。&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.csie.ntu.edu.tw/%7Er88052/MyArticles/Embedded_Linux/Pictures/j2me.jpg"&gt;&lt;img src="http://www.csie.ntu.edu.tw/%7Er88052/MyArticles/Embedded_Linux/Pictures/j2me_small.jpg" /&gt; (按一下放大) &lt;/a&gt;&lt;br /&gt;圖：J2ME在整個Java體系的關係圖(取自Sun網站)&lt;br /&gt;&lt;br /&gt;&lt;img src="http://www.csie.ntu.edu.tw/%7Er88052/MyArticles/Embedded_Linux/Pictures/kaffe.jpg" /&gt;&lt;br /&gt;圖：在iPaq上使用kaffe執行一個Java程式的執行畫面(取自kaffe網站) &lt;/p&gt; &lt;p&gt; &lt;a name="advantage"&gt;&lt;span style="color:red;"&gt;嵌入式Linux的優點&lt;/span&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;那麼使用嵌入式Linux到底有什麼好處呢？筆者認為使用嵌入式Linux的好處不外乎下列幾點： &lt;/p&gt;&lt;ol&gt;&lt;li&gt;通常非商業版本的嵌入式Linux元件可以免費的從網路上下載&lt;/li&gt;&lt;li&gt;使用者可以取得linux 核心的完整原始碼&lt;/li&gt;&lt;li&gt;支援多種類的CPU，包括x86，ARM，MIPS，PowerPC等等&lt;/li&gt;&lt;li&gt;穩定性佳&lt;/li&gt;&lt;li&gt;Linux核心採用模組化的設計&lt;/li&gt;&lt;li&gt;可以獲得來自全世界的支援&lt;/li&gt;&lt;li&gt;Linux 核心具有一個標準的程式設計介面&lt;/li&gt;&lt;li&gt;眾多的免費開發工具&lt;/li&gt;&lt;/ol&gt;  &lt;p&gt; &lt;a name="realtime"&gt;&lt;span style="color:red;"&gt;嵌入式Linux系統的即時性&lt;/span&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;而在最近幾年的核心發展當中，有項很重要的議題一直被拿出來討論，那就是即時的（Real-Time）Linux系統。在kernel 2.4版當中，雖然進行了一些有關即時系統的改進，但一般說來，並沒有辦法達到一般的即時系統要求。不過在之後的核心發展當中，有很多新的改進被加入到核 心裡面，因此到了kernel 2.6版的時候，整個的即時特性有著很大的進步。在kernel 2.6中有關即時系統的改進有： &lt;/p&gt;&lt;ol&gt;&lt;li&gt;在2.4版核心的後續發展中，有很多關於增進即時性的修補檔(patch)被加入到核心的原始碼裡面，而這些成果都已經被正式的加入到2.6版核心內。&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Linux核心的發展人員在2.6版核心內設計了一個新的排程(schedule)演算法，這個新的排程演算法具有比之前版本還要快速的行程間內容轉換(context switching)時間。&lt;/li&gt;&lt;br /&gt;&lt;li&gt;由於在2.4版之前的核心當中，當某個行程呼叫了核心服務之後(例如系統呼叫)，其他的行程就沒有辦法搶奪CPU的使用權，一直要等到該呼叫核心 服務的行程完成了該服務之後，其他行程才有機會搶奪CPU的使用權。這樣的缺點是，高優先權的行程有可能必須等待低優先權行程，因此在2.6版的核心當中 插入了許多個新的強佔點(preemption point)，來讓2.6版核心的排程器(scheduler)有機會可以中斷目前正在執行的行程。&lt;/li&gt;&lt;br /&gt;&lt;li&gt;一個全新的POSIX執行緒系統。由於之前linux系統上預設的執行緒系統(名叫 LinuxThreads)有許多的缺點，其中包括了不完全符合POSIX的標準，後來就有一些新的執行緒系統(threading subsystem)被開發出來，這包括了Redhat公司的NPTL(Native Posix Thread Library)系統以及IBM公司的NGPT(Next Generation Posix Threading)系統等等。到最後由Redhat公司的NPTL系統勝出，作為未來linux環境下預設的執行緒系統，因此在2.6版的核心當中提供 了NPTL系統所需要的核心支援。&lt;/li&gt;&lt;br /&gt;&lt;li&gt;與uCLinux的整合。uCLinux主要是一個可被用在缺少記憶體管理單元(MMU) CPU上的linux核心版本，由於完整的虛擬記憶體機制需要MMU硬體的支援，所以uCLinux針對這個硬體受限的環境對之前版本的linux核心做 出了相對應的修改，而這些修改也被正式的加入到2.6版的核心當中。&lt;/li&gt;&lt;br /&gt;&lt;li&gt;由於linux核心內會使用虛擬記憶體(virtual memory)系統中的分頁置換(page swapping)機制來將使用者程式(user code)從虛擬記憶體中移進移出，但分頁置換將會花費大量且不確定的時間，這對即時系統來說是個巨大的致命傷，因此在2.6版的核心當中，新增了一個編 譯時期的設定選項，可以讓使用者製作出一個不使用分頁置換機制的核心出來。&lt;/li&gt;&lt;br /&gt;&lt;li&gt;另外，在最新的核心發展當中，一位名叫Ingo Molnar的程式設計師發展出一個名為CONFIG_PREEMPT_RT的套件，號稱將這個套件加入到核心的原始碼後，可以讓2.6版核心達到更好的即時性。&lt;/li&gt;&lt;/ol&gt; 透過上面的介紹，我們了解到其實可以透過自行修改核心的原始碼來讓目前的linux系統取得更好的即時性。這種方法的好處是整個系統的架構將會比較簡單， 對上層的應用程式撰寫者來說，也比較容易。然而，雖然Linux核心在2.6版當中新增了許多有助於增進即時性的架構，但由於2.6版的核心在這方面只是 剛起步而已，並不夠完備，所以除非是經過大量的修改，否則並沒有辦法達到所有即時環境的要求。另外，每當Linus Torvalds發佈新的核心版本時，之前所做的自行修改也必須要重新移植到新的核心版本上，因此維護不容易便是這種方法的另一個缺點。&lt;br /&gt;&lt;br /&gt;由於觀察到了這種不易維護的缺點，因此就有了第二種方法來達到linux系統的即時特性。這種方法是在系統中加入第二個核心。這個核心是一個獨立 於linux 核心之外的即時作業系統(RTOS，Real-Time Operating System)，而linux 核心只是運作在其上的一個程序而已。&lt;br /&gt;&lt;br /&gt;&lt;img src="http://www.csie.ntu.edu.tw/%7Er88052/MyArticles/Embedded_Linux/Pictures/rtai.jpg" /&gt;&lt;br /&gt;圖：新增一個RTOS來達到即時性，而linux只是運作在RTOS上的一個工作而已&lt;br /&gt;&lt;br /&gt;由於linux 核心只是RTOS上的一個程序，所以linux 核心將沒有辦法禁止CPU中斷(interrupt)的發生，因此就沒有辦法影響到RTOS的即時特性。所以在這種系統上，所有需要即時性的工作 (real-time task)都由這個新的RTOS來處理，而其他不需要即時性的工作(non real-time task)就可以由linux 核心來處理。&lt;br /&gt;&lt;br /&gt;採用這種雙核心架構的有名例子主要有兩個，其中一個是義大利米蘭大學 (Department of Aerospace Enginnerring of Politecnico di Milano，又叫做DIAPM)的RTAI，而另一個則是FSMLabs的RTLinux。  &lt;p&gt; &lt;span style="color:red;"&gt;RTAI&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;RTAI目前的主持人是Paulo Mantegazza教授，這個計畫所使用的RTOS是基於Adeos nano-kernel所發展出來的。這個RTAI計劃的成果可以從網路上免費的下載到。 &lt;/p&gt; &lt;p&gt; &lt;span style="color:red;"&gt;RTLinux&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;RTLinux是FSMLabs所開發的一個類似RTAI架構的即時linux系統，也是免費的，它所使用的底層RTOS名叫RTCore，不過 FSMLabs有另一款商業版的RTLinux/Pro，在這個RTLinux/Pro裡面具有很多免費版RTLinux所沒有的新功能。&lt;br /&gt;&lt;br /&gt;不過在RTAI及RTLinux的環境中，有一個蠻常被人提及的缺點，那就是由於所有的即時工作(real-time task)都必須在RTOS下執行，所以所有的即時工作(real-time task)都必須執行在核心空間(kernel space)之下，這就代表行程與行程之間沒有辦法做到資料的隔離與保護。因此在這個問題上，就有一些新的架構被提了出來。以RTAI來說，一個新的基於 RTAI的機制名叫LXRT，它的一個最重要的好處是可以讓運作在使用者空間(user space)中的程式也能夠兼顧到即時性。&lt;br /&gt;&lt;br /&gt;此外，以目前的情況來看，以內建第二個RTOS 核心的方法來增進linux環境的即時性還是要比單純的使用2.6版核心要來的好上許多。 &lt;/p&gt; &lt;p&gt; &lt;a name="cpu"&gt;&lt;span style="color:red;"&gt;常見的嵌入式平台CPU&lt;/span&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;有別於我們常見的x86系列CPU，在嵌入式平台上比較常見的有下列幾種：&lt;br /&gt;&lt;br /&gt;&lt;table&gt; &lt;tbody&gt;&lt;tr&gt; &lt;td&gt;ARM&lt;/td&gt; &lt;td&gt;&lt;a href="http://www.arm.com/"&gt;http://www.arm.com/&lt;/a&gt;&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;MIPS&lt;/td&gt; &lt;td&gt;&lt;a href="http://www.mips.com/"&gt;http://www.mips.com/&lt;/a&gt;&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;Xscale&lt;/td&gt; &lt;td&gt;&lt;a href="http://www.intel.com/design/intelxscale/"&gt;http://www.intel.com/design/intelxscale/&lt;/a&gt;&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;FreeScale&lt;/td&gt; &lt;td&gt;&lt;a href="http://www.freescale.com/"&gt;http://www.freescale.com/&lt;/a&gt;&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;SuperH&lt;/td&gt; &lt;td&gt;&lt;a href="http://www.superh.com/home/index.htm"&gt;http://www.superh.com/home/index.htm&lt;/a&gt;&lt;/td&gt; &lt;/tr&gt; &lt;/tbody&gt;&lt;/table&gt; 表：嵌入式平台常見的CPU &lt;/p&gt; &lt;p&gt; &lt;span style="color:red;"&gt;ARM&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;img src="http://www.csie.ntu.edu.tw/%7Er88052/MyArticles/Embedded_Linux/Pictures/arm_logo.jpg" /&gt;&lt;br /&gt;圖：ARM公司的標誌(取自ARM公司首頁)&lt;br /&gt;&lt;br /&gt;目前在手機或PDA上，ARM的使用佔了很大的比例。ARM是由一家名叫ARM(Advanced RISC Machines)的公司所發展的，最早是由Acorn，Apple，和VLSI這三家公司在1990年合資成立的。目前的ARM CPU的架構已經推進到第五代，由於ARM CPU是屬於RISC的架構，所以每一個指令的長度都是固定的，基本的ARM指令長度是4個位元組，但從第4代開始，新增了一個名叫Thumb的指令集， 它的指令長度只有2個位元組，因此透過Thumb指令集的運用，開發者可以大幅的減少程式的大小。並且從第三代開始，ARM可以定址到4GByte的記憶 體，以及從第二代開始，ARM可以藉由協同處理器的幫助來擴充額外的功能，例如MMU的功能就位於第15號系統協同處理器(system co-processor)內。&lt;br /&gt;&lt;br /&gt;在ARM CPU內總共區分出7種狀態，分別是USR(user)、FIQ (Fast Interrupt)、IRQ (Normal Interupt)、SVC (Superuser)、SYS(system)、ABT(Abort)、及UND(Undefined)狀態。另外，在ARM CPU內總共有16個一般暫存器可用，以及一個用來紀錄CPU狀態的狀態暫存器。&lt;br /&gt;&lt;br /&gt;ARM系列的CPU由於耗電量低，以及擁有不錯的效能，所以在很多領域中都以著廣泛的應用。此外，ARM公司不僅僅只是販賣自家的CPU，他還透 過販賣CPU的知識產權來增加獲利。比方說，ARM公司目前將CPU的技術授權給全球的很多家廠商，例如有Intel、IBM、LG等等大廠，因此這些獲 得授權的廠商就可以生產屬於ARM架構的CPU了。&lt;br /&gt;&lt;br /&gt;&lt;img src="http://www.csie.ntu.edu.tw/%7Er88052/MyArticles/Embedded_Linux/Pictures/ipaq.jpg" /&gt;&lt;br /&gt;圖：使用Intel Xscale CPU(屬於ARM架構)的HP iPaq系列PDA &lt;/p&gt; &lt;p&gt; &lt;span style="color:red;"&gt;MIPS&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;img src="http://www.csie.ntu.edu.tw/%7Er88052/MyArticles/Embedded_Linux/Pictures/mips_logo.jpg" /&gt;&lt;br /&gt;圖：MIPS公司的標誌(取自MIPS公司首頁)&lt;br /&gt;&lt;br /&gt;MIPS是由MIPS公司所開發的CPU，它的全名是Microprocessor Without Interlocked Piped Stages。由於它的低耗電量，以及不錯的效能，因此在嵌入式環境中常可看見它的蹤跡，除此之外，其實在SGI的圖形工作站，Sony的Play Station裡面，都可以看到MIPS的身影。另外，在最近越來越熱的數位電視領域中，MIPS的使用也佔據了非常重要的地位。&lt;br /&gt;&lt;br /&gt;&lt;img src="http://www.csie.ntu.edu.tw/%7Er88052/MyArticles/Embedded_Linux/Pictures/casio.jpg" /&gt;&lt;br /&gt;圖：使用MIPS CPU的Casio CASSIOPEIA系列PDA &lt;/p&gt; &lt;p&gt; &lt;a name="development"&gt;&lt;span style="color:red;"&gt;開發嵌入式Linux的步驟&lt;/span&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;在開發嵌入式Linux方面，大概可以分為下列幾個階段： &lt;/p&gt;&lt;ol&gt;&lt;li&gt;開發環境的建置階段&lt;/li&gt;&lt;li&gt;開機啟動程式(開機啟動程式)建構階段&lt;/li&gt;&lt;li&gt;核心移植(porting)階段&lt;/li&gt;&lt;li&gt;上層系統建構階段&lt;/li&gt;&lt;/ol&gt;  &lt;p&gt; &lt;span style="color:red;"&gt;開發環境的建置階段&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;首先在開發環境的建置階段，最重要的大概就算是編譯器(compiler)了。一般說來，我們平常所用的CPU平台是以x86為主，然而在嵌入式 的環境中，x86平台比較少見，通常是以ARM，MIPS等等系列為主要對象。因此我們所需要的編譯器將是一個可以在x86平台上執行，但卻可以編譯出執 行在目標平台上的二進位機器碼。這一類的特殊編譯器就叫做跨平台編譯器(cross compiler)。如果廠商有提供跨平台編譯器的話，通常都有標準且方便的安裝程序可以參考。然而，如果廠商沒有提供這類特殊編譯器的話，一般說來， GNU 組織所開發的GCC系列的編譯器可以產生我們所需要的跨平台編譯器版本。&lt;br /&gt;&lt;br /&gt;&lt;img src="http://www.csie.ntu.edu.tw/%7Er88052/MyArticles/Embedded_Linux/Pictures/cross_compiler.jpg" /&gt;&lt;br /&gt;圖：藉由Cross Compiler的幫助，我們可以在一個平台上編譯出另外一個平台的執行檔&lt;br /&gt;&lt;br /&gt;如果要從GNU GCC編譯器的原始碼產生出我們所需的跨平台編譯器大概可以分為下列五個步驟： &lt;/p&gt;&lt;ol&gt;&lt;li&gt;指定目標平台上所使用的核心版本標頭檔(header file)的位置&lt;/li&gt;&lt;li&gt;安裝binutils (一個GCC會需要使用到的額外工具組)&lt;/li&gt;&lt;li&gt;從GCC原始碼中先編譯出一個沒有支援C語言函式庫的跨平台編譯器&lt;/li&gt;&lt;li&gt;再利用上一步驟所建構起來的跨平台編譯器來編譯出在目標平台上所使用的C語言函式庫&lt;/li&gt;&lt;li&gt;最後利用上一步驟所產生的C語言函式庫來從GCC原始碼中編譯出一個支援C語言函式庫的跨平台編譯器&lt;/li&gt;&lt;/ol&gt;  &lt;p&gt; &lt;span style="color:red;"&gt;開機啟動程式(開機啟動程式)建構階段&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;在準備好跨平台編譯器之後，就可以來考慮開機啟動程式(開機啟動程式)的選擇了。目前在嵌入式環境中已經有很多現成的開機啟動程式可以使用，比較 有名的大概有BLOB，U-Boot，RedBoot，bootldr等等。我們平常在桌上linux電腦可見的lilo並不太適合使用在嵌入式系統端， 最主要的原因是lilo只支援x86平台。然而，雖然已經有很多現成的開機啟動程式可供使用，但在某些情況下，開發者可能需要自行的修改開機啟動程式的原 始碼來符合現實平台的需求。&lt;br /&gt;&lt;br /&gt;當然，開發者也可以捨棄目前常見的一些開機啟動程式，而自行撰寫一個新的開機啟動程式出來。通常這一步驟會由先撰寫一個硬體測試程式來偵測並檢驗目標平台上的硬體裝置是否正常，接下來才會更進一步的把這個硬體測試程式開發成一個真正的開機啟動程式。&lt;br /&gt;&lt;br /&gt;另外，除了在目標平台上安裝一個開機啟動程式（boot loader）來啟動整個系統之外，通常在整個嵌入式系統的開發初期，會透過網路連結的方式把系統啟動起來。在這邊可以使用的網路機制有 BOOTP/DHCP，TFTP（Trivial File Transfer Protocol），NFS（Network File System）等等。透過網路來啟動系統的好處是，大部份的檔案更動都可以在本機（host）端完成，而不需要下載到目標平台（target platform）上。由於通常目標平台的儲存裝置會是flash ROM，而flash ROM有最多寫入次數的限制，所以更加深了經由網路連結啟動的吸引力。&lt;br /&gt;&lt;br /&gt;不管是自行開發一個開機啟動程式，或是從現有的開機啟動程式中做修改，在這一階段裡面勢必要進行除錯（debug）的動作。在這一階段裡面，最方 便的除錯器（debugger）要算是支援JTAG，BDM，OnCE，或OCDS等等除錯介面的除錯器了。而在購買這類型的除錯器時，有幾點需要注意： &lt;/p&gt;&lt;ol&gt;&lt;li&gt;所購買的除錯器是否可以跟目標平台連結&lt;/li&gt;&lt;li&gt;所購買的除錯器是否可以在本機(host)端使用，有些除錯器只有microsoft windows的驅動程式，而沒有linux的版本。&lt;/li&gt;&lt;li&gt;在某些目標平台上，只有DRAM這一類型的儲存裝置，而沒有ROM，因此你可能會需要一個可以初始化DRAM的除錯器，如此一來，開發者才可以把程式下載到DRAM內。&lt;/li&gt;&lt;/ol&gt; &lt;img src="http://www.csie.ntu.edu.tw/%7Er88052/MyArticles/Embedded_Linux/Pictures/jtag.jpg" /&gt;&lt;br /&gt;圖：American arium所開發的具有JTAG介面的硬體模擬器&lt;br /&gt;&lt;br /&gt;另外，目前市面上大部份的這類型除錯器都有支援gdb(一個GNU組織所發展的除錯器軟體)，或是正準備要支援gdb，因此開發者可以透過gdb來使用這類型的除錯器。  &lt;p&gt; &lt;span style="color:red;"&gt;核心移植(porting)階段&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;在完成了開機啟動程式的準備及安裝之後，接下來就要進行linux 核心的移植了。由於核心的版本眾多，不同的版本也有不同的小錯誤(bugs)，也可能某些版本只能被某些版本的GCC編譯，不過通常提供這些特殊平台版本 的網站上會提供相關的修補程式(patch)來解決這些問題。&lt;br /&gt;&lt;br /&gt;而在設定核心的時候，可以根據你的開發版來載入一些預設的設定值，比方說你的開發版是基於assabet來設計的話，那麼在設定核心的時候就可以使用make assabet_config來載入assabet的預設值。&lt;br /&gt;&lt;br /&gt;&lt;img src="http://www.csie.ntu.edu.tw/%7Er88052/MyArticles/Embedded_Linux/Pictures/assabet.jpg" /&gt;&lt;br /&gt;圖：Intel的assabet開發版&lt;br /&gt;&lt;br /&gt;可以使用在這一階段的除錯器，一般說來跟開機啟動程式階段相同，也就是一個可以支援JTAG等等除錯介面的除錯器是最好用的了。 &lt;/p&gt; &lt;p&gt; &lt;span style="color:red;"&gt;上層系統建構階段&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;在完成核心的移植之後，接下來就是整個系統的安裝與設定了。由於在核心以上的軟體套件比較不具備跟平台相關的相依性，而且在嵌入式平台上比較難以 去做分析比較，因此最好的方法是先在x86平台上把Linux系統的整體架構搞清楚，之後在建置一套嵌入式Linux環境時，將會容易許多。 &lt;/p&gt; &lt;p&gt; &lt;a name="emulator"&gt;&lt;span style="color:red;"&gt;可用來模擬嵌入式平台的模擬器&lt;/span&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;這些模擬器或多或少在某些情況下可以幫助嵌入式軟體的開發，這種模擬器最有名的要算是VMware了。不過VMware是模擬x86的環境，所以在嵌入式系統的開發上並沒有很大的用處。&lt;br /&gt;&lt;br /&gt;而一些跟嵌入式環境相關的模擬器大概有：&lt;br /&gt;&lt;br /&gt;&lt;table&gt; &lt;tbody&gt;&lt;tr id="title" style="border-bottom-width: 3px;"&gt; &lt;td&gt;名稱&lt;/td&gt; &lt;td&gt;用途&lt;/td&gt; &lt;td&gt;官方網站&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;PearPC&lt;/td&gt; &lt;td&gt;模擬PowerPC&lt;/td&gt; &lt;td&gt;&lt;a href="http://pearpc.sourceforge.net/"&gt;http://pearpc.sourceforge.net&lt;/a&gt;&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;ARMphetamine&lt;/td&gt; &lt;td&gt;模擬ARM（發展中止）&lt;/td&gt; &lt;td&gt;&lt;a href="http://armphetamine.sourceforge.net/"&gt;http://armphetamine.sourceforge.net/&lt;/a&gt;&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;Tarmac&lt;/td&gt; &lt;td&gt;模擬ARM（發展中止）&lt;/td&gt; &lt;td&gt;&lt;a href="http://davidsharp.com/tarmac/"&gt;http://davidsharp.com/tarmac/&lt;/a&gt;&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;SkyEye&lt;/td&gt; &lt;td&gt;模擬ARM&lt;/td&gt; &lt;td&gt;&lt;a href="http://www.skyeye.org/"&gt;http://www.skyeye.org/&lt;/a&gt;&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt;ARMware&lt;/td&gt; &lt;td&gt;模擬ARM&lt;/td&gt; &lt;td&gt;&lt;a href="http://www.csie.ntu.edu.tw/%7Er88052/ARMware/tw/frame.html"&gt;http://www.csie.ntu.edu.tw/~r88052/ARMware/tw/frame.html&lt;/a&gt;&lt;/td&gt; &lt;/tr&gt; &lt;/tbody&gt;&lt;/table&gt; 表：常見的嵌入式平台模擬器 &lt;/p&gt; &lt;p&gt; &lt;span style="color:red;"&gt;PearPC&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.csie.ntu.edu.tw/%7Er88052/MyArticles/Embedded_Linux/Pictures/osx_ichat.jpg"&gt;&lt;img src="http://www.csie.ntu.edu.tw/%7Er88052/MyArticles/Embedded_Linux/Pictures/osx_ichat_small.jpg" /&gt; (按一下放大) &lt;/a&gt;&lt;br /&gt;圖：PearPC執行Apple OS X的畫面(取自PearPC網站)&lt;br /&gt;&lt;br /&gt;PearPC幾乎可以完美的模擬出PowerPC的執行環境，目前的最新版本為0.3.1版。另外，PearPC內建有一個動態編譯器，所以它的執行效能比起簡單的PowerPC模擬器來說已經要好上許多。 &lt;/p&gt; &lt;p&gt; &lt;span style="color:red;"&gt;ARMphetamine&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;ARMphetamine是一個內建動態編譯器技術的ARM模擬器，不過他只提供簡單的ARM核心模擬，並沒有辦法模擬出整個embedded linux可以運作的環境出來。另外，目前的版本也不穩定，有很多的錯誤急需修正。 &lt;/p&gt; &lt;p&gt; &lt;span style="color:red;"&gt;Tarmac&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Tarmac是個建構在Red Squirrel模擬器上的動態編譯器，雖然它的完成度較ARMphetamine完整，不過它的設計也比較簡單。 &lt;/p&gt; &lt;p&gt; &lt;span style="color:red;"&gt;SkyEye&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.csie.ntu.edu.tw/%7Er88052/MyArticles/Embedded_Linux/Pictures/uclinuxonskyeye.jpg"&gt;&lt;img src="http://www.csie.ntu.edu.tw/%7Er88052/MyArticles/Embedded_Linux/Pictures/uclinuxonskyeye_small.jpg" /&gt; (按一下放大) &lt;/a&gt;&lt;br /&gt;圖：skyeye模擬器執行uCLinux(取自SkyEye網站)&lt;br /&gt;&lt;br /&gt;SkyEye是個由大陸那邊的清華大學所開發的一款ARM模擬器。能夠在上面執行uCLinux，不過不支援動態編譯器技術。不過它的優點是支援很多種類的CPU，以及種類不多的週邊設備。 &lt;/p&gt; &lt;p&gt; &lt;span style="color:red;"&gt;ARM模擬器：「ARMware」&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;img src="http://www.csie.ntu.edu.tw/%7Er88052/MyArticles/Embedded_Linux/Pictures/armware_start.jpg" /&gt;&lt;br /&gt;圖：ARMware模擬器的起始畫面&lt;br /&gt;&lt;br /&gt;ARMware是由筆者所自行撰寫的一個ARM平台模擬器。&lt;br /&gt;&lt;br /&gt;&lt;img src="http://www.csie.ntu.edu.tw/%7Er88052/MyArticles/Embedded_Linux/Pictures/armware_about.jpg" /&gt;&lt;br /&gt;圖：筆者是ARMware的作者&lt;br /&gt;&lt;br /&gt;ARMware是個類似VMware或Bochs的硬體平台模擬器，不過相對於VMware或Bochs所模擬的x86平台，ARMware提供 了一個模擬ARM處理器的環境。目前ARMware所能模擬的核心為第五代的ARM架構(ARM Architecture V)，並且以Intel StrongARM SA1110為模擬的對象，包括了StrongARM SA1110 內部的中斷控制器(Interrupt Controller)，記憶體管理單元(MMU)，LCD控制器(LCD Controller)，即時時鐘(Real Time Clock)，序列埠(Serial Port)等等。而在未來將會加入Intel Xscale PXA系列的模擬。除了CPU的模擬之外，ARMware還以HP iPaq H3600為目標，模擬出一個可以執行embedded linux的環境。在未來，ARMware將會以HP iPaq H5500為目標，提供一個模擬Intel Xscale的整體環境。&lt;br /&gt;&lt;br /&gt;&lt;img src="http://www.csie.ntu.edu.tw/%7Er88052/MyArticles/Embedded_Linux/Pictures/armware_running.jpg" /&gt;&lt;br /&gt;圖：在ARMware內執行embedded linux的畫面&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.csie.ntu.edu.tw/%7Er88052/MyArticles/Embedded_Linux/Pictures/armware_arch.jpg"&gt;&lt;img src="http://www.csie.ntu.edu.tw/%7Er88052/MyArticles/Embedded_Linux/Pictures/armware_arch_small.jpg" /&gt; (按一下放大) &lt;/a&gt;&lt;br /&gt;圖：ARMware模擬器的架構圖&lt;br /&gt;&lt;br /&gt;除此之外，使用者可以調整模擬環境的記憶體大小，比方說雖然iPaq H3600只提供了32MB的DRAM，但在ARMware內可以調整記憶體容量到最高512MB，因此可以模擬出一台經過修改的iPaq H3600。&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.csie.ntu.edu.tw/%7Er88052/MyArticles/Embedded_Linux/Pictures/dram_modify.jpg"&gt;&lt;img src="http://www.csie.ntu.edu.tw/%7Er88052/MyArticles/Embedded_Linux/Pictures/dram_modify_small.jpg" /&gt; (按一下放大) &lt;/a&gt;&lt;br /&gt;圖：使用者可自行修改記憶體大小&lt;br /&gt;&lt;br /&gt;要製作這類型的硬體模擬器，最簡單的方法是採用傳統的直譯器(interpreter)模式，也就是一個一個的去解釋目標平台上的機器指令 (machine instruction)，這種方法最簡單，但其效率也最慢。由於通常模擬器的速度要比真正的目標硬體平台要慢上許多，因此便有許多較進步的技術被發展出 來應用在模擬器內部。這些先進的技術大概包括了threaded code，或是一種稱為動態編譯器(dynamic compiler，或稱做 dynamic translator)的技術。&lt;br /&gt;&lt;br /&gt;而在ARMware內部，筆者實做了所謂的threaded code以及dynamic compiler技術。 &lt;/p&gt; &lt;p&gt; &lt;span style="color:red;"&gt;Threaded code技術&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;threaded code有點像是一種快取(cache)的機制，會把解碼後的目標平台指令(target machine instruction)儲存起來，這樣一來在下一次的執行時，就不需要再進行一次複雜的解碼動作，如此可以加速執行的速度。 &lt;/p&gt; &lt;p&gt; &lt;span style="color:red;"&gt;動態編譯器(Dynamic compiler)技術&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;而dynamic compiler則是在邊執行目標平台指令的同時，邊將其編譯成本機平台的機器碼(例如編譯成x86平台的機器碼)，這就類似我們一般所知的編譯器，只不 過他是在程式執行的時候才去把該程式給編譯出來，因此特別稱他做動態編譯器(dynamic compiler)。比較有名的dynamic compiler應用應該是在Java虛擬機器裡面，比較為人所知的名字是JIT (Just-In-Time) compiler或是HotSpot compiler。而在ARMware 0.3.0版之後，就已經內建了一個類似HotSpot的動態編譯器，並且目前所實做出來的最佳化技術大概有下列幾項，因此對整體的執行速度有所助益： &lt;/p&gt;&lt;ol&gt;&lt;li&gt;Redundant condition code calculation elimination&lt;/li&gt;&lt;li&gt;Global grouping conditional execuating instruction &lt;/li&gt;&lt;li&gt;Redundant jump elimination&lt;/li&gt;&lt;li&gt;Dead code elimination&lt;/li&gt;&lt;li&gt;Constant folding&lt;/li&gt;&lt;li&gt;Global Common Subexpression Elimination&lt;/li&gt;&lt;li&gt;Global redundany memory operation elimination&lt;/li&gt;&lt;li&gt;Algebraic canonicalization&lt;/li&gt;&lt;li&gt;Global SSA form based linear scan register allocation &lt;/li&gt;&lt;/ol&gt; 因此目前在ARMware內部，當要執行一段ARM的機器碼時，會以下列的步驟來進行： &lt;ol&gt;&lt;li&gt;當第一次碰到一段從未執行過的ARM機器碼時, ARMware會先使用內建的直譯器(interpreter)來解釋這段ARM機器碼。&lt;/li&gt;&lt;br /&gt;&lt;li&gt;之後，當第二次碰到這段ARM機器碼時，會先由ARMware內建的分析器(profiler)來決定這段ARM機器碼是否值得被 threaded-code化，如果決定profiler決定將其threaded -code化的話，ARMware就會將這段ARM機器碼餵給ARMware內建的threaded code引擎來產生相對於該段ARM機器碼的threaded codes.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;在產生完threaded codes之後，當ARMware再度碰到這段ARM機器碼時，就會使用新產生的threaded codes去解釋。然而，如果在執行threaded codes的時候，程式的流程會跳到一個還沒有被threaded code化的ARM程式碼時，ARMware就會回到直譯器(interpreter)的模式去解釋。&lt;/li&gt;&lt;br /&gt;&lt;li&gt;之後，每當再度碰到這段ARM機器碼時，ARMware 內建的 profiler會決定該段程式碼值不值得被動態的編譯成x86的機器碼(dynamic compiling)，如果決定值得的話，ARMware就會將該段ARM機器碼餵給 ARMware內建的動態編譯器(dynamic compiler)來產生相對於該段ARM機器碼的x86機器碼。&lt;/li&gt;&lt;br /&gt;&lt;li&gt;在產生完 x96機器碼之後，當 ARMware 再度碰到這段ARM機器碼時，就會使用新產生的 x86機器碼來解釋。然而，如果在執行這段x86機器碼的過程當中，碰到一個還沒被動態編譯過的ARM程式碼，就會回到原始的直譯器 (interpreter)模式或是先前的threaded code模式去解釋。&lt;/li&gt;&lt;/ol&gt; &lt;a href="http://www.csie.ntu.edu.tw/%7Er88052/MyArticles/Embedded_Linux/Pictures/armware_core.jpg"&gt;&lt;img src="http://www.csie.ntu.edu.tw/%7Er88052/MyArticles/Embedded_Linux/Pictures/armware_core_small.jpg" /&gt; (按一下放大) &lt;/a&gt;&lt;br /&gt;圖：ARMware核心的執行流程&lt;br /&gt;&lt;br /&gt;除此之外，筆者也對ARMware做了一些微調的動作，比方說使用組合語言的方式去最佳化一些模擬的動作，例如在LCD螢幕的模擬方面，由於要把iPaq 的畫面顯示在一般的螢幕上，必須要進行一些顏色格式的轉換，以及座標軸轉換的動作(ARMware必須把螢幕資料旋轉270度，這樣使用者看到的畫面才是 正確的)，而這些動作是以一個pixel為機準的，因此可以使用x86的SIMD型態指令 (例如MMX，SSE，SSE2等等)來一次處理好幾個pixel，進而加速ARMware對整個LCD螢幕的模擬。&lt;br /&gt;&lt;br /&gt;&lt;img src="http://www.csie.ntu.edu.tw/%7Er88052/MyArticles/Embedded_Linux/Pictures/screen_rotate.jpg" /&gt;&lt;br /&gt;圖：由於iPaq的硬體配置，ARMware必須把螢幕資料旋轉270度，這樣使用者看到的畫面才是正確的&lt;br /&gt;&lt;br /&gt;另外，由於幾乎每個CPU內都有狀態暫存器(status register)的設置，而要模擬目標平台的狀態暫存器最簡單的方法就是透過軟體的模擬，但是這樣的方式很慢。而一個比較快的模擬方式是直接拿本機 CPU的狀態暫存器去模擬目標平台的狀態暫存器，但由於高階的電腦語言通常碰不到CPU內部的狀態暫存器，所以要完成這樣的最佳化，必須要透過組合語言的 撰寫，而在ARMware內部就實做了這樣的一個最佳化狀態暫存器處理的組合語言程式碼。&lt;br /&gt;&lt;br /&gt;&lt;img src="http://www.csie.ntu.edu.tw/%7Er88052/MyArticles/Embedded_Linux/Pictures/ccbit_mapping.jpg" /&gt;&lt;br /&gt;圖：ARM狀態暫存器上的condition位元與x86狀態暫存器上condition位元的對應關係&lt;br /&gt;&lt;br /&gt;除了LCD螢幕的顯示之外，ARMware還可以使用一個模擬出來的serial console來與使用者做互動。使用者可以從這個serial console中輸入命令給模擬的環境，也可以從該serial console中獲得模擬環境的一些輸出訊息，並且這個serial console也支援ANSI顏色碼，因此可以正確的看到例如ls等指令所輸出的帶有顏色的訊息。&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.csie.ntu.edu.tw/%7Er88052/MyArticles/Embedded_Linux/Pictures/serial_console.jpg"&gt;&lt;img src="http://www.csie.ntu.edu.tw/%7Er88052/MyArticles/Embedded_Linux/Pictures/serial_console_small.jpg" /&gt; (按一下放大) &lt;/a&gt;&lt;br /&gt;圖：ARMware的執行畫面，左邊是模擬出來的PDA螢幕，右邊是模擬出來的serial console&lt;br /&gt;&lt;br /&gt;而在進行iPaq等PDA或手機的系統開發時，通常需要進行Flash ROM的錄製工作，這項工作通常會由廠商所提供的工具來完成。而在ARMware內部，也內建了一個用來燒錄Flash ROM的工具程式，透過這個工具程式，使用者可以將數個分割區的映像檔(image file)組合成一個單一的Flash ROM檔，而ARMware就可以使用該Flash ROM檔來啟動整個模擬的環境。&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.csie.ntu.edu.tw/%7Er88052/MyArticles/Embedded_Linux/Pictures/burning.jpg"&gt;&lt;img src="http://www.csie.ntu.edu.tw/%7Er88052/MyArticles/Embedded_Linux/Pictures/burning_small.jpg" /&gt; (按一下放大) &lt;/a&gt;&lt;br /&gt;圖：ARMware內建的Flash ROM製作工具&lt;br /&gt;&lt;br /&gt;最後，如果讀者對這個ARMware模擬器有興趣的話，可以到筆者的網站http://www.csie.ntu.edu.tw/~r88052/ARMware/tw/frame.html下載，裡面有詳細的安裝說明與解說，目前的最新版本是0.5.0版。  &lt;p&gt; &lt;span style="color:red;"&gt;結語&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;最後，由於Linux本身的開放性及種類繁多的功能，因此嵌入式Linux系統是個龐大且複雜但卻很有趣的一門學問，不僅在過去是如此，在未來的數年之間，也將會是個越來越熱門，有越來越多焦點會投注在裡面的一個領域。 &lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3931381955158939823-488236312401444083?l=wei-hu-tw.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/wei-hu-tw/~4/SOAxCTbz_y0" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/wei-hu-tw/~3/SOAxCTbz_y0/embedded-linux.html</link><author>noreply@blogger.com (Wei)</author><thr:total>0</thr:total><feedburner:origLink>http://wei-hu-tw.blogspot.com/2007/11/embedded-linux.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-3931381955158939823.post-7004054675121776763</guid><pubDate>Mon, 12 Nov 2007 16:25:00 +0000</pubDate><atom:updated>2008-01-20T18:50:05.526+08:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Java</category><title>MIDP 的使用方向</title><description>目前國內在使用 J2ME 的 MIDP 套件上, 主要分成三類: &lt;ul&gt;&lt;li&gt;撰寫 midlet:&lt;br /&gt;&lt;br /&gt;所謂的 midlet 就是專門在 MIDP 這個環境中所執行的 Java 程式. 這也就是說, 如果你是這一類的 programmer 的話, 你所需要具備的技能將會是 Java 程式的撰寫能力, 以及 midlet programming 的相關知識. 由於當初 MIDP 在設計的時候, 就是要使用在那些系統資源比較差的小型裝置上, 因此你所撰寫出來的 midlet 程式也將會受到一些限制, 包括你必須要遵循著某種固定的格式來撰寫你的 midlet. 基本上, 撰寫 midlet 跟撰寫一般的 Java 程式一樣, 一點都不難, 你只需要看個文件, 花點時間, 搞懂撰寫 midlet 的方法後, 就可以開始撰寫你自己的 midlet 了. &lt;/li&gt;&lt;br /&gt;&lt;li&gt;增加特定功能的 class 模組:&lt;br /&gt;&lt;br /&gt;由於 Sun 的 R.I 只提供了基本的 class 模組, 例如 java.lang.Integer, java.lang.Object, java.io.DataInput 等等類別, 以及一些專屬於 J2ME 領域內的 javax.microedition.io.Datagram, javax.microedition.io.Connection 等等類別. 但是由於廠商想要創造出一些與其他品牌不同的特點, 因此通常都會自行增加一些額外的功能, 比方說振動, 閃光等等, 而在這些額外的功能之中, 有不少已經標準化了, 比方說 MMAPI (Mobile Media API) 這個提供多媒體功能的額外類別模組. &lt;/li&gt;&lt;br /&gt;&lt;li&gt;移植到新的 GUI 系統上:&lt;br /&gt;&lt;br /&gt;J2ME 最主要的使用範圍是在小型的嵌入式系統 (embedded system) 中, 而在這些所謂的小型裝置上, 很難找到一個統一的圖形使用者介面 (GUI), 因此, 當廠商拿到 Sun 的 R.I. 之後, 通常第一件要作的事情便是把 Sun 的 R.I. 給移植到該廠商所使用的 GUI 系統上. 而目前常見的 Embedded GUI 包括了 Embedded Qt, MiniGUI, 以及 Microwindows 等等.&lt;br /&gt;&lt;br /&gt;在進行 GUI 層面的移植時, 所需要修改的部份有下列數項:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Soft button 的模擬.&lt;br /&gt;&lt;br /&gt;MIDP 的執行環境中, 有兩顆專門叫做 Soft button 的按鍵, 這兩顆按鍵可以由真正的硬體或軟體來模擬出來. &lt;/li&gt;&lt;br /&gt;&lt;li&gt;水平以及垂直方向的捲動指示.&lt;br /&gt;&lt;br /&gt;當一個 midlet 的畫面超過螢幕的大小時, MIDP 會在螢幕上顯示上下左右的箭頭, 來指示使用者目前可以往那個方向捲動. &lt;/li&gt;&lt;br /&gt;&lt;li&gt;基本繪圖動作的處理, 包括畫腺, 畫方形, 畫圓等等.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;聲音的產生.&lt;br /&gt;&lt;br /&gt;            基本的 beep 聲.             &lt;/li&gt;&lt;br /&gt;&lt;li&gt;字型的處理.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;圖形檔的顯示.&lt;br /&gt;&lt;br /&gt;            Sun 的 R.I. 只可以顯示 png 檔案, 如果你想顯示更多的檔案格式, 那麼必須要自行修改 MIDP 原始碼. &lt;/li&gt;&lt;br /&gt;&lt;li&gt;按鍵的對應.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;螢幕的重繪.&lt;br /&gt;&lt;br /&gt;            一個好的螢幕重繪機制將可以大幅的增加執行時期的效率. &lt;/li&gt;&lt;br /&gt;&lt;li&gt;事件的處理.&lt;br /&gt;&lt;br /&gt;            J2ME 內部的事件處理機制要如何得知使用者目前的動作. &lt;/li&gt;&lt;br /&gt;&lt;li&gt;計時器 (Timer) 的模擬.&lt;br /&gt;&lt;br /&gt;            MIDP 內部使用了計時器的觀念, 因此我們必須要實作一個計時器給它. &lt;/li&gt;&lt;br /&gt;&lt;li&gt;與 JAM (Java Application Manager) 的配合.&lt;br /&gt;&lt;br /&gt;            如何由 JAM 來啟動一個 midlet. &lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3931381955158939823-7004054675121776763?l=wei-hu-tw.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/wei-hu-tw/~4/EMc_EFjJrgg" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/wei-hu-tw/~3/EMc_EFjJrgg/midp.html</link><author>noreply@blogger.com (Wei)</author><thr:total>0</thr:total><feedburner:origLink>http://wei-hu-tw.blogspot.com/2007/11/midp.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-3931381955158939823.post-8589524740605327463</guid><pubDate>Mon, 12 Nov 2007 16:09:00 +0000</pubDate><atom:updated>2008-01-20T18:50:05.527+08:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Java</category><title>CLDC 的使用方向</title><description>你可以把 CLDC 切割為兩大塊, 這兩大塊的關係分別是 "上與下" 的關係. 位於下層的是一個小型的 Java 虛擬機器 (Java Virtual Machine), 名字叫做 KVM. 而位於上層的則是一些 Java 環境中最基本的 class 模組. 而目前在國內提到有關 CLDC 的使用時, 不外乎可以區分為下面幾大類: &lt;ol&gt;&lt;li&gt;修改 KVM:&lt;br /&gt;&lt;br /&gt;Ok, 在討論這一項之前, 我先描述一個名詞, 這個名詞叫做 R.I, 它的全名叫做 Reference Implementation. Ok, 那麼甚麼叫做 Reference Implementation 呢? 基本上, 你可以想像一個情景, 有一本專門用來規範 KVM 架構的書, 而這本書就叫做 Reference. 而依照這本規格書中所定義的內容所撰寫出來的程式碼, 就叫做 Reference Implementation.&lt;br /&gt;&lt;br /&gt;而 Sun 這家公司呢, 有撰寫它自己的 Reference Implementation, 而其中的某個版本便可以從 Sun 的網站 (http://wwws.sun.com/software/communitysource/j2me/cldc/download.html) 下載回來使用. 不過想當然爾, 能夠讓你下載的原始碼, 並沒有非常認真的考慮到程式撰寫的最佳化, 以及執行時期的效率等等議題.&lt;br /&gt;&lt;br /&gt;但也就是因為 Sun 有釋放出一個版本的 KVM R.I., 因此目前大多數廠商在 CLDC 上所作的使用就是去 Sun 的網站下載原始碼, 然後回來作一些修改. 基本上, 目前大部份的修改不外乎屬於下面幾類:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;移植到其他的作業系統:&lt;br /&gt;&lt;br /&gt;由於 Sun 的 R.I. 是以 UNIX 或 Mircosoft Windows 為預設的作業系統所撰寫出來的, 因此, 假如說今天你所要跑得作業系統跟這兩者差很多的話, 那你就得作出相對應的修改. 比方說, 在某些情況下, 你得在 Nucleus (http://www.acceleratedtechnology.com/) 這個作業系統上執行 KVM, 那麼你就必須要針對 Nucleus 的特性來在 KVM 裡面作修改.&lt;br /&gt;&lt;br /&gt;通常這些修改包括了下列數項:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Big-endian 以及 little-endian 的選擇.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;64-bit 整數型態的加減乘除:&lt;br /&gt;&lt;br /&gt;如果你所使用的編譯器 (Compiler) 有支援 64-bit 整數型態的話, 那麼你就很簡單的直接使用編譯器內建的 64-bit 整數型態. 但假如你的編譯器不支援這種資料型態的話, 你就必須撰寫程式碼來模擬它. &lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;          &lt;/li&gt;&lt;li&gt;嘗試讓 Sun 的 R.I. 執行的更快:&lt;br /&gt;&lt;br /&gt;由於 Sun 的 R.I. 只是一個 Reference Implementation, 它並沒有非常詳細的考慮到程式的最佳化, 因此雖然 Sun R.I. 的執行速度還算可以, 但實際上, 我們可以作些手腳讓它執行的更快, 而且加快的空間還不小. 目前常見的加速方法大概有下列兩種:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;使用組合語言 (Assembly Language) 來改寫某些程式碼.&lt;br /&gt;&lt;br /&gt;雖然說編譯器 (Compiler) 可以幫我們作很多形式的最佳化, 但是再好的編譯器所產生出來的程式碼, 或多或少都還有人為調整的空間. 比方說, Java 虛擬機器內部通常都有一個非常大的迴圈在反覆地執行 Java bytecode, 而 Java 虛擬機器大部份的時間便花在這個迴圈上, 因此這個迴圈便是我們以組合語言來改寫的好目標.&lt;br /&gt;&lt;br /&gt;但是使用組合語言就像是 "跟惡魔打交道", 因為當你使用了組合語言來最佳化之後, 最主要將會碰到的問題是 - 後續的程式碼維護工作會變得很難. 因為所有本來可以由 compiler 來幫你 take care 的東西, 現在都必須要由你自己來處理了. 而且你的文件也必須要寫的夠詳細, 否則不要說是之後維護的其他人, 縱使是你自己, 在隔個半年, 一年之後再回來看你所寫的組合語言程式碼, 可能也都無法一下子就看出來當初為甚麼要這麼撰寫.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;加入 JIT (Just-In-Time Compiler) 或 Hot-Spot Compiler 的技術.&lt;br /&gt;&lt;br /&gt;在編譯器的世界裡, 有好幾種分類的方法, 其中的一種便是把編譯器分成兩大類, 分別是:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;靜態編譯器 (Static Compiler)&lt;br /&gt;&lt;br /&gt;在程式執行前就先把程式整個編譯出來. 這是最常見的方式, 比方說一般常見的 Visual C++, GNU GCC 編譯器等等, 都是屬於 static compiler 的一種. 這種編譯器的好處是, 編譯的時間並沒有受到限制, 不論花多久的時間, 就是要把程式給編譯出來. 因此 static compiler 的設計者便可以在編譯器內部實作任何他認為合適的最佳化方法, 來加速最後程式的執行.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;動態編譯器 (Dynamic Compiler)&lt;br /&gt;&lt;br /&gt;這種編譯器一般來說, 我們很少會去使用到. 並且很有可能的, 大部份的使用者都沒有使用過動態編譯器的經驗. 縱使有, 你也不會知道自己使用到了動態編譯器. 為甚麼呢? 最主要的原因是, 動態編譯器是在程式的執行過程中, 程式邊執行, 邊把下一步所要執行的程式碼給編譯出來 (所以才叫做動態編譯器阿). 所以你只能看到程式執行的表象過程與結果, 並沒有辦法看到程式內部實際在運作的編譯過程. 基本上, 為甚麼要發展出所謂的動態編譯器呢? 主要的原因大概有下列幾點:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;可以在上一代的機器所執行的程式, 不需要經過修改或重新編譯, 便可以跑在下一代的機器上.&lt;br /&gt;&lt;br /&gt;比方說, 有些廠商所出產的電腦系統, 上一代跟下一代並不相容. 而在正常的狀況下, 那些原本在上一代電腦所執行的程式, 必須要經過重新編譯之後, 才能夠執行在下一代電腦上. 但是如果沒有辦法拿到舊程式的原始碼, 那麼也就無從編譯起了. 在這種情況下的解決辦法, 就是將舊程式的執行碼 (executable code) 把他翻譯成新電腦看得懂得格式.&lt;br /&gt;&lt;br /&gt;而這種翻譯的動作, 可以靜態編譯器或動態編譯器的方式來實做出來. 那為甚麼需要發展動態編譯呢? 有一部份的原因是因為靜態編譯需要人為的事先介入來進行編譯的動作, 然而對於不懂電腦系統的人來說, 這將會是一個門檻. 如果改採用動態編譯的話, 對一般使用者來說, 他所作的一樣是直接執行程式, 而程式將會動態的把自己編譯成在下一代電腦上可以執行的型態.&lt;br /&gt;&lt;br /&gt;因此你可以把動態編譯器, 看成是以某一種電腦的執行碼為輸入, 而以另外一種電腦的執行碼格式為輸出的執行時期編譯器.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;加速模擬器的執行速度.&lt;br /&gt;&lt;br /&gt;所謂模擬器, 就是用軟體來模擬一台真實的電腦. 想而易見的, 這種用軟體模擬出來的電腦, 它的執行速度一定是緩慢的. 這是因為本來只要數個 CPU clock cycle 便可執行完畢的指令, 在軟體模擬器下, 將需要數十個, 甚至數百個 CPU clock cycle 才能夠模擬完成, 因此, 軟體模擬器的執行速度將會比所模擬的真實機器要慢上數十倍或數百倍之多.&lt;br /&gt;&lt;br /&gt;所以, 有些方法就被發展出來加速軟體模擬器的執行, 其中的一種方法便是在軟體模擬器當中加入所謂的動態編譯器, 在邊執行的過程當中, 邊去把另一個電腦系統的執行碼翻譯成本機電腦系統所看得懂得執行碼. 並且藉由編譯器的最佳化技術來達到加速執行的目的. &lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;Ok, 那麼再重新回到在 KVM 內部加入動態編譯器的議題. 這個題目跟剛剛所提到的動態編譯器有關係嗎? 答案是有的. 原因是 Java 虛擬機器本來就是一個軟體模擬器, 它用來模擬一個假想的 Java 機器. 而既然它是一個軟體模擬器, 我們就可以使用之前在軟體模擬器領域中被發展出來的動態編譯技術, 來加速 Java 虛擬機器的執行.&lt;br /&gt;&lt;br /&gt;而由於 Java 虛擬機器的特性, 所以在其內部進行動態編譯動作時, 是以一個 Java method 為單位. 這也就是說, 如果今天位於 Java 虛擬機器內部的動態編譯器決定要把某一段 Java bytecode 翻譯成本機電腦所用的 machine code 時, 該段 Java bytecode 將會是一整個 Java method.&lt;br /&gt;&lt;br /&gt;而在 Java 虛擬機器內部常用的動態編譯器主要分成下面兩類: &lt;ul&gt;&lt;br /&gt;&lt;li&gt;Just-In-Time (JIT) Compiler&lt;br /&gt;&lt;br /&gt;所謂的 Just-In-Time 編譯器, 就是只要碰到函式呼叫 (比方說執行到 Invoke virtual, Invoke static, Invoke interface, 或 Invoke special 這四個 Java bytecode), 就會把該函式翻譯成本機電腦所用的 machine code. 這個作法的好處是較為簡單. 但是壞處是記憶體的需求量將會較大. 這是因為並不是每個函式都會被重複的執行到, 某些函式可能只會被用到一次, 而這些只被用到一次的函式, 如果花費了額外的時間去進行翻譯的動作, 但在之後卻不會執行到它, 那麼整體來說, 反而無助於整體執行速度的提昇. 而且還必須花費額外的記憶空間來儲存之後完全用不到的 machine code. 所以, 就有下一種類的動態編譯器被發展出來. &lt;/li&gt;&lt;br /&gt;&lt;li&gt;Hot-Spot Compiler&lt;br /&gt;&lt;br /&gt;所謂的 Hot-Spot 編譯器, 就是指當呼叫某個函式達到一定的次數之後, 動態編譯器才會去編譯該函式. 這種架構比較複雜, 因為你要處理原本位於虛擬機器內部的 interpreter 跟動態編譯器之間的互動以及連結. 但是這種 Hot-Spot 編譯器將可以避免上述的 Just-In-Time 編譯器的若干缺點. &lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ol&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3931381955158939823-8589524740605327463?l=wei-hu-tw.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/wei-hu-tw/~4/5vZVHPkEVkg" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/wei-hu-tw/~3/5vZVHPkEVkg/cldc.html</link><author>noreply@blogger.com (Wei)</author><thr:total>0</thr:total><feedburner:origLink>http://wei-hu-tw.blogspot.com/2007/11/cldc.html</feedburner:origLink></item><language>en-us</language><media:rating>nonadult</media:rating></channel></rss>

