2011年6月16日 星期四

Introduction to IPsec

IPsec protocols主要可以分為兩大種類:

1. packet handling
主要工作是將 normal IP packets 轉成 secure IPsec packets
對packets修改的動作有以下幾種,
加密(encryption)
解密(decryption)
簽章(signing)
封裝(encapsulation)
解封裝(decapsulation)

因為由於對packets的修改動作要求速度、效率以及低延遲
所以這些動作都由 kernel 來完成

2. trust relationship management

2010年10月8日 星期五

憑證格式的介紹與轉換

X.509是常見通用的憑證格式標準
其他跟憑證有關係的標準則都定義在 PKCS 當中
PKCS 為 Public-Key Cryptography Standard 的縮寫
目前共發布過15個標準,細節可參考 Reference 中的wiki

管理存儲憑證常用的格式有以下幾類:[from wikipedia 公開金鑰密碼編譯標準]
PKCS#6 證書擴展語法標準(Extended-Certificate Syntax Standard)
將原本X.509的證書格式標準加以擴充。

PKCS#7 密碼訊息語法標準(Cryptographic Message Syntax Standard)
規範了以公開金鑰基礎設施(PKI)所產生之簽章/密文之格式。
其目的一樣是為了拓展數位證書的應用。其中,包含了S/MIME與CMS。

PKCS#10 證書申請標準(Certification Request Standard)
規範了向證書中心申請證書之CSR(certificate signing request)的格式。

PKCS#12 個人訊息交換標準(Personal Information Exchange Syntax Standard)
定義了包含私鑰與公鑰證書(public key certificate)的文件格式。
私鑰採密碼(password)保護。常見的PFX就履行了PKCS#12。

X.509 DER encoding 的 postfix 為 .der (BINARY)
X.509 PEM encoding 的 postfix 為 .pem (ASCII)
<格式轉換>
$ openssl rsa -in privatekey.pem -inform PEM -out privatekey.der -outform DER
$ openssl rsa -in privatekey.der -inform DER -out privatekey.pem -outform PEM

PKCS#7 常用的 postfix 有 .p7b .p7c .spc
p7b 以樹狀展示 certficate chain,不含 private key

PKCS#12 常用的 postfix 有 .p12 .pfx(MS)
p12/pfx 用於存放 certificate 加 private key
將此兩樣打包的過程中會要求輸入 Export Password 來保護這個p12檔案
相反地,你要取用p12檔案中的個別資訊時,就需要輸入 Import Password來解開保護
*Import/Export Password為同樣一組,只是方向不同







[Reference]
公開金鑰密碼編譯標準
http://zh.wikipedia.org/zh-hk/公開金鑰密碼編譯標準
常见证书格式及相互转换
http://355665.blog.51cto.com/345665/265679

2010年8月3日 星期二

OpenSSL Certificate Management

#
# 製作 RSA Private Key,並且將 Key 設定為只有 owner 才能存取的權限
#
openssl genrsa -out myhost.key.pem 2048
chmod og-rwx myhost.key.pem

*** genrsa 是 openssl 產生 rsa key 用的 command ***
*** -out 是表示 output 的 key name ***
*** 2048 是 key 的強度,一定要放在最後面 ***


#
# 填寫憑證申請書
#
openssl req -new -key myhost.key.pem -out myhost.req.pem

*** req 是 openssl 產生 CSR 用的 command ***
X.509 Certificate Signing Request (CSR) Management
*** -new 是產生新的 certificate request ***
*** -key 是指定要從哪邊讀 private key ***
*** -out 是表示 output 的 request name ***


#
# 顯示憑證申請書
#
openssl req -text -noout -in myhost.req.pem

*** -text 是印出 CSR 的 text form ***
*** -noout 是不要印出 CSR 的 encoded form ***
*** -in 表明要處理的 request file ***


#
# 簽憑證 (CA certificate)
#
openssl x509 -req -days 7305 -sha1 \
-extfile ~/etc/ssl/openssl.cnf -extensions v3_ca \
-signkey ~/etc/ssl/private/myrootca.key.pem \
-in ~/tmp/myrootca.req.pem -out ~/etc/ssl/certs/myrootca.crt.pem

