顯示具有 程式設計 標籤的文章。 顯示所有文章
顯示具有 程式設計 標籤的文章。 顯示所有文章

2012年11月16日 星期五

Blogger 嵌入 Facebook Comments 留言板功能教學


最近看了很多網誌和新聞網頁,下方都會有個 Facebook 的留言板,一時興起也想來弄一個。

用 Facebook 留言板的好處是,FB 帳號比較像實名制,善良的使用者也只有一個Facebook帳號,有名字和頭像,大家比較不敢胡亂留言,減少垃圾留言或機器人洗版的可能。而且留言者可以順便貼到塗鴉牆,等於間接提高文章的曝光度,而且他塗鴉牆朋友回覆他的留言時,原來的這邊的留言板也會同步在此顯示,我覺得這超棒的!等於我的網誌直接從 Web2.0 無痛升級成 Web3.0 了!而我認為社群的核心概念,就是建立在這種無私的分享與良性互動的討論上面。

用 Facebook 留言板的壞處是,畢竟是你介接別人的東西,萬一有一天 Facebook 不爽給你用或甚至倒了,所有留言就會歸零(別說不可能,我當初也以為 Facebook 可以永久快快樂樂使用下去,但直到有一天他無預警的停用我帳號後我才恍然大悟,免費的服務,他才是老大,朕賜你的,才是你的,朕沒給的,你不能要!)。再來就是沒有臉書帳號的人就無法留言(這問題倒是還好,這年頭可能家裡的小狗或陽台的盆栽都有 Facebook 帳號了),最後就是留言的管理問題,基本上你是沒有權限刪除任何一則留言的,就算設了後台管理介面頂多也只能隱藏留言(就跟陳懷生少校一樣,看不見可是他依舊存在),他本人和他的朋友還是都看的見,別問我為什麼,因為你是借用別人的,臉書才是老大,規則他說了算!

原本以為是很簡單設定的東西,但是到真正完全搞定還是花了不少功夫。原因在於研究一些網路上的教學文章,發現隨著 Facebook 不斷的小改版,很多文章都已經不合時宜了,所以才會多花點時間在 try&error,在此還是把我成功的步驟經驗分享一下吧。


在此分為兩種版本,一個是「超級簡易版」,一個是「後台管理版」。「超級簡易版」就是沒有管理功能的版本,把程式碼複製貼上就馬上能用了,適合跟這種有字天書的程式碼不是很熟的朋友。另一種「後台管理版」則設定複雜很多,但好處就是具有管理模式,可以把不想看到的留言給隱藏起來,眼不見為淨,適合喜歡掩耳盜鈴的朋友。


超級簡易版

1. 在 Blogger 後台的「版面配置」找一塊你想放留言板的地方「新增小工具」,類型選擇「HTML/JavaScript」,然後把下面程式碼複製貼上到內容區塊。

<div id="fb-root"></div>
<script>(function(d, s, id) {
  var js, fjs = d.getElementsByTagName(s)[0];
  if (d.getElementById(id)) return;
  js = d.createElement(s); js.id = id;
  js.src = "//connect.facebook.net/zh_TW/all.js#xfbml=1";
  fjs.parentNode.insertBefore(js, fjs);
}(document, 'script', 'facebook-jssdk'));

document.write('<div class="fb-comments" data-href="'+document.location+'" data-num-posts="5" data-width="470"></div>');
</script>


像這樣新增一個 HTML/JavaScript 的區塊
2. 按下「儲存」和「版面配置」頁的「儲存排列方式」,搞定!(註)


後台管理版

1. 取得應用程式 ID
首先要去 Facebook 開發人員網頁建立一個新的應用程式(可按我前往),按照網頁的步驟一個個過關斬將輸入完成,而 Website with Facebook Login 那邊記得順便填入你的網誌首頁的URL,總而言之,言而總之,最後就是要取得所謂的應用程式 ID (APP ID)就對了(若有申請好應該可按這裡找到)。


2. 取得帳號ID
再來就是要取得管理者也就是自己 Facebook帳號的 ID,方法如下:


Facebook查看個人首頁,如果網址是以下這種,那數字部分就是你的帳號ID
http://www.facebook.com/profile.php?id=數字

如果你的個人頁面網址是長的像以下這種
http://www.facebook.com/帳號名稱

代表你的個人首頁已經命名過了,那請將上面的「帳號名稱」代入以下的網址進入
https://graph.facebook.com/帳號名稱

進去後會看到「"id":"數字"」,那串數字就是你的帳號ID。


3. 在 Blogger 後台的「範本」->「編輯HTML」->「展開小裝置範本」打勾,開始艱辛的修改程式碼的步驟(變動前最好先將整份範本備份一下)。

(可按下Ctrl+F)搜尋 "<head>" (是""裡的字串不包括""),在這行下方新增一行貼上這兩行:(記得帳號ID和應用程式ID要置換成你剛剛取得的)

<meta property='fb:admins' content=' 你的帳號ID ' />
<meta property='fb:app_id' content=' 你的應用程式ID '/>



4. 搜尋 "<body" (是""裡的字串不包括""),在這行下方新增一行貼上以下的程式碼:

<div id='fb-root'/>
<script>
    window.fbAsyncInit = function() {
        FB.init({
            appId  : '你的應用程式 ID',
            status : true, // check login status
            cookie : true, // enable cookies to allow the server to access the session
            xfbml  : true  // parse XFBML
        });
        FB.Event.subscribe('xfbml.render', function(response) {
        });
        FB.Event.subscribe('auth.sessionChange', function(response) {
            // 當 Facebook session 改變時通知
        });
        FB.Event.subscribe('edge.create', function(response) {
            // 當有人按讚時通知
        });
        FB.Event.subscribe('comments.create', function(response) {
            // 當有新留言時通知
        });

    };
(function(d, s, id) {
  var js, fjs = d.getElementsByTagName(s)[0];
  if (d.getElementById(id)) return;
  js = d.createElement(s); js.id = id;
  js.src = "//connect.facebook.net/zh_TW/all.js#appId=你的應用程式ID&amp;xfbml=1";
  fjs.parentNode.insertBefore(js, fjs);
}(document, 'script', 'facebook-jssdk'));</script>


注意要把程式碼裡頭的兩個 "你的應用程式ID" 給置換掉,這個步驟的目的是初始化你的Facebook JavaScript SDK 還有註冊一些事件,當有人按讚和留言時,才會在你(管理者)的 Facebook 通知頁面通知你唷!

5. 最後一個步驟就是在想要放 Facebook留言板的地方放上程式碼,通常建議都放每篇文章結束後的下方,所以我們可以搜尋"<b:includable id='comments' var='post'>" (是""裡的字串不包括""),找到這個位置,在下面新增一行貼上這行:

<div class='fb-comments' expr:href='data:post.url' data-num-posts='5' data-width='650'/>

注意 data-num-posts 後面的數字代表你想要最多顯示幾則(若有更多則下方會出現「顯示更多...」), data-width 後面的數字則代表留言板的寬度,這兩個數字都是可以按照個人偏好自行改變調整的。

最後按下「儲存範本」,沒有錯誤的話就大功告成了!


那,如何知道有沒有成功呢?如果留言板出現如下圖那行「公開的回覆」、「管理模式」和齒輪的「設定」按鈕,就代表具備後台管理功能了!

比「超級簡易版」多出上面那行
而我們辛辛苦苦這麼多做這麼多步驟,無非就是為了可以管理呀(不然就用超級簡易版就好了)!按下「管理模式」切換到管理頁面就可以隱藏你不想出現的留言了,或者你也可以去專屬的後台網站去管理,網址是:https://developers.facebook.com/tools/comments

