發表文章

目前顯示的是 九月, 2007的文章

親手打造 HTTP 網路服務:超小 Web Server 的撰寫

今天一時心血來潮下,前後花了 30 分鐘,動手寫了一個 Web Server,這是個僅僅使用 170 行﹝若是移除空行和註解也許只有 100 行不到﹞左右 C 語言程式所寫的『超小』Web Server,只有支援 GET 命令,沒有 CGI 、虛擬目錄的其他功能。

以下是瀏覽器對伺服器一個單純的 HTTP 通訊:

GET /index.html HTTP/1.0<CF><LF>
<CF><LF>


HTTP 協定中,標準網路通訊 Port 是 80,瀏覽器使用『GET /index.html HTTP/1.0』命令來指定抓取網站根目錄的 index.html 檔案,每行指令以換行字元『\r\n』結尾,最後再一次的『\r\n』代表等待伺服器回傳資料。就這段非常單純的通訊內容而言,我寫的 Web Server,最少要能夠解析這行命令。


撰寫 Web Server 比較需要的程式技術,大概就是 Daemon、多執行緒、網路連線操作。


關於背景服務的 Daemon 程式寫法,我在另一篇筆記上有簡單記錄,應該不是什麼大問題。

而多執行緒的使用,是為了提供多使用者同時連線,我們需要同時處理眾多用戶端的連線要求,而不是等一個用戶處理完再接受下一個人連線。但是,為了不使用太複雜的多執行緒系統機制,在這程式中我改用 fork() 多行程的方式撰寫,這樣不但簡化了程式,也剛剛好讓我的 Web Server 可以在許多嵌入式系統中執行,因為多數微型的嵌入式系統,並沒有支援多執行緒。

最後一個會用到的程式技術是網路連線操作,會和寫用戶端網路程式有極大不同,因為要監聽網路卡上的 Port,等到有用戶端連線時再進行處理。其中依照流程會呼叫下面四個函式:

socket() /* 開啟網路 Socket */
bind() /* 開啟網路監聽器 */
listen() /* 開始監聽網路 */
accept() /* 等待客戶端連線 */


這 Web Server 將會使用 /tmp 當根目錄,每次有使用者連線,就會 fork() 出一個子行程去處理用戶端的要求。主要由 main() 啟動和初始化網路監聽、fork(),然後交由自訂的 handle_socket() 去解析命令和回傳資料。

Web Server 原始碼:

#include <stdio.h&g…

親手打造一個背景執行的Daemon程式

這是我在過去在 Linux 上撰寫微型 Web Server 時的筆記,目的是要讓我的程式能夠在背景執行,也就是要寫所謂的 Daemon 程式。關於 Daemon 的解釋,中文有人翻做『守護神程式』,若是對照在 DOS/Windows 系統底下的講法,就是所謂的『常駐程式』了。

Daemon 要怎麼寫呢?簡單來說:
使用系統呼叫 fork(),在背景複製一個自己繼續活下去,然後讓母體自我終結。

以下是一個簡單的範例:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

void main(void)
{
pid_t pid;
pid = fork();

if (pid>0) {
exit(0);
}

while(1) {
/* 子程式在系統背景跑無限迴圈 */
}
}
使用 fork() 後會回傳一個 pid 值,也就是行程處理 ID,這 ID 如果『小於零』,代表作業系統有問題令 fork() 失敗,無法複製生成一個新的程序。但是如果 fork 成功,會回傳零或是大於零的數字。

複製自己成功以後,需要了解的是,我們的程式有兩個正在執行,一個是母體,一個是剛被複製出來的子程式。或許你也注意到了,目前正在跑的程式是完全一樣的,要怎麼讓程式自己發現自己是本尊還是分身?關於這個問題,我們可以使用 pid 來判斷:如果得到的 pid 是『大於零』就是母體;得到『等於零』就是子程式。然後,只要讓母體自我終結就好,從範例中可以看到這段的程式判斷。

後記

這有點像電影『魔鬼複製人』的情節,在程式被複製成功以後,就告知本尊:『你該死去了。』對人來說,這是件很悲哀的事,尤其是對被複製的本尊來說。以後電腦開機前,想想你這一次的開機,會殺死多少生命,或許你就不願開機了﹝笑﹞。