*** x509 是證書資料管理的 command ***
*** -req 特別表示處理的是 request file,一般都是 certificate ***
*** -days 表明證書的有效天數 ***
*** -sha1 表示要使用的 digest 演算法 ***
*** -extfile 表示包含 certificate extensions 的檔案 ***
file containing certificate extensions to use
If not specified then no extensions are added to the certificate
*** -extensions v3_ca ***
the section to add certificate extensions from
*** -signkey 表示要用哪一把 private key 去 self-sign request ***
this option causes the input file to be self signed using the supplied private key


#
# 簽憑證 (Server certificate)
#
openssl x509 -req -days 3650 -sha1 \
-extfile ~/etc/ssl/openssl.cnf -extensions v3_req \
-CA ~/etc/ssl/certs/myrootca.crt.pem -CAkey ~/etc/ssl/private/myrootca.key.pem \
-CAserial ~/etc/ssl/myrootca.srl -CAcreateserial \
-in /tmp/myhost.req.pem -out ~/etc/ssl/certs/myhost.crt.pem

*** -CA ***
specifies the CA certificate to be used for signing
*** -CAkey ***
sets the CA private key to sign a certificate with.
If this option is not specified then it is assumed that the CA private key is present in the CA certificate file
*** -CAserial ***
sets the CA serial number file to use
*** -CAcreateserial ***
with this option the CA serial number file is created if it does not


#
# 顯示憑證
#
openssl x509 -text -noout -in myhost.crt.pem



[Reference]
如何製作 SSL X.509 憑證
http://www.imacat.idv.tw/tech/sslcerts.html

OpenSSL official Documents
http://www.openssl.org/docs/apps/openssl.html

2010年7月16日 星期五

major number 和 device node 以及 device driver 間的關係

每個 device 會有一組 (Major number, Minor number) 來作為區別的資訊

到 /dev 資料夾底下,使用 ls -l 就可得到各個 device node的資訊

以 ppp 這個 device node為例,ls -l 輸出如下
crw------- 1 root root 108, 0 Apr 21 12:46 ppp

前面的 permission field 中,第一個字元 c 表示這個 device 是 char device
接下來介於 Group name 之後,Modification date 之前
就是 ppp 這個 device 的 (major number, minor number) 資訊 108,0

有了 device node 與 (major,minor) 之間關係的觀念後

接下來就來探討 device driver 和 (major,minor) 有什麼樣的關係

關係圖:device node --- (major,minor) --- device driver

恰巧,這個關係也就是為什麼 kernel 能正確找到 device 其所有的 driver 的原因

答案很簡單

device driver 需要向 kernel 註冊其所屬 device 的 (major,minor) pair

接下來就來解釋為什麼會有(major,minor)這樣的資訊存在


在系統中新增一個硬體,許多環節彼此相扣
  1. hardware
  2. driver
  3. Linux OS 中配給硬體的 dev node (在 /dev 底下)

driver 向 kernel 註冊一些 handler software 以及一些 hardware 資源 (io ports,etc)
好讓 kernel 得知此 hardware 的存在,並且接受此 hardware 的 interrupt

在 /dev 底下需要替這個 hardware 新建一個 device node 好讓 kernel 可以使用它
但這項工作不是 driver 的 job
因此需要手動建立這個 device node

而 device node 的 (major,minor) 資訊
需要和 driver 中向 kernel 註冊的 (major,minor) 一樣

因此 kernel 就可經由 (major,minor) 搭建起來的橋樑找到 hardware 和 driver 的關連

也就是此關係圖:device node --- (major,minor) --- device driver

Linux 驅動程式的中斷處理

轉貼自 Jollen 的 Blog

Linux 驅動程式的中斷處理, #1: request_irq 基本觀念
http://www.jollen.org/blog/2008/03/interrupt_handling_1.html

Linux 驅動程式的中斷處理, #2: 深入淺出中斷模式
http://www.jollen.org/blog/2008/03/interrupt_handling_semaphore.html

Linux 驅動程式的中斷處理, #3: Bottom Half 的觀念
http://www.jollen.org/blog/2008/03/interrupt_handling_bottom_half.html


[Reference]
http://www.jollen.org/cgi-bin/mt3/mt-tb.cgi/481

2010年6月30日 星期三

網路安全工具 - nmap

nmap - Network Mapper

Network exploration tool and security / port scanner


