星期日, 12月 15, 2013

skype 安裝使用

2023/07/19 Lubuntu 20.04.5:skype 網站下載 skypeforlinux-64.deb 後 sudo dpkg -i ~/Downloads/skypeforlinux-64.deb。

Ubuntu 12.04 以後的版本,不管是 32 位元或是 64 位元都下載 Skype 版本 Ubuntu 12.04 (multiarch),然後

sudo dpkg -i skype-ubuntu*.deb # 會因相依性關係而安裝失敗
sudo apt-get -f install # 實際安裝
另外還有 dynamic 版本,解開後執行裡面的 skype,出現錯誤:「 ./skype: error while loading shared libraries: libQtWebKit.so.4: cannot open shared object file: No such file or directory」,安裝 libqtwebkit4
sudo apt-get install libqtwebkit4
再執行 skype 就可以了

設定:
  • 關閉「啟用事件」:待處理項目→不勾選下列的「啟用事件」
    • Skype 登入
    • Skype 登出
    • 聯絡人已經上線
    • 聯絡人已經離線
  • 關閉「Skype WiFI」:進階→啟用 Skype WiFi
使用
參考:
  1. 在 Ubuntu Linux 中安裝 Skype 4.2 版
  2. http://lxlinux.com/#10
延伸閱讀:
  1. MultiArch
  2. Skype for Linux 4.2
相關文章  
  1. Lubuntu 13.10 安裝與使用

星期五, 12月 13, 2013

inline

行內函數、內聯函數

就軟體工程觀點,使用函數是很好的作法,但多了函數呼叫來回的額外負擔,特別是小的、經常呼叫的函數。將函數 qualifier 為 inline 可節省呼叫的額外負擔。
  • 空間換取時間 -- 函數程式碼會複製多份,可能使得程式變大了。
  • 如果 inline 函數的參數有常數,編譯時可以加以簡化,所以未必包含整個 inline 函數的程式碼。
  • 只是建議編譯器 inline 處理,未必採納,編譯器保有最終決定權。
    • 比較:static inline 強迫編譯器 inline 處理
    • GCC -Winline 提供 inline 函數失敗的原因
  • 只需要定義於表頭檔
  • inline 的函數改變時,使用它的程式都需要重新編譯。
  • 告訴 GCC 嘗試 inline 所有夠簡單的函數:-finline-functions

跟 #define (巨集) 比較
  • 巨集不能將 C++ 非 public 變數傳出去
  • 兩者結果有時不同。巨集像是字串取代,inline 像是函數
  • 巨集在行數多時不易理解
  • 題外話:#define function(x) do{...}while(0) /* 避掉 ; 問題 */


參考:
  1. http://blog.yam.com/swwuyam/article/11745212
  2. GCC: An Inline Function is As Fast As a Macro

git stash 暫存異動

stash 是「藏起來」的意思
用法很簡單

暫存異動
git stash
取出暫存的異動
git stash pop

查看
git stash list

參考:
[Git]使用git stash暫存有異動的部分

延伸閱讀:
http://blog.wu-boy.com/2013/08/git-rebase-stash-tip/

星期五, 12月 06, 2013

Lubuntu 雙螢幕延伸桌面設定

Lubuntu 使用 LXDE 桌面環境,使用的螢幕設定程式 LXRandR 只是一個很陽春的xrandr 前端,只能讓雙螢幕複製顯示,不能設延伸桌面。外接 VGA 投影機時,不但無法使用 LibreOffice Impress 雙螢幕環境簡報播放的效果,且顯示的長寬比不同,造成部份畫面會被切割不見的問題。

參考《LXDE and multiple screens: replacing lxrandr with a script》,只要執行
xrandr --output VGA1 --auto --right-of LVDS1
就可以自動偵測 VGA1 有無外接及解析度來開關雙螢幕延伸桌面。執行
xrandr --output VGA1 --off
強制關閉。

整合到 Fn+F7
  • 編輯 ~/.config/openbox/lubuntu-rc.xml,例如在 <keybind key="XF86AudioRaiseVolume"> 之前新增
        <!-- Keybinding for display switch -->
        <keybind key="XF86Display">
            <action name="Execute">
                <command>xrandr --output VGA1 --auto --right-of LVDS1</command>
            </action>
        </keybind>
    重新登入
已知問題:工作列跟著延伸到延伸桌面,造成右側的關機、時鐘、網路、輸入法、音量等項目只顯示在外接螢幕
  • 我使用簡單的解法,由於我的筆電螢幕解析度是 1366 x 768,將工作列的寬度設為固定 1366 像素就可以將工作列限制在筆電螢幕。
  • 設定方式:工具列右鍵→設定工具列→大小及位置→寬度:1366 像素 
  • 問題:點選時鐘顯示的月曆仍會跑到外接螢幕
相關文章:Lubuntu 13.10 安裝與使用

星期四, 12月 05, 2013

Lubuntu 13.10 安裝與使用

(修改自舊版文章:Linux 安裝與使用 )
安裝準備
安裝
  1. 進 BIOS 關閉 Security Boot
  2. USB 開機,「Try xxx without installing」
    • 也可以「Install xxx」直接安裝,但似乎沒地方可設定上網方式。
    • 設定 PPPoE 上網:新增 (Add) Connection Type DSL,設定 Username 及 Password (Service 不用設),勾選「Automatically connect to this network when it is available」,最後儲存 (Save)。
    •  可執行 gpartd 編輯硬碟分割
  3. 執行桌面上的「Install xxx」安裝。
  4. Welcome 選「中文 (繁體)」
  5. 時區、鍵盤皆用預設值。
其它安裝:

使用


參考:
  1. 使用 Ubuntu 12.10
延伸閱讀:
  1. http://lxlinux.com:有許多設定的參考資訊
  2. Back on 13.10 release
  3. Lubuntu 13.10 "Saucy Salamander" Review: Offers fantastic performance and possibly the best Lubuntu release I have used:使用 conky 等
  4. youtube-dl:下載 YouTube 影片的指令工具(支援 Windows、Linux 與 Mac OS X):可以下載 YouTube、土豆網等數百個網站影片的命令列工具 
  5. 给 Linux 系统“减肥”

星期三, 11月 27, 2013

Embeddedd Web Server

需求
  • Embedded System 控制界面
  • 登入
  • 防止技術洩漏

沒有檔案系統
有檔案系統
參考:OpenWrt WebUI

Ubuntu 瘦身

sudo apt-get remove landscape-client-ui-install thunderbird tracker ubuntuone-client
註:上述這些,Lubuntu 13.10 都沒有安裝
sudo apt-get purge ibus-table

移除已不需要的套件以及清除套件快取檔。
sudo apt-get autoremove --purge
sudo apt-get clean

參考:
  1. Ubuntu 進階優化和調校
  2. Ubuntu 12.04 & 12.10 調校備忘 (by Jamyy)
  3. [教學] Ubuntu 12.04、12.10的調校 [論壇 - Ubuntu 文件資源]
  4. Linux 安裝與使用

星期二, 11月 26, 2013

regular expression

正規表示式、字串樣本、字串比對

正規表示式是一種進階的字串比對,用「符號」描述字串的樣式,說明某個位置可以是哪些字元、符合的次數等。只要了解這些特殊「符號」,英文稱 metacharacter,可翻作「字元符」,就可以了解正規表示式。正規表示式在許多地方都可以見到,例如 grepsed、vi、JavaScript、git grep、IMS PSI 等。

字元描述

大部分字元,包括英文字母及數字,代表的就是它自己。其它的是有特殊意義的符號,可描述字元、位置、次數等。
  • .:任何字元。
  • \:跳脫字元,跳脫下個字元原本的解釋,原本是 metacharacter,就不解釋為 metacharacter。原本不是 metacharacter,改解釋為 metacharacter。
  • \d:數字。
  • \D:非數字,和 \d 相反。
  • \s:
  • \S:
  • []: bracket 表示式,[] 包起來,內含比對單一字元符合的列表。但如果內容以 ^ 開頭,則為不包含的列表。
    • 可用「-」表示範圍。例如「a-d」相當於「abcd」(在有些 locale 的字典順序不同,會變成「aBbCcDd」)。
    • 列表中也可以包含特定事先定義的類別,包括 [:alnum:], [:alpha:], [:blank:], [:cntrl:], [:digit:], [:graph:],[:lower:], [:print:], [:punct:], [:space:], [:upper:], 和 [:xdigit:]。注意,這裡的 [] 是類別名稱的一部分,[[:alnum:]] 代表數字及英文字母。
    • 大多 metacharacter 在 [] 裡失去其原本的特殊意義。要解除 ] 特殊意義,可放在列表第一個,^ 就不要放在第一個,- 放在最後。
  • \w:底線、數字或英文字母,相當於 [_[:alnum:]]。
  • \W:和 \w 相反,相當於 [^_[:alnum:]]。

位置描述

代表位置
  • ^:行開頭
  • $:行結尾
  • \< 及 \>
  • \b
  • \B

次數描述

說明重複的次數,沒有的話就是一次。
  • { }:重複次數。{2} 表重複兩次,{2,5} 表重複 2 至 5 次,{2,} 表兩次以上
  • *:0 次以上,相當於 {0,}。
  • +:1 次以上,相當於 {1,}。
  • ?:0 次或 1 次,相當於 {0,1}。

Alternation

|

subexpression

()

返回參考

\n:n 是一位數字,代表前面第 n 個 subexpression 符合的子字串。

BRE 和 ERE

一開始的正規表示式只支援 [、]、.、^、$、*,稱為 BRE (Basic Regular Expressions)。後來 POSIX 的 BRE 新增字元符來擴充功能,但為了相容,這些字元符前面需要加反斜線跳脫。而 POSIX ERE 則相反。
ERE:chapter 9 in IEEE 1003.1-2004 Part 1

BREPOSIX BRE
ERE
基本字元符支援支援支援
跳脫基本字元符反斜線反斜線反斜線
擴充字元符一般字元反斜線跳脫支援
跳脫擴充字元符支援反斜線

PCRE (Perl-compatible Regular Expressions)

  • 凡是標點符號, 加上倒斜線, 一定沒有特殊意義。
  • 常用的 [...] 定義了簡寫:
    • \d:[0-9], "任何一個數字"
    • \D:[^0-9], "任何一個非數字"
    • \w:[a-zA-Z0-9_], "任何一個文數字",不同 locale 有所不同。
    • \W:[^a-zA-Z0-9_], "任何一個非文數字"
    • \s:[ \t\n], "任何一個空白類字元"
    • \S:[^ \t\n], "任何一個非空白類字元"
  • ...

參考

  1. https://www.cyut.edu.tw/~ckhung/b/re/
  2. http://blog.roodo.com/rocksaying/archives/2670695.html
  3. Shell Script 文章