讓SoundMAX Integrated Digital HD Audio在Linux唱出聲音

這幾天在一台 NB(IBM T61) 上安裝 Linux,除了這台 NB 的顯示卡在 X Server 上一定得用新版 nvidia 官方的驅動程式或是使用標準的 vesa driver 驅動外﹝註:在 Xorg 7.0 用 nv 不能動﹞,最大的問題就是聲音無法出來。我使用出廠預設的 Windows Vista 檢查硬體裝置後,發現 T61 使用的是『SoundMAX Integrated Digital HD Audio』,在陸續猜測各種聲音晶片的驅動程式下,終於成功的使用 snd-hda-intel 模組驅動聲音晶片。

以下是我驅動的過程:
modprobe snd-hda-intel
modprobe snd-pcm-oss
modprobe snd-mixer-oss
後記

由於我已經有好一陣子沒去下載使用各家 Linux 套件最新的版本使用,或許在它們新版的系統中已經解決了無法驅動 SoundMAX Integrated Digital HD Audio 的問題。

Kerrighed - 建置 Linux Cluster﹝叢集﹞的另一個選擇

說到叢集電腦(Cluster Computer),過去最容易建置的 Cluster 方案 openMosix,一向擁有許多的用戶和支持者,相較其他的專案如:OpenSSI,openMosix 對 Linux Kernel 的改動最小,而且,就它的發展歷史來看,也是取經於過去已經存在的 Mosix 架構,因此不論是在安裝建置或是可用性上,openMosix都是良好且值得一用的不二選擇。但是,openMosix在今年突然宣佈了將要停止開發的消息,這消息令許多人錯愕,也都紛紛尋找其他替代方案;就在這時候一向被認為不成熟的 Kerrighed 專案﹝http://www.kerrighed.org/﹞,在今年度開發的表現亮眼,逐漸跳脫出給人不成熟的印象。

Kerrighed 在不久前支援了 2.6.20 的新核心,也釋出了 2.0、2.1 版本,代表的是從 1.0 的概念實作,提升了到開始針對實用面的研發,並立即支援了多處理器和64位元架構的硬體。

以下是 Kerrighed 官方網站上的目前發展特色說明:


Current Features
Global Process ManagementCluster wide PIDsProcess migration with open files, pipes, sockets, shared memory segments, etc.Mosix-like global process scheduler.Full cluster wide UNIX process management interface (ps, top, kill, etc).
Global Memory ManagementSupport for distributed system V memory segments.
Checkpoint / restartCheckpoint/restart of single processes (EXPERIMENTAL)
Kerrighed 在網站上的研發行程表示,將在年底改進執行程序轉移的效能,更會在明年增進數個關於記憶體、檔案暫存等特色,值得另人矚目。

後記

我將會在有空的時候詳細測試 Kerrighed 的能力,若有更多相關心得和問題,也將陸續記錄下來。

考作文必背的一段『論小人』

雖然還沒決定要搬去哪,但這個月是確定要搬家了。所以一有空就整理東西,不管是硬碟裡的資料,還是桌上書架上的資料。不過有趣的是,最近翻到了高中時所記錄的一段『論小人』文章段落。還記得,當時看到了一篇名叫『論君子與小人』的文章,作者我忘記了,其中講到小人這段當時實在是讓我覺得,如果寫作文時用出來一定非常的逗趣而且很酷,所以我當時就記錄下來並背了一小段。