-PN [No Ping]
$ nmap
This option skips the Nmap discovery stage altogether.
Normally, nmap uses this stage to determine active machines for heavier scanning.
Used to be -P0 <- it's a nubmer zero, not a character O


-sL [List Scan]
$ nmap -sL 192.168.1.0/24
列出子網路所有IP及對應的主機名稱,但不作ping及通訊埠偵測
(degenerate form of host discovery without sending any packets)


-sP [Port Scan]
$ nmap -sP 192.168.1.0/24
僅使用ping掃瞄子網路內的所有IP,並列出有回應的IP,不作進一步測試


-PS [TCP SYN Ping]
$ nmap -PS 192.168.1.1
偵測遠端主機已開啟的通訊埠
為縮短掃瞄時間,可指定特定的port number,例如 -PS22,23,80,25
This option sends an empty TCP packet with the SYN flag set.
-remote host responds with a RST packet (The queried port is closed)
-remote host responds with a SYN/ACK packet (The queried port is open)
利用的原理是 TCP 3-way-handshake mechanism
A --SYN--> B
A <--SYN/ACK-- B
A --ACK--> B


-PU [UDP Ping]
$ nmap -PU 192.168.1.0/24
使用UDP協定 ping 遠端的主機。


-sS [TCP SYN scan]
$ nmap -sS 192.168.1.0/24
使用 TCP SYN packet 掃瞄,這是一個半開放的掃瞄方式,
三方交握不會完成,所以掃瞄速度較快,也比較常被使用。
此選項可以列出有回應的遠端主機已開啟的網路服務埠。


-sT [TCP connect scan]
$ nmap -sT 192.168.1.0/24
如無法以 TCP SYN packet 掃瞄時,就得改用 socket API connect() 來掃瞄
在這種情況底下,connection 會被正式建立完成,花費的時間也較- sS 選項多


-sU [UDP scan]
$ nmap -sU 192.168.1.0/24
用 UDP 協定掃瞄遠端主機群


-sO [IP protocol scan]
$ nmap -sO 192.168.1.1
偵測遠端主機已開啟哪些通訊協定 TCP,UDP,ICMP,等等


-O [Enable OS detection]
nmap -O 192.168.1.1
nmap -A 192.168.1.1
偵測遠端主機的作業系統類型


-v -vv -vvv [Increase verbosity level]
nmap -v scanme.nmap.org
掃瞄遠端主機,並列出相關詳細的資訊


[example]

$ nmap -sS -O 192.168.1.0/24
以 SYN 掃瞄網域為192.168.1.0所屬 C class 網段的所有存在的主機作業系統類型

-sV [Version detection]
-p [Only scan specified ports]
$ nmap -sV -p 22,53,110,143,4564 198.116.0-255.1-127
進行主機列表及TCP掃瞄特定網路服務,-p 指定 22,53,110,143,4564 這幾個 port
遠端主機的網路含括 198.116.(0-255).(1-127) 網段
(version detection is used to determine what application is running)

-iR [Choose random targets]
$ nmap -v -iR 100000 -P0 -p 80
隨機選擇100000台主機,偵測是否開啟 Web 服務,
由於此掃瞄較耗時,所以加上 -P0(ie,-PN) 不作 active machines detection。
(The argument -iR 0(zero) can be specified for a never-ending scan)


[Reference]
http://nmap.org/book/man.html
http://idobest.pixnet.net/blog/post/22040775

2010年6月29日 星期二

虛擬網卡 TUN/TAP 工作原理

TUN/TAP是一個虛擬網卡的介面,在 Linux 以及 window$ 上面都有支援
一些 VPN projects 像是 OpenVPN 都是基於這個介面實現 tunneling 的機制

tun (network TUNnel) 虛擬的是 點對點 設備
-simulates a network layer device
-layer 3 packets, such as IP packet
-used with routing

tap (network TAP) 虛擬的是 乙太網路 設備
-simulates an Ethernet device
-layer 2 packets, such as Ethernet frames
-used to create a network bridge

下圖是原作者麻利輝所畫的簡圖 (請查閱Reference中的網頁)



以下就已建立好的 VPN 連線來探討封包流經的順序:

1. Outgoing

