發表文章

目前顯示的是 十二月, 2011的文章

【Startup 談心酸】 當革命情感對上體制

我總認為,當別人問起職業,回答『Startup(新創)』是一件很自傲的事。雖然公司不大,但是從兩手空空開始,完成理想的感覺真的是棒呆了!你必需經歷『養活自己』、『勒緊褲帶』、『想破腦袋』還有『革命不怕失敗』的種種過程,最重要的是,伴隨而來的『人的問題』,很有可能成為最後一根稻草,壓垮我們。但每當跨越過每一個階段,彷彿就吃了甜美多汁的果實,相當有滋味。

常聽到有人說:『先不談成功與否,Startup能做超過一年,就相當不容易了。』,其實是事實,從創業中敗陣下來的人不在少數,敗陣的原因更不勝枚舉,有人是受不了壓力,有人把持不住Cash Flow(現金流),有人經營心態不正確,或是 idea 失敗等等。但是,這些原因真的都比不上『同伴』所造成的打擊。

如果你不是一個人創業,而是三五好友有志一同,那我要恭喜你,畢竟要能找到方向相同,又有足夠能力的人一起是非常困難的。但是,我也要為你感到遺憾,因為『人的問題』會帶來更多波折和困難,造成創業失敗的比例更高。『同伴』是個雙刃劍,雖能共患難,有革命情感,但也會因決裂而一夕之間毀滅。

這裡有一個朋友的小故事,相當常見,或許大家都很熟悉其中情節:
有一群人在學校就是好朋友,而所會的技術也讓他們相當出類拔粹,於是,他們孕釀出創業的想法。為了小試身手,這些人開始共同接一些小案子,並培養革命情感。看似一切很美好,但在過程中問題出現了,有人怠惰(或是能力不足)造成其他人負擔增加,又或者是因此造成案子無法順利結案。好不容易,其他隊員們跳出來『Cover』,讓一切過了關,客戶也付了錢。 然而,問題才正要發燒,在分配利益時,有人開始提出不滿:『為什麼出包的同伴,可以拿的錢和沒出包的人一樣多?為什麼救火的人,幫出包的人完成不是自己的大部份工作,卻只拿到原本的待遇?』此外,對工作的分配也頗有微詞,有人認為自己做的工作,相對困難許多,應該分到更多的錢。更誇張的是,每一個人都生怕別人多拿或是拿的比自己多。 還好,為了讓大家不要決裂,盡可能滿足大家的要求,有人跳出來處理這件事,除了自己掏腰包,甚至動用了原本大家講好要保留下來的『公基金』。然後發現,雖然大家都同意切出一部份成為公基金,但心中仍然認定這公基金有一部份是屬於自己的,隨時都可以要回去,有人更不時想動用或拿回這個錢。一旦動用公基金,就會牽動到大夥的神經,引發更多莫明其妙的問題。 問題並沒有因為時間…

從 Linux Kernel 出發看!探討 Process 組成結構!

對所有電腦使用者而言,執行一支應用程式就像吃蛋糕一樣簡單。對於程式開發者而言,寫支 Hello World Program 並跑起來,也是三十秒內可以完成的事。但是,這樣容易的動作,其實底層有著複雜的機制,否則短短十行程式碼的 Hello World 能夠動起來,真的是奇跡了。想要知曉程式是怎麼被作業系統執行,要追溯到 Process 的機制,在研究過 Linux Kernel 的 Process 相關機制後,一切就將明朗。

註:在本篇文章內,都將會假設 binary program 已經被作業系統解析並放到記憶體執行,說明只著重於 Process 的部份 。雖然 Process 與 binary program 和其載體息息相關,但本文不會討論 ELF 的細節,有興趣的讀者可以自己去尋找相關文件閱讀。

若你是程式開發者,對『Process(程序)』一詞應該不陌生。嚴格來說, Process 就是處於執行狀態的程式,如果參考一些原文書或英文文獻,它們也許會這樣定義:『Process is a program in execution』。所以我們可以認定,Process 的組成,是擁有著『程式執行檔的 binary code + 記錄資料的記憶體』。

本文將 Process 分成內外兩個角度來探討:
從 Process 內部,程式執行的觀點 從 Process 外部,也就是作業系統的觀點 
程式執行的觀點