小人者,心邪性乖,巧言令色,刻薄奸詐,投機取巧,慣用媚騙,愛占便宜,坐井觀天,妄自尊大,口是心非,狡滑無信,幸災樂禍,損人利己,驕奢淫佚,寡廉鮮恥,愛拍馬屁,喜獻殷勤,只知貪利,不知修身,只知利己,不知利人,記人之過,忘人之功,記人之仇,忘人之恩,不識大體,不顧大局,只顧眼前,不顧後果,患得患失,禍國禍民,尤其對人用心險惡,處處虛偽,對事強詞奪理,歪曲事實,對時愛弄玄妙,故意爽約,對地得寸進尺,任意侵占,對物無所不欲,任意貪求,性好動而不好靜,心望亂而不望治,且喜道他人之短,誇耀自己之長,其容貌不足以動人,其言語不足以眩世,雖具人類之面,確為禽獸之心,常蓄有違法亂紀之想,專門作傷天害理之事,寫匿名信,打小報告,成事不足,敗事有餘,有如此奸邪之心,醜惡之行者,可謂之真小人矣。
可惜的是,我們已經不是過去的八股年代,君子小人這種考試作文題目,早已經絕種。這段形容小人的文句,我看現在也只能截取精華片斷來罵人了﹝笑﹞。

跨入 Web 2.0 的時代!讓網站支援 RSS 即時書籤

曾經燒光了全世界投資人的錢,導致網路泡沫化的那群人,在他們臨死前的那一刻,喊出了 Web2.0 口號,他們企圖想用這新的名目來延續自己的燒錢事業。可是所謂的 Web 2.0 在技術上真的有重大突破嗎?答案是否定的,其實它與傳統 Web 只有觀念不同,所使用的技術並無多大改變,舊內容新包裝,完完全全是專門拿來詐騙股票投資人的幌子。但無知的媒體炒得沸沸揚揚,還以為 2.0 意指的是 Web 在技術上有所重大突破。

Web2.0 到底是什麼?事實上,Web2.0 指的只是網路發展的趨勢 - Service 導向,主要訴求是讓網路用戶選擇需要的專業服務,意即網路用戶將不再於網際網路上到處閒逛網站,而是會選擇專門的服務使用,例如:MSN即時通、 Blog、網路相簿、拍賣網、新聞網、Google搜尋。Service 導向的網站將提供專門的資訊給用戶,每個網站的功能很明確直接。另外,還有一種常見的應用,就是提供使用者做建立數位內容和交流的服務,以使用者提供的資訊當做網站主體。

雖然 Web2.0 這名詞只是炒股票用的,可是 Web2.0 推出後,確實改變了許多技術人員的思路,以 Web 2.0 所謂的 Service 導向設計了很多的應用技術。RSS即時書籤就是項目之一,它與傳統的『我的最愛』和『書籤』﹝bookmark﹞不同,除了提供原有網站書籤記錄功能外,還擁有自動更新資訊的能力,用戶不必再一一自行檢查各大網站是否有更新,任何的更新資訊將可以透過RSS傳遞到網路用戶的瀏覽器上,因此RSS即時書籤在即時新聞上有著很大的應用價值。因為使用了 XML 當資料標準格式,RSS獲得了可攜性高的優點,除了可以在電腦瀏覽器上,各種通訊裝置上也都可以使用。

一個簡單的例子讓網站支援 RSS 即時書籤

RSS即時書籤是建構在 HTTP 通訊協定之上,並採用 XML 當資料標準格式﹝傳統網頁是以 HTML 當資料標準格式﹞。

要使用 RSS 即時書籤必須先建立一個 XML 檔案:
<?xml version="1.0"?>
<rss version="2.0">
<channel>
<title>我的RSS</title>
<item>
<title>新…

PC 作業系統實作馬上入門

最近在整理過去的許多筆記,看到了很多懷念的東西,尋思當初許多的瓶頸,都缺少一個人幫我打通任督二脈,讓我一路走起來倍感艱辛,雖然不後悔這樣沒章法的強幹式學習,但許多冤枉路我心裡明白是白走了,尤其在作業系統這部份,對大多數人來說,更是不易突破的關卡。因為,看程式方面的書籍它不會教你,看硬體架構的書又不告訴你程式實作,如果想自己融會貫通,又因為沒有良好的入門範例,不知道該注意哪些事項而挫折連連。

開始前,你要有個體認,我們要寫的是作業系統,整台電腦都將由我們的程式完全控制,所以,如果你的程式不正常,將會落得停格當機下場,沒有『程式關閉,請聯絡...』或是『Core...』這套。另外,不要想說有任何 API 可以用,你都要一一自己打造這一切,因為系統開發本來就是一件辛苦的事,你正在開拓一個沙漠的綠洲。