hex string to binary


echo -ne '\x5a'
echo -n 5a | perl -pe 's/([0-9a-fA-F]{2})/chr hex $1/gie'
echo 5a | perl -ne 's/([0-9a-fA-F]{2})/print chr hex $1/gie'
perl -lne 'print pack "H*", $_'
echo -n 5a | sed 's/\([0-9A-F]\{2\}\)/\\\\\\x\1/gI' | xargs printf
echo -n 5a | xxd -r -p

$ a=5a
$ printf "\x${a}"


參考來源:
  1. linux shell scripting: hex string to bytes
  2. Shell Script 文章

sed

sed (stream editor) 是一個 stream 編輯軟體,直接對檔案一行一行處理。不像一般編輯軟體將檔案載入 buffer 後進行處理。sed 支援正規表示式及流程控制,可視為一種小型指令檔語言。

指令格式
  • sed [選項] [-e] '編輯命令' [輸入檔]
  • sed [選項] -e '編輯命令1' -e '編輯命令2' [輸入檔]
  • sed [選項] -f 命令檔 [輸入檔]
編輯命令放在選項 -e 之後,如果只有一個編輯命令可省略 -e。編輯命令也可以放在選項 -f 指定的命令檔裡。其它常用選項:
  • -n:不自動列印。預設除非刪除,不然每行都會印出。加了 -n 選項,
  • -i:直接修改檔案內容
編輯命令格式:
  • [位址[,位址]]動作

位址

用來決定哪些行套用動作,不然每行都套用。有些動作不能有位址;有些可以有一個,指定符合的那些行;有些可以有兩個用「,」隔開,標示行的範圍。位址格式如下:

  • 數字:代表行數
  • 數字~step數字開始每 step 行。在 GNU 數字可以為 0。
  • /正規表示式/\c正規表示式c:比對符合的行,c 是任何字元。
  • $:最後一行
  • 整組位址後加「!」代表否定
GNU 額外支援的位址:
  • 0,位址位址正規表示式的比對,讓第 1 行可作為結束。
  • 位址,+N位址到其之後 N 行。
  • 位址,~N位址到其之後行號為 N 倍數的行。

動作

不能有位址的動作
  • #comment:整行為註解。
  • : label:供動作 bt 跳躍的 label。
  • }:{ } 命令區塊的結束。
沒位址或單一位址的動作
  • =:印出行號。
  • a[字串]:(append) 後面附加行放字串。新增多行,行尾用 \ 後換行。
  • i[字串]:(insert) 插入新行,類似 a,但是新增在前面。
  • q[結束碼]:
  • Q[結束碼]:
  • r檔名:後面附加檔案裡的內容。
  • R檔名:
接受範圍的動作:
  • {:命令區塊開始。
  • b[label]:(branch) 跳到 label 或命令檔最後。
  • c[字串]:(change) 整行取代
  • d:(delete) 整行刪除
  • D: 
  • l:類似 p
  • l[width]:
  • n
  • N:合併下一行。例如 sed 'N;s/\n/ /' 合併下行,並把換行取代成空白
  • p:列印,通常搭配選項 -n 使用
  • P
  • s/正規表示式/替代文字/[取代選項]:(substitute) 取代,比對正規表示式符合的話用替代文字取代。
    • 「/」可以用其它符號代替,例如「,」。
    • 替代文字」可以包含的特殊符號
      • &:整個比對符合的部份
      • \1 到 \9:比對的群組
      • \L:改為小寫
      • \l:首字改為小寫
      • \U:改為大寫
      • \u:首字改為大寫
    • 取代選項
      • 未指定只取代一行中第一個符合
      • g:global,一行中全部的符合都取代
      • 數字:一行中第幾個符合才取代
      • w file:寫到檔案
    • 範例
      • s/^/#/:每行開頭插入 #。
  • t[label]:(test) 執行 s 如果成功則跳到 label 或命令檔最後。
  • T[label]:同 t,GNU 擴展。
  • w
  • W
  • y/source/dest/:

使用保留空間的動作

保留空間 (hold space) 是一個另外的儲存空間,用來記憶內容。這些動作都接受位址範圍。
  • g:取代為保留空間內容
  • G:後面附加保留空間內容
  • h:覆蓋保留空間
  • H:附加到保留空間
  • x:跟保留空間內容互相交換

範例:pattern/hold space的處理

一系列編輯命令用「;」隔開。 

範例

  • sed 's/\(NAME=\).*/\1abc/g' config.file:將設定檔 config.file 中的 NAME= 設為 abc
  • sed -ne '/MHz/ { /disabled\|passive\|radar/d; s/.*\[//; s/\].*//; p; q }')
  • sed ':a;/0$/{N;s/\n//;ba}':迴圈執行,如果目前行以 '0' 結束,則合併下一行,並移除換行
  • Shell 變數字串處理
  • 目錄檔案字串替換
  • 多行處理:http://www.study-area.org/cyril/scripts/scripts/node57.html
  • 跳躍:http://www.study-area.org/cyril/scripts/scripts/node58.html
  • 多檔處理:http://www.study-area.org/cyril/scripts/scripts/node59.html

參考來源

延伸閱讀:
http://www.tldp.org/LDP/abs/html/

參考:Shell Script 文章

awk

以欄位為處理單位
指令格式:awk '條件類型1{動作1} 條件類型2{動作2} ...' filename
動作有 print 等
變數
  • $0 代表「整列資料」,$1 代表其中第一欄,$2 代表第二欄,...
  • NF 代表目前行有多少欄位
  • NR 代表目前是第幾行
  • FS 代表目前欄位的分隔字元,預設是空白或 Tab
一篇 awk 文章筆記
取檔案大小
ls -l $filename | awk '{print $5}'
印出第 1 行及最後一行
awk 'NR==1; END{print}' testing.txt
應用:
  • OpenWrt 的 ipcalc.sh:用 awk 作 IP 位址相關計算,包括 broadcast 位址、network 位址、prefix、起始位址、及結束位址。

參考:
  1. http://dywang.csie.cyut.edu.tw/dywang/linuxProgram/node37.html
Shell Script 文章

bash ARITHMETIC EVALUATION

bash 的算術運算用在內建指令 letdeclare、複合指令 (( ))、和算術擴展,使用固定寬度的整數,不檢查溢位,除以 0 會補抓為錯誤。

下列是運算子列表,以相同優先序為群組,越往下優先權越低 (優先序 和 C 語言一樣?)。括號裡的算式會先算。
id++ id--post-increment and post-decrement
++id --idpre-increment and pre-decrement
- +unary minus and plus
! ~logical and bitwise negation
**exponentiation
* / %multiplication, division, remainder
+ -addition, subtraction
<< >>left and right bitwise shifts
<= >= < >comparison
== !=equality and inequality
&bitwise AND
^bitwise exclusive OR
|bitwise OR
&&logical AND
||logical OR
expr?expr:exprconditional operator
= *= /= %= += -= <<= >>= &= ^= |=assignment
expr1 , expr2comma

參考:
  1. osl3 Shell 設計入門: 10.算術運算 (另外還有 expr、$[]、let 三種,其中 expr 可攜性較好)
  2. Shell Script 文章
  3. bash man-page ARITHMETIC EVALUATION 

bash 判斷式