首先,應用程式會利用 tun 這個網卡將資料送到 VPN 的 peer去
而這個應用程式正是圖中的「使用tun/tap驅動的進程」
在經過 TCP/IP protocol stack 之後來到 tun (Virtual NIC Part) 成為 VPN 封包

下一步,「數據處理進程(OpenVPN)」
會由 tun ( Char device Part) read 出剛剛的VPN封包
再次丟往 TCP/IP protocol stack,最後到達 Real NIC 而送往「物理鏈路」(外部網路)

下圖是就原圖所做的一點更動,明確表示出資料流的順序


2. Incoming

從物理鏈路收到給 OpenVPN 的封包,
接下來此封包經過 protocol stack 被拔掉一層層的 headers
最後就是原始封包的 data payload 部份,也就是 VPN"封包"

OpenVPN 再把這個 VPN"封包"經由 tun (Char device part) write 到 Virtual NIC

Virtual NIC 收到封包後,再把他送往 protocol stack
最後就回到使用 tun interface 的應用程式

圖例與 outgoing 一樣,只是數字順序相反


[Reference]
虛擬網卡 TUN/TAP 驅動程序設計原理 by 麻利輝
http://www.ibm.com/developerworks/cn/linux/l-tuntap/index.html
TUN/TAP - Wikipedia
http://en.wikipedia.org/wiki/TUN/TAP

2010年6月28日 星期一

Linux的防火牆 - iptables

防火牆的概念在鳥哥的網站有很棒很詳盡的介紹
鳥哥關於防火牆的介紹文章網址放在reference中

下圖是鳥哥所簡化的 chain 圖,
觀賞度10,實用度10,綜合係數10 (...某足球十大精妙過人影片爛梗XD)



作為普通PC的Linux,其防火牆處理流入本機封包的流程是
1. nat-PREROUTING [跳過]
2. Forward封包轉遞 [走 flow A,因此導向本機 Linux]
3. filter-INPUT [!!本機防火牆主要工作的地方!!]
4. Linux本機的資源
5. nat-OUTPUT [跳過]
6. filter-OUTPUT [!!本機防火牆主要工作的地方!!]
7. nat-POSTROUTING [跳過]

整理以後的流程如下,
1. Forward封包轉遞
2. filter-INPUT --負責把關流入本機的封包
3. Linux本機的資源
4. filter-OUTPUT --負責把關流出本機的封包


===============================================
若是Linux作為NAT(router)的機器,其防火牆處理流入本機封包的流程是
1. nat-PREROUTING --更改 DESTINATION
2. Forward封包轉遞 [走 flow B,NAT]
3. filter-FORWARD
4. nat-POSTROUTING --更改 SOURCE


===============================================
VPN的亂入,tun介面來襲,防火牆流程是?!

首先,先看從VPN安全通道流入的封包
[VPN client] ---> [VPN server with firewall]
(以下內容基於VPN通道已建立好的前提)

一開始,server會從對外開放的 *interface 拿到封包
(*interface,例如擁有 Public IP 的 eth0,:p)
其source IP和destination IP都是public的
source IP 是 client 的 public address
destination IP 是 server 的 public address
也就是該 server 對外的 interface 上的 IP

所以一開始是判斷為流入本機的封包
因此 forward 到 filter-INPUT 檢查
接下來就進入Linux存取本機資源

通過 Protocol Stack,在封包被拔掉 header 之後
便交由 application layer 的 VPN program 處理
此時會發現 application data payload 又是一個"封包"
其 source IP 和 destination IP 都是 private 的
source IP 是 client 的 VPN private address (通道建立過程中,由 server 分配)
destination IP 是:
1. server 的 VPN private address (表示存取 VPN server 本機資源)
2. LAN 內 VPN private address (表示存取企業內部網路的資源,VPN server as NAT-Router)

接下來,就是TUN上場的時候了
這個 VPN program 會把這個"封包"往本機上名為 tun 的 virtual interface 丟
然後呢....

tun 也是主機上的一個 interface (雖然是虛擬的),所以收到"封包"的時候
防火牆處理的過程也跟其他實體 interface 一樣,需要通過罩杯的考驗

在封包進來 tun interface 之後,若是封包是要傳給 server 的
則封包會被 forward 到 filter-INPUT 處理
(由此可知,VPN的使用也需要對防火牆做好適當的設定,免得VPN封包被擋掉...)