而大多數人在學習作業系統撰寫時,常都會卡在第一步:我要如何讓自己的作業系統啟動?然後如同第一次學寫程式時,出現一行 Hello World?當初的我也在這問題上打轉好一陣子,縱使我會組合語言、有過不少寫程式經驗、看過許許多多的相關書籍,但我還是不知道該從哪開始。


我們先來了解電腦啟動的流程:
電腦開啟電源,會啟動 ROM 裡面的 BIOS 執行硬體檢查和初始化。BIOS 會依序搜尋 BIOS 設定中的啟動裝置(Boot Device),如硬碟。一旦在某個啟動裝置上發現了啟動磁區(Boot Sector 大小為 512 Bytes),就會將此磁區 512 Bytes 的程式載入到記憶體位址 0000:7c00BIOS 會跳到記憶體位址 0000:7c00 執行被載入的程式,並將執行權全權交給它。

以下是一個 512 Bytes 的簡單開機程式實作範例﹝組合語言﹞:

org 07c00h ;此程式將被載入到 0000:7c00 執行
mov ax, cs
mov ds, ax
mov es, ax
call Disp ;呼叫 Disp 顯示字串
jmp $ ;無限回圈

Disp:
mov ax, BootMsg
mov bp, ax ;指定 BootMsg 的位址
mov cx, 1…

喉嚨都要生豬豬﹝蜘蛛﹞網了

久違了 KTV 的我,在這個暑假期間精打細算下,光單單一個月就去 KTV 少說有三十幾次﹝汗﹞。大家都知道,一個月不是只有31天,怎麼會三十幾次?騙肖!我的解釋是,因為有時候是一天兩攤,所以才會三十幾次了!你可以說我是個瘋子,因為正常人是不會這樣天天唱的。

回想以前高中時,喜歡一群人去歡樂,一度迷上了 KTV 內狂歡的感覺﹝我不吸毒,我唱歌中毒。笑﹞,每次一有空、大考一考完、慶祝、慶生,就會和朋友去好樂迪報到,只有兩個人去唱也是常有的事,唱到最後都沒聲音了。那鬼叫胡鬧的年代,看似荒唐,但卻開啟了我與唱歌的不解之緣。

再來看看現在,其實之前我已經有一年半左右不曾去唱過歌,這段日子裡,我把去唱歌狂歡的癮給戒掉了,真的一度以為,我不會再是 KTV 的常客了,但最後事實不如我所預料的。就在兩個多月以前,也就是暑假開始前,一次大學朋友的慶生會中,再次勾起我過去唱歌的回憶、激情與瘋狂。讓我發現,其實這些是我一直無法忘卻的。於是,我在這暑假中,計劃一群過去的狂歡人馬,密集的到好樂迪報到﹝好樂迪暑假有特價方案﹞,去到幾乎都快要把每一家店的價格背起來了。這一去,從當紅的歌曲,到有些年紀的,再到老到不行的老歌﹝『月琴』我的最愛 XD﹞,都一一都點出來被我們摧殘。但話又說回來,許多戰友的喉嚨也都被摧殘得體無完膚而陣亡,讓我必須不停的去招齊人馬補上。

暑假結束的日子慢慢逼近,隨著好樂迪的價格也慢慢回調,我也開始厭倦了這段狂飆的日子,停止了這場無止盡與喉嚨的戰爭﹝不會壞的嗓子戰勝了心理的欲望﹞。但我還是太小覷了我心裡的唱歌大怪獸,在這幾天短暫的平靜日子,牠已經精力十足又準備爬出來大肆胡鬧一番了。

遠傳 3.5G 山頂洞人專用的大頻寬

遠傳 3.5G 是欺騙消費者的東西,我個人稱它為山頂洞人專用的大頻寬。因為,你要到越遠越偏僻的地方,最好是山頂上﹝前提要收得到訊號﹞才會有一流的速度!雖然遠傳號稱能 3.6M,但實際上半數時間比他的 2G 網路服務還要慢!不信嗎?騙你是小狗!