bash 判斷式 (Conditional Expression) 用在內建指令 test 和 [、以及複合指令 [[ 來測試檔案屬性、進行字串或算術比較。[ 可以視為傳統 test 指令一樣的指令行,但最後要有引數 ]。由於每一項是引數,特殊字元要跳脫,但符合 POSIX 可攜性較好。[[ 算是 [ 的進階版,對應以 ]] 結束,不進行 Word splitting 和 pathname expansion,另外還有 Pattern Matching 功能。

真假值判斷可針對字串、整數、及檔案三大類,並且可以邏輯結合起來。

字串比較

[ str1 = str2 ]
[ str1 == str2 ]
字串相等 POSIX 相容 test 指令要用「=」。

[ str1 != str2 ] 字串不相等
[ str1 \> str2 ] 字串大於 「\」是 shell 的跳脫字元,消除「>」「<」輸出入轉向之意。
[ str1 \< str2 ] 字串小於
[ -z str ] 空字串,字串長度為 0
[ str ]
[ -n "str" ]
非空字串,字串長度大於 0 兩者結果有些不一樣,似乎 -n 字串前後要加 " 才會對
下列都是判斷空字串:
[ "$var" = "" ]
[ ! "$var" ]
[ -z "$var" ]
[ "X${var}" = "X" ]

排序按照 lexicographical,[[ 指令用照 locale 排序,test 指令用 ASCII 順序。

當 == (或 =) 或 != 用在 [[ 指令,右邊是 pattern 進行 Pattern Matching,如同啟用選項 extglob。如果啟用選項 nocasematch,比對不分大小寫。pattern 任何部份可以 quoted 來強迫直接字串比對。

整數比較

[ n1 -eq n2 ] 相等
[ n1 -ne n2 ] 不相等
[ n1 -gt n2 ] 大於
[ n1 -ge n2 ] 大於等於
[ n1 -lt n2 ] 小於
[ n1 -le n2 ] 小於等於
若要用「<」、「>」、「<=」、「>=」來比較數字,則判斷式需擺在 (( )) 中,如:(( "982" > "24" ))

檔案測試

判斷檔案是否存在,或測試檔案的屬性,如類型或權限等。
[ -a file ] 檔案存在 (和 -e 有何不同?)
[ -b file ] 存在為 block 裝置
[ -c file ] 存在為 character 裝置
[ -d file ] 存在為目錄
[ -e file ] 檔名存在
[ -f file ] 存在為一般檔案
[ -g file ] 檔案存在且 set-group-id
[ -h file ] 檔案為 symbolic link (和 -S 有何不同?)
[ -k file ] 存在且有設 sticky bit
[ -p file ] 存在為 named pipe (FIFO)
[ -r file ]存在為可讀
[ -s file ] 存在為非空檔案
[ -t fd ]file descriptor fd is open and refers to a terminal
[ -u file ] 存在且 set-user-id
[ -w file ] 存在為可寫
[ -x file ] 存在為可執行
[ -G file ] 存在為 effective group id 擁有
[ -L file ] 存在為 symbolic link
[ -N file ] 存在,且上次讀取後有更改
[ -O file ] 存在為擁有者
[ -S file ] 存在為 socket
[ file1 -ef file2 ] 兩者是否為同一個檔案 (同一個 inode)
[ file1 -nt file2 ] 較新,或 file1 存在 file2 不存在
[ file1 -ot file2 ] 較舊,或 file1 不存在 file2 存在
除非特指定,檔案是 symbolic link 應用在 link 的 target,而不是 link 本身。
如果檔案是 /dev/fd/n,檢查 file descriptor n。如果是 /dev/stdin、/dev/stdout、或 /dev/stderr,則分別檢查 file descriptor 0、1、或 2。

其它

-o optname:shell 選項 optname 已啟用。
-v varname:shell 變數 varname 已設 (已指定值)。
-R varname:shell 變數 varname 已設且是 name reference.

藉由「-a」(and, 且)、「-o」(or, 或)、「!」(非) 邏輯運算,可結合好幾個真假值判斷:

[ -r filename1 -a -x filename ] ==> 若 filename1 可讀且可執行

[ -r filename1 -o -x filename ] ==> 若 filename1 可讀或可執行

[ ! -r filename1 ] ==> 若 filename1 不是可讀

[[ 不進行 Word splitting 和 pathname expansion。進行 tilde expansion、parameter and variable expansion、arithmetic expansion、command  substitution、process  substitution、和 quote removal。Conditional operators such as -f must be unquoted to be recognized as primaries.

當 == (或 =) 或 != 用在 [[ 指令,右邊是 pattern 進行 Pattern Matching,如同啟用選項 extglob。如果啟用選項 nocasematch,比對不分大小寫。pattern 任何部份可以 quoted 來強迫直接字串比對。

另外還有額外 binary operator「=~」使用 extended  regular  expression (regex()),如果  regular  expression syntactically 錯誤回傳 2。Substrings  matched  by parenthesized subexpressions within the regular expression 存在 BASH_REMATCH 陣列,其中 index 0 是整個符合的部份,index n 是第 n 個parenthesized subexpression 符合的部份。

用下列優先權,表示式可以結合:
( expression ):優先進行。
! expression:True if expression is false.
expression1 && expression2:expression1 false 回傳 false,否則看 expression2 是否 true。
expression1 || expression2:expression1 true 回傳 true,否則看 expression2 是否 true。

if-than-elsetest
case

參考:
  1. 善用判斷式 [鳥哥的 Linux 私房菜]
  2. 真假值判斷 [Shell 設計入門 by 臥龍小三] mirror
  3. Shell Script 文章
  4. man bash 的  CONDITIONAL EXPRESSIONS 段落
  5. http://mywiki.wooledge.org/BashFAQ/031
  6. https://stackoverflow.com/questions/3427872/whats-the-difference-between-and-in-bash

export

指令格式:export [-fn] [name[=word]]
將 name export 為環境變數,給接下來指令使用

-f:export function
-n:在子程序時清除

參考:Shell Script 文章

星期一, 11月 25, 2013

JSON

JSON (JavaScript Object Notation) 是採用 JavaScript 物件寫法的資料交換格式,可用 JavaScript eval() 函數或其它程式語言讀入。

  • 一個物件以大括號 { } 包起來,包含一系列以「,」分開的「名稱:」對。
    • 名稱以「:」分開,名稱是 "字串",可以是 "字串"、數字、true、false、陣列、或是物件、null。
    • 陣列用中括號 [ ] 包起來,內容是一系列以「,」分開的
  • RFC 4627 -- The application/json Media Type for JavaScript Object Notation (JSON)
    • 回傳 JSON 時, 特別是有中文, 記得送 header
  • 安全問題:eval() 能編譯並執行任意的 JavaScript 代碼,不可靠的資料來源可能產生安全問題。建議使用 JSON.parse(),較舊的瀏覽器可用 JavaScript Library https://github.com/douglascrockford/JSON-js
  • 與 XML 比較:XML 是完整的標記語言,判讀需要較多功,但有很好的延展性,是 JSON 所缺乏的。JSON 不是完整的標記語言,但比 XML 小巧,瀏覽器內建快速解析支援,適用於網路資料傳輸。
  • JSON 壓縮
  • 雖然 JSON 是可閱讀的文字檔,但有時需要美化才好閱讀

星期五, 11月 22, 2013

Gargoyle HTTP Server

Gargoyle 基於 OpenWrt,除了採用簡易的 WebGUI 設定外,亦提供 QoS, bandwidth monitor 等進階功能。

Gargoyle 有自己的網頁伺服器,改良自 mini_httpd
source reference: httpd_gargoyle.c
主程式呼叫 handle_request()
  1. 從 socket 讀取 HTTP header
    • 每次最多讀 10000 bytes,直到有兩個換行
    • ssl or not
  2. parse request line
    • method, url, protocol
    • method: GET, HEAD, POST
    • url: with '?' for query
  3. parse all other headers,包括 Authorization:、Content-Length:等
  4. url: decode, remove ../, virtual host
    • 檔案不存在處理
    • 目錄:如有 defaultPageFile 或 index 檔,則依照檔案方式處理;不然則 list directory
    • 檔案:不能是禁止取用的檔案,如果符合 CGI 檔格式 (由設定檔 cgipat 參數或指令行 -c 參數設定) 則執行它,不然直接傳送檔案
    • 執行 CGI 檔
      • 必須是 GET 或 POST
      • 建立環境變數 envp
      • 建立執行參數 argp
      • stdin, stdout, stderr 導到 socket,中間可能插入另一個 process
      • execve(CGI 檔, argp, envp)
相關文章:OpenWrt WebUI

星期四, 11月 21, 2013

Shell Script

shell 是電腦文字操作界面,可以互動地 (interactive) 提示讓使用者從鍵盤輸入指令和顯示結果。

也可以非互動使用,可能直接執行另一個程式要求的指令,沒有輸入指令個過程,或沒人可以看到輸出 (例如寫到 log 檔)。

執行 shell 可以是登入動作的一部分 (login shell),通常會順便設定使用者需要的環境。 不是登入動作執行的 shell 就是 non-login shell。

多數 shell 可將多個指令寫在檔案裡面成為指令搞來執行,並提供額外程式結構而可擴展為程式語言。

大部份 Unix/Linux 系統有多個 shell 可選擇,如 bash、csh、ksh、sh、tcsh、zsh 等,有不同的選項和功能。

說明:
  • Shell:可以是輸入文字的命令列界面 (Command Line Interface, CLI),也可以是圖形使用者界面 (Graphical User Interface, GUI)。CLI 是個互動式的指令語言,也可以作為作業系統的命令檔語言用來控制電腦如何執行,稱為 Shell Script。
  • 指令語言直譯器 (command language interpreter):是指令直譯器,也是程式語言。作為指令直譯器,提供各式指令。作為程式語言,這些指令可以組合起來,建立包含指令的檔案成為一個指令,客製化用戶環境來自動化完成日常工作。
基本上,shell 就是執行指令的巨集處理器,擴展 text 及符號來建立較大的表示式。

shell 可以同步地或非同步地執行指令。同步的話,shell 等候指令完成才讀取下個指令。非同步的話,現行指令跟 shell 再去執行下個指令持續並行進行。轉向架構允許精確控制指令的輸出入。再則,shell 可設定指令執行環境的內容。

shell 提供內建指令實作一些外部程式不方便處理的功能,例如 cd、break、continue、及 exec 直接處置 shell 自己,無法在外部程式實作。history、getopts、kill、或 pwd 等內建指令可以在外部實作,但使用內建指令較方便。

雖然 shell 執行指令是重要的基本功能,大部分複雜的地方在於內建程式語言功能,像許多高階語言,shell 也提供變數、流程控制架構、quoting、及函數。

shell 特別為互動使用提供許多功能,包括 job control、指令行編輯、command history 及 aliases。

IO 導向

Shell 變數字串處理
正規表示式
外部命令
expr
應用
參考:
延伸閱讀

星期二, 11月 19, 2013

使用 Lua 的應用程式

使用 Lua 的應用程式
  • lua -- Lua interpreter
  • luac -- Lua compiler
  • 許多遊戲,例如 WoW、Angry Bird
  • Web Server
    • LightTPD supports the FastCGI, SCGI, and CGI interfaces to external programs。Understand and harness Lua/FastCGI
    • uHTTPd
    • haserl
    • lighttpd
    • Apache
  • OpenWrt device configuration, iwinfo
  • Security: scripting vulnerability scanners (nmap, Wireshark, Snort), iptables
  • Scripting and template language for Wikipedia
  • Embedded software: printers (Olivetti, Océ), routers (Cisco), telephones (FreeSwitch, Asterisk) and smartphones (several, including Huawei), smart tvs (Samsung), Logitech keyboards, Lego Mindstorms...
  • Adobe Photoshop Lightroom
  • VLC, Tex, vim, nginx...
參考:
  1. http://www.dcc.ufrj.br/~fabiom/lua/00Introduction.pdf
  2. 本站 Lua 相關文章

Lua 課程

http://www.dcc.ufrj.br/~fabiom/lua/

參考:
  1. 本站 Lua 相關文章

Lua C API 概述

Lua 實際上是指 C 函式庫 liblua,必須寄居在某個應用程式下才能使用,所以是一個嵌入式語言 (embedded language)。而 lua 這個獨立 (stand-alone) 應用程式,只是一個 Lua 的小外殼,少於 500 行程式碼,提供一個使用者界面方便使用 Lua,真正執行 Lua 程式碼的不是外殼,而是 Lua。Lua 嵌入式語言的角色 ,使得它成為應用程式的擴展語言 (extension language),讓應用程式得以使用 Lua 的設施 (facilities),來擴展應用程式的功能。

另外,Lua 也是一個可擴展的語言 (extensible language),可在 Lua 環境下用其它語言 (例如 C) 來擴展 Lua 所沒有的新功能。

就 Lua 的擴展語言及可擴展語言兩個角色,皆可使用 C 語言。Lua 可作為 C 語言的擴展語言,C 實作為應用程式,使用 liblua 提供 Lua 環境來擴充 Lua 語言功能。反過來,C 也可以擴展 Lua 語言,提供 Lua 沒有的功能。這兩者使用相同的 API 跟 Lua 溝通,稱為 C API,包括一些函數:讀寫 Lua 全域變數,呼叫 Lua 函數,運行 Lua 程式碼,登記 C 函數好讓能被 Lua 呼叫,等等。

跟 Lua 是完全不同的是,C API 延續 C 嚴謹的特性。在寫 C 語言程式時,必須注意類型 (type) 檢查,錯誤處理,memory-allocation 錯誤等。大多數 API 中的函數不檢查參數的正確性,在呼叫函數之前,必須確保參數是對的。否則,可能出現「segmentation fault」或類似的激烈結果,而不是委婉的告訴你錯誤訊息。此外,API 強調靈活性和簡易性,而不是易用,常見的工作可能要呼叫好幾個 API 函數,但讓你完全控制所有細節,比如錯誤處理,緩​​衝區大小等等。

Lua 和 C 之間通信中的重要組成部分是虛擬堆疊。幾乎所有的 API 都對這個堆疊裡的值操作。所有從 Lua 到 C 及從 C 到 Lua 的資料交換都是經過這個堆疊。此外,可以使用堆疊來存放中間結果。堆疊有助於解決 Lua 和 C 之間的兩個不匹配:一是 Lua 使用垃圾收集 (garbage collection),而 C 需要明確的釋出記憶體;二是來自 Lua 使用動態類型 (dynamic typing),而 C 使用靜態類型 (static typing)。

正如標題所說,本章是一個概述,不用急著去理解所提到的所有細節。稍後會補上那些細節。然而,不要忘了,可以在 Lua 參考手冊找到特定功能的更多細節。此外,可以在 Lua 的分佈 (distribution) 本身找到幾個使用 API 例子。獨立的 Lua 直譯器 (lua.c) 提供應用程式的例子,而標準庫 (lmathlib.c,lstrlib.c 等) 提供 Lua 的函式庫的例子。

參考:
  1. 本文翻譯 Programming in Lua, 1st ed.§24 – An Overview of the C API,並加以修改整理。
  2. 本站 Lua 相關文章

星期一, 11月 18, 2013

OpenWrt WebUI

OpenWrt 的 WebUI 主要有三種:LuCI、X-Wrt Webif、及 Gargoyle。

LuCI
  • Web Server 預設用 uhttpd
  • 使用 Lua 命令檔語言
X-Wrt Webif
  • Web Server 用 busybox httpd
  • shell + awk + haserl 命令檔語言
Gargoyle:基於 OpenWrt 的發行版本,有較易用的 GUI 介面及其它特別的功能,例如:可以對特定 IP 限制頻寬、主動式 QoS

haserl 是一個命令檔語言,本身編譯後約只有 20k,可在 HTML 檔嵌入 shell scripts 作為伺服器端命令檔,產生最終的 HTML 檔案。haserl 程式碼:
  • 本身是執行檔,首行是 #!/usr/bin/haserl
  • 其它內容是 HTML 格式,需要動態產生的部份用 <? ?> 包起來,執行 shell script 產生
參考:
  1. http://wiki.openwrt.org/doc/howto/webinterface.overview
  2. Web Server Comparisons -- 一些網頁伺服器比較,其中 thttpd 似乎不錯。而 gargoyle_httpd 是基於用 fork 的 mini_httpd,效能可能較差。
延伸閱讀:十大易用性原則

星期日, 11月 17, 2013

Lua 文章

Lua 是個輕小的指令檔語言 (Scripting Language),由於巴西在 1977 ~ 1992 年對電腦軟硬體進行嚴格的貿易管制,買不到只好自己開發,Pontifical Catholic 大學的大型實驗室 Tecgraf 在前身 DEL、SOL 發展後而誕生。特性
  • 容易和 C/C++ 間互相呼叫,擴充性極高
  • ...
本站 Lua 相關文章規劃:(參考自 Programming in Lua)
    Part I · The Language
  1. Getting Started (Hello World)
  2. Types and Values
    • 2.1 Nil
    • 2.2 Booleans
    • 2.3 Numbers
    • 2.4 Strings
    • 2.5 Tables
    • 2.6 Functions
    • 2.7 Userdata and Threads
  3. Expressions
    • 3.1 Arithmetic Operators
    • 3.2 Relational Operators
    • 3.3 Logical Operators
    • 3.4 Concatenation
    • 3.5 Precedence
    • 3.6 Table Constructors
  4. Statements
    • 4.1 Assignment (多值指定)
    • 4.2 Local Variables and Blocks
    • 4.3 Control Structures
      • 4.3.1 if then else
      • 4.3.2 while
      • 4.3.3 repeat
      • 4.3.4 Numeric for
      • 4.3.5 Generic for
    • 4.4 break and return
  5. Functions
    • 5.1 Multiple Results
    • 5.2 Variable Number of Arguments
    • 5.3 Named Arguments
  6. More about Functions
    • 6.1 Closures
    • 6.2 Non-Global Functions
    • 6.3 Proper Tail Calls
  7. Iterators and the Generic for
    • 7.1 Iterators and Closures
    • 7.2 The Semantics of the Generic for
    • 7.3 Stateless Iterators
    • 7.4 Iterators with Complex State
    • 7.5 True Iterators
  8. Compilation, Execution, and Errors
    • 8.1 The require Function
    • 8.2 C Code
    • 8.3 Errors
    • 8.4 Error Handling and Exceptions
    • 8.5 Error Messages and Tracebacks
  9. Coroutines
    • 9.1 Coroutine Basics
    • 9.2 Pipes and Filters
    • 9.3 Coroutines as Iterators
    • 9.4 Non-Preemptive Multithreading
  10. Complete Examples
    • 10.1 Data Description
    • 10.2 Markov Chain Algorithm
  11. Part II · Tables and Objects
  12. Data Structures
    • 11.1 Arrays
    • 11.2 Matrices and Multi-Dimensional Arrays
    • 11.3 Linked Lists
    • 11.4 Queues and Double Queues
    • 11.5 Sets and Bags
    • 11.6 String Buffers
    • 11.7 Graphs
  13. Data Files and Persistence
    • 12.1 Data Files
    • 12.2  Serialization
      • 12.2.1 Saving Tables without Cycles
      • 12.2.2 Saving Tables with Cycles
  14. Metatables and Metamethods
    • 13.1 Arithmetic Metamethods
    • 13.2 Relational Metamethods
    • 13.3 Library-Defined Metamethods
    • 13.4 Table-Access Metamethods
      • 13.4.1 The __index Metamethod
      • 13.4.2 The __newindex Metamethod
      • 13.4.3 Tables with Default Values
      • 13.4.4 Tracking Table Accesses
      • 13.4.5 Read-Only Tables
  15. The Environment
    • 14.1 Accessing Global Variables with Dynamic Names
    • 14.2 Declaring Global Variables
    • 14.3 Non-Global Environments
  16. Packages
    • 15.1 The require Function
    • 15.2 The Basic Approach for Writing Modules
    • 15.2 Privacy
    • 15.3 Packages and Files
    • 15.4 Using the Global Table
    • 15.5 Other Facilities
    • Using Environments
    • The module Function
    • Submodules and Packages
  17. Object-Oriented Programming
    • 16.1 Classes
    • 16.2 Inheritance
    • 16.3 Multiple Inheritance
    • 16.4 Privacy
    • 16.5 The Single-Method Approach
  18. Weak Tables
    • 17.1 Memoize Functions
    • 17.2 Object Attributes
    • 17.3 Revisiting Tables with Default Values
  19. Part III · The Standard Libraries
  20. The Mathematical Library
  21. The Table Library
    • 19.1 – Array Size
    • 19.2 – Insert and Remove
    • 19.3 – Sort
    • Concatenation
  22. The String Library
    • Basic String Functions
    • 20.1 Pattern-Matching Functions
    • 20.2 Patterns
    • 20.3 Captures
    • Replacements
    • 20.4 Tricks of the Trade
  23. The I/O Library
    • 21.1 The Simple I/O Model
    • 21.2 The Complete I/O Model
      • 21.2.1 A Small Performance Trick
      • 21.2.2 Binary Files
    • 21.3 Other Operations on Files
  24. The Operating System Library
    • 22.1 Date and Time
    • 22.2 Other System Calls
  25. The Debug Library
    • 23.1 Introspective Facilities
      • 23.1.1 Accessing Local Variables
      • 23.1.2 Accessing Upvalues
    • 23.2 Hooks
    • 23.3 Profiles
  26. Part IV · The C API
  27. An Overview of the C API
    • 24.1 A First Example
    • 24.2 The Stack
      • 24.2.1 Pushing Elements
      • 24.2.2 Querying Elements
      • 24.2.3 Other Stack Operations
    • 24.3 Error Handling with the C API
      • 24.3.1 Error Handling in Application Code
      • 24.3.2 Error Handling in Library Code
  28. Extending your Application
    • The Basics
    • 25.1 Table Manipulation
    • 25.2 Calling Lua Functions
    • 25.3 A Generic Call Function
  29. Calling C from Lua
    • 26.1 C Functions
    • 26.2 C Libraries
  30. Techniques for Writing C Functions
    • 27.1 Array Manipulation
    • 27.2 String Manipulation
    • 27.3 Storing State in C Functions
      • 27.3.1 The Registry
      • 27.3.2 References
      • 27.3.3 Upvalues
  31. User-Defined Types in C
    • 28.1 Userdata
    • 28.2 Metatables
    • 28.3 Object-Oriented Access
    • 28.4 Array Access
    • 28.5 Light Userdata
  32. Managing Resources
    • 29.1 A Directory Iterator
    • 29.2 An XML Parser
  33. Threads and States
    • 30.1 Multiple Threads
    • 30.2 Lua States
  34. Memory Management
    • 31.1 The Allocation Function
    • 31.2 The Garbage Collector

其它

romfs

romfs 是一個非常精簡、唯讀、block-based 的檔案系統,沒壓縮,所有檔案 root 擁有。

genromfs

特性

  • 只保留作為一個檔案系統的最小需求:
    • No modification dates
    • No unix permissions

用途

每 個 Linux 系統都至少需要配合一個檔案系統來執行,而大多其他檔案系統含有許多功能,不適合在某些資源較吃緊的情況下使用,這時改用 romfs 就很完美。例如:可以把壓縮過的 Linux kernel 放在 romfs 裡,給認得 romfs 的 bootloader 解壓縮放到 RAM 中執行。

延伸閱讀

  1. http://romfs.sourceforge.net/
  2. Kernel /Documentation/filesystems

星期六, 11月 02, 2013

ATtiny


ATtinypinIOinstsregistersFlashSRAMEEPROMPeripheralHardware
ATtiny4/9645416x8512/1024320PWMhttp://hackaday.com/tag/attiny9/
ATtiny5/10PWM, ADChttp://hackaday.com/tag/attiny10/
ATtiny13
ATinty13A
8612032x81K6464PWM, ADChttp://hackaday.com/tag/attiny13/
ATtiny25
ATtiny45
ATtiny85
2/4/8K128/256/512PWM, ADC, USIi2c-tiny-usb
Digispark
ATtiny24
ATtiny44
ATtiny84
1412PWM, ADC, USI, Temperaturehttp://hackaday.com/tag/attiny24/
http://hackaday.com/tag/attiny44/
http://hackaday.com/tag/attiny84/
ATtiny2011216x82K1280PWM, ADC, SPI, TWIPWM
ATtiny2313201812032x82K128128PWM, ADC, USI, USARTUSBtinyISP


星期二, 10月 29, 2013

Asterisk call transfer context

這幾天抓 transfer 問題剛好看到程式裡 transfer 用的 context 怎麼決定的

次序是
  1. transferer 的 TRANSFER_CONTEXT
  2. transferee 的 TRANSFER_CONTEXT
  3. transferer 的 macrocontext
  4. transferer 的 context
TRANSFER_CONTEXT 應該是 dialplan 可以設定的變數
macrocontext 是什麼我就不清楚了

參考:
  1. Asterisk channel indications for transferee

星期一, 10月 28, 2013

OpenWrt feed for Asterisk

asterisk-1.8.x
  • svn://svn.openwrt.org/openwrt/packages (net 目錄) 
    • 33541 複製成 svn://svn.openwrt.org/openwrt/branches/packages_12.09/net/asterisk-1.8.x@33626
      • 34123 更新 lantiq channel driver
    • 34121 最後一版
    • 36485 移除 (36502 移除目錄)
  • http://feeds.openwrt.nanl.de/openwrt/telephony.git
    • 100f27f3 (Fri Jun 21 13:55:47 2013) 跟 34121 的差異
      • 增加套件 asterisk18-pgsql, asterisk18-pbx-lua
      • asterisk18-cdr 及 asterisk18-odbc 的 conffiles 及 install 不同
asterisk-11.x
  • svn://svn.openwrt.org/openwrt/packages (net 目錄) 
    • 35954 最後一版
    • 36485 移除 (36502 移除目錄)
  • http://feeds.openwrt.nanl.de/openwrt/telephony.git
dahdi-linux & dahdi-tools

asterisk-1.4.x
參考:
  1. OpenWrt Feeds (提供一些 feeds 連結)

星期六, 10月 26, 2013

上網費

客服來電推銷升級 6M,因為原本上傳速度慢了些,所以有點心動,但最後還是維持 4M,Wi-Fi 目前也用不用。

2013/10/26

下載/上傳合計Hinet 上網費電路費老客戶八五折
ADSL4M/128K473269
(原價 299)
204427=254+173
ADSL5M/384K526296
(原價 329)
230476=280+196
光世代
VDSL + Wi-Fi
6M/2M699341
358499 綁約 2 年
註:ADSL 上網費好像有特別降價,但老客戶還是以原價來打折

星期二, 8月 27, 2013

Ralink Ethernet Driver

OpenWrt 有 Ralink Ethernet Driver

module init
  • debugfs 初始化 (選擇性)
  • esw 初始化
  • 註冊 platform driver:登記 probe 及 remove 函數
platform driver 的 probe 函數
  • get memory base
  • alloc ether net dev
  • get irq
  • 登記 net dev ops:包括 init, uninit, open, stop, start_xmit, tx_timeout, ... 等函數
  • 設定 net dev priv data
  • 註冊 net dev
net dev 的 init 函數
  • ...
  • hardware init
    • request irq
    • alloc 256 rx_info, 256 tx_dma, 256 rx_dma, one skb per rx_info
    • 初始化 tx_dma, 初始化 rx_info dma_addr (來自 skb), 初始化 rx_dma
    • set macaddr to SoC
    • 初始化 SoC tx_dma, rx_dma
    • set sys_freq to SoC
    • tasklet init: tx & rx
    • other SoC init
net dev 的 open 函數
  • ...
net dev 的 start_xmit 函數
  • ...
net dev 的 tx_timeout 函數
  • ...
封包接收
  • ...
硬體加速
  • Hardware NAT, QoS, TCP/UDP/IP checksum offloading
延伸閱讀

星期三, 8月 21, 2013

Linux bridge

將電腦當作 Ethernet Switch 使用,除了原有的 Ethernet 介面外,需要再多一個 Ethernet 介面,例如用 USB Ethernet,方便第三者抓封包 (註:用既有的 Ethernet Switch 搭配 ettercap 也可以抓封包,參照《第三者 Ethernet 抓封包》)。

Ethernet Switch 的工具軟體在 bridge-utils
sudo apt-get install bridge-utils

軟體 Ethernet Switch 設定
sudo ifconfig eth0 0.0.0.0
sudo ifconfig eth1 0.0.0.0
sudo brctl addbr br0
sudo brctl addif br0 eth0
sudo brctl addif br0 eth1
sudo dhclient br0

設定在 /etc/network/interfaces 的話,新增
auto br0
iface br0 inet dhcp
然後
sudo vi /etc/network/interfaces
sync && sudo init 6

參考:
  1. http://www.linuxfoundation.org/collaborate/workgroups/networking/bridge
  2. Ubuntu 12.04 & 12.10 調校備忘 的 Network bridge
延伸閱讀

寫程式用字型

下載字型檔會開啟「字型檢視程式」,然後按「安裝」就可以使用。
或者放到 ~/.local/share/fonts/,執行 fc-cache -f -v。

Monaco (來自 Apple Inc.)
Consolas (來自 Microsoft)
  • 搜尋「Consolas.ttf」可以找到
設定
cp /etc/fonts/conf.d/69-language-selector-zh-tw.conf ~/.config/fontconfig/fonts.conf
vi ~/.config/fontconfig/fonts.conf # 修改 monospace 那段如下方
fc-cache -f -v
修改內容,只保留
 <?xml version="1.0"?>
<!DOCTYPE fontconfig SYSTEM "fonts.dtd">
<fontconfig>
    <!-- Set fonts selection for zh-tw monospace -->
    <match target="pattern">
        <test qual="any" name="family">
            <string>monospace</string>
        </test>
        <test name="lang">
            <string>zh-tw</string>
        </test>
        <edit name="family" mode="prepend" binding="strong">
            <string>Monaco</string>
            <!--string>Microsoft JhengHei</string-->
        </edit>
    </match>
</fontconfig>

註:放字型的目錄
  • ~/.local/share/fonts/
  • /usr/share/fonts/
註:字型相關程式:fc-cache, fc-list 等

參考文章:
  1. Programmer 專用最佳字型 - Monaco font
  2. Monaco + LiHei 字型優化 on Ubuntu 10.04+
  3. Linux 安裝與使用
  4. 電腦漢字體
  5. Ubuntu 14.04 LTS 中文修正 (刪除不需要的設定檔,修改設定檔) 

OpenWrt 套件定義的 KCONFIG

OpenWrt 套件都要定義
define Package/套件名

define KernelPackage/套件名
裡面的一些參數,例如 TITLE:= 是填顯示的標題名稱。

其中有一項是 KCONFIG:=,預設是空的,可用來增加 Kernel 的設定,例如 package/hostap-driver/Makefile 的 define KernelPackage/hostap,就有設定
KCONFIG:=CONFIG_HOSTAP CONFIG_HOSTAP_FIRMWARE=y CONFIG_HOSTAP_FIRMWARE_NVRAM=y
,如果選了 hostap 套件,Kernel 設定就會增加

CONFIG_HOSTAP=m
CONFIG_HOSTAP_FIRMWARE=y
CONFIG_HOSTAP_FIRMWARE_NVRAM=y
,對應到 Kernel 程式,包括外部模組,就會有

#define CONFIG_HOSTAP_MODULE
#define CONFIG_HOSTAP_FIRMWARE
#define CONFIG_HOSTAP_FIRMWARE_NVRAM

的定義。

套件額外的選單設定 define Package/套件名/config 只影響 OpenWrt 的設定,且不會有對應的程式碼定義。

星期六, 8月 17, 2013

OpenWrt Unified Configuration Interface

Unified Configuration Interface (UCI) 是 OpenWrt 的設定環境,大部分的設定都使用 UCI,然而還有一些設定並不在 UCI

使用 UCI 的設定檔是文字檔,放在 /etc/config/ 目錄下,可以用文字編輯器編譯,也可以透過 uci 指令存取,或者其它程式 API 存取,例如 shell script 的 /lib/config/uci.sh、C library /lib/libuci.so、lua library /usr/lib/lua/uci.so 等,適合用於資源有限不好執行一個資料庫的環境。

uci 設定檔有三層架構
  1. <config>:/etc/config/ 下的設定檔檔名
  2. <section>、<section-type>:每個設定檔內容分成許多 config 開始的 section,section 有 <section-type>。格式是:
    config <section-type> [<section>]
    <section> 是 section 的名稱,可有可無。沒有 section 名稱時用 @<section-type>[index] 的方式存取。
  3. <option>、<value>:每個 section 有 option 或 list。
uci 設定檔格式
config section-type section-name
config section-type
option option-name option-value
list option-name option-value
# 開始為註解註界
config 表示一個 section 開始,type 是必要的,讓程式決定如何應用。可以沒有 name,稱為 anonymous section。
option 提供選項 name 到 value 的對應,list 單一 name 可以有多個 value。

檔案範例 /etc/config/foo
# cat /etc/config/foo

config bar first
        option name 'Mr. First'
config bar
        option name 'Mr. Second'
config bar third
        option name 'Mr. Third'
        list kid aaa
        list kid bbb
首先這裡存在 <config> 檔 foo,內容分成許多 config 開頭的 section,每個 section 有 option 或 list。範例裡 <section-type> 都是 bar。每個 option 定義一對<option> 及 <value>,而 list 讓一個 <option> 有許多 <value>。

<config>、<section>、<section-type>、<option>、<value>

uci 指令:
# uci
Usage: uci [<options>] <command> [<arguments>]

Commands:
        batch  
        export     [<config>]
        import     [<config>]
        changes    [<config>]
        commit     [<config>]
        add        <config> <section-type>
        add_list   <config>.<section>.<option>=<string>
        show       [<config>[.<section>[.<option>]]]
        get        <config>.<section>[.<option>]
        set        <config>.<section>[.<option>]=<value>
        delete     <config>[.<section[.<option>]]
        rename     <config>.<section>[.<option>]=<name>
        revert     <config>[.<section>[.<option>]]
        reorder    <config>.<section>=<position>

Options:
        -c <path>  set the search path for config files (default: /etc/config)
        -d <str>   set the delimiter for list values in uci show
         -f <file>  use <file> as input instead of stdin
        -L         do not load any plugins
        -m         when importing, merge data into an existing package
        -n         name unnamed sections on export (default)
        -N         don't name unnamed sections
        -p <path>  add a search path for config change files
        -P <path>  add a search path for config change files and use as default
        -q         quiet mode (don't print error messages)
        -s         force strict mode (stop on parser errors, default)
        -S         disable strict mode
        -X         do not use extended syntax on 'show'

透過 <config>.<section>.<option> 存取 <value>,而透過 <config>.<section> 取到的是 <section-type>。<section> 可用特定 <section-type> 的 index 表示法取代,index 從 0 開始,第一個是 @<section-type>[0]。也可以從後面數,此時 index 是負的,從 -1 開始,最後一個是 @<section-type>[-1]。
# uci get foo.first
bar
# uci get foo.first.name
Mr. First
# uci get foo.@bar[0].name
Mr. First
# uci get foo.@bar[1].name
Mr. Second
# uci get foo.@bar[-1].name
Mr. Third
# uci get foo.third.kid
aaa bbb
要注意的是 uci show [<config>] 時,會顯示所有的 <section-type> 及 <value>,<section-type> 的 index 不計有 <section> 的,所以可能會有所不同。
# uci show foo
foo.first=bar
foo.first.name=Mr. First
foo.@bar[0]=bar
foo.@bar[0].name=Mr. Second
foo.third=bar
foo.third.name=Mr. Third
foo.third.kid=aaa bbb


新增
uci add <config> <section-type>
uci set <config>.<section>=<section-type>

touch /etc/config/pbx
uci set pbx.201=user
uci set pbx.201.CFUC=202
uci commit pbx

參考:
  1. http://wiki.openwrt.org/doc/uci
  2. http://wiki.openwrt.org/doc/techref/uci
  3. Using UCI as stand alone (使用範例)
  4.  https://openwrt.org/docs/guide-user/base-system/uci
待續:
  • 設定/新增
    • uci  set <config>.<section>[.<option>]=<value>
    • uci add <config> <section-type>
    • uci add_list <config>.<section>.<option>=<string>
    • uci commit [<config>]
    • uci revert     <config>[.<section>[.<option>]]
  • 其它
    • uci batch
    • uci export [<config>]
    • import     [<config>]
    • changes    [<config>]
    • delete     <config>[.<section[.<option>]]
    • rename     <config>.<section>[.<option>]=<name>
    • reorder    <config>.<section>=<position>

星期五, 8月 16, 2013

Linux MODULE_LICENSE

MODULE_LICENSE("許可證") 會在產生 .ko 檔裡面的 .modinfo section 放 "lincense=許可證" 的資訊,可用 objdump 去看。

其中,只有許可證是 "GPL", "GPL v2", "GPL and additional rights", "Dual BSD/GPL", "Dual MIT/GPL", "Dual MPL/GPL" 之一,才認為是 GPL 相容。

如果不是 GPL 相容,有下列影響:
  • 關掉 debug_locks (作用不是很清楚),並顯示「Disabling lock debugging due to kernel taint」
  • 不能用 EXPORT_SYMBOL_GPL 的函數,這個應該是最大的限制
  • 污點 (存在 tainted_mask) 紀錄有使用非 GPL 相容的模組。其它污點有模組強迫載入等,只是除錯用的紀錄。

Network Interface Checksum Offload

如果網路界面硬體有提供計算 TCP/UDP/IP Checksum 功能,這樣軟體就可以省下計算的負擔。

TCP/UDP/IP Checksum 基本上是使用 16-bit 1's complement 相加,也就是用一般的 16-bit 相加,再把進位加進來。這對 32-bit 處理器而言,使用 16-bit 相加,全部進位會累積在高位元的 16-bit,最後再把高位元的 16-bit 加進來,有可能再進位所以再加一次高位元的 16-bit。

IP checksum 只計算 IP header 的部份 (20 bytes),任何一個欄位改變,例如 time-to-live 每經過一個 router 減一,就要重算。而 TCP/UDP checksum 計算的範圍包括 TCP/UDP header 跟 data,以及來自 IP header 的一些欄位 (pseudo header),計算份量較多。雖然經過 router 不需要重算,但經過 NAT router 時 IP 變了則需要重算,這會對原本處理器效能就不高的 NAT home router 造成一些負擔。不過 UDP checksum 是選擇性的,可以不算,填 0 就好。TCP checksum 是不能省略的。

ICMP header checksum?

Tx Checksum Offload

首先需設定 net_device features,告訴 Kernel 硬體有什麼 checksum 功能,Kernel 就不會去算:
  • NETIF_F_IP_CSUM:TCP/UDP over IPv4 的 checksum
  • NETIF_F_IPV6_CSUM:TCP/UDP over IPv6 的 checkcum
  • NETIF_F_HW_CSUM:以上兩者
再來 hard_start_xmit() 或 ndo_start_xmit() 時,如果 skb 的 ip_summed 有設 CHECKSUM_PARTIAL,表示需要硬體去產生 checksum。

Rx Checksum Offload

netif_rx()netif_receive_skb() 前,將 skb ip_summed 設為 CHECKSUM_UNNECESSARY,表示不需要再算 checksum,包括 loopback 界面也不需要算 checksum。

net_device features 可設定 NETIF_F_RXCSUM 來紀錄有 Rx Checksum Offload 功能。

參考

  1. Linux kernel source
  2. TCP/IP Illustrated, Volume 1 The Protocols, W. Richard Stevens

相關文章

最後更新 20200721

TUN and TAP: Virtual Network Device

在某些情況,需要軟體提供虛擬的網路界面,方便網路應用程式使用,例如 VPN 或 Virtual Machine 等。

VPN 是對 WAN 網路連線做加密等保護,讓你覺得好像在使用 LAN 環境一樣安全,所以 VPN 程式會去攔截 WAN 界面所有往來的封包,加以改良,加上 VPN header、資料加密等。但為了讓本來就有的網路應用程式不用更改,VPN 程式提供另一個軟體虛擬的網路界面給網路應用程式使用。

Virtual Machine 是用軟體模擬的一台電腦,常常需要提供網路界面給外界存取,又很有可能沒有多餘的、實體的網路界面可用,於是提供虛擬的網路界面,搭上母體電腦的 bridge 或 router。

虛擬網路界面一般有兩種,TAP 跟 TUN。TAP (network tap) 就是 Ethernet 插座的意思,模擬 Ethernet 設備的網路介面,可送收 L2 封包作為 bridge。而 TUN (network tunnel) 模擬成網路層的設備,可送收 L3 封包,跟 routing 搭配使用。

在 Linux,TUN 跟 TAP 都是由 tun 驅動程式實作,載入時會建立一個 /dev/net/tun 的 char device 。當 user-space 程式 (通常是常駐的 daemon 程式) 開啟 /dev/net/tun 並 ioctl TUNSETIFF 做設定,便會建立虛擬的網路介面。此時網路應用程式就可以透過 ifconfig 設定 IP 等啟用建立的虛擬網路介面,開始送收封包。

參考文獻
  1. TUN/TAP [Wikipedia]
  2. tun 驅動程式原始碼:drivers/net/tun.c 
相關文章

Linux timeout by jiffies

之前這篇提到,Linux 的 udelay() 以迴圈延遲 1µs。每個 tick 可以跑 loops_per_jiffy 個延遲迴圈,一秒就是 loops_per_jiffy * HZ 個迴圈,1µs 就是 loops_per_jiffy * HZ / 1000000 個迴圈。mdelay() 或 ndelay() 也是類似的作法。但這些函數都是 busy waiting,等待時不能做其它事。

jiffies 是 Linux 全域變數,每 1/HZ 秒會自動加一,可用來判斷 timeout。範例如下:

unsigned long timeout;

timeout = jiffies + HZ/2; /* 500 ms timeout */

do{
        /* do something */
        if (some_state)
                break;
} while (time_after(timeout, jiffies)); /* 500ms timeout */

jiffies 跟 time_after 定義在 inclue/linux/jiffies.h。

相關文章

星期三, 8月 14, 2013

Network Interface Packet Reception

網路界面驅動程式有兩種接收封包的方式 -- 中斷驅動和 NAPI。傳統是用中斷驅動,在中斷服務程式裡接收封包,但封包量大時會有中斷次數太多而效能變差的問題。NAPI (意思是 New API) 改成中斷服務程式只通知有封包,Kernel 再排程一次接收多個封包來提昇效能。

中斷驅動方式
  • 收到 frame 呼叫中斷服務程式
  • 在中斷服務程式通常依封包大小 dev_alloc_skb() 取得 sk_buff 放入封包,struct net_device *dev 指到網路界面、辨別 protocol (什麼時候用到?)、填寫ip_summed 等參數,最後呼叫 netif_rx()。
  • 每個處理器有個 softnet_data,netif_rx() 將 sk_buff 放到執行中斷處理器的 softnet_data 的 input_pkt_queue。如果原本 input_pkt_queue 是空的,執行netif_rx_schedule() 將 backlog_dev 加到 softnet_data 的 poll_list 並啟用 NET_RX_SOFTIRQ。如果 input_pkt_queue 大於 netdev_max_backlog 表示滿了,則 drop 並回傳 NET_RX_DROP,可知道壅塞程度。
  • 技巧:預先以最大封包為考量取得 skb,讓封包直接接收到 skb。change_mtu() 可知道最大封包大小。
NAPI 用 polling 方式接收封包,底層需要有數個封包的 buffer 放新進封包,當已知有封包進來的情況下,kernel 才擇時去執行 net_device 的 poll 函數並一次將 buffer 中的全部封包接收。這段時間如有新封包再進來,不需要再通知 kernel。當封包流量大時,例如每秒幾千個封包,可以大大減少中斷的次數,降低 kernel 分心。
  • 初始化:net_device 設 poll 函數及 weight,weight 說明界面的重要度,不可超過可 buffer 封包的數目。
  • 封包進來的中斷呼叫 netif_rx_schedule() 就好,kernel 會排程用 poll 去取封包。
  • poll 函數一次最多接收 budget 或 quota 個封包,一樣呼叫 dev_alloc_skb() 取得 skb,放進收到的封包,設定 skb dev、protocol、ip_summed 等參數,但最後是呼叫 netif_receive_skb()。如果接收的封包都處理了,呼叫 netif_rx_complete(),並啟用中斷。
NAPI 有另一個好處,需要拋棄封包時,也可以在收進 kernel 之前就處理掉。例如網路子系統壅塞,可以只收額定的封包。

NAPI 還有更新的改進,從 net_device 獨立出 napi_struct 資料結構,改由驅動程式提供。好處是一個界面可以有多個 napi_struct 來對應硬體支援 multiple receive queues。此外使用的函數也大多不同,如下表:
\中斷驅動NAPINew NAPI
初始化-
  • 登記 net_device poll 函數
  • netif_napi_add() 加入一個 napi_struct 並登記 poll 函數
  • napi_enable
中斷服務程式dev_alloc_skb()
複製封包、設定參數
netif_rx
netif_rx_schedule()napi_schedule()
接收封包dev_alloc_skb()
複製封包、設定參數
netif_receive_skb
buffer 處理完畢-netif_rx_complete()napi_complete()
結束使用--napi_disable()
netif_napi_del()
註:skb 可以事先準備,在初始化時就 dev_alloc_skb

參考:
  1. LDD3 ch17
  2. Newer, newer NAPI
  3. 每個接收封包會在 netif_rx() 或 netif_receive_skb() 執行 netpoll_rx() 一次。
  4. Understanding the Linux Kernel, 3rd Edition 的 4.7 Softirqs and Tasklets (說明 softirq)
相關文章
延伸閱讀
  • Linux Network Scaling: Receiving Packets
    • RSS (Receive Side Scaling)
    • RPS (Receive Packet Steering)
    • RFS (Receive Flow Steering)
    • aRFS (Accelerated Receive Flow Steering)
  • Linux network stack, Packet ingress flow, NAPI interruption coalescence, zero-copy (DMA, mmap())
最後更新 20200721

GPT

GUID Partition Table (GPT) 是一種新的硬碟分割表,擺脫 MBR 分割表 2.2TB 的限制,使用 GUID (Globally Unique IDentifier) 來表示分割的用途。

MBR 分割表使用 32-bit logic block addressing (LBA),所以有 512 bytes x 232 = 2.2 TB 的限制,除非改用較大的 logic block (也就是 sector 大小)。而 GPT 使用 64-bit LBA,大大地擺脫這個限制。

雖然 GPT 是 UEFI 的一部分,但可以獨立使用。64-bit 的Windows Vista/7/8 支援 GPT,並且必須是 UEFI 模式開機。而 Linux 支援 GPT,可用 Legend BIOS 開機;UEFI 開機的話,需要 64-bit Linux。
圖片來自 Wikipedia

GPT 的結構如圖,LBA 0 放 MBR,以便於跟 MBR 相容,當作 MBR 硬碟使用。接下來 LBA 1 放 GPT Header,內含指示分割表 (Partition Entry Array) 在哪裡,通常是 LBA 2。然後從 LBA 2 開始就是分割表,至少預留 16,384 bytes。每個 Partition Entry 預設為最小的 128 bytes,可有 16,384 ÷ 128 = 128 entries,用來表示 128 個分割。

如果 sector 大小是 512 bytes,16,384 bytes 需要 32 sectors,所以分割表佔 LBA 2 到 LBA 33,分割就從 LBA 34 開始。但實際上為了對齊,可能預留更大的分割表空間,例如從 LBA 40 (對齊 4KB sector)、LBA 63 (對齊 cylinder boundary)、或 LBA 2048 (對齊 1 MiB) 開始。在硬碟的最後面,會有 GPT Header 跟分割表的備份。

參考:
  1. GUID Partition Table
相關文章:

星期三, 8月 07, 2013

OpenWrt telnet

要能 telnet,telnetd 需要執行。我想設計的理念是剛安裝完,root 沒密碼,此時便執行 telnetd,所以 telnetd 在特定條件下才會執行。

/etc/init.d/telnet:

#!/bin/sh /etc/rc.common
# Copyright (C) 2006-2011 OpenWrt.org

START=50

has_root_pwd() {
 local pwd=$([ -f "$1" ] && cat "$1")
       pwd="${pwd#*root:}"
       pwd="${pwd%%:*}"

 test -n "${pwd#[\!x]}"
}

get_root_home() {
 local homedir=$([ -f "$1" ] && cat "$1")
 homedir="${homedir#*:*:0:0:*:}"

 echo "${homedir%%:*}"
}

has_ssh_pubkey() {
 ( /etc/init.d/dropbear enabled 2> /dev/null && grep -qs "^ssh-" /etc/dropbear/authorized_keys ) || \
 ( /etc/init.d/sshd enabled 2> /dev/null && grep -qs "^ssh-" "$(get_root_home /etc/passwd)"/.ssh/authorized_keys )
}

start() {
 if ( ! has_ssh_pubkey && \
      ! has_root_pwd /etc/passwd && ! has_root_pwd /etc/shadow ) || \
    ( ! /etc/init.d/dropbear enabled 2> /dev/null && ! /etc/init.d/sshd enabled 2> /dev/null );
 then
  service_start /usr/sbin/telnetd -l /bin/login.sh
 fi
}

stop() {
 service_stop /usr/sbin/telnetd
}

包括:
  1. 沒有 ssh pubkey 且
  2. 沒有 root password 且
  3. ssh server (dropbear 或 sshd) 未啟用 (註:)
註:未啟用 (not enabled) 未必未執行 (not started),有無啟用是檢查對應的 /etc/rc.d/Sxxx 是否存在

再來,telnet 進來的 login script 是 /bin/login.sh

#!/bin/sh
# Copyright (C) 2006-2011 OpenWrt.org

if ( ! grep -qs '^root:[!x]\?:' /etc/shadow || \
     ! grep -qs '^root:[!x]\?:' /etc/passwd ) && \
   [ -z "$FAILSAFE" ]
then
 echo "Login failed."
 exit 0
else
cat << EOF
 === IMPORTANT ============================
  Use 'passwd' to set your login password
  this will disable telnet and enable SSH
 ------------------------------------------
EOF
fi

exec /bin/ash --login
會再檢查一次 root passwd (但方式不同)

OpenWrt package Config.in

有時候套件需要額外設定,可在 menuconfig 選單新增選項
  1. package 的 Makefile 新增定義 define Package/套件名稱/config 或 define KernelPackage/套件名稱/config,例如
  2. 
    define Package/uhttpd/config
      config PACKAGE_uhttpd_debug
        bool "Build with debug messages"
        default n
    endef
    

    或者
    
    define Package/busybox/config
            source "$(SOURCE)/Config.in"
    endef
    

    可以直接寫在裡面,或者寫在另一個檔案。$(SOURCE) 是 Makefile 同一目錄。
  3. package 的 Makefile 可以對新增的選項參數做 ifdef-endif 等判斷,可能用來決定一些編譯參數等。
  4. make menuconfig 套件的選擇下會多出 Configuration  --->
  5. 預設設定如果要跟設定檔不同,且要存下來的話,可能只能自己存一個 .config 到其它地方,裡面有填好 TARGET 及你要的特別設定,複製到 .config,然後 make defconfig 產生完整的 .config,包含其它預設設定。[參考]

OpenWrt package 範例:
  1. package/busybox -- 可能是最大的範例
  2. 搜尋,用「grep 'define .*\/config\>' package/*/Makefile」

星期日, 7月 21, 2013

Asterisk channel indications for transferee

撥通後,被轉接 (Blind transfer 或 Attended transfer),從 channel .indicate 收到的 indicatations
  1. RINGING (3):遠端振鈴,該聽到 ringback tone
  2. -1:遠端接通,該停止 ringback tone
  3. SRCUPDATE (20)
  4. 數個 SRCUPDATE 加上 HOLD (16):遠端進行 Attended transfer,該聽到 Music on hold
  5. UNHOLD (17)、RINGING (3):遠端振鈴,持續 Music on hold 或變為 ringback tone
  6. SRCCHANGE (26)、CONNECTED_LINE (22):轉接完成,停止 Music on hold 或 ringback tone
  7. SRCUPDATE (20)

星期二, 7月 16, 2013

一篇 awk 文章筆記

如何在 Linux 與 GnuCash 上使用 Awk 進行文字搜尋與排序

筆記:awk
  • 處理文字檔案的命令檔語言
  • 將檔案中的每一行視為個別的記錄,一行中的每一個項目則是個別的欄位。
  • 對每一行都會套用一個「樣式{動作}」,如果符合樣式,就執行指定的動作。如果沒有樣式,表示對每一行都執行該項動作;如果沒有動作,表示要顯示符合樣式的行。
  • 經典的方式是以 /etc/passwd 來作說明,列出 UID 與用戶名稱
    • $ awk -F":" '{ print $3 " " $1 }' /etc/passwd 
    • -F 用來定義欄位分隔字元,預設是 tab 或空白
    • $0 代表整行,$3 是第三個欄位 UID,$1 是第一個欄位用戶名稱
  • 搜尋文字,顯示區塊 (grep 難以作到)
    • 語法:awk '/開始樣式/,/結束樣式/'
    • 從完整 lspci 輸出中找出特定設備
      • $ lspci -v | awk '/VGA/,/^$/'
      • /^$/ 會找出文字區塊間的空白行
  • 截取不重複記錄並儲存在新的檔案中 
    • $ awk '!x[$0]++' filewithdupes > newfile
  • 要對正規表示式有不錯的理解,作者推薦 Mastering Regular Expressions 這本書

星期日, 7月 14, 2013

IP CAM = Web CAM + Wi-Fi router

有 USB 的 Wi-Fi router 安裝 OpenWrt、Web CAM 驅動程式、mjpg-streamer,接上 Web CAM,就變成 IP CAM

相關文章

FIVN Asterisk Management GUI

FIVN 的 Asterisk GUI 可以查看 Asterisk 設定、狀態、紀錄檔,也可以編輯 Asterisk 設定檔,適合用在資源有限、並提供 CGI 的網頁伺服器。提供 non-commercial 使用,commercial 用途則需詢問原作者。

整個 GUI 相當精簡,只有下列檔案:
  • asterisk.html:Asterisk GUI 網頁,實際上只是用來載入下列 js 檔及 css 檔,產生網頁內容。
  • asterisk.js, main.js:產生網頁的 JavaScript,並透過 AJAX 去網頁伺服器取得需要的資料或執行動作。
  • settings.js:網頁顯示設定
  • style.css, loading.gif
  • asterisk.sh:在網頁伺服器端負責執行動作的 shell script,包括取得資料、儲存檔案等。
  • readme.txt:說明檔

在網頁伺服器資源有限的環境,就要利用瀏覽器端較充足的記憶體及運算能力,使用 JavaScript 產生網頁,用 AJAX 去網頁伺服器只取得必要的資料或執行必要的動作。網頁伺服器需要支援 CGI 以便呼叫 asterisk.sh,處理 AJAX 的 HTTP POST 請求,會有 action 參數指示要執行什麼動作,而可能需要其它額外參數,包括 command (Asterisk 指令)、file (Asterisk 設定檔檔名)、content (檔案內容)。

雖然只是個精簡的 GUI,Asterisk 的設定需要透過直接編輯 Asterisk 設定檔完成,但可作為不錯的參考。

關於 CGI (Common Gateway Interface):
  • CGI 是網頁伺服器呼叫外部程式的界面,有點像是副程式。網頁伺服器判斷瀏覽器要請求的網址是 CGI 程式時,就會將請求的參數存在環境變數後去呼叫 CGI 程式,並將請求的內容透過標準輸入傳給 CGI 程式。網頁伺服器會將 CGI 程式執行結束的回傳資料 (標準輸出) 傳給瀏覽器。
  • 網頁伺服器需要靠 CGI 程式產生動態資料 (未必是 HTML 網頁,例如給 JavaScript 的資料為未必是 HTML 格式),不然只能取到靜態資料。
  • CGI 程式可以用任何支援的程式語言撰寫,只要能接收輸入並回傳結果。
  • 可能會有安全問題。
  • 一個 CGI 介紹及範例:http://ind.ntou.edu.tw/~dada/cgi/

星期六, 7月 13, 2013

Digispark

Digispark 是基於 Attiny85 微控器的 USB 發展板,類似 Arduino,但較便宜、較小、較省電,可使用 Arduino IDE。使用軟體 USB,主機需要安裝 Digispark USB driver,而不是使用一般的 USB to serial 驅動程式。8 KB flash 中 bootloader 佔 2KB,另外有 512B RAM、512B EEPROM。

電源可來自 USB 或外接 5V,或者外接 7~35V 透過板上的 regulator 轉換。Attiny85 只有 8 根接腳,除了 5V 跟 GND 外,有 6 I/O 接腳:
  • 2 for USB 燒錄程式用,之後可作為 I/O
  • I²C and SPI (via USI)
  • PWM on 3 pins
  • ADC on 4 pins
相關文章

星期二, 7月 09, 2013

lua interpreter

指令 lua 是 Lua 直譯器 (interpreter),可執行文字檔或 bytecode 格式的 Lua 命令檔,也可以用在互動模式。

指令格式:

lua 首先會執行環境變數 LUA_INIT 的內容,LUA_INIT 也可以是「@filename」格式,會去執行 filename 的內容。

script 是 Lua 命令檔,整個指令行每個欄位會變成執行 script 時,名為「arg」的全域表格,其中
  • arg[0]:是 script
  • arg[1] 開始分別是每一個 args,每個 args 如果有空格或其它 shell 特殊字元,則需要加 quoted。shell 會移除這些 quotes。
  • #arg:args 的數目,也等於最後 argument 的 index
  • arg 負的 index 包括 script 前面的指令行,一直到 interpreter 名稱。
範例:
編輯 hello.lua,內容如下:(說明:print("印出的字串"),用「..」結合字串)
# this line ignored
print("number args:"..#arg)
print("arg[-2]:"..arg[-2])
print("arg[-1]:"..arg[-1])
print("arg[0]:"..arg[0])
print("arg[1]:"..arg[1])
print("arg[2]:"..arg[2])
print("arg[3]:"..arg[3])
在 shell 執行指令
LUA_INIT='print("LUA_INIT first")' lua -v arg.lua Hello Word "last arg"
其輸出如下:
LUA_INIT first
Lua 5.1.5  Copyright (C) 1994-2012 Lua.org, PUC-Rio
number args:3
arg[-2]:lua
arg[-1]:-v
arg[0]:arg.lua
arg[1]:Hello
arg[2]:Word
arg[3]:last arg
可看出 lua 先執行 LUA_INIT,然後選項 -v 顯示版本訊息,最後才是執行 arg.lua 的結果,印出 args 數目及所有 args,其中 last arg 中間有空格,所以需要用 quote。

script 檔案的第一行如果是「#」開頭,會忽略。如果寫成「#!/usr/bin/lua -v」,在 Linux 檔案就可以直接執行。

指令「luac arg.lua」會將 arg.lua 編譯成二進位的 lua bytecode 程式 luac.out,用法跟 arg.lua 一樣,只是加速 lua 載入時間,不用再編譯成 bytecode。bytecode 檔並不表示執行較快,或檔案較小。

指令「lua -e stat」直接執行 lua statement stat。例如「lua -e 'print("Hello Word")'」

指令「lua -」執行來自 stdin 的 lua 程式,例如「echo 'print("Hello Word")' | lua -」

lua option「-l name」用來載入 library,相當於呼叫 require('name') 。

只執行指令「lua」進入互動模式,prompt the user and execute lines from the standard input。輸入 end-of-file 字元結束,在 Linux 是 Ctrl-D, 在 DOS/Windows 是 Ctrl-Z (Ctrl-Z 在 Linux 會讓程式進入背景執行), 或呼叫來自 os library 的 os.exit()。
  • lines are read until a complete statement is formed or a syntax error is found 
  • 一種中斷不完整的 statement,強迫 syntax error 的方式是輸入「;」。
  • If a line starts with '=', then lua displays the values of all the expressions in the remainder of the line. The expressions must be separated by commas.
  • The default prompts are "> " and ">> ". The global variables _PROMPT and _PROMPT2 can change the prompts.
「lua -i script」在執行完 script 也會進入互動模式

References
  1. man lua
  2. man luac
  3. 本站 Lua 相關文章

星期六, 3月 09, 2013

[OpenWrt] patch 管理及 quilt

OpenWrt 編譯環境會去抓程式的原始檔來 patch 使用。當原始檔版本更新時,只需要更新 OpenWrt 的 Makefile,修改抓取的版本,再執行
make package/xxx/refresh

make target/linux/xxx/refresh
就可以一次更新所有相關的 patch 檔。當然,這是理想狀況,實際上可能會有衝突發生。

OpenWRT 內部是靠 quilt 來管理 patch 檔的,在製作自己的 patch 檔時,需要
make package/xxx/{clean,prepare} QUILT=1 V=99
cd built_dir/target-yyy/xxx/ 下的編譯目錄
執行需要的 quilt 及編輯指令
最後,回到原本目錄,執行 make package/xxx/update

make target/linux/xxx/{clean,prepare} QUILT=1 V=99
cd built_dir/linux-xxx/xxx/ 下 Linux Kernel 的編譯目錄
執行需要的 quilt 及編輯指令
最後,回到原本目錄,執行 make target/linux/xxx/update
複製 patch 檔到該有的目錄

為了讓上述執行 quilt 指令產生的 patch 檔跟 OpenWrt 產生的格式一致,需設定 ~/.quiltrc 如下:
QUILT_DIFF_OPTS="-p"
QUILT_REFRESH_ARGS="-p ab --no-index --no-timestamps"
參考:
  1. OpenWrt: Working with patches
  2. Jserv's blog: quilt - 強大的 patch 管理工具
  3. git 產生 patch 檔

星期日, 2月 24, 2013

Raspberry Pi Boot Process

Raspberry Pi 的 SoC 是 BCM2835,看起來只能從 FAT32 的 SD 卡開機。以下是開機程序:
  1. [GPU] 執行 on-chip ROM,從 SD 卡載入 bootcode.bin 到 L2 cache。(一開始 ARM core 跟 SDRAM 是停用的)
  2. [GPU] 執行 bootcode.bin,啟用 SDRAM,並從 SD 卡載入 start.elf 到 SDRAM。(以前還有一個 loader.bin 步驟,現在整合在一起)
  3. [GPU] 執行 start.elf,讀取 config.txt、cmdline.txt 及 kernel.img,啟用 ARM (另外不確定是否還有 bcm2835.dtb)
  4. [ARM] 開始 Linux kernel booting,kernel.img 就是 kernel,而 cmdline.txt 放 kernel 開機參數。kernel 的 rootfs 可以是另一個分割
上述韌體可在 https://github.com/raspberrypi/firmware 取得,GPU 部份的原始碼並未開放。


參考:
  1. http://www.raspberrypi.org/phpBB3/viewtopic.php?f=63&t=6685
  2. https://github.com/dwelch67/raspberrypi (一些 non-OS 的低階程式)

[iptables] xt_recent

300 秒內最多只能有 10 次 ssh 連線嘗試

iptables -t filter -A "input_wan" -p "tcp" --dport 22 -m recent --set --name SSH_CHECK
iptables -t filter -A "input_wan" -m recent --update --seconds 300 --hitcount 10 --name SSH_CHECK -j DROP

指令格式
iptables -t filter -A "input_wan" 規則:新增規則到 filter 表格的 input_wan 鏈

使用 xt_recent 模組建立兩個規則,前者將 TCP port 22 連線的來源 IP 位址紀錄到名為 SSH_CHECK 的列表。後者更新列表,找出最近 300 秒內出現 10 次以上的連線,drop 掉它

/proc/net/xt_recent/* 可看或設定列表

http://snowman.net/projects/ipt_recent/ 有其它例子,詳細說明可見 `man iptables`

延伸閱讀

PWM 轉成聲音輸出

下面是從 Raspberry Pi Rev.20 電路圖剪下來的,只需要簡單的電路,就可以將 PWM 轉成聲音輸出
至於如何將 PCM 轉換成 PWM 訊號又是另一個問題。

Raspberry Pi 的 SPI

Raspberry Pi 使用 BCM2835,而 BCM2835 共有 1 組 SPI slave 跟 3 組 SPI master (SPI0, SPI1, SPI2),其中只有 SPI0 透過 Raspberry Pi 的 P1 接出,如下表。


Chip-SelectMISOMOSISCLK
Raspberry Pi
SPI slaveGPIO 21GPIO 20GPIO 18GPIO 19
只有部份接出 (P1, S5)
SPI0 masterGPIO 7/8GPIO 9GPIO 10GPIO 11
接到 P1
GPIO 35/36GPIO 37GPIO 38GPIO 39
未接出
SPI1 masterGPIO 16/17/18GPIO 19GPIO 20GPIO 21
只有部份接出 (LED, P1, S5)
SPI2 masterGPIO 43/44/45GPIO 40GPIO 41GPIO 42
只有部份接出 (S6)
Picture from http://ruten-proteus.blogspot.tw/2012/10/raspberry-pi-model-b.html

除了一般 3-wire SPI 外,SPI0 亦可將 MISO 跟 MOSI 合併成一條雙向的訊號,或者作為 LoSSI (Low Speed Serial Interface) 的 master。運作模式支援 polling、interrupt 及 DMA。

參考文獻
  1. BCM2835 ARM Peripherals datasheet
  2. Raspberry Pi 電路圖
  3. http://elinux.org/RPi_Low-level_peripherals

星期六, 2月 23, 2013

忽略 stdout 及 stderr 輸出

Linux 下要忽略 stdout 及 stderr 時,會將兩者輸出重新導向 /dev/null,常常看到的寫法是指令後面加上「>/dev/null」及「2>&1」。前者將標準輸出,也就是 stdout (檔案編號 1),導向 /dev/null。後者將檔案編號 2,也就是 stderr,導向已經導向 /dev/null 的檔案編號 1。在孤島日誌的《Unix 重新導向跟 2>&1》有細節解說。


此外「&>/dev/null」將所有輸出,不單只有 stdout 跟 stderr,全部導向 /dev/null。上述孤島日誌的作者查了一下回答說這是 bash 專用語法,不是 POSIX 標準語法。

另外「>/dev/null 2>/dev/null」是不是也可以呢?有什麼不同呢?

延伸閱讀
  • csh/tcsh 導向是用「> & file」