單純以 Process 內部的角度來看,Process 就是一般的程式碼被放到記憶體執行。曾於舊文『Linux 下程序的記憶體映射』略為提及,一支程式擁有著數個 segments(區段),並仰賴著這些 segment 來持續運作。大致上來說,每個 segment 有不同的用途:
Code Segment - 存放主要程式Data Segment - 存放已被初始化並賦予值的全域變數BSS Segment - 紀錄尚未被賦予值的全域變數Stack Segment(Stack/Heap) - 紀錄 Process 在執行時動態註冊的變數包括 function 中的 local variable
對程式本身來說,會動態並隨機使用的是 Stack Segment,程式向作業系統(OS) 要記憶體空間後,就可以在 Stack Segment 讀寫該記憶體空間。而實際上 OS 底層的…

如何在 Debian 建置 NodeJS + Express 環境

截至目前為止,只有 Debian Sid(unstable) 提供 Nodejs 和 Express 套件可讓使用者直接安裝。但是,在 Server 的環境之下,一般都使用 Debian 5.0/6.0 (Lenny/Squeeze) 穩定版的系統,因此沒有套件可以直接安裝,唯一的方法就是自己下載編譯 Nodejs。還好自己手動安裝的過程並不困難,幾個步驟就可以完成。

安裝 Nodejs

更新系統並安裝編譯 Nodejs 所需的套件:
sudo apt-get update sudo apt-get install git-core curl build-essential openssl libssl-dev
從 Git Repository 下載 Nodejs 原始碼:
git clone https://github.com/joyent/node.git
進入 Nodejs 原始碼目錄,並切選擇我們要的版本(截至本文,0.6.6 是最新版):
cd node git checkout v0.6.6 # Note: 可以使用 git tag 看到 Nodejs 所有的版本列表
編譯並安裝 Nodejs (預設會裝到 /usr/local/lib/node):
./configure make sudo make install
如果安裝過程中沒有任何問題,就可以使用 node 指令查看 Nodejs 的版本了:
node -v
手動設定公用的 Nodejs Module 路徑:
echo "NODE_PATH=/usr/local/lib/node_modules" >> .bashrc # Note: 如果想讓所有 Server 上的 user 都套用設定,可以放在 /etc/profile

安裝 Express Web Framework

使用 npm 安裝 express(使用 -g 選項會安裝到公用的目錄 /usr/local/lib/node_modules):
sudo npm install express -g
Express 通常預設使用 jade template engine,也需要手動安裝:
sudo npm install jade -g
安裝完成後,就可以立即測試 nodejs + express:
mkdir te…

Nodejs + Express 的 Route 流程規劃

如大多數人的習慣,往往我們都把 Route 的路徑都定義在 app.js 當中。Express 所提供的眾多範例程式中,雖然有將 Route 抽出來放在 routes 目錄下的實作方式,但也太簡單,只支援一層的設計。這意味著,如果 routes 之下有更多子目錄,放著更多的 route 設定,都是不會被讀取的。

這邊做了簡單的修改,利用遞迴的做法,掃描所有的子目錄,然後去載入所有的 js 檔案以擴充 Route 的設定。