原因是因為 3.6M 只是你的網卡、手機與基地臺的傳輸速度能到這麼快,並不代表基地台對外的網路線路能提供這麼快的速度。經過在三的定點測試,其實從基地台對外的頻寬根本少得可以!只要同一地區用的人一多,速度別說比 2G 慢,56K 撥接都可以被稱為超大寬頻了!嚴重時甚至會有封包 Lost 的情況﹝在命令字元模式輸入 ping 168.95.1.1 會發現很多 Timeout 的情況﹞,簡單來說會導致根本無法上網!

尤其,這個月來遠傳主推 3.5G,使用者大量增加後速度的降低和不穩定更為明顯!半夜的平均下載速度從之前的200KB以上,掉到現在最高只有30KB左右(約240Kb),白天有15KB就要偷笑了,平均是7~9KB﹝在板橋江子翠測試的結果﹞,用中華電信的網頁測速,你還有機會看到難得一見的下行 3KB(24Kb)奇景。同一地區所有人分享那基地臺小小的頻寬,線路整個就塞爆﹝因為大家都讓它吃到飽﹞!

結論是辦 3.5G 根本就是白白繳錢給遠傳,根本分不到多少頻寬,你不會有吃到飽的感覺。除非,你是需要到處趴趴走上網、或住非鬧區的人﹝如果你是住在超級鬧區就不在此限,因為使用者多,遠傳自然配較多的網路頻寬在那﹞,不然,請不要退掉你的ADSL、更不要去辦遠傳的 3.5G。不旦會被綁約兩年,線路改善前的這幾個月你都會用得極痛苦!

後記

打電話去遠傳客服是沒有用的,他們會先告訴你在不同區域速度會不同,不然會說他們工程師會處理,弄到最後,不但問題沒解決,你還是要繼續繳費。用 3.5G 跑得比 2G 還慢,遠傳是把消費者當笨蛋嗎?

正在考慮轉移原本的 Blog 到這來

我並不是嫌棄原來在 blog.twpug.org 的 Blog﹝由此連入﹞ ,事實上,我反而非常喜歡它。一方面是它的網址和整個系統沒有商業的氣息,多了一分與世無爭的感覺﹝這也是為什麼我當初去申請的是它而不是無名、雅虎的原因﹞;另一方面,整個系統非常順暢快速﹝大概是只有我一個人在那發表文章吧XD﹞。只是,最近自從加入了 PostgreSQL 中文社群網誌的作者群之後,經常登入 Blogger ,也因此順便申請了它的 Blog。把玩的過程中,發現 Blogger 提供許多完整的功能模組,和完全可客制化的樣版架構,令人耳目一新。

但這陣子下來,發現在 Blogger 和 TWPUG Blog 兩邊跑實在是累人,一下弄完這邊,又要去管另外一邊。在疲憊之下,轉移原本的 Blog 到這來的想法就產生了,我必須要擇其一。一邊是複雜又商業化的環境,一邊是簡單平庸的世界,真是難做抉擇!

PL/pgSQL:呼叫函數、SQL查詢與回傳值處理

使用 PL/pgSQL 不外乎就是撰寫資料庫的預儲程序(Stored Procedure)、函數(Function)、觸發器(Trigger) 等。設計這些內部程序,其中除了迴圈、真假值判斷、回傳等等特別需求的語法外,主要的內容還是由各種 SQL 查詢命令或是呼叫其他已存在的函數所構成。由於使用 PL/pgSQL 呼叫其他函數或執行SQL命令時,多半是要等待回傳值、資料列並更進一步處理,所以與平時用前端程式或SQL命令列對函數與SQL指令的操作上,有比較不 同的習慣性用法。要了解在 PL/pgSQL 處理各種呼叫查詢,必須從回傳值處理的角度去深入。

以下是幾個常用處理函數和SQL命令回傳值的方法:

將回傳資料列指向 rs 變數﹝將 rs 定義為 record 類型﹞SELECT * INTO rs FROM mytable;

然後可讀取回傳資料列的各欄位內容:

rs.id
rs.name
rs.address
...

註:此 SELECT INTO 使用方法很特別,並非是你想的那樣,請參考下文說明。