過了 filter-INPUT之後,進入本機
一樣也是通過 Protocol Stack,一層層的 header 被拔掉
最後就可以到達 server 的 application layer... finally :)

廢話連篇,一圖解千文



在封包進來 tun interface 之後,若是封包是要傳給 Private LAN 其他主機的話
則封包會被 forward 到 filter-FORWARD 處理

以下是廢圖二連發



[Reference]
鳥哥的Linux私房菜 - 防火牆與NAT
http://linux.vbird.org/linux_server/0250simple_firewall.php

2010年6月10日 星期四

Dynamic Programming

There is an ordering on the subproblems, and a relation that shows how to solve a subproblem given the answer to "smaller" subproblems, that is, subproblems that appear earlier in the ordering.

解釋之,就是一個問題可以細分為許多小問題,而這些分解下去的小問題之間又有順序上的關係,使得小問題的答案可以成為大問題答案的基石。

一般來說,我們會以陣列的形式來依序儲存小問題的答案,以供後續大問題解答時使用。

經典問題包含:
背包問題 (knapsack)
最長遞增序列 (Longest increasing subsequences)


[Reference]
Chapter 6 DP, from "Algorithms"
by S. Dasgupta, C.H.Papadimitriou, and U.V. Vazirani

2010年5月29日 星期六

GNU automake manual 筆記

在正常遵循 GNU 標準的 packages(套件) 內容中
標準的安裝程序就是
  1. $ ./configure
  2. $ make
  3. $ make install (或許需要sudo)
第一步的 configure 檔案
會去偵測該 package 所在主機上的一些設定
以及檢測一些相依性 package 是否存在
最後產生一個符合該主機的 Makefile 供下一步的 make 使用

以上所述為 native compilation 的情況
也就是 package 是在要使用該 package 的主機上編譯

在 cross compilation 的情況下事情就變得有些棘手

首先 configure 原先是要偵測主機上的設定
但現在 package 是要在 HOST machine 上編譯 (ex. X86)
最後是安裝在 TARGET machine 上執行 (ex. arm)

所以要是直接執行 configure 的話
偵測到的是 HOST 上的設定,而非 TARGET 的

舉個顯例,configure 假設去抓 HOST 上 CC 變數的設定 (C Compiler)
會得到 CC=gcc,可是這個 gcc 是編出 x86 binary 使用的
並非我們要的 arm binary compiler
所以 configure 要抓的 CC 變數應該是 CC=linux-arm-gcc

那要怎麼做才能讓 configure script 在 cross compilation 的情形下
得到 TARGET machine 上的偵測設定值呢?

這個學問真是太高了 XDDD 撒謀啊


以下的參考是慢慢演進的,會說是參考表示他可能不是正確解答
google 過這個議題,但找不到顯而易見的解答,只好自己 try and error
--------------------------------------------------------------------------------------------------------

首先提及幾個 configure script 可使用的參數 (可用./configure -h 查看)

[GNU automake manual text]
--build=BUILD
The system on which the package is built.

--host=HOST
The system where built programs and libraries will run.

當使用--host參數的時候,configure script 會搜尋這個HOST的 cross-compiling suite
例如說,當設定--host=arm-linux-gnu,則以下的編譯工具會被使用
編譯器 arm-linux-gnu-gcc
連結器 arm-linux-gnu-ld
組譯器 arm-linux-gnu-as

上述的 HOST 的名詞跟先前提到的 HOST machine 中的 HOST 定義剛好相反
這邊要特別注意,一開始沒看 manual 之前,我的 HOST 都給它設成 HOST machine...

為了怕混淆,這裡再特別解釋一次好了
在 cross compilation 的語境中
HOST 指的是進行cross compilation的機器
此處借重HOST的高運算能力來負責編譯的工作
所以一般HOST都是以高效能的 desktop 居多
TARGET 指的是執行程式的目標機器,也就是執行HOST幫忙編譯的程式的目標機器

而在 configure script 的語境中
HOST 指的是執行程式或函式庫的目標機器,BUILD 才是進行 cross compilation 的機器
在 configure 的參數中也剛好有個 --target=TARGET 可以設定
這裡的 TARGET 是設定 Canadian cross 用的,對於一般人用不太到,可以忽略