若你需要有人一回覆留言或按讚都要通知你的話,可以點右上角的齒輪「設定」去把你的臉書帳號設到版主那一欄,最後記得按下方的「儲存」即可。

如上圖藍色部分,如果前面的設定都OK的話這塊 Debugger 區是會抓的到正確的資料的,如果這塊有奇奇怪怪的錯誤資訊,代表你有哪個地方沒設對,可以去 Debugger網站抓一下 bug,網址是:https://developers.facebook.com/tools/debug 。如果這網址下面有任何紅色Error區,代表你有哪個環節有問題,請自行照上面的錯誤提示去修改囉!修改完再測一次,紅色區塊消除的話,代表設定成功囉!
這個Debug網頁可以協助判斷應用程式有無設定成功


以上的步驟和程式碼,我是參考最新官方網站的步驟去實做的,保證2012年底前有效,之後若臉書老大不爽又有變動,當然以官方為準囉!


註:如果使用「超級簡易版」用「新增小工具」排放的位置怎麼樣都不滿意,還是想放到每篇文章結尾的下方的話,還是可以的!只要多做「後台管理版」步驟5.的部分,搜尋"<b:includable id='comments' var='post'>" ,然後在下面把「超級簡易版」的程式碼複製貼上就可以了!



2012年11月9日 星期五

[iOS] 關於 App States & Multitasking 與 Push Notification 機制心得

最近主管問起 iOS 的多工機制和 Push Notification 的機制,在回答之餘,趁機整理一份到自己的網誌,備份一下以備不時之需。

Q:關於 iOS 的 App States有哪些? 
A:

APP States 變化關係圖


iOS 在 iOS4 支援多工後,APP 的生命週期主要分為 Foreground(前景)、Background(背景)、Suspended(暫停) 三種狀態。 一般的APP在離開 Foreground 時會被推到 Background,會有一段 X時間(大約是數秒)是可以在背景執行一些 code,然後 OS 就會再把 APP 推到 Suspended。

那段X時間是非常短暫的,只能讓你做些必要事件處置(Finite-Length Task),例如儲存 user data 或 APP 的 state information 等等。

APP 從 foreground 移動到 background 的流程圖


Q:關於可長時間 Background 下可執行的 Task 有哪些? 
A:

承上題可知, APP 在 Background 下的時間是非常短的,只能迅速執行一些必要的 APP 狀態資料儲存(以便將來回到 Foreground 可以回復到先前狀態),但有某些 OS 特別允許的 Task 是例外,這些 Tasks 是可以長時間佔用CPU運算資源而一直處於 Background 狀態下的唷!

iOS 可「長時間」在 Background 下可執行的 Task,我記得主要有以下三種:

1. audio (例如音樂播放器,再按 Home 鍵回主畫面後音樂可持續播放)
2. location (例如導航軟體或行程軌跡記錄軟體)
3. voip (例如 Skype、Viber等 VOIP 軟體)

但後來看了一下官方文件,他後來又新增了以下幾種: 

4. newsstand-content (官方雜誌架APP的內容背景下載)
5. external-accessory (連接外部裝置保持持續作用,例如跑步時外接心跳頻率機)
6. bluetooth-central (保持藍牙裝置連接性)
7. bluetooth-peripheral (保持藍牙周邊裝置連接性)

無論如何,「只有」以上的 tasks 才被允許長時間在 Background 執行 (其餘的都不被允許!)且需要先被註冊,其方法是: 在APP內的 Info.plist 新增一個 UIBackgroundModes 的 Key,然後 Value 以 Array 形式填以上有用到的 task string (例如audio)。


Q:收到來自 APNS 的 Push Notification後APP可如何處理? 
A:

將 APP 開啟至前景後,該 APP 始有權限處理 Push 內容。細節來說,當收到 Push 時只可能有兩種可能:
Case 1 : APP尚未被執行過
Case 2 : APP執行過 (無論正在 Foreground 執行或在 Suspended 狀態)

Case 1 :
點擊通知訊息開啟APP後會呼叫「application:didFinishLaunchingWithOptions」這個method
- (BOOL)application:(UIApplication *)app didFinishLaunchingWithOptions:(NSDictionary *)launchOptions;

然而 Push Notification 的 Payload 就存在 launchOptions 裡頭,可在此 method 去做你想要的處理
他是個 NSDictionary,可用 UIApplicationLaunchOptionsRemoteNotificationKey 這個 key 去取值…
譬如:
NSDictionary* userInfo = [launchOptions objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey];


Case 2 :
點擊通知訊息開啟 APP 後會呼叫「 application:didReceiveRemoteNotification」這個method

- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo;

Push Notification 的 Payload 存在 userInfo 裡頭,可在此 method 去做你想要的處理
也可以根據 APP 的現在狀態(是在前景或背景)分別去做不同的處理
譬如:

- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo
{
    if ( application.applicationState == UIApplicationStateActive )
        // app was already in the foreground
    else
        // app was just brought from background to foreground
    ...
}


以上這只是我個人的理解,如果路過的網友發現我有說錯的地方,也歡迎留言指正,謝謝!^__^


參考官方文件來源:
  1. App States and Multitasking
  2. Scheduling, Registering, and Handling Notifications


2010年11月4日 星期四

Nokia Qt Hands-on Course 研習課程心得

超級潮的penk講師
主管指派我去參加10/21這一天 Nokia Qt 的研習課程,地點是在很遙遠的宜蘭大學。我之前從來沒去過這間大學,查了一下原來是在我最不熟的宜蘭市,這樣晚上要怎麼去礁溪泡溫泉或去羅東夜市吃小吃呢?出發前又在猶豫到底該開車去還是搭車去?眼看著陰雨綿綿的天氣,這場雨不知嚇到何時方休,不管了,還是坐火車去吧!

後來事實證明我果然有先見之明,10/21也是梅姬颱風來台的日子,我恰好跑到宜蘭去見證了這百年罕見的水災,沒開車去是對的,車子開過去鐵定是泡水的,況且我買的又不是牛頭牌的「神車」(神舟?)可以當做水陸兩棲的潛水艇(見證神車的影片可以看這裡或在Youtube搜尋「凡那比颱風~淹水記」)。

略微遲到的到了教室後,發現人還挺多的,我想大部分是宜蘭大學資工系所的學生吧(畢竟是他們主辦的),就當主講的老師要開始開場白時,我向後一瞄,我的主管赫然出現了!!這可嚇壞我了,還好我旁邊的位置已經坐滿了,他就只能坐在比較偏後面的位置。

NOKIA在開場白的時候說到他們是芬蘭公司,北歐人比較隨性,天性浪漫自由(freestyle?),所以在他們自家的Symbian OS上一直沒有一套很完善的開發工具,一直到Nokia併購Trolltech後有了Qt......(我心裡OS:這是啥藉口阿?也難怪Qt還是這麼難裝...當初裝Qt_SDK再加上Nokia_Qt_SDK這兩套一起裝可折騰死我了...)

而他們這次請的是一家叫MOVIAL的芬蘭公司的Penk Chen(陳品勳)講師來做NOKIA的開發工具Qt Development Kit的教學,他可長得超性格的,穿一襲黑衣服又綁個大馬尾,猛一看我真的以為莊圓師父也來教Qt了,我一直很期待他講到一半忽然拿出小劍出來跳一段天帝Qt劍頓戰幻舞! XD