只回傳單獨欄位內容並指向 addr 變數﹝將 addr 定義成與 address 欄位類型相同﹞
SELECT address INTO addr FROM mytable;


拋棄所有查詢和函數的回傳值EXECUTE myfunction();
PERFORM myfunction();

註:EXECUTE 和 PERFORM 的詳細差異不在本文討論範圍,請參考官方說明文件。


一般來說,在 PL/pgSQL 之中我們還是可以照常使用 SELECT、UPDATE、DELETE 等指令,差別在於執行查詢命令時『有無回傳值』。另外,以下有幾點,是使用 PL/pgSQL 呼叫及執行任何 SQL 命令時該注意的重點:


任何命令所回傳的值不能隨便忽略

在 過去使用前端外部程式去執行 SQL 命令,你可以忽略不管回傳值的問題,就算有回傳任何資料,我們也可以省略不處理它;但在 PL/pgSQL 中就有所不同了,尤其在『觸發器(Trigger) 』函數的設計中,更是不可放任回傳值不處理,所以,通常在觸發器中我們如果要拋棄回傳值,請使用 PERFORM 。


SELECT INTO 的不同

在 PL/pgSQL 與平時使用 SELECT INTO 是完全不同的意義,後者是建立一個新的資料表,並將所查尋到的數個資料列寫入此資料…

研發人員的心態

上個月初,Linux 的父親也就是 Linus ,對核心的未來做了一個重大的決定,也就是選擇了 CFS 這個在短短 62 小時內就被開發出來的行程排班器。這個決定讓大家熟知的 ck-patch 其創始者就此和 Linus 槓上了,因為 ck-patch 中包括著一個 SD 行程排班器,雖然經過多年的努力,卻一直遲遲無法被正式納入 Linux 核心;可是才短短的幾天之內就被完成的 CFS ,馬上就被 Linus 採用並準備納入下一版的核心之中。雖然 Linus 有充份且良好理由選擇 CFS 並放棄 SD,但這對於一個努力為自由軟體付出多年的程式研發人員,無疑是最大的打擊。

這個事件的確值得令人省思。由 Linus 放棄 SD 的理由可以知道,其實有很大的因素是程式人員的心態:

Linus 批 ck-patch 的創始者 Con kolivas 面對使用者回報的問題,總是爭論對抗,不肯用心與用戶一同解決,認為自己是正確完美的。


不只是在國外,國內企業裡 RD、研發工程人員和老闆之間也總是存在著相同的問題,老闆回報的問題和意見總是被研發人員駁斥爭論,一些無奈的老闆也只能暗自恨己不是專業人員,而有魄力的頭家在一氣之下乾脆就把整個部門給裁了。

暫且不論企業中的點點滴滴,相同問題在國內的自由軟體界也是存在著。面對著許多過路客的問題,也總是激烈爭論對抗,就因為他們不是使用自由軟體、他們對自由軟體存有疑慮或誤解。


我只能說,研發人員們,你們真的嚇到他們了!


另外一件有趣的事順帶一提,CFS 其實是我的中文姓名縮寫,其中更引伸了一段小小故事。

在多年前,我還是清純國中生﹝笑﹞的時候,就曾妄想寫一個如同 MD5 ﹝當時被資訊界視為非常安全的加密方法﹞一般的單向加密程式。正好,當時我正在經營一個 ASP 的相關技術網站 - ASP技術廣場﹝不知道還有誰記得?:p﹞,我理所當然的就直接使用 ASP 寫了一段當時覺得很棒的加密程式﹝現在回頭看,真的是覺得很丟臉!﹞,整個開發的時間就如同 CFS 排班器一樣,很短,大概只花了62分鐘﹝笑﹞,最後這個加密方法當然也叫做 CFS。

到這裡都還沒什麼,之後,我開心的將這 CFS 加密函式放在網站上供所有人下載使用,並寫了一篇教學文章教大家如何用它,這篇文章標題是:『加密處理使密碼更安全[CFS編碼加密] 』,常逛大陸網站的人或許有些印象,沒錯!你現在從 Googl…