*Canadian cross (3-way cross-compilation)
簡言之是在A機器 cross-compile 出一個在B機器使用的 cross-compiler
而這個在B機器的 cross-compiler 會產出在C機器使用的 binary


所以在 cross compilation 的環境下
安裝套件的第一步 ./configure 似乎是得到解決的方案

[example]
$ ./configure --build=i686-pc-linux-gnu --host=i586-mingw32msvc

2010年5月21日 星期五

Concurrency and Race conditions

在 semaphore 的術語中,有分為
1.鎖定的 P 動作
2.解鎖的 V 動作

P 動作簡單說就是對 semaphore 的 value 值作遞減(down)的動作
V 動作則恰好相反,他是執行對 semaphore 的 value 值作遞增(up)的動作

而在 Linux kernel function 中
P 動作是以 down 為函式名稱
V 動作則是 up 為函式名稱

down又分為三個函式

void down(struct semaphore* sem);
int down_interruptible(struct semaphore* sem); /*建議使用版本*/
int down_trylock(struct semaphore* sem);

2010年4月28日 星期三

Android 編譯 Native C module

Android編譯環境本身比較複雜,不像普通的編譯環境:
只有頂層目錄下才有Makefile文件,而其他的每個component都使用統一標準的Android.mk。Android.mk文件本身是比較簡單的,不過它並不是我們熟悉的Makefile,而是經過了Android自身build system的很多處理,因此要真正釐清其中的聯繫還蠻複雜的,不過這種方式的好處在於,編寫一個新的Android.mk來給Android增加一個新的Component會比較簡單。

編譯Java程式可以直接採用Eclipse的IDE來完成,這裡就不重複了。
我們主要針對C/C++來說明,下面通過一個小例子來說明,
如何在Android 中增加一個C程式的Hello World:

1. 在$(YOUR_ANDROID)/external 目錄下創建hello目錄,
其中$(YOUR_ANDROID)指的是Android source code所在的目錄。
# mkdir $(YOUR_ANDROID)/external/hello

2. 在$(YOUR_ANDROID)/external/hello/目錄中編寫hello.c文件,
hello.c的內容當然就是經典的HelloWorld程式:

#include stdio.h

int main()
{
printf("Hello World!\n");

return 0;
}



3. 在$(YOUR_ANDROID)/external/hello/目錄編寫Android.mk文件。
這是Android Makefile的標準命名,不要更改。
Android.mk文件的格式和內容可以參考其他已有的Android.mk文件的寫法,
針對helloworld程式的Android.mk文件內容如下:

LOCAL_PATH:= $(call my-dir)

include $(CLEAR_VARS)

LOCAL_SRC_FILES:= \

hello.c

LOCAL_MODULE := helloworld

include $(BUILD_EXECUTABLE)


注意上面LOCAL_SRC_FILES用來指定 source file;
LOCAL_MODULE指定要編譯的module的名字,下一步驟編譯時就要用到;
include $(BUILD_EXECUTABLE)表示要編譯成一個可執行文件,
如果想編譯成動態庫則可用 BUILD_SHARED_LIBRARY,
這些可以在 $(YOUR_ANDROID)/build/core/config.mk 查到。

4. 回到Android source code頂層目錄進行編譯:

# cd $(YOUR_ANDROID) && make helloworld

注意make helloworld中的目標名helloworld就是上面Android.mk文件中
由LOCAL_MODULE指定的module名。編譯結果如下:

target thumb C: helloworld <= development/hello/hello.c target Executable: helloworld (out/target/product/generic/obj/EXECUTABLES/helloworld_intermediates/LINKED/helloworld) target Non-prelinked: helloworld (out/target/product/generic/symbols/system/bin/helloworld) target Strip: helloworld (out/target/product/generic/obj/EXECUTABLES/helloworld_intermediates/helloworld) Install: out/target/product/generic/system/bin/helloworld



5.如上面的編譯結果所示,編譯後的可執行文件存放在
out/target/product/generic/system/bin/helloworld
,通過”adb push”將它傳送到模擬器上,
再通過”adb shell”登錄到模擬器終端,就可以執行了


[Reference]
http://www.j2medev.com/android/ShowArticle.asp?ArticleID=5436

2010年4月27日 星期二

[書評] 嵌入式系統—使用 C 和 GNU 開發工具