不過很可惜的他沒有跳頓幻舞,但他說話還是蠻幽默的,很多話都一直戳中我的笑點,只不過台下不是學生就是阿宅工程師,反應都很冷漠(我想主講人若換成隨便一位NOKIA的展場ShowGirl台下應該就會超熱烈的吧,哈哈)。然後花了整整一個早上竟然只是在安裝開發環境(VirtualBox+Ubuntu+Qt)和設定,這不是在來之前就要裝好的東西嗎?而且Qt SDK本來就有windows版的為啥要這麼麻煩呀?好吧!只好告訴自己這一切都是為了Meego,因為據說SDK for Meego只有在Linux的環境下才有。(結果第二天才是Meego的課程,根本沒上到阿阿阿~~)

吃了便當到了下午,好棒阿!終於要開始「hello world」了。我們一字一字的寫好main.cpp,再寫好hello.pro,再打qmake hello.pro編譯project檔,最後再打make去build整個project,終於跳出了裡頭有"hello world" label的視窗了。我發現老師這時眼角泛著淚光,應該是覺得超感動的,想不到這平常像吃飯喝水一樣簡單的東西,到現場要帶領大家實做到這一步竟然要花這麼大的力氣阿!(他說賈柏斯他們都是「Never Live Demo」,寧可都播放預錄好的影片,因為你永遠不知道現場會出什麼狀況,不過penk他現在是「Live Coding」境界可就更高了!哈哈!)

然後,終於,有獎徵答的時候到了,他出了一題小習題,題目就如下面的圖片所示,要做個Slider bar和SpinBox的UI,兩者的值都要可以改變,但彼此的顯示的值都要是同步連動的,前三名做出來的會贈送NOKIA牌的「超大超粗」原子筆 (超大超粗老師有特別加強語氣 XD)。


這很明顯就是兩個connect彼此的SINGAL和SLOT可以搞定的事情,而且提示通通在投影片上了就是valueChanged()setValue(),老實說真的要加的code差不多四五行而已,一下就可以寫完了,程式碼大概像這樣:

(重點就是加了30~35這幾行,還有40、41行記得把它add到layout裡面)

我其實沒有很想要那隻筆也沒有想舉手的,但是我瞬間轉念一想:這麼簡單的問題如果不舉手,主管會不會以為我不會阿?!那他會不會以為我平常上班都在混阿?那我豈不是黑掉了?那我今年的考績豈不是糗了?那我的人生豈不是完蛋了?我越想越深就越覺得恐怖,我發現我的右手不爭氣的在顫抖中舉起來了!!!


於是,我得到了一支黑色的「NOKIA牌超大超粗」原子筆。


後來又教了多國語系的製作,這部份我倒覺得很新奇有趣,也是我此行最大的收穫,因為我一直不知道Qt裡面的「Linguist」是幹什麼用的,原來他就是「Qt語言家」讓你方便設計多國語言的工具,只要在程式碼裡面的QString字串都用tr()包起來,就可以在這裡頭找得到。作法步驟大致如下:

1. 在你的程式碼把所有用到的字串都用tr()包起來
2. 在hello.pro內加上一行「TRANSLATIONS += hello_zh.ts」
3. 輸入指令「lupdate hello.pro」用lupdate 來產生hello_zh.ts檔 (lupdate應該在Qt\bin\裡面找的到)
4. 輸入指令「linguist hello_zh.ts」用linguist 來開啟hello_zh.ts編輯,你會發現tr()包的字串都找到了,就在此編輯你要的文字(這裡就不多說了)
5. 輸入指令「lrelease hello.pro」用lrelease 來產生hello_zh.qm檔 (lrelease 應該也在Qt\bin\裡面)
6. 如果.qm檔已經順利產出,其實已經大功告成了,接下來只是在程式內吃的語系設定,就像這樣:(其中 QLocale::system().name()就是自動抓系統設定的語系來決定要用哪一套語系檔)


課程的最後,又出了一個小題目來當做ending,這次第一個答對要送的是本次課程中的最大獎,「NOKIA最新N8戰鬥超宅藍色POLO衫一件」!哇!本日最大獎耶!老師說這上面有OVI、還有杜比、還有HDMI等狗皮貼紙,穿出去可以說「我的度量有1080P這麼大」(很冷,乾脆說我的X頭有12百萬像素,還是蔡司鏡頭的好了...)

題目是要做一個Yes/No確認關閉視窗的對話方塊,這題目乍看起來好像有難度,但其實還是三四行解決的東西。原因在於Qt Creator本身就是一個很強大的GUI編輯器,類似這種Dialog都有一個個寫好的Class,只要套用就好了。於是我飛快的用了QMessageBox寫下了下面的code:


然後害羞的我就開始花了數分鐘,猶豫到底要不要舉手。不過想要超宅藍色POLO衫的慾望很快的克服了我內心的恐懼,我還是舉起了手請老師來看......喔耶!PASS了!POLO衫入手!也終於結束了一天的課程。此時梅姬颱風的狂風暴雨不停狂洩而下,宜蘭大學的操場早已是汪洋一片,學生也早就在三點就停課回家了,只剩我們這群不知所措的阿宅們還在學校裡奮戰。

今日戰利品

由於這是兩天的課程我們是早有安排住宿的,我和同事們到預定的旅館,到了旅館後不久就接獲由於颱風重創宜蘭,明天課程取消的通知。我一個人怔怔的望著那件超宅藍色POLO衫,不知道自己為什麼剛剛那麼想要,開始思考我到底敢不敢穿這種衣服出門的哲學問題來了......(完)

這麼宅的衣服,你會怎麼穿?XD


補充說明:N8是NOKIA今年力挽狂瀾的最新代表作手機,具有超多智慧型手機的功能,其中最讓我羨慕的就是下降頭」的功能!可以讓你喜歡的人情不自禁的愛上你。不要以為我在唬爛,不相信的話可以看下面這隻N8的泰國廣告......XD

2010年10月16日 星期六

2010 Google DevFest開發者大會參加心得

Google DevFest的正式開場


10/1這天是2010 Google DevFest的台北場,算是Google相關開發者的聚會party,剛好我們主管也希望有人參加,於是我就很主動的請了公假去參加了。

由於是全程免費的,參加前還得上網填寫一份英文的報名表,除了基本資料外還要填寫一些為何想來和所感興趣的議題問答,最後一題還考個非常簡單的小程式題(我第一次答錯了,後來發現後不死心的再上傳一遍正式答案,我不清楚這題是不是一定要答對才行,不過我另一位跟我一起答錯的同事就沒收到邀請函了......)。

後來收到Google的確認邀請函,邀請函是全英文的,上頭還很心機的附了一個Link,那是如果不克前來要取消報名的Link,如果看到英文信有個連結,就不明就裡點下去的工程師們,就無法參加了,這一定是Google發現報名的人太多,為了控制參加者數量而想到的奸計阿!XD

至於我想參加的動機,除了我是Google的忠實粉絲之外,很大的一個原因是,去年Google辦的Develope Lab送的可是每一位與會者都送一支Nexus One手機呀!(詳情請看這一篇新聞這一篇)如果這次也送一支Desire那該有多好!(痴心妄想中......)


這次講的主題比較廣泛,除了Android之外,還包括了HTML5、Chrome、Google Apps、 Google Maps API、Google Buzz API等等議題,算是Google最新技術的宇集合套餐。其中除了Android的簡介和HTML5 in Chrome外,其他議題都是在下午,分成三個Lab、三間教室來上課的,除非你是會影分身術,不然只能很遺憾的選其中一個Lab來聽。