以下是 route.js 的程式碼:
var vm = require('vm'); var fs = require('fs'); module.exports = function(app) { var dir = __dirname + '/routes'; var context = { app: app, require: require }; var newContext; /* Initializing Context */ for (var key in global) context[key] = global[key]; newContext = vm.createContext(context); /* Loading all routes */ loadRouteDir(newContext, dir); }; function loadRouteDir(context, path) { /* Scanning files */ fs.readdirSync(path).forEach(function(file) { loadRouteFile(context, path, file); }); } function loadRouteFile(context, path, file) { var fullpath = path + '/' + file; fs.stat(fullpath, function(err, stats) { if (stats.isFile()) { /* Loading route */ var …

Openmoko 永遠活在我們的心中

圖片
還記得 2006 年 12 月業界出現了一個瘋狂的想法:『Openmoko 的開放手機』,但就在 2011 年 12 月滿五年,這家公司(Openmoko, Inc) 也將劃下了一個圓滿的句點。

回顧過去,Openmoko 不只是單純的軟體層面開放,而是連硬體設計的細節都公開。這對當時的大環境,高端手機技術和 Know-how 都被嚴密掌握在特定公司的時局下,無疑是個瘋狂的舉動。想當然,Openmoko 花了大量錢財與人力物力,還有國內外社群的力量,終於做出了自己的第一代手機原型(參考圖 Neo 1973),爾後又開發出第二代硬體加強版的機種(參考圖 Neo FreeRunner)。

還記得,當時大多數人都還是使用功能手機(Feature phone),智慧型手機(Smart Phone)也還停留在被難用 Windows CE 稱霸的時代,誰也還沒有想到未來會有 iPhone 和 Android Phone,對絕大多數人而言,手機是個神祕且只有少數人可以參與開發的領域。有趣的是,Openmoko 除了做開放的手機之外,也對應用程式(Apps)安裝於手機上的想法有了初步的構想,而這些想法,都觸動了不少軟體開發者和投資人的目光。

雖然直到最後,Openmoko 的手機還不足以讓一般消費者順暢使用,但許多構想,無論是開放手機,有擴充性的應用程式平台,還是使用 Linux 開發前衛的智慧型手機,都確實已深埋在不少人心中。世界各地的 Hacker 和高手,無一不想擁有這樣一台的開放手機。

Openmoko 也在教育界扎根,除了提供開發的教育訊練外,也去拜訪了許多大專院校,讓許多原本沒有機會碰到手機開發的學生和技術人員,有機會一睹這神秘的領域。然後,也有不少學校買了 Openmoko 的手機,做為開發教學使用,直至今天,這些手機還是相當好的開發教材,甚至,也已經有不少教授在這上面開發了一系列教材。(如:淡江大學資工系已經將 Openmoko 手機當成 C 語言教學和相關基礎技術的實作平台)

隨著 iPhone 的問市,Google Android 的出現,Openmoko 逐漸失去了媒體焦點,也有不少不為人知的事情,讓公司逐漸縮編並轉型(之後轉做過 WikiReader),以致現在的人,多半都只是耳聞,漸漸忘了當時 Openmoko 花大錢招頂級人才,遍布全世界的開發者和分公…

Android 問題百出之 2.3.x 的 JavaScript Interface

有鑑於 Android 問題太多,只好定了個系列標題『Android 問題百出』當開頭,並將碰到的問題和解決或避開的方法記錄在內。話說回來,筆者個人其實相當討厭 Android,自 Android 出現以來,從未真的投入其中並賺過什麼錢,會接觸,多半是興趣玩弄或是幫一些朋友的公司臨時打工救火。不過,既然是救火,任何千奇百怪的問題或狀況都會遭遇到,甚至還得『限時』解決別人解決不了的問題。

這次碰到的問題就是 Android 2.3.x Gingerbread 缺少 JavaScript Interface 的實作,如果你的應用程式有自己實作 API 供 JavaScript 程式使用,那這些 API 將會完全失效。而這樣的問題,對於使用 Web 技術(HTML5 + Javascript)的應用程式來說,相當嚴重。

話說 Android 在 2.3 版本之後,採用了 V8 做為 JavaScript Engine。在快速掃過 Android 關於 WebView 和 WebKit 的程式碼後,發現不幸的是『Google 再次未將程式寫完』。但這一次,不只是功能未完成,而是將原本可以用的功能(在 Android 2.2),變成不能用。這讓筆者非常不能理解,為何 Google 換了 V8 Engine 後,明知功能沒有改完,卻仍將這部份實作隨新版 Android 釋出?然後,絕大多數廠商,在毫無感覺之下,直接繼承了這樣的 Bug。

對硬體裝置的廠商來說,重新實作這個 JavaScript Interface 支援是最佳的解決辦法,髒一點的方法是將 V8 改回舊的 JSCore。但很可惜的是,就算有人改好了,也沒有廠商願意釋出這部份的程式碼。(所以才會不停有人願意花大錢找筆者這種臨時救火工呀。)

此外,如果你是一般的應用程式開發者,因為動不了底層,則完全無解。但是,這邊有個 Workaround,可以暫時代替 JavaScript Interface,讓應用程式開發者可以避開這問題(以下假設自定的 JavaScript Interface Class 為 myAPI)。

定義將會用到的變數:
/* Define private variable */ private static WebView mWebView; private static myAPI mJSIF; p…