花了幾天的時間把這本兩百多頁的薄書看完
個人是覺得內容有一看的價值
不過要花錢入手一本還是緩緩先

這本書有點像是給RD看的小說一樣
技術面其實沒有很深入
可是卻也不會太淺
我覺得有點像雞肋
不太適合初學者與進階者看
好在個人就是在這中間 XD
所以就花了點時間把它看完

可能嵌入式系統的技術真的是太雜太廣
沒辦法有一個專門的介紹
但通盤的講解所帶來的效應就是不深入

這本書在網路上也有原文版電子書
可以google一下,應該不難找
推薦看原文的
O'Reilly 的中文譯者...
我不曉得是翻譯工作太枯燥還是如何
本書章節翻譯品質參庛不齊 (O'Reilly其他本也有這毛病...)
有些地方的語意端詳半天還是不得其解
查看原文才知道其意...
這就是翻譯書的大缺點啊

好險這本書是跟我同事借的
幾天就可以看完的雞肋本
因此沒有浪費錢的感覺 XDrz

順帶一提
今年六月 O'Reilly 要出三本必敗新書
希望不要太貴..

Autotools
A Practioner's Guide to GNU Autoconf, Automake, and Libtool

The Linux Programming Interface
A Linux and UNIX System Programming Handbook

LPI Linux Certification in a Nutshell (3rd)

2010年4月26日 星期一

bitfield 位元欄位

蠻特殊的一種bitwise的宣告方法
可以視方便性與bitmask交換使用

struct
{
     unit8_t bit0 : 1;
     unit8_t bit1 : 1;
     unit8_t bit2 : 1;
     unit8_t bit3 : 1;
     unit8_t nibble : 4;
} foo;

2010年4月23日 星期五

I/O-mapped and Memory-mapped

The first address space is called the memory space and is intended mainly for memory devices;
the second is reserved exclusively for peripherals and is called the I/O space.

However, peripherals can also be located within the memory space,
at the discretion of the hardware designer.
When that happens, we say that those peripherals are memory-mapped and
that system has memory-mapped I/O.
Some processors support only a memory space,
in which case all peripherals are memory-mapped.

2010年4月19日 星期一

Ubuntu 9.10 Koala on ASUS W7S

service pack一包接一包
在不錯的硬體上面跑也是有如老牛龜車的M$ XP
實在是讓人好生失望

話說其實會使用XP也是為了一些PC game
現在開始工作以後
因為沒啥時間玩遊戲
所以必玩的遊戲都要過濾再過濾
想玩的遊戲硬體要求已是W7S不堪應付了
Intel CoreDuo T7300
2.5G RAM
nVIDIA GeForce 8400M G 128MB
以上正是W7S的硬體規格
要拿來跑Diablo III以及StarCraft II
應該會有很大的問題 XD

基於以上廢話的種種原因
決定將W7S的OS換成Ubuntu/Linux

使用的版本是Ubuntu 9.10 Karmic Koala Desktop edition

整個安裝過程就是一個順字
所有的硬體驅動也順利完成
WiFi
Bluetooth
Ethernet
Sound Card
都沒問題啦!

唯一需要手動選擇的只有nVIDIA的官方顯示驅動
因為nVIDIA這片顯卡的Linux驅動程式 source code沒有 open source
所以 Ubuntu community 不推薦使用此種 proprietary driver
也造成此driver不會被自動安裝
但還是可以自行手動選擇安裝此driver

=======
安裝完作業系統後
接下來就是一些使用者程式的選擇

輸入法我選擇使用ibus
只要安裝好語言包
就可以使用其他語言的輸入法
例如
ibus+Chewing (酷音)
ibus+Anthy (日文輸入)

使用到現在也沒有什麼特別問題,穩定。

看影片推薦使用SMPlayer

BT下載推薦 Deluge or 內建的 Transmission

本篇網誌就是在W7S+Ubuntu的組合下完成!

2010年4月15日 星期四

Linux Shell 彩色控制以及色碼簡介

\33[ pattern ; foreground ; background m
YOUR_CONTENT
\33[0m

例如: \33[1;33;40mMYMESSAGE\33[0m
==> 高亮度(1);黃字(33);黑底(40)
  • pattern
0 一般亮度
1 高亮度
4 加底線
5 灰底

[Reference]
Tinux Blog
http://tinux.no-ip.com/wordpress/?p=89

2010年4月14日 星期三

Linux Device Driver note

Linux 驅動程式的類別:
- 字元設備 char device
- 區塊設備 block device
- 網路設備 network device

一些重要的資料結構:
  • Char Device Driver
struct file_operations
struct file
struct inode
  • Block Device Driver
struct block_device
struct block_device_operations
struct gendisk
struct request
  • Network Device Driver
struct net_device
struct sk_buff

2010年4月8日 星期四

archive 程式 ar 簡介 with ranlib

ar ( archive ) 以下節錄自 Linux man page

ar - create, modify, and extract from archives
ar 這支程式可以對 archive(靜態函式庫) 做以下的動作,
create(建造),modify(修改),extract(擷取)

以下列出幾個常用的 options 解釋:

d: delete
=> 將 files 從 archive 中移除
r: replace
=> 將 files 以取代的方式插入 archive 中
u: update
=> 通常r option 是取代所有,但u option 僅會將較 archive中新的 files 插入
v: verbose
=> 顯示執行情況以及額外的資訊

ar uv mylib.a first.o second.o
上述指令就是將兩個obj 檔建立成一個 mylib.a,並且顯示建立過程的執行資訊


ranlib - generate index to archive

ranlib generates an index to the contents of an archive and stores it in the archive. The index lists each symbol defined by a member of an archive that is a relocatable object file.
ranlib這支程式會產生一個index檔,存的是archive的組成內容,並且將這個index也塞入archive中。index 會列出每個 archive 中的 member 所定義的 symbol,這些 member 說穿了就是 relocatable object file (可重定位的目的檔)。

可以使用 nm -s 或者 nm --print-armap 來列出這個 index

跑這支程式的作用是增加 linking 到 library 的速度,而且可以讓在 library 內的 routines 可以互相呼叫,而不必顧慮到這些 routines 在 archive 中的擺置順序。

實際上,GNU ranlib 就是執行 ar -s

2010年3月30日 星期二

IPC facility - Pipes

Process Pipes

#include stdio.h

FILE* popen( const char* command, const char* open_mode );
int pclose( FILE* pipe_stream );

open_mode 必須是 "r" or "w",但不允許同時開放讀寫的權限,
這是 pipe 與一般 file stream 不同的特性

FILE* read_fp;
read_fp = popen( "cat prog.c | wc -l", "r" );
nread = fread( buf, sizeof(char), sizeof(buf), read_fp );
pclose( read_fp );


The Pipe Call

#include unistd.h

int pipe( int file_descriptor[2] );
任何寫到 file_descriptor[1] 的資料,可以從 file_descriptor[0] 讀回來
*資訊的順序是 FIFO

另外由於 file descriptor 是屬於較低階的檔案處理,
所以不可以使用 file streams 相關的函數,
而需要使用較低階的 read 和 write 等等的 system calls來讀寫

一般來說,pipe 都會使用在相關的兩個 process 之間,例如 parent & child
file descriptors 會跨 fork,所以 parent 開啟的 fd,child 會有同樣的值

int pipefd[2]
pipe( pipefd );
pid_t pid = fork();

switch( pid ) {
case 0: /* parent */
close( pipefd[0] ); /* parent 關閉讀的 pipe */
write( pipefd[1], data, sizeof(data) );
break;

case -1: /* error */
exit( 1 );
break;

default: /* children */
close( pipefd[1] ); /* children 關閉寫的 pipe */
read( pipefd[1], data, sizeof(data) );
break;
}


Named Pipe: FIFO

#include sys/types.h
#include sys/stat.h

int mkfifo( const char* filename, mode_t mode );
mode 是設定 RWX 的權限,例如 0666,實際建置結果還要看系統的 mask 設定
mkfifo 執行成功後,就會產生一個 pipe file
例如 prwxr-xr-x ...... /tmp/myfifo
之後就使用 open, close, read, write 等低階函數來操作它

open 一個 pipe file,有以下三個 flag 可以使用
O_RDONLY, O_WRONLY, O_NONBLOCK (會對 open read write 3個函數產生影響 )





[Reference]
Begining Linux Programming 4th edition
Chapter 13 Inter-Process Communication: Pipes