早上一開場的是Fred Chung,中英夾雜說了很多Froyo(Android 2.2)帶來的的新功能,最令人振奮的消息是:台灣 Android Market 即將支援付費功能了!對於台灣的開發者來說,開發Android應用程式終於能夠賺得到錢了!對於使用者來說,現在上Android Market也都是以台幣計價,可預期的將來也會有各式各樣台灣在地化的軟體上線了,這真的是一件很棒的好消息!

接下來是Arne Roomann-Kurrik對於「HTML5 in Chrome」的介紹,HTML5帶來了嶄新的技術,諸如Canvas 2D和3D(WebGL)、SVG、Local Storage、Web Worker、Web Fonts、GeoLocation、CSS3、多媒體影片直接的支援...等等。雖然他是外國人,全程使用英文,但是他講得非常生動有趣,我可是聽的津津有味,完全沒有打瞌睡,這份投影片都是用HTML5所完成的,內容超精彩的,讓在場的人讚嘆不已,叫好連連!這個簡報的網址在 http://goo.gl/WQOV,有興趣的讀者可以連過去看(當然最好是用Chrome瀏覽器觀看囉!)其他HTML5的reference可以參考以下網址:
下午的Lab課程,我理所當然的是選擇Android的lab教學,第一堂課是「UI Best Practice for Android Application」,主講的是Ken Liu,是個中國人,他一開口我就知道是個大陸人,講的方式也是非常的幽默風趣,他說到了在開發Android Application時UI的重要,很幽默的打了個比方:工程師沒日沒夜寫了老半天的程式,開發了最新最了不起的軟體,家裡的家人卻都不懂你在做啥,這是相當鬱悶的一件事。所以我們要設計好的UI介面,讓老婆和小孩也能很輕易的使用它,這樣才算真正的成功了。


「為何我們要關注UI?獲得老婆和孩子們的肯定,這是第一!」

聽到這句真的是戳中我的笑點了,馬上筆記下來。這個理由比什麼都還說服我阿!他從「Android activity life-cycle」講起,接著他又說到「Design Philosophy」(設計哲學),說了很多UI設計上的盲點,還有一個正確的UI可以多麼地增進程式的效率,接著的重點是:
  • Clear vs. Simple
  • Content vs. Chrome
  • Consistent yet engaging
  • Enhanced by the cloud
最後舉了兩個範例要大家動手實做一下,這兩個範例的原始碼如下:
總結一下我這次參加的心得:
  • Google辦的研討會經費越來越少了,這讓我對他的前途非常堪慮。
  • Google的工程師們無論中國人或外國人,都非常地幽默風趣,感覺很有活力與朝氣。
  • Google在Web上的各種技術,毫無疑問,是持續處於領導地位的。
  • Google在Android平台上的開發是不斷精進的,Android應該還可以紅個好幾年沒問題。

很可惜的是,這次沒有送手機了,這次的戰利品只有一件很宅的DevFestT恤(如上圖),不僅沒有Google的Logo字樣,而且質料很差,下水洗過一次就快爛掉了,算是有點美中不足的小遺憾。

不過,我想我還是會繼續支持Google的「Don't be evil」,繼續的使用GMail和Chrome,繼續的愛用Google的各種免費軟體的!

2010年7月11日 星期日

有關C語言的struct進階初始化

之前在trace強者學長們寫的C code時,一直對某種struct initialization的方法很感興趣,卻不知道該如何使用。稍微研究一下終於有了小小心得,在此筆記一下。

假設有一個student的結構定義如下:

typedef struct student{
  char name[50];
  int studentNo;
  int age;
}student;


按照一般教科書上的寫法,初始化的方式是先宣告一個struct student的變數,然後再用點(dot)運算子去存取內部成員並賦值,例如:

struct student st1;
st1.name = "Peter";
st1.studentNo = 1234;
st1.age = 18;


但是進階的初始化方法卻是宣告直接再以點(dot)運算子賦值,例如:

student st1={
  .name = "Peter",
  .age = 18,
  .studentNo = 1234
};


原來點運算子就可以等同struct內的成員,多個成員則用(,)來分開,類似陣列(array)的宣告方法,不同的是,他賦值的順序是可以不用按照struct定義內的先後順序的!

說到陣列(array),他的宣告也是有幾種神奇的方法。
例如:

int a[7] = { [4]=29, 33, [2]=15 };
相當於
int a[7] = { 0, 0, 15, 0, 29, 33, 0 };

可以用[index]= value 的方法指定給特定的元素,沒有指派的值就是0這樣。

結合上面struct的用法,也可以一併使用combo連續技,例如:

student st2[5]={
  [3]={
      .name = "Titus",
      .age = 22,
      .studentNo = 1041 },
  [2]={
      .studentNo = 1042
      .age = 23,
      .name = "Stephen", },
}

[index]= 可以不必按照順序,裡頭的成員也不必按照順序,其餘沒指派的元素會自動初始化為0。


當然也可以將一連串連續的元素賦予相同的值,例如:

int a[]= { [0 ... 9]=1, [20 ... 99]=2, [100] =3};


其實這些進階的寫法有什麼實際的好處我也還沒參透(難道是這樣「看起來」有比較OO嗎?哈哈),但至少能看懂這些,以後再看別人的code有用這種語法時就不會再覺得好古怪好神奇了。這些小東西看在用JAVA或C#的人可能不值一提,不過我在這古老而傳統的C語言上能看見這些寫法,仍是感到十分特別又有趣的,所以說,C語言也是會與時俱進的!C語言好棒阿!(這種將C變成既簡潔又充滿彈性的極致語言我看就是Ruby了吧!哈哈!)

PS:以上應該都是使用革奴牌(GNU gcc)的延伸C語法,而不是標準的C語法,如果你是在非GNU gcc的compiler上要特別注意這種寫法是否能夠使用囉!

2010年7月1日 星期四

有關C語言的static用法

由於工作的關係使用的是C語言,而static的關鍵字我卻常以JAVA的角度來理解而造成誤解,經過trace大量的code和翻查一些書後,我總算搞懂static在C語言中的用法了。原來他是依修飾的對象不同而有不同的功能,大致上就分為兩種,簡單筆記如下,以免以後自己又忘了:


1. 使用在全域變數或全域函式 (Global variable & Global function)
讓該變數(或該函式)的可視範圍只侷限在該檔案內,其他的 .c檔看不到此變數(或函式)的存在。
既使其他檔案用extern宣告也看不到!套句行話來說,他把Global的變數或函數變成了「internal linkage」,當Linker在找symbol時是會忽略它的。
(在C++中也相容這種用法,不過被視為比較不建議的舊的用法,C++比較建議使用unnamed namespace。)

使用時機:當此全域變數(或全域函式)不想被其他檔案引用和修改時,或者不同檔案可以使用相同名字的全域變數(或全域函式)而不會產生命名衝突。

2. 使用在函式內的區域變數 (Local variable)
因為區域變數預設就是動態變數,而在區域變數前加上static修飾字則會將變數由動態(dynamic)變數轉為靜態(static)變數,靜態變數的壽命(lifetime)與動態變數不同,靜態變數會一直存在,直到程式結束為止。

使用時機:這種很適合用來做統計次數的功能(某函式被呼叫幾次),例如以下的代碼...


void count();
int main()
{
int i;
for (i = 1; i <= 10; i++)
count();
return 0;
}
void count()
{
static cnt = 0;
cnt++;
printf(" It have been called %d",cnt,"times\n");
}

其執行結果就會是:
It have been called 1 times.
It have been called 2 times.
It have been called 3 times.




做個總結,static的用法整理如下表:

修飾對象   使用在...    Linkage    Scope
---------------------------------
變數     函式裡       internal    Block
變數     函式外       internal    File
變數     成員        external     Class    (for C++)
函式     global       internal     File
函式     成員        external     Class    (for C++)


static感覺是很簡單的東西,解釋起來卻這麼複雜,也難怪我花了這麼久的時間才把他搞懂了...如果高手看到這篇還有我觀念錯誤的地方,還請不吝指教阿 ^^|||

PS:又有同學舉一反三的問我:那C語言中的static和const還有volatile在用法上各有什麼差異?這問題實在是問的太好了,請這位童鞋自己去找答案後再告訴我吧!C我也不熟阿!

2010年6月22日 星期二

[Linux] screen進階用法

上一篇說到screen的基本用法,這一篇來補完一下他「分割視窗」和其他的強大功能的用法吧!基本熱鍵如下:
  • 分割視窗(split) Ctrl-a, S
  • 他是採水平分割,按幾次就分割幾個,分割10幾個也行(不過你螢幕應該沒這麼大……)
  • 切換視窗(focus) Ctrl-a, Tab
  • 切換到新的region後可以按Ctrl+a, c新增,或按上一個、下一個切換原來已開啟的…
  • 離開分割視窗(Quit) Ctrl-a, Q
  • 分割的N個視窗通通消失,只剩下你目前focus的那一個…

以上是官方正式用法,或者你也可以像我一樣,將下面這三行bindkey設定加進 .screenrc中
(這是我喜歡的按法,你也可以設成你自己的熱鍵)

bindkey "^[s" split
bindkey "^[f" focus
bindkey "^[q" only

存檔離開screen再進screen後,熱鍵變成

分割視窗: Alt+s
切換視窗: Alt+f
離開分割視窗: Alt+q

簡單多了吧!

有人問道,至於跨視窗的複製貼上怎麼用?

問的好!不巧這剛剛也被我給找出來了!在此便不藏私的一併寫出來吧!首先你得先輸入「Ctrl-a ESC」或「Ctrl-a [」進入「複製模式」(有點像vi的一般模式),進去此模式後就可以用類似vi的指令來移動游標,例如「h, j, k, l, 0, ^, $, H, M, L, G, |, w, b, e, B, E, Ctrl-u , Ctrl-d, Ctrl-b, Ctrl-f, g, %」等等(如果你的screen版本夠新,應該也是可以直接用上下左右鍵來移動才是)。

若要複製的話,在起始點和終點各按一次空格鍵,這就copy了居於中間High-light的文字並退出「複製模式」,進入「正常模式」,最後用「Ctrl-a ]」就可以貼上了。

如果要做字串搜尋的話,也只要在「複製模式」下輸入類似vi 的「/ 和?」的指令就可以了。複製和搜尋看起來很複雜,但如果你本來就有在用vi編輯器的話,這些指令操作應該覺得很親切、順手才對。

總之,分割視窗也是screen很好用的功能(我知道很多人懶得學,索性會開很多個putty視窗來切換工作,但那樣多重登入實在太佔伺服器資源了...),若再任意搭配vim的垂直分割功能(這...不會的請去問鳥哥),你就可以隨心所欲的切視窗看code了,例如下圖:


或者一邊編輯code一邊看compile的error來debug,學會用screen來開多重分割視窗,是非常實用的!


另外,使用上有時後可能會發現,screen畫面都不會動,分頁都沒反應了!
原來原因是你不小心按到了預設的鎖住螢幕組合技「組合鍵 Ctrl-a s
解決之道是按對應的組合技「組合鍵 Ctrl-a q 」來離開(Quit)

如果你想要永遠ban掉這個討厭的預設熱鍵的話,可以在.screenrc 裡面加上

bind s

這行bind掉這個組合鍵,避免誤按


# remove some stupid / dangerous key bindings
bind s
bind k
bind W
bind ^k
bind .
bind ^\
bind \\
bind ^h
bind h

以上這些是網路上建議remove掉的指令,可以一併加上…

PS:如果你真的是暫時離開想鎖住螢幕的話,可以用「組合鍵 Ctrl-a x 」,要解鎖的話要輸入Login密碼才能繼續使用,增加不少安全性!

2010年5月19日 星期三

[Linux] screen教學與bindkey設定用法

聽說常在用Linux的老手老早都知道使用screen這個工具,我這新手當然是最近看學長用才知道的,於是花了點時間研究和整理一下他的使用方法。

screen的全名叫做(full-screen window manager),是在Linux or BSD上一個很好用的工具,可以讓你在一個terminal下開啟多重視窗執行,讓你只要靠一個putty/pietty視窗就可以同步地處理很多的事情,視窗彼此的切換又很方便迅速,有點像瀏覽器的「分頁」功能一樣。

例如說你可以開一個視窗正在compile程式,另開一個視窗開vim看code,再開第三個視窗連ftp抓一個大檔,最後再開一個視窗用偷偷telnet連BBS逛PTT這樣(最後一個上班不要亂用,雖然screen也是超級好用的BBS「掛站」利器),視窗間可以隨時用熱鍵切換,彼此卻又運作順暢互不干擾。

我覺得screen對我來說最無可取代的強大好處有三點:
  1. 提供多視窗工作
  2. 提供離線繼續工作
  3. 提供終端機編碼轉換
第一點剛剛講了,第二點是說,你在screen模式下的每個視窗畫面和進度都會被存起來,離開時只要用「detach」不要真正exit,所有process就會都還在背景執行中,你甚至可以logout帳號,下次再登入再把screen「叫起來」(正式點的動詞叫做resume session),就可以繼續剛剛的工作,例如你在公司執行上述的四個視窗,累了就按Ctrl+a+d 「detech」收工回家,回家再putty連到主機輸入screen -rd,剛剛vim看到哪一行,BBS和妹聊到哪一句,通通輕鬆回復原來的樣子!至於第三點後面會提到......

screen的下載及安裝:

這部份省略,Linux版本眾多族繁不及備載,官方網站在這裡,請查明自己的OS後自行去ftp安裝相對應的版本,安裝指令不外乎打rpm或者tar解壓縮後make、make install之類的那幾招。(如果不會這些,你大概也不可能是會用Linux的人,更不需要這工具了...)

screen操作簡易教學:

進入與脫離screen的指令是:
  • screen //第一次執行screen
  • Ctrl a+d //關閉screen(至背景),也就是detached
  • screen -rd //重新回到(resume)剛剛的screen 裡
  • exit //關閉視窗(若只剩一個視窗則為關閉screen)
在進入screen的世界後,都是以熱鍵來做操控,他的原生熱鍵都是以Ctrl+a開始的,(以C-a 代表,C-a c 代表按住 Ctrl 鍵不放再按 a 鍵,然後放開按 c 鍵)最基本必會的幾個熱鍵是:
  • C-a c 或 C-a C-c #開啟新的視窗,並同時切換到這個新的視窗
  • C-a n 或 C-a C-n 或 C-a (space) #切換到下一個視窗(0->1 1->2 ...)
  • C-a p 或 C-a C-p #切換到上一個視窗(1->0 2->1 ...)
  • C-a C #清除目前的視窗內容
  • C-a d 或 C-a C-d #脫離(detach)目前的 screen ,並放到背景執行
  • C-a ? 或 C-a C-? #熱鍵查詢

其實只要知道上面這些,實際再按個兩三下感覺一下,馬上就上手,可以使用愉快了。當然還有很多很多熱鍵,不過光上面的那些我都覺得很難按了,什麼Ctrl+a放掉再按這麼彆扭的按法,又不是在格鬥遊戲輸入豪華連續技。好在他有提供bindkey的功能,也就是可以自定義熱鍵,這需要動到screen的設定檔,也就是你的安裝目錄下的.screenrc那個檔案,如果你要讓你的screen使用上更加順手和個人化,請接著看下去......

screenrc設定檔教學:(進階設定)

請vim .screenrc修改裡頭的檔案,以下是我的配置,大家可以參考一下:

.screenrc

# Start message
startup_message off

# Set hardstatus always on
hardstatus alwayslastline " %-Lw%{= Bw}%n%f %t%{-}%+Lw %=| %M %d %0c:%s "

# Set default encoding using utf8
defutf8 on

# Refresh the display when exiting programs
altscreen on

# Dynamic title
shelltitle '$ |bash'

# Disable vbell
vbell off

# Keboard binding
# bind F11 to move to previous window
bindkey -k F1 prev
# bind F12 to move to next window
bindkey -k F2 next
# bind Alt`~= to screen0~12
bindkey "^[`" select 0
bindkey "^[1" select 1
bindkey "^[2" select 2
bindkey "^[3" select 3
bindkey "^[4" select 4
bindkey "^[5" select 5
bindkey "^[6" select 6
bindkey "^[7" select 7
bindkey "^[8" select 8
bindkey "^[9" select 9
bindkey "^[0" select 10
bindkey "^[-" select 11
bindkey "^[=" select 12
# bind F7 to detach screen session (to background)
bindkey -k k7 detach
# bind F8 to kill current screen window
bindkey -k k8 kill
# bind F9 to create a new screen
bindkey -k k9 screen
# bind F10 to rename current screen window
bindkey -k k; title


由上而下簡介: (#的都是註解請忽略)
第一個是把惱人的screen開啟訊息關掉
第二個是在視窗底下新增一個很好用的狀態列(這很方便!一定要加這行!) (註1)
第三個是強制終端機編碼為utf8 (這樣就能正常看中文字囉!) (註2)
第四個是離開視窗時自動refresh一下螢幕
第五個是支援動態顯示視窗的「標題名稱」(註3)
第六個是把熱鍵操作錯誤時的逼逼聲給關掉
接下來重點來了,就是Keboard bindkey,也就是自行定義熱鍵,以上那些是我個人喜歡的配置方式,我將熱鍵定義如下:
  • F7 關閉screen(至背景) (相當於C-a d )
  • F8 kill目前screen視窗
  • F9 開一個新的screen視窗 (相當於C-a c)
  • F10 將目前screen視窗「標題名稱」重新命名
  • F11 往前切換視窗 (相當於C-a p)
  • F12 往後切換視窗 (相當於C-a n)
  • Alt+` 切換至screen 0
  • Alt+1 切換至screen 1
  • Alt+2 切換至screen 2
    ...…(依此類推)
  • Alt+= 切換至screen 12

當然這是我喜歡的配置方式,你看懂後也可以自行變化對應按鈕,總之自己按的順手就好!

最後我再分享一個screen應用的最終密技,那就是——「分割視窗」!熱鍵是「Ctrl + a  S 」(大寫的 S唷,也就是Split的意思),螢幕就會切成兩半了,此時再按「Ctrl + a  tab」就可以切換focus的視窗,接著再「Ctrl + a  c」 建立新視窗,或著以號碼跳選其它視窗。(恕沒有圖解教學,請自行操作領會)分割視窗有啥好處呢?相信常在trace code的人都能感受,有時常看某個.c檔就想開著他refer 到 header include 的檔案去查找macro定義或struct宣告之類的,或者是兩個檔案做diff比對,此時若能分割視窗就方便多啦!(雖說VIM也支援分割視窗啦!)



註1:那行狀態列等於是瀏覽器上的分頁列那樣,強烈建議常駐,可以很清楚的知道你身處於哪個screen,至於那些""內百分比的東西是自定義的風格(如標題格式、顏色...等等)我的設定是走藍色低調風,還在右下角加了日期和時間,網路上有各式各樣的風格分享。例如:

第一種

caption always "%{= wk} %{= KY} [%n]%t @ %H %{-} %= %{= KR} %l %{-} | %{= KG} %Y-%m-%d %{-} "
hardstatus alwayslastline " %-Lw%{= Bw}%n%f %t%{-}%+Lw %=| %0c:%s "

第二種

caption always "%{=u .G} %-w%<%{=ub .y}%n %t%{=u .G}%+w "
hardstatus alwaysignore
hardstatus alwayslastline "%{= .K} [%l]%<%=%{= .W}@%H %=%{= .y} %Y/%m/%d%{= .m} %0c:%s "

第三種

caption always "%{=u .G} %-w%<%{=ub .y}%n %t%{=u .G}%+w "
hardstatus alwaysignore
hardstatus alwayslastline "%{= .K} [%l]%<%=%{= .W}@%H %=%{= .y} %Y/%m/%d%{= .m} %C %A"

第四種

caption always "%{=u .G} %-w%<%{=ub .y}%n %t%{=u .G}%+w "
#hardstatus alwayslastline "%{= wk} %{by} %H %{wk} | %-Lw%{kw}◣%{= g}%n%f* %t%{wk}◤%{wk}%+Lw%< %= %{kw}◣%{= R} [%m/%d %c] %{-}"

顏色那些參數可以看這篇教學(或者man screen),請自行更換調整囉!

註2:這個也就是上述提到的第3個好處,你也可以default設成big5,端看你的終端機是什麼格式的,或者你也可以big5 的 terminal裡看utf8,或在utf8的terminal裡看big5,(好像在念rap...),可以設個熱鍵如下:

terminal使用big5的:

# C-a b --(switch to)--> view big5 data
bind b encoding big5 big5
# C-a u --(switch to)--> view utf8 data
bind u encoding utf8 big5

terminal使用utf8的:

# C-a b --(switch to)--> view big5 data
bind b encoding big5 utf8
# C-a u --(switch to)--> view utf8 data
bind u encoding utf8 utf8


註3:關於動態支援標題名稱的設定(例如開VIM編輯wtf.c檔案,標題就自動換成wtf.c),這是進階中的進階用法,小弟我也還在參透中,有興趣的可以看這一篇教學文這一篇教學文,在此就不敢掠美了。

延伸閱讀:

沒有延伸啦!這篇已經盡我所能講完screen的用法囉,很多高手都有分享自己的screenrc設定方法,大家可以自行google,其餘的東西,請自行問「男人」,也就是man screen去發掘囉!


2010/06更新:我又寫了一篇 [Linux] screen進階用法 囉!有興趣的看官請一起打包帶走,謝謝!

2010年4月28日 星期三

網誌新增項目介紹之FaceBook「讚」外掛教學

最近又將我的部落格加了點新東西,簡單介紹如下:

1. 每篇文章底下加了FaceBook的「讚」按鈕,這是看了Facebook官方網頁新推出的「Like Box」功能而改良的,我看了覺得挺有趣的,便想把他安裝到自己的網誌裡頭。

與官方教學的程式碼不同之處是,原本範例是只能放在固定的網頁(例如部落格首頁),我想要放在每篇文章底下,勢必得動態抓取文章的網址才行。於是我開始動工想用Javascript來抓取目標的url,太久沒寫Javascript了很多語法都忘光光了,只記得應該要用location.href來抓取目前的url,還有用document.write()來印出字串。但是我試了兩個晚上,類似「javascript:document.write(location.href);」的語法在那邊兜來兜去,怎麼試都試不成功,程度實在退化的太多了。

後來終於被我試出來了,原來抓取文章網址要用Blogger內的 data:post.url 語法才行,在此分享給大家:


把下面程式碼貼到想要顯示的地方即可。


<script>
document.write(&#39;&lt;iframe src=&quot;http://www.facebook.com/plugins/like.php?href=<data:post.url/>&amp;layout=standard&amp;show_faces=true&amp;width=450&amp;action=like&amp;font=verdana&amp;colorscheme=light&quot; scrolling=&quot;no&quot; frameborder=&quot;0&quot; allowTransparency=&quot;true&quot; style=&quot;border:none; overflow:hidden; width:450px; height:65px&quot;&gt;&lt;/iframe&gt;&#39;);
</script>


以Blogger為例,登入Blogger 的控制台後,進入「版面配置」的「修改HTML」,勾選「展開小裝置範本」,如果你想要貼在文章開頭處請搜尋這一行:

<b:includable id='post' var='post'> 

然後在這行的下面貼上上面的那坨code就完成了。但如果你要像我一樣貼在文章最後面就要自己尋找位置了(因為每個網誌文章結尾的code都不一樣),我喜歡貼在最後的原因是因為,你得要看完文章才能決定我寫的這篇「讚」不「讚」阿!放在開頭固然可以吸引人去按,但那對我而言是毫無意義的!我喜歡的是真實的鼓勵而不是那數字上的增減。

2. 文章最後再新增「您或許對這些文章有興趣:」的widget。這個就簡單多了,只要登入「LinkWithin」的官網去填一填資料,馬上就有一段程式碼可以貼了...在此就不多加贅敘。

3. 左欄最下方新增「KOUMIS試聽貼紙」,這是我老弟最近極力推薦的創作歌手,我也覺得挺清新好聽的,所以就放上來幫她打個免費廣告,這也是只要複製貼上以下的程式碼到你想要放的地方就好:


<div id="koumisBlogStick" style="width:160px;height:400px;"></div>
<iframe id="rFrame" width="0" height="0" frameborder="0" src=""></iframe>
<script type="text/javascript" src="http://www.koumis.cc/BlogSticker/js/koumis.js"></script>


大家可以點來聽聽看,真的是很難得一聞的Vocal唷!如果大家還不認識Koumis蓓麗的話,除了可以去她的官方網站瞧瞧或加她的Facebook粉絲外,在此要內舉不避親的推薦我老弟寫的「介紹文」和「CD開箱文」。(我老弟也是愛攝影、愛寫文章的文藝青年!最重要的,他目前還是單身!)


其實還有很多想新增的元素,但是我的網誌開啟速度已經很慢了,不想變得更慢,故在此作罷,其實對我而言,「捨棄」永遠比「留下」要困難的多阿!

2010年4月19日 星期一

Source Insight 外掛 Artistic Style 程式碼自動格式化

之前一份工作寫JAVA (J2EE、Struts、JSP...)的時候IDE用的是Eclipse,以JAVA語言而言他真的是一個非常好用的IDE,其中我最愛的內建熱鍵是Ctrl+Shift+F,無論我怎麼用空格、Tab亂七八糟縮排,一按這個熱鍵就幫我自動格式化,排的整整齊齊了。

現在換用Source Insight寫C code,他是更強大沒錯,號稱「地球上最強的Trace Code神兵利器」也不為過,但是這個「程式碼自動格式化」(Code Formatter)功能卻怎麼也找不著,套句對岸的用語,「相當鬱悶」!後來經由明查暗訪,由好友丁爺的推薦和懶魚學長的部落格教學,我終於找到完美的Solution了!(興奮貌!)

安裝教學步驟如下:

1. 去SourceForge 下載 Artistic Style
   下載網址:http://sourceforge.net/projects/astyle/files/
2. 將AStyle解壓縮,本例放在根目錄下 (C:\astyle)
3. 開啟SourceInsight,上方選單列選擇"Options-->Custom Commands-->Add", 輸入"Artistic Style"後按OK
Custom Commands視窗

4. Run那列輸入"C:\astyle\bin\AStyle.exe --style=allman %f",Dir列保持空白 (註)
5. 下面將Iconic Window打勾,其餘通通取消打勾
6. 點選右側按鈕"Menu-->(右上方)Menu-->(下拉選)View-->"、
   "Menu Contents的第一個Toolbars點一下-->按右側Insert-->按OK"
Menu Assignments視窗

7. 接下來還可以自訂喜歡的熱鍵,在"Options-->Custom Commands"
   點選右側按鈕"Keys-->Assign New Keys",按你喜歡的熱鍵,我是設"Ctrl+Alt+F"
Key Assignments視窗
8. 如此就大功告成了!你可以按"Options-->View"看到剛剛設好的Command和熱鍵!
大功告成!
9. 接下來只要按熱鍵"Ctrl+Alt+F",就會背景呼叫AStyle幫你目前的檔案做自動格式化(排版)啦!


註:"--style=allman %f"其中 --style是排版風格的參數、%f則是檔案路徑
Artistic Style非常彈性,有多種格式化(縮排)的風格可以選擇,詳細文件可以參閱:
http://astyle.sourceforge.net/astyle.html

經過多次試驗,我個人喜愛的配置是"C:\astyle\bin\AStyle.exe --style=allman --indent=spaces --indent-switches --indent-labels --indent-preprocessor %f"

大家可以參考看看!!

2009年5月19日 星期二

Linux Kernel時序的三種機制

最近在寫Driver時,常常遇到需要「等待一段時間」再處理的動作,以往我都傻傻的用msleep()或mdelay(),殊不知這種busy waiting會hold住cpu資源,在這段期間內都無法讓給其他process執行,時間短(10ms以下等級)或許還可以,太長就不行了,所以需要Kernel本身就有提供的「時序」機制來做處理,於是我漸漸學會了如何使用Timer、Tasklet和Workqueue的用法,在O'ReillyLinux Device Drivers第七章有詳細的講解,我將書上的精華茲簡單整理如下:

##CONTINUE##
一、Timer


#include <linux/timer.h>

struct timer_list
{
/* ... */
unsigned long expires;//期望運行的 jiffies 值
void (*function)(unsigned long);
unsigned long data;//傳給function的參數
};//使用前必須初始化

void init_timer(struct timer_list *timer);
//初始化一個timer_list
struct timer_list TIMER_INITIALIZER(_function, _expires, _data);
//初始化一個靜態的timer_list
void add_timer(struct timer_list * timer);
int mod_timer(struct timer_list *timer, unsigned long expires);
int del_timer(struct timer_list * timer);
int del_timer_sync(struct timer_list *timer);
//同 del_timer 一樣,但保證函數return時,定時器函數不在任何 CPU 上運行
//避免在SMP 系統上競爭

int timer_pending(const struct timer_list * timer);
//返回真或假來指示是否定時器已被運行

二、Tasklet


#include <linux/interrupt.h>

struct tasklet_struct {
/* ... */

void (*func)(unsigned long);
unsigned long data;
};

void tasklet_init(struct tasklet_struct *t,
void (*func)(unsigned long), unsigned long data);
//將定義好的結構體初始化,才可用

DECLARE_TASKLET(name, func, data);
//直接申明就可用了

DECLARE_TASKLET_DISABLED(name, func, data);
void tasklet_disable(struct tasklet_struct *t);
void tasklet_disable_nosync(struct tasklet_struct *t);
//對正在運行的tasklet無效,當它返回時,這個 tasklt 被禁止並且不會在以後被調度,直到重新enable.

void tasklet_enable(struct tasklet_struct *t);
//如果這個 tasklet 已經被調度, 它會很快運行. 一個對 tasklet_enable 的調用必須匹配每個對tasklet_disable 的調用, 因為內核跟蹤每個 tasklet 的"禁止次數".

void tasklet_schedule(struct tasklet_struct *t);
//調度 tasklet 執行.一般只運行一次,但可在一個tasklet中再調用,到達多次運行的目的

void tasklet_hi_schedule(struct tasklet_struct *t);
//調度 tasklet 在更高優先級執行.高於一般的tasklet優先級

void tasklet_kill(struct tasklet_struct *t);
//當一個設備正被關閉或者模塊卸載時,被調用。若tasklet被調度,則從運行的list中去掉 tasklet.若tasklet在另一個 CPU 上運行,則阻塞等待tasklet終止.

注意:tasklet是不可中斷的,一個tasklet只在一個CPU上運行

三、Workqueue

非共享隊列

#include <linux/workqueue.h>

struct workqueue_struct {

unsigned long pending;
struct list_head entry;
void (*func)(void *);
void *data;
void *wq_data;
struct timer_list timer;
};

1.創建工作隊列
struct workqueue_struct *create_workqueue(const char *name);
struct workqueue_struct *create_singlethread_workqueue(const char *name);
2.創建工作
DECLARE_WORK(name, void (*function)(void *), void *data);
//一個函數搞定定義和初始化
INIT_WORK(struct work_struct *work, void (*function)(void *), void *data);
PREPARE_WORK(struct work_struct *work, void (*function)(void *), void *data);
//要先定義work_struct,再調用這兩個函數
//INIT_WORK做更全的初始化,若需要改變工作隊列,則用PREPARE_WORK


3.提交工作給一個工作隊列
int queue_work(struct workqueue_struct *queue, struct work_struct *work);
int queue_delayed_work(struct workqueue_struct *queue, struct work_struct *work, unsigned long delay);
//返回0,添加成功,非0表明已存在此工作
int cancel_delayed_work(struct work_struct *work);
//返回非0,取消成功,返回0,取消不成功,工作仍在運行
void flush_workqueue(struct workqueue_struct *queue);
//確保cancel_delayed_work調用返回0後,停止運行工作
4.刪除隊列
void destroy_workqueue(struct workqueue_struct *queue);
//用完後刪掉工作隊列

共享隊列

1.創建工作
同非共享
2.提交工作給一個工作隊列
int schedule_work(struct work_struct *work);
int schedule_delayed_work(struct work_struct *work, unsigned long delay);
void flush_scheduled_work(void);
//刷新 同flush_workqueue一樣

注意:工作隊列可休眠

2007年4月23日 星期一

十年自學程式設計

文章連結:十年自學程式設計
原文網址:Teach Yourself Programming in Ten Years

這篇文章挺有趣的,文章很短,值得想要靠程式設計吃飯謀生的人一讀。
文中提到我覺得是最重點的一句話:
以下是我在程式設計這個領域獲致成功的秘訣:對程式設計感興趣,因為樂趣而寫程式。確信你自始至終都能樂在其中,這樣你才願意 將十年光陰投入。


##CONTINUE##
我自認我對程式設計毫無興趣也無熱忱,但世事總是事與願違(或說是莫非定律也罷),我現在的的確確得靠寫程式來養活自己,但是由於不符合上述的條件,所以我想我Coding的日子也不可能超過十年光陰吧(苦笑)。看我身旁的前輩,雖是前輩但年紀也才與我同年,他的程式設計經驗卻已經有10年左右了,收入也很可觀,但我只是個剛出社會的 "菜鳥程序員"(Junior Programmer),從不妄想也不可能達到他的成就和技術。說來可笑,我的程式從大學以來就都沒學好了,與其說是在混不如說真的是沒興趣,因為我大學成績好像是全系第四還第五,研究所成績也是全系第二左右,但我對寫程式真的很沒有Sense耶。這也是台灣教育的失敗之處,在我們資工系,成績前幾名的往往寫起程式都不怎麼樣,程式超強的高手往往成績也不在乎,都是低空飛過就好,自己老早就靠寫程式在外面接Case了。我想那種專科高職專攻資訊科的或者是在外面拿多張國際程設證照的人們一定比我們這打混的死資工大學生強,那麼有念資工系跟沒念有啥差別呢?過了數年後,課堂上教的那些技巧、理論還不是通通還給老師,充其量,也只是念一個Sense吧。

我覺得勉強要我寫程式寫個幾年應該還OK,但我深知,這終究不是我的興趣和專長。我以為,無論工作還是學習,熱忱(enthusiasm)絕對是第一要素(雖然我的英文奇爛無比,但是高中一開始學到enthusiasm這個單字還是覺得他的長相和發音都很酷,這也是我少數記得的高中單字之一),如果一開始是充滿熱忱的,過程再怎麼痛苦也會甘之如飴,畢竟下定決心時自己要有覺悟。如果對他失去熱忱了,剩下的就只是與現實妥協的硬撐,最後時間一長就是只有意志力的挑戰了,對於認識自我、發展自我到超越自我等等人生必經階段一點幫助也沒有。

猶記得拿破崙就有一句名言類似是說:價值產生信心,信心產生熱忱,而熱忱則征服世界。所以我也奉勸一樣走錯路的老弟,他也是不愛寫程式(我相信他也是"不愛"而非"不會")卻糊里糊塗地踏入了資工的領域,我給他的建議是,在考研究所時可以考慮轉換跑道,都到大三了,可以認真的思考自己的長處與興趣,思考將來第一份工作要做什麼?如果不是寫程式,那就不要考資工所,可以佐以興趣結合一點點在資工四年所念的東西和觀念,去考其他的相關系所。或許這樣走很累,或許得要延畢來準備研究所考試,來補回該科系的背景知識,甚至修一些外系相關的課程,但總比像我唸完研究所後恍然大悟我不是這塊料來的好。希望有人能在事先告訴他一些方向,而不是像我當年大三一樣糊里糊塗的跟著大家一起準備研究所考試,然後靠著成績推甄上了中字輩研究所便去念,最後出來仍覺得自己啥都不會,自己有幾斤幾兩重自己最清楚了。我覺得我的邏輯演繹功夫是不錯,但是思考的嚴謹度和縝密度則不足,這反映在寫出來的程式上,也會成為我的未來致命傷(滿地是蟲?哈哈),畢竟寫程式一字一句不可馬虎、一個大小寫打錯就會錯給你看的工具。我仍覺得我的大腦天生是比較偏感性的,比較具有創意方面的天分,例如美術、設計、文學等等,但是從高中選自然組以來一連串的理性訓練後,大概僅存的一點點的美感感受也消失殆盡了吧!這...難道我又要推說是台灣教育的失敗嗎?!

寫在參加309反核遊行之前

圖片出自:日本藝術家 奈良美智(Yoshitomo Nara) 的經典反核作品 一開始,先來聽首好聽的【 棉花糖 katncandix2 - 深黑的河 】 吧! 我一直以來都犯個毛病,就是有時會過於理性,相信「證據會說話」,換句話說就是愛當「認真魔人」,...