2007年11月4日 星期日

[forward] How to Repair a Corrupt MBR and boot into Linux

How to Repair a Corrupt MBR and boot into Linux


There are times when you inadvertently overwrite your Master Boot Record. The end result being that you are unable to boot into Linux. This is especially true when you are dual booting between windows and Linux OSes. Once when I was working in Windows XP, I accidentally clicked the hibernate button instead of shutdown. And windows somehow overwrote my MBR which housed the GRUB boot loader. At such times, it pays to have this cool tip at hand.



This is what you do to restore the GRUB boot loader when faced with the above problem. First you need a Linux distribution CD. If you are using Fedora (RedHat) then the first CD is sufficient. But you may also use any of the live CDs like Knoppix, Ubuntu Live CD and so on.


With Fedora CD

Boot your computer with the first CD of Fedora in your CD drive (You have to enable your PC to boot from the cdrom, which you can set in the BIOS settings). At the installation boot prompt that you get, enter the following command:

boot: linux rescue

... and press Enter. The installer will ask you a few questions like the language you would like to use, the type of keyboard etc. Then, if you have linux previously installed on your machine, the Fedora installer will automatically detect it and mount it in the /mnt/sysimage directory. Once the linux partition is mounted, you are dropped into the command shell prompt. The next step is to make your newly mounted directory the root (or parent) directory. This you do by running the chroot command as follows:

# chroot /mnt/sysimage
# _

Now you are in the shell with respect to the parent directory which is the linux partition on your harddisk.



From here, the steps needed depends on which bootloader you are using. You have to have a fair idea what is the device node of your harddisk partition housing your MBR. In most cases, it is /dev/hda if you have an IDE harddisk. But if you have a SCSI harddisk, it will be /dev/sda.


Restoring GRUB
Execute the following command :

# grub-install /dev/hda

... to install GRUB boot loader on to your MBR. And then type exit to reboot the machine. Now your GRUB boot loader is fixed.


Restoring LILO

LILO stands for LInux LOader which was the boot loader used before GRUB was developed. It is fairly cryptic and is the default bootloader prior to and in RedHat 7.0 .

Here you just type the command :

# /sbin/lilo

... to install the bootloader on to the MBR.


If you don't have a Fedora CD, then you need not despair. You can also repair the boot loader using one of the numerous live CDs available.


Using Knoppix CD to repair the boot loader

Here you have to boot into knoppix (either GUI mode or text mode). Once you are logged in, fire up a terminal (in GUI mode) and type the following commands:

$ su -
# fdisk -l

This will list your hard disk partition information. From the listing, you can know in which partition you have linux installed. Now you have to mount the partition which contains the linux filesystem. For the sake of this discussion, let us assume it is /dev/hda3 .

# mount -t ext3 -o rw /dev/hda3 /mnt
#_

Now your linux partition is mounted at /mnt . Next you have to use the chroot command as follows:

# chroot /mnt
#_

The rest of the steps are the same as listed above for Restoring GRUB and LILO boot loaders.

Update (August 01 2007) : Many have said when they run the grub-install command after following the above steps, they get an error saying that /dev/hda is missing. The most probable reason is that when you chroot to the mount location, it does not have a copy of the device nodes on your machine. Here is a solution for that. If you have installed Linux with /boot, /usr and / in different partitions then the above method may not get the desired results and running the grub-install /dev/hda command after running chroot might give the error that there is no /dev/hda. This is because you have mounted only one of the partitions which houses '/' . And the error tells you that it cannot find the device nodes. In this scenario you can do the following :

Lets say I have Linux installed with / in /dev/hda2, /boot in /dev/hda1 with an ext3 filesystem. I boot using a Live CD as described above and then mount the partitions as follows :

# mount -t ext3 /dev/hda2 /mnt
# mount -t ext3 /dev/hda1 /mnt/boot

Remember that you are mounting the boot partition into the boot directory inside /mnt. Now mount the proc filesystem of your liveCD as follows (This is really an optional step):

# mount -t proc none /mnt/proc

Finally bind the device nodes build by your liveCD to the /mnt/dev location as follows :

# mount -o bind /dev /mnt/dev

Now you can chroot to the /mnt location and run the grub-install command as described above.

# chroot /mnt
# grub-install /dev/hda

Please note: This updated method is applicable only if you have a Linux installation spread across multiple partitions. If you have installed Linux in a single partition, the first and second step works flawlessly. At least it works for me.

2007年10月16日 星期二

grep的用法

語法 : grep [options] pattern 檔案

[options] 說明
-n 附帶列號
-i 不區分大小寫
-v 和pattern相反
-l 印出含有pattern之檔名
-c 只印出列號
-w 符合整個word,非部分符合
-r 遞迴遍歷目錄
-2 找到pattern那一列,並印出前後兩列,包含自已
-A 2 找到pattern那一列,並印出後兩列,包含自已
-B 2 找到pattern那一列,並印出前兩列,包含自已
-e 視pattern裡的所有character為一般的character
-x 除非pattern 符合 entire line , 否則不列印出來
-f 把patten放到檔案中

命令列程式

命令列程式
命令列程式通常是單獨存在的程式,執行前會先在搜尋路徑中去尋找。

常見的有:

cp, date, who, w, ls, cat, wc, last, mv, mkdir, rmdir, mv, ps, top, df, du, dd
ln, sort, sed, awk, ifconfig, dmesg, hostname, dnsdomainname, chmod, chown, chgrp
cut, grep, kill, more, less, mount, nice, ping, sleep, su, tar, gzip, touch,
uname, basename, dirname, tr, uniq, mail


以下介紹幾個簡單命令的用法

date
用途:顯示 or 設定 系統的日期和時間

用法:



date

結果顯示現在的日期時間

date MMDDhhmmYY

調整時間,格式為 月 MM 日 DD 時 hh 分 mm 年 YY

如: date 080109252002 是將時間調為 2002/08/01 09:25

date +格式

控制日期時間的輸出格式

如: date +'%d %H %M' 將顯示現在的 "日 時 分"

其它進一步的用法,請 man date 查閱線上文件。


who
用途:顯示現在誰登入主機

用法:

who

顯示: ols3 pts/0 Aug 1 13:54

whoami 則顯示自己的登入帳號

ls
用途:列出目錄內容

用法:



ls

結果:列出目前所在目錄的內容

ls -a

結果:列出目前所在目錄的內容,包括隱藏檔。

ls -la

結果:使用長列模式列出目前所在目錄的內容,包括隱藏檔。

其它進一步的用法,請 man ls 查閱線上文件。


cat
用途:連結檔案內容並顯示出來

用法:



cat dataf1

結果:顯示 dataf1 的檔案內容

cat dataf1 dataf2

結果:連結 dataf1, dataf1 的內容,並予顯示。

cat >>urmail.txt

kdkdkdkdkdkdkdkdkdk (Enter)

^D

將 cat 拿來當作簡易編輯器。

其它進一步的用法,請 man cat 查閱線上文件。


wc
用途:計算檔案內字數或列數

用法:



wc -l dataf1

結果:顯示 dataf1 的檔案內共有幾列

wc -c dataf1

結果:顯示 dataf1 共有多少字元。

wc -w dataf1

結果:顯示 dataf1 共有多少句元。

其它進一步的用法,請 man wc 查閱線上文件。


ln
用途:鏈結檔案;ln 提供一個方便的機制,使同一個檔案可以有多個檔名

用法:



ln f1 f2

結果:將 f1 鏈結到 f2 (硬式鏈結),f2 的檔案內容和 f1 一模一樣

ln -s f1 f3

結果:將 f1 鏈結到 f3 (軟式鏈結),f3 是 f1 的別名,取用 f3 時,實際上是存取 f1

ln -sf f1 f3

結果:同上,唯若 f3 早已存的話,將被刪除後再重建一個新的

其它進一步的用法,請 man ln 查閱線上文件。


basename
用途:取得路徑名稱中最後的檔名部份

用法:



basename /usr/local/bin/sftp

結果:出現 sftp

以下可以得到相同結果:

baseNAME.sh #! /bin/sh
# 模擬 basename 指令
bn=${1##*/}
echo $bn

===============
./baseNAME.sh /usr/local/bin/sftp
結果為
sftp



dirname
用途:取得路徑名稱中的目錄部份

用法:



dirname /usr/local/bin/sftp

結果:出現 /usr/local/bin

以下可以得到相同結果:

dirNAME.sh #! /bin/sh
# 模擬 dirname 指令
dn=${1%/*}
echo $dn

===============
./dirNAME.sh /usr/local/bin/sftp
結果為
/usr/local/bin



sort
用途:對文字檔的列做排序

用法:



sort dataf4

結果:將 dataf4 做升冪排序

sort -r dataf4

結果:將 dataf4 做降冪排序

sort -n dataf4

結果:將 dataf4 做升冪排序,但以字串的數值大小為比較的標準

sort -n +2 dataf3

結果:跳過前二欄,以 dataf3 中的第三欄做排序,且以字串的數值大小為比較的標準

sort -nr +2 -t: /etc/passwd

結果:-t: 是說改用 : 為分隔符號,+2 是說跳過前二欄,以 /etc/passwd 中的第三欄做降序排序,且 -n 指示 sort 以字串的數值大小為比較的標準,-r 是降冪排列

其它進一步的用法,請 man sort 查閱線上文件。


uniq
用途:對已排序好的檔案刪除重覆列

用法:



uniq dataf3

結果:若重覆列並未連續擺在一起, 則不會有任何作用

sort dataf3 | uniq

結果:刪除 dataf3 檔中的重覆列

sort dataf3 | uniq -d

結果:挑出重覆列

sort dataf3 | uniq -c

結果:計算每一列的重覆數目

其它進一步的用法,請 man uniq 查閱線上文件。


cut
用途:對檔案的每一列抽出某一部份

用法:



cut -c2 dataf1

結果:抽出 dataf1 中每一列的第 2 個字元

cut -c3-10 dataf1

結果:抽出 dataf1 中每一列的第 3 到第 10 個字元

cut -c9- dataf1

結果:抽出 dataf1 中每一列的第 9 以後的字元

cut -c1-3,22- dataf1

結果:抽出 dataf1 中每一列的第 1 到第 3 個字元、以及第 22 個以後的的字元

cut -d: -f1 /etc/passwd

結果:抽出 /etc/passwd 中的第一欄位,-d: 指示 cut 改用 : 為分隔符號,-f1 是第一欄之意

上述指令可拿來找出所有系統的帳號名稱

cut -d: -f3,4 /etc/passwd

結果:抽出 /etc/passwd 中的第3,4欄位

其它進一步的用法,請 man cut 查閱線上文件。


paste
用途:對檔案以列和列合併

用法:



paste dataf1 dataf2

結果:dataf1 的每一列 和 dataf2 的每一列合併,預設以 TAB 分隔

paste -d'#' dataf1 dataf2

結果:dataf1 的每一列 和 dataf2 的每一列合併,以 # 分隔

paste -s dataf4

結果:dataf4 的每一列自己合併在一起 (-s : same file),預設以 TAB 分隔

其它進一步的用法,請 man paste 查閱線上文件。


tr
用途:轉換或刪除字元

用法:



tr k K < dataf1

結果:dataf1 的 k 換成 K 字元

tr ',' '\n' < ttt

結果:ttt 的 , 號換成 換行字元(\n)

tr -d k

結果:k 字元全刪除

cut -d: -f1-6 /etc/passwd | tr : '+'

結果:將 passwd 的六個欄改以 + 分隔

tr '[A-Z]' '[a-z]' < dataf1

結果:將大寫全換成小寫字母

tr '[a-z]' '[A-Z]' < dataf1

結果:將小寫全換成大寫字母

tr -s ' ' ' ' < dataf1

結果:將多餘的空白移除只剩一個 (-s 是壓擠的意思)

其它進一步的用法,請 man tr 查閱線上文件。


grep
用途:顯示符合樣式的列

用法:



grep A *

結果:將含有 A 這個字元的檔案及列顯示出來

grep -i A *

結果:將含有 A或a 這個字元的檔案及列顯示出來 (-i 是不分大小寫之意)

grep -v La data3

結果:將不含 La 的列顯示出來 (-v 是不包含之意)

grep -l La *

結果:只顯示那些檔案包含 La,不秀出符合的列

grep -n La *

結果:也秀出列號

dmesg | grep eth0

結果:將含有 eth0 的訊息列顯示出來

grep -q keyword filename

結果:若 filename 含有 keyword 則傳回 0 (真),否則傳為非 0

命令執行完之後,它的傳回值放在 $? 這個變數中,只要 echo $? 便可得知成功與否,請記住:0 為成功,非 0 為失敗 !


練習用的資料檔
dataf1 的內容:

John TNC 721 7654321
Marry TCC 678 1234567
Jack KCC 123 ABCDEFG
Bob PTC 345 efghijk
Anne TPC 987 1098643


dataf2 的內容:

Susan XXX 121 1AB57RT
Jeff AAA 478 JaBdkdk
Henry BBB 193 LaLaLaL
Allan DDD 621 Bobojto
Ken JJJ 094 sssssss


dataf3 的內容:

987 XXX 121 1AB57RT
234 AAA 478 JaBdkdk
765 BBB 193 LaLaLaL
512 DDD 621 Bobojto
363 JJJ 094 sssssss
765 BBB 193 LaLaLaL


dataf4的內容:

98
2341
7
51
363


常用的特殊字元
\b 後退
\f 跳頁
\n 換行字元
\r return
\t TAB


一個命令列執行好幾個命令
有二種方式:


每個命令之間用 ; 號隔開

如 ./configure ; make ; make install

每個命令之間用 && 號隔開

如 ./configure && make && make install

問題:這二者有何差別?

&& 表示前一個命令執行成功之後,才會接著執行下一個,這樣可讓我們確保所有的命令是否都成功執行。

這經常運用在自動安裝 script 檔中,以下是我平時使用的自動安裝 Apache 及 PHP 的 script 檔:

#! /bin/sh

tar xvzf apache*.gz &&
tar xvzf php*.gz &&


echo "Configure apache ...." &&
cd apache* &&
./configure --prefix=/usr/local/apache &&
cd .. &&
cd php* &&
./configure \
--with-apache=../apache_1.3.26 \
--with-mysql=/home/mysql &&
make &&
make install &&
cd .. &&

cd apache* &&
./configure \
--prefix=/usr/local/apache \
--activate-module=src/modules/php4/libphp4.a &&
make &&
make install &&

cd ../php* &&
cp -f php.ini-dist /usr/local/lib/php.ini



註: 若一列寫不完,可在該列末尾加上接續符號 \

註: 另有 || 的用法:如 命令1 || 命令2 || 命令3

|| 是或之意,當命令1執行成功時,就不會再往下執行,若命令1執行失敗,才會執行命命2

只有當前面二個命命都執行失敗,命令3 才會被執行

也可以把數個命令弄成一組,然後整組去執行它:

第一種方法:(命令1; 命令2; 命令3; ....)

( ) 會開啟一個子 shell 環境來執行括號中的命令組

以下是把一組命令放入背景中執行:

(sort mydata -o result.txt; procdata result.txt) &

第二種方法:{ 命令1; 命令2; 命令3; .... }

不同的是,此法是把這些命令組在現行的 shell 中執行,而非在子 shell 中執行

注意 { 右方、} 左方都要有空白,每個命令都要以 ';'這個符號結束

命令列郵寄帶檔的方法
以下是將 README 這個檔案郵件帶檔寄給 ols3@www.tnc.edu.tw

#! /bin/sh

# 由命令列寄帶檔的信件

# 方法 1: 使用 uuencode 編碼

例1
uuencode README README | mail -s "test attach msg file" ols3@www.tnc.edu.tw

上述的意思是說:把 README 這個檔案(第一個 README)予以 uuencode 編碼,且將 README (第二個 README) 這個名字寫入編碼檔的檔頭,再交給 mail 寄給收信者。

例2
uuencode nc11nt.zip nc11nt.zip | mail -s "test attach msg file" ols3@www.tnc.edu.tw

# 解碼法: uudecode 編碼檔
# 或由 OutLook Express 等讀取信件的程式自動解碼。

# ------------------------------------------------------------------------------

# 方法 2: 使用 base64 編碼

uuencode -m README README | mail -s "test attach msg file" ols3@www.tnc.edu.tw

# 解碼:
# uudecode 編碼檔
# 或
# uudecode 編碼檔 -o 指定輸出檔名
# 如 uudecode encode.txt -o nc11.zip

WinZip 也可以對 uuencode 編碼檔加以解碼,方法如下:
1. 把 uuencode 檔存為 .uue,若是 base64 編碼可存成 .b64
2. 用 WinZip 開啟編碼檔,即可按一般解壓動作來予以解碼。

=========================================================

# 註: uuencode 的用法例:

uuencode nc11nt.zip nc11nt.zip > p.txt

第一個檔名 nc11nt.zip 告訴 uuencode 要編碼的檔案是那一個,
第二個檔名 nc11nt.zip 是要 uuencode 把該檔名寫入 p.txt 表頭
它會在 p.txt 的第一列出現:
begin 600 nc11nt.zip

這樣子別人收到您的編碼檔,對方才知道您編碼之前的檔案格式為何?
因此,一般而言,uuencode 之後的二個檔名,我們都會弄成一樣。

p.txt 的內容截錄如下:

begin 600 nc11nt.zip
M4$L#!!0``@`(`.B88QW[!E;'=`<``)T2```(````9V5T;W!T+FC%5]MNXS@2
M?8X!_T-A%IAM[#B77LS+-B*T)9'%JE.G3I5.CNBSS"MAA5=&.UH82TOIS=I_Z':(J&_63U8M
M2T\'_4,Z_?3/3QE]^HCK%-<9KI]P_94NK90T,0O_**RD2U/K(AC,:*!S6.IV
MIJ6"=55)PO]K83V9!?E2TM7PEOITK>96V*-@Q'TV93
MM\.[^E3%'1F5YE$^2(NM4[QXOK52#]*1TG2R+$Z6NC[!KN3.SLE\RH*C<"F*
M5"DY6%>WAC">ABQ-CNYV5*=3BB9\@7)S)?N'LE=L.K3%_);6T
MHJ*;>EZI'(]SJ9TDX;J=-3]RI2QH_A3VO87F.4F%]Y80KL,]G:63NIUD+R/D
M[T!X]MT2LHA5AW#XB2KA-QO?AF`3:<&PL3>E62.N$D81Z:.J*II+JIUM[6`I?1M,OXQNI]0;WM&WWGC<&T[OSK'4EP9OD9QH2*W6E8)=1&6%]D\AF5\O
MQOTOV-#[>7`]F-ZQ_Y>#Z?!B,J'+T9AZ=-,;3P?]V^O>F&YNQS>CR04R/9&R
M09AC?Q=BIO3*`,A">J$J%X*_0VX=W*L**L6#1(YS":X4)"@'Y;^?P19R$I71
MRQ#M2SZ?DTN>!NKW1S=W@^'5A^O!S\QTA*^-S^C1*C#+FW>3'TLIH[__XV_T
......省略
M`@`(`%9^1B0K8B6N!%\``%3Q```*``````````$`(`"V@50,`0!H;V)B:70N
M='AT4$L!`A0`%``"``@`H8Y&),B0K1B*"P``D@&L!`')E861M92YT>'102P4&``````D`"0#I`0``,G`
end

==============================================================

用以下方法即可解碼回來:

uudecode p.txt -o nc11.zip

[精華] Grep 用法

Grep : g (globally) search for a re (regular expression ) and p (print ) the results.

1、參數:
-I :忽略大小寫
-c :列印匹配的行數
-l :從多個檔中查找包含匹配項
-v :查找不包含匹配項的行
-n:列印包含匹配項的行和行標

2、RE(正則運算式)
\ 忽略正則運算式中特殊字元的原有含義
^ 匹配正則運算式的開始行
$ 匹配正則運算式的結束行
\< 從匹配正則運算式的行開始
\>; 到匹配正則運算式的行結束
[ ] 單個字元;如[A] 即A符合要求
[ - ] 範圍 ;如[A-Z]即A,B,C一直到Z都符合要求
. 所有的單個字元
* 所有字元,長度可以為0

3、舉例
# ps -ef | grep in.telnetd
root 19955 181 0 13:43:53 ? 0:00 in.telnetd

# more size.txt size檔的內容
b124230
b034325
a081016
m7187998
m7282064
a022021
a061048
m9324822
b103303
a013386
b044525
m8987131
B081016
M45678
B103303
BADc2345

# more size.txt | grep '[a-b]' 範圍 ;如[A-Z]即A,B,C一直到Z都符合要求
b124230
b034325
a081016
a022021
a061048
b103303
a013386
b044525
# more size.txt | grep '[a-b]'*
b124230
b034325
a081016
m7187998
m7282064
a022021
a061048
m9324822
b103303
a013386
b044525
m8987131
B081016
M45678
B103303
BADc2345

# more size.txt | grep '' 單個字元;如[A] 即A符合要求
b124230
b034325
b103303
b044525
# more size.txt | grep '[bB]'
b124230
b034325
b103303
b044525
B081016
B103303
BADc2345

# grep 'root' /etc/group
root::0:root
bin::2:root,bin,daemon
sys::3:root,bin,sys,adm
adm::4:root,adm,daemon
uucp::5:root,uucp
mail::6:root
tty::7:root,tty,adm
lp::8:root,lp,adm
nuucp::9:root,nuucp
daemon::12:root,daemon

# grep '^root' /etc/group 匹配正則運算式的開始行
root::0:root


# grep 'uucp' /etc/group
uucp::5:root,uucp
nuucp::9:root,nuucp

# grep '\uucp::5:root,uucp


# grep 'root$' /etc/group 匹配正則運算式的結束行
root::0:root
mail::6:root


# more size.txt | grep -i 'b1..*3' -i :忽略大小寫

b124230
b103303
B103303

# more size.txt | grep -iv 'b1..*3' -v :查找不包含匹配項的行

b034325
a081016
m7187998
m7282064
a022021
a061048
m9324822
a013386
b044525
m8987131
B081016
M45678
BADc2345

# more size.txt | grep -in 'b1..*3'
1:b124230
9:b103303
15:B103303

# grep '$' /etc/init.d/nfs.server | wc -l
128
# grep '\$' /etc/init.d/nfs.server | wc –l 忽略正則運算式中特殊字元的原有含義

15
# grep '\$' /etc/init.d/nfs.server
case "$1" in
>;/tmp/sharetab.$$
[ "x$fstype" != xnfs ] && \
echo "$path\t$res\t$fstype\t$opts\t$desc" \
>;>;/tmp/sharetab.$$
/usr/bin/touch -r /etc/dfs/sharetab /tmp/sharetab.$$
/usr/bin/mv -f /tmp/sharetab.$$ /etc/dfs/sharetab
if [ -f /etc/dfs/dfstab ] && /usr/bin/egrep -v '^[ ]*(#|$)' \
if [ $startnfsd -eq 0 -a -f /etc/rmmount.conf ] && \
if [ $startnfsd -ne 0 ]; then
elif [ ! -n "$_INIT_RUN_LEVEL" ]; then
while [ $wtime -gt 0 ]; do
wtime=`expr $wtime - 1`
if [ $wtime -eq 0 ]; then
echo "Usage: $0 { start | stop }"


# more size.txt

the test file
their are files
The end

# grep 'the' size.txt
the test file
their are files

# grep '\the test file
their are files

# grep 'the\>;' size.txt
the test file

# grep '\;' size.txt
the test file

# grep '\<[Tt]he\>;' size.txt
the test file
The end

2007年9月4日 星期二

轉貼-嵌入式設備上的 Linux 系統開發

嵌入式設備上的 Linux 系統開發
級別: 初級
Anand K Santhanam (mailto:asanthan@in.ibm.com?subject=嵌入式設備上的 Linux 系統開發&cc=asanthan@in.ibm.com), 軟體工程師, IBM Global Services
Vishal Kulkarni (mailto:kvishal@in.ibm.com?subject=嵌入式設備上的 Linux 系統開發&cc=kvishal@in.ibm.com), 軟體工程師, IBM Global Services

2002 年 3 月 01 日
如果您剛接觸嵌入式開發,那麼大量可用的引導裝載程式(bootloader)、規模縮小的分發版(distribution)、檔系統和 GUI 看起來可能太多了。但是這些豐富的選項實際上是一種恩賜,允許您調整開發或用戶環境以完全符合您的需要。對 Linux 嵌入式開發的概述將幫助您理解所有這些選項。
Linux 正在嵌入式開發領域穩步發展。因為 Linux 使用 GPL(請參閱本文後面的 參考資料),所以任何對將 Linux 定制於 PDA、掌上機或者可佩帶設備感興趣的人都可以從網際網路免費下載其內核和應用程式,並開始移植或開發。許多 Linux 改良品種迎合了嵌入式/即時市場。它們包括 RTLinux(即時 Linux)、uclinux(用於非 MMU 設備的 Linux)、Montavista Linux(用於 ARM、MIPS、PPC 的 Linux 分發版)、ARM-Linux(ARM 上的 Linux)和其他 Linux 系統(請參閱 參考資料以鏈結到本文中提到的這些和其他術語及產品。)
嵌入式 Linux 開發大致涉及三個層次:引導裝載程式、Linux 內核和圖形用戶介面(或稱 GUI)。在本文中,我們將集中討論涉及這三層的一些基本概念;深入瞭解引導裝載程式、內核和檔系統是如何交互的;並將研究可用於檔系統、GUI 和引導裝載程式的眾多選項中的一部分。
引導裝載程式
引導裝載程式通常是在任何硬體上執行的第一段代碼。在象臺式機這樣的常規系統中,通常將引導裝載程式裝入主引導記錄(Master Boot Record,(MBR))中,或者裝入 Linux 駐留的磁片的第一個磁區中。通常,在臺式機或其他系統上,BIOS 將控制移交給引導裝載程式。這就提出了一個有趣的問題:誰將引導裝載程式裝入(在大多數情況中)沒有 BIOS 的嵌入式設備上呢?
解決這個問題有兩種常規技術:專用軟體和微小的引導代碼(tiny bootcode)。
專用軟體可以直接與遠端系統上的快閃記憶體設備進行交互並將引導裝載程式安裝在快閃記憶體的給定位置中。 快閃記憶體設備是與存儲設備功能類似的特殊晶片,而且它們能持久存儲資訊 ― 即,在重新引導時不會擦除其內容。
這個軟體使用目標(在嵌入式開發中,嵌入式設備通常被稱為 目標)上的 JTAG 埠,它是用於執行外部輸入(通常來自主機機器)的指令的介面。JFlash-linux 是一種用於直接寫快閃記憶體的流行工具。它支援為數眾多的快閃記憶體晶片;它在主機機器(通常是 i386 機器 ― 本文中我們把一台 i386 機器稱為 主機)上執行並通過 JTAG 介面使用平行埠訪問目標的快閃記憶體晶片。當然,這意味著目標需要有一個平行介面使它能與主機通信。Jflash-linux 在 Linux 和 Windows 版本中都可使用,可以在命令行中用以下命令啟動它:
Jflash-linux

某些種類的嵌入式設備具有 微小的引導代碼― 根據幾個位元組的指令 ― 它將初始化一些 DRAM 設置並啟用目標上的一個串列(或者 USB,或者乙太網)埠與主機程式通信。然後,主機程式或裝入程式可以使用這個連接將引導裝載程式傳送到目標上,並將它寫入快閃記憶體。
在安裝它並給予其控制後,這個引導裝載程式執行下列各類功能:
• 初始化 CPU 速度
• 初始化記憶體,包括啟用記憶體庫、初始化記憶體配置寄存器等
• 初始化序列埠(如果在目標上有的話)
• 啟用指令/資料快取記憶體
• 設置堆疊指標
• 設置參數區域並構造參數結構和標記(這是重要的一步,因為內核在標識根設備、頁面大小、記憶體大小以及更多內容時要使用引導參數)
• 執行 POST(加電自檢)來標識存在的設備並報告任何問題
• 為電源管理提供掛起/恢復支援
• 跳轉到內核的開始
帶有引導裝載程式、參數結構、內核和檔系統的系統典型記憶體佈局可能如下所示:

清單 1. 典型記憶體佈局
/* Top Of Memory */
Bootloader
Parameter Area
Kernel
Filesystem
/* End Of Memory */

嵌入式設備上一些流行的並可免費使用的 Linux 引導裝載程式有 Blob、Redboot 和 Bootldr(請參閱 參考資料獲得鏈結)。所有這些引導裝載程式都用於基於 ARM 設備上的 Linux,並需要 Jflash-linux 工具用於安裝。
一旦將引導裝載程式安裝到目標的快閃記憶體中,它就會執行我們上面提到的所有初始化工作。然後,它準備接收來自主機的內核和檔系統。一旦裝入了內核,引導裝載程式就將控制轉給內核。


設置工具鏈
設置工具鏈在主機機器上創建一個用於編譯將在目標上運行的內核和應用程式的構建環境 ― 這是因為目標硬體可能沒有與主機相容的二進位執行級別。
工具鏈由一套用於編譯、彙編和鏈結內核及應用程式的元件組成。 這些組件包括:
• Binutils ― 用於操作二進位檔的實用程式集合。它們包括諸如 ar 、 as 、 objdump 、 objcopy 這樣的實用程式。
• Gcc― GNU C 編譯器。
• Glibc― 所有用戶應用程式都將鏈結到的 C 庫。避免使用任何 C 庫函數的內核和其他應用程式可以在沒有該庫的情況下進行編譯。
構建工具鏈建立了一個交叉編譯器環境。 本地編譯器編譯與本機同類的處理器的指令。 交叉編譯器運行在某一種處理器上,卻可以編譯另一種處理器的指令。重頭設置交叉編譯器工具鏈可不是一項簡單的任務:它包括下載源代碼、修補補丁、配置、編譯、設置頭檔、安裝以及很多很多的操作。另外,這樣一個徹底的構建過程對記憶體和硬碟的需求是巨大的。如果沒有足夠的記憶體和硬碟空間,那麼在構建階段由於相關性、配置或頭檔設置等問題會突然冒出許多問題。
因此能夠從網際網路上獲得已預編譯的二進位檔是一件好事(但不太好的一點是,目前它們大多數只限於基於 ARM 的系統,但遲早會改變的)。一些比較流行的已預編譯的工具鏈包括那些來自 Compaq(Familiar Linux )、LART(LART Linux)和 Embedian(基於 Debian 但與它無關)的工具鏈 ― 所有這些工具鏈都用於基於 ARM 的平臺。
內核設置
Linux 社區正積極地為新硬體添加功能部件和支援、在內核中修正錯誤並且及時地進行常規改進。這導致大約每 6 個月(或 6 個月不到)就有一個穩定的 Linux 樹的新發行版。不同的維護者維護針對特定體系結構的不同內核樹和補丁。當為一個專案選擇了一個內核時,您需要評估最新發行版的穩定性如何、它是否符合專案要求和硬體平臺、從編程角度來看它的舒適程度以及其他難以確定的方面。還有一點也非常重要:找到需要應用於基本內核的所有補丁,以便為特定的體系結構調整內核。
內核佈局
內核佈局分為特定於體系結構的部分和與體系結構無關的部分。內核中特定於體系結構的部分首先執行,設置硬體寄存器、配置記憶體映射、執行特定於體系結構的初始化,然後將控制轉給內核中與體系結構無關的部分。系統的其餘部分在這第二個階段期間進行初始化。內核樹下的目錄 arch/ 由不同的子目錄組成,每個子目錄用於一個不同的體系結構(MIPS、ARM、i386、SPARC、PPC 等)。每一個這樣的子目錄都包含 kernel/ 和 mm/ 子目錄,它們包含特定於體系結構的代碼來完成象初始化記憶體、設置 IRQ、啟用快取記憶體、設置內核頁面表等操作。一旦裝入內核並給予其控制,就首先調用這些函數,然後初始化系統的其餘部分。
根據可用的系統資源和引導裝載程式的功能,內核可以編譯成 vmlinux、Image 或 zImage。vmlinux 和 zImage 之間的主要區別在於 vmlinux是實際的(未壓縮的)可執行檔,而 zImage是或多或少包含相同資訊的自解壓壓縮檔 ― 只是壓縮它以處理(通常是 Intel 強制的)640 KB 引導時間的限制。有關所有這些的權威性解釋,請參閱 Linux Magazine的文章“Kernel Configuration: dealing with the unexpected”(請參閱 參考資料)。
內核鏈結和裝入
一旦為目標系統編譯了內核後,通過使用引導裝載程式(它已經被裝入到目標的快閃記憶體中),內核就被裝入到目標系統的記憶體(在 DRAM 中或者在快閃記憶體中)。通過使用串列、USB 或乙太網埠,引導裝載程式與主機通信以將內核傳送到目標的快閃記憶體或 DRAM 中。在將內核完全裝入目標後,引導裝載程式將控制傳遞給裝入內核的位址。
內核可執行檔由許多鏈結在一起的物件檔組成。物件檔有許多節,如文本、資料、init 資料、bass 等等。這些物件檔都是由一個稱為 鏈結器腳本的檔鏈結並裝入的。這個鏈結器腳本的功能是將輸入物件檔的各節映射到輸出檔中;換句話說,它將所有輸入物件檔都鏈結到單一的可執行檔中,將該可執行檔的各節裝入到指定位址處。 vmlinux.lds是存在於 arch// 目錄中的內核鏈結器腳本,它負責鏈結內核的各個節並將它們裝入記憶體中特定偏移量處。典型的 vmlinux.lds 看起來象這樣:

清單 2. 典型的 vmlinux.lds 文件
OUTPUT_ARCH() /* includes architecture type */
ENTRY(stext) /* stext is the kernel entry point */
SECTIONS /* SECTIONS command describes the layout
of the output file */
{
. = TEXTADDR; /* TEXTADDR is LMA for the kernel */
.init : { /* Init code and data*/
_stext = .; /* First section is stext followed
by __init data section */
__init_begin = .;
*(.text.init)
__init_end = .;
}
.text : { /* Real text segment follows __init_data section */
_text = .;
*(.text)
_etext = .; /* End of text section*/
}
.data :{
_data=.; /* Data section comes after text section */
*(.data)
_edata=.;
} /* Data section ends here */
.bss : { /* BSS section follows symbol table section */
__bss_start = .;
*(.bss)
_end = . ; /* BSS section ends here */
}
}

LMA 是裝入模組位址;它表示將要裝入內核的目標虛擬記憶體中的位址。 TEXTADDR 是內核的虛擬起始位址,並且在 arch// 下的 Makefile 中指定它的值。這個位址必須與引導裝載程式使用的位址相匹配。
一旦引導裝載程式將內核複製到快閃記憶體或 DRAM 中,內核就被重新定位到 TEXTADDR — 它通常在 DRAM 中。然後,引導裝載程式將控制轉給這個位址,以便內核能開始執行。
參數傳遞和內核引導
stext 是內核入口點,這意味著在內核引導時將首先執行這一節下的代碼。它通常用組合語言編寫,並且通常它在 arch// 內核目錄下。這個代碼設置內核頁面目錄、創建身份內核映射、標識體系結構和處理器以及執行分支 start_kernel (初始化系統的主常式)。
start_kernel 調用 setup_arch 作為執行的第一步,在其中完成特定於體系結構的設置。這包括初始化硬體寄存器、標識根設備和系統中可用的 DRAM 和快閃記憶體的數量、指定系統中可用頁面的數目、檔系統大小等等。所有這些資訊都以參數形式從引導裝載程式傳遞到內核。
將參數從引導裝載程式傳遞到內核有兩種方法:parameter_structure 和標記列表。在這兩種方法中,不贊成使用參數結構,因為它強加了限制:指定在記憶體中,每個參數必須位於 param_struct 中的特定偏移量處。最新的內核期望參數作為標記列表的格式來傳遞,並將參數轉化為已標記格式。 param_struct 定義在 include/asm/setup.h 中。它的一些重要欄位是:

清單 3. 樣本參數結構
struct param_struct {
unsigned long page_size; /* 0: Size of the page */
unsigned long nr_pages; /* 4: Number of pages in the system */
unsigned long ramdisk /* 8: ramdisk size */
unsigned long rootdev; /* 16: Number representing the root device */
unsigned long initrd_start; /* 64: starting address of initial ramdisk */
/* This can be either in flash/dram */
unsigned long initrd_size; /* 68: size of initial ramdisk */
}

請注意:這些數表示定義欄位的參數結構中的偏移量。這意味著如果引導裝載程式將參數結構放置在位址 0xc0000100,那麼 rootdev 參數將放置在 0xc0000100 + 16,initrd_start 將放置在 0xc0000100 + 64 等等 ― 否則,內核將在解釋正確的參數時遇到困難。
正如上面提到的,因為從引導裝載程式到內核的參數傳遞會有一些約束條件,所以大多數 2.4.x 系列內核期望參數以已標記的列表格式傳遞。在已標記的列表中,每個標記由標識被傳遞參數的 tag_header 以及其後的參數值組成。標記列表中標記的常規格式可以如下所示:

清單 4. 樣本標記格式。內核通過 頭來標識每個標記。
#define
struct {
u32 ;
u32 ;
};
/* Example tag for passing memory information */
#define ATAG_MEM 0x54410002 /* Magic number */
struct tag_mem32 {
u32 size; /* size of memory */
u32 start; /* physical start address of memory*/
};

setup_arch 還需要對快閃記憶體存儲庫、系統寄存器和其他特定設備執行記憶體映射。一旦完成了特定於體系結構的設置,控制就返回到初始化系統其餘部分的 start_kernel 函數。這些附加的初始化任務包含:
• 設置陷阱
• 初始化中斷
• 初始化計時器
• 初始化控制臺
• 調用 mem_init ,它計算各種區域、高記憶體區等內的頁面數量
• 初始化 slab 分配器並為 VFS、緩衝區快取記憶體等創建 slab 快取記憶體
• 建立各種檔系統,如 proc、ext2 和 JFFS2
• 創建 kernel_thread ,它執行檔系統中的 init 命令並顯示 lign 提示符。 如果在 /bin、/sbin 或 /etc 中沒有 init 程式,那麼內核將執行檔系統的 /bin 中的 shell。






回頁首



設備驅動程式
嵌入式系統通常有許多設備用於與用戶交互,象觸摸屏、小鍵盤、滾動輪、感測器、RA232 介面、LCD 等等。除了這些設備外,還有許多其他專用設備,包括快閃記憶體、USB、GSM 等。內核通過所有這些設備各自的設備驅動程式來控制它們,包括 GUI 用戶應用程式也通過訪問這些驅動程式來訪問設備。本節著重討論通常幾乎在每個嵌入式環境中都會使用的一些重要設備的設備驅動程式。
幀緩衝區驅動程式
這是最重要的驅動程式之一,因為通過這個驅動程式才能使系統螢幕顯示內容。幀緩衝區驅動程式通常有三層。最底層是基本控制臺驅動程式 drivers/char/console.c,它提供了文本控制臺常規介面的一部分。通過使用控制臺驅動程式函數,我們能將文本列印到螢幕上 ― 但圖形或動畫還不能(這樣做需要使用視頻模式功能,通常出現在中間層,也就是 drivers/video/fbcon.c 中)。這個第二層驅動程式提供了視頻模式中繪圖的常規介面。
幀緩衝區是顯卡上的記憶體,需要將它記憶體映射到用戶空間以便可以將圖形和文本能寫到這個記憶體段上:然後這個資訊將反映到螢幕上。幀緩衝區支援提高了繪圖的速度和整體性能。這也是頂層驅動程式引人注意之處:頂層是非常特定於硬體的驅動程式,它需要支援顯卡不同的硬體方面 ― 象啟用/禁用顯卡控制器、深度和模式的支援以及調色板等。所有這三層都相互依賴以實現正確的視頻功能。與幀緩衝區有關的設備是 /dev/fb0(主設備號 29,次設備號 0)。
輸入設備驅動程式
可觸摸板是用於嵌入式設備的最基本的用戶交互設備之一 ― 小鍵盤、感測器和滾動輪也包含在許多不同設備中以用於不同的用途。
觸摸板設備的主要功能是隨時報告用戶的觸摸,並標識觸摸的座標。這通常在每次發生觸摸時,通過生成一個中斷來實現。
然後,這個設備驅動程式的角色是每當出現中斷時就查詢觸摸屏控制器,並請求控制器發送觸摸的座標。一旦驅動程式接收到座標,它就將有關觸摸和任何可用資料的信號發送給用戶應用程式,並將資料發送給應用程式(如果可能的話)。然後用戶應用程式根據它的需要處理資料。
幾乎所有輸入設備 ― 包括小鍵盤 ― 都以類似原理工作。
快閃記憶體 MTD 驅動程式
MTD 設備是象快閃記憶體晶片、小型快閃記憶體卡、記憶棒等之類的設備,它們在嵌入式設備中的使用正在不斷增長。
MTD 驅動程式是在 Linux 下專門為嵌入式環境開發的新的一類驅動程式。相對於常規塊設備驅動程式,使用 MTD 驅動程式的主要優點在於 MTD 驅動程式是專門為基於快閃記憶體的設備所設計的,所以它們通常有更好的支援、更好的管理和基於磁區的擦除和讀寫操作的更好的介面。Linux 下的 MTD 驅動程式介面被劃分為兩類模組:用戶模組和硬體模組。
用戶模組
這些模組提供從用戶空間直接使用的介面:原始字元訪問、原始塊訪問、FTL(快閃記憶體轉換層,Flash Transition Layer ― 用在快閃記憶體上的一種檔系統)和 JFS(即日誌檔系統,Journaled File System ― 在快閃記憶體上直接提供檔系統而不是類比塊設備)。用於快閃記憶體的 JFS 的當前版本是 JFFS2(稍後將在本文中描述)。
硬體模組
這些模組提供對記憶體設備的物理訪問,但並不直接使用它們。通過上述的用戶模組來訪問它們。這些模組提供了在快閃記憶體上讀、擦除和寫操作的實際常式。
MTD 驅動程式設置
為了訪問特定的快閃記憶體設備並將檔系統置於其上,需要將 MTD 子系統編譯到內核中。這包括選擇適當的 MTD 硬體和用戶模組。當前,MTD 子系統支援為數眾多的快閃記憶體設備 ― 並且有越來越多的驅動程式正被添加進來以用於不同的快閃記憶體晶片。
有兩個流行的用戶模組可啟用對快閃記憶體的訪問: MTD_CHAR 和 MTD_BLOCK 。
MTD_CHAR 提供對快閃記憶體的原始字元訪問,而 MTD_BLOCK 將快閃記憶體設計為可以在上面創建檔系統的常規塊設備(象 IDE 磁片)。與 MTD_CHAR 關聯的設備是 /dev/mtd0、mtd1、mtd2(等等),而與 MTD_BLOCK 關聯的設備是 /dev/mtdblock0、mtdblock1(等等)。由於 MTD_BLOCK 設備提供象塊設備那樣的類比,通常更可取的是在這個模擬基礎上創建象 FTL 和 JFFS2 那樣的檔系統。
為了進行這個操作,可能需要創建分區表將快閃記憶體設備分拆到引導裝載程式節、內核節和檔系統節中。樣本分區表可能包含以下資訊:

清單 5. MTD 的簡單快閃記憶體設備分區
struct mtd_partition sample_partition = {
{
/* First partition */
name : bootloader, /* Bootloader section */
size : 0x00010000, /* Size */
offset : 0, /* Offset from start of flash- location 0x0*/
mask_flags : MTD_WRITEABLE /* This partition is not writable */
},
{ /* Second partition */
name : Kernel, /* Kernel section */
size : 0x00100000, /* Size */
offset : MTDPART_OFS_APPEND, /* Append after bootloader section */
mask_flags : MTD_WRITEABLE /* This partition is not writable */
},
{ /* Third partition */
name : JFFS2, /* JFFS2 filesystem */
size : MTDPART_SIZ_FULL, /* Occupy rest of flash */
offset : MTDPART_OFS_APPEND /* Append after kernel section */
}
}

上面的分區表使用了 MTD_BLOCK 介面對快閃記憶體設備進行分區。這些分區的設備節點是:

簡單快閃記憶體分區的設備節點
User device node Major number Minor number
Bootloader /dev/mtdblock0 31 0
Kernel /dev/mtdblock1 31 1
Filesystem /dev/mtdblock2 31 2

在本例中,引導裝載程式必須將有關 root 設備節點(/dev/mtdblock2)和可以在快閃記憶體中找到檔系統的位址(本例中是 FLASH_BASE_ADDRESS + 0x04000000 )的正確參數傳遞到內核。一旦完成分區,快閃記憶體設備就準備裝入或掛裝檔系統。
Linux 中 MTD 子系統的主要目標是在系統的硬體驅動程式和上層,或用戶模組之間提供通用介面。硬體驅動程式不需要知道象 JFFS2 和 FTL 那樣的用戶模組使用的方法。所有它們真正需要提供的就是一組對底層快閃記憶體系統進行 read 、 write 和 erase 操作的簡單常式。






回頁首



嵌入式設備的檔系統
系統需要一種以結構化格式存儲和檢索資訊的方法;這就需要檔系統的參與。Ramdisk(請參閱 參考資料)是通過將電腦的 RAM 用作設備來創建和掛裝檔系統的一種機制,它通常用於無盤系統(當然包括微型嵌入式設備,它只包含作為永久存儲媒質的快閃記憶體晶片)。
用戶可以根據可靠性、健壯性和/或增強的功能的需求來選擇檔系統的類型。下一節將討論幾個可用選項及其優缺點。
第二版擴展檔系統(Ext2fs)
Ext2fs 是 Linux 事實上的標準檔系統,它已經取代了它的前任 ― 擴展檔系統(或 Extfs)。Extfs 支持的檔大小最大為 2 GB,支持的最大檔案名稱大小為 255 個字元 ― 而且它不支援索引節點(包括資料修改時間標記)。Ext2fs 做得更好;它的 優點是:
• Ext2fs 支援達 4 TB 的記憶體。
• Ext2fs 檔案名稱最長可以到 1012 個字元。
• 當創建檔系統時,管理員可以選擇邏輯塊的大小(通常大小可選擇 1024、2048 和 4096 位元組)。
• Ext2fs 了實現快速符號鏈結:不需要為此目的而分配資料塊,並且將目標名稱直接存儲在索引節點(inode)表中。這使性能有所提高,特別是在速度上。
因為 Ext2 檔系統的穩定性、可靠性和健壯性,所以幾乎在所有基於 Linux 的系統(包括臺式機、伺服器和工作站 ― 並且甚至一些嵌入式設備)上都使用 Ext2 檔系統。然而,當在嵌入式設備中使用 Ext2fs 時,它有一些 缺點:
• Ext2fs 是為象 IDE 設備那樣的塊設備設計的,這些設備的邏輯塊大小是 512 位元組,1 K 位元組等這樣的倍數。這不太適合於磁區大小因設備不同而不同的快閃記憶體設備。
• Ext2 檔系統沒有提供對基於磁區的擦除/寫操作的良好管理。在 Ext2fs 中,為了在一個磁區中擦除單個位元組,必須將整個磁區複製到 RAM,然後擦除,然後重寫入。考慮到快閃記憶體設備具有有限的擦除壽命(大約能進行 100,000 次擦除),在此之後就不能使用它們,所以這不是一個特別好的方法。
• 在出現電源故障時,Ext2fs 不是防崩潰的。
• Ext2 檔系統不支援損耗平衡,因此縮短了磁區/快閃記憶體的壽命。(損耗平衡確保將位址範圍的不同區域輪流用於寫和/或擦除操作以延長快閃記憶體設備的壽命。)
• Ext2fs 沒有特別完美的磁區管理,這使設計塊驅動程式十分困難。
由於這些原因,通常相對於 Ext2fs,在嵌入式環境中使用 MTD/JFFS2 組合是更好的選擇。
用 Ramdisk 掛裝 Ext2fs
通過使用 Ramdisk 的概念,可以在嵌入式設備中創建並掛裝 Ext2 檔系統(以及用於這一目的的任何檔系統)。

清單 6. 創建一個簡單的基於 Ext2fs 的 Ramdisk
mke2fs -vm0 /dev/ram 4096
mount -t ext2 /dev/ram /mnt
cd /mnt
cp /bin, /sbin, /etc, /dev ... files in mnt
cd ../
umount /mnt
dd if=/dev/ram bs=1k count=4096 of=ext2ramdisk

mke2fs 是用於在任何設備上創建 ext2 檔系統的實用程式 — 它創建超級塊、索引節點以及索引節點表等等。
在上面的用法中, /dev/ram 是上面構建有 4096 個塊的 ext2 檔系統的設備。然後,將這個設備( /dev/ram )掛裝在名為 /mnt 的臨時目錄上並且複製所有必需的檔。一旦複製完這些檔,就卸裝這個檔系統並且設備( /dev/ram )的內容被轉儲到一個檔(ext2ramdisk)中,它就是所需的 Ramdisk(Ext2 檔系統)。
上面的順序創建了一個 4 MB 的 Ramdisk,並用必需的檔實用程式來填充它。
一些要包含在 Ramdisk 中的重要目錄是:
• /bin ― 保存大多數象 init 、 busybox 、 shell 、檔管理實用程式等二進位檔。
• /dev― 包含用在設備中的所有設備節點
• /etc― 包含系統的所有配置檔
• /lib― 包含所有必需的庫,如 libc、libdl 等
日誌快閃記憶體檔系統,版本 2(JFFS2)
瑞典的 Axis Communications 開發了最初的 JFFS,Red Hat 的 David Woodhouse 對它進行了改進。 第二個版本,JFFS2,作為用於微型嵌入式設備的原始快閃記憶體晶片的實際檔系統而出現。JFFS2 檔系統是日誌結構化的,這意味著它基本上是一長列節點。每個節點包含有關檔的部分資訊 ― 可能是檔的名稱、也許是一些資料。相對於 Ext2fs,JFFS2 因為有以下這些 優點而在無盤嵌入式設備中越來越受歡迎:
• JFFS2 在磁區級別上執行快閃記憶體擦除/寫/讀操作要比 Ext2 檔系統好。
• JFFS2 提供了比 Ext2fs 更好的崩潰/掉電安全保護。當需要更改少量資料時,Ext2 檔系統將整個磁區複製到記憶體(DRAM)中,在記憶體中合併新資料,並寫回整個磁區。這意味著為了更改單個字,必須對整個磁區(64 KB)執行讀/擦除/寫常式 ― 這樣做的效率非常低。要是運氣差,當正在 DRAM 中合併資料時,發生了電源故障或其他事故,那麼將丟失整個資料集合,因為在將資料讀入 DRAM 後就擦除了快閃記憶體磁區。JFFS2 附加檔而不是重寫整個磁區,並且具有崩潰/掉電安全保護這一功能。
• 這可能是最重要的一點:JFFS2 是專門為象快閃記憶體晶片那樣的嵌入式設備創建的,所以它的整個設計提供了更好的快閃記憶體管理。
因為本文主要是寫關於快閃記憶體設備的使用,所以在嵌入式環境中使用 JFFS2 的 缺點很少:
• 當檔系統已滿或接近滿時,JFFS2 會大大放慢運行速度。這是因為垃圾收集的問題(更多資訊,請參閱 參考資料)。
創建 JFFS2 檔系統
在 Linux 下,用 mkfs.jffs2 命令創建 JFFS2 檔系統(基本上是使用 JFFS2 的 Ramdisk)。

清單 7. 創建 JFFS2 檔系統
mkdir jffsfile
cd jffsfile
/* copy all the /bin, /etc, /usr/bin, /sbin/ binaries and /dev entries
that are needed for the filesystem here */
/* Type the following command under jffsfile directory to create the JFFS2 Image */
./mkfs.jffs2 -e 0x40000 -p -o ../jffs.image

上面顯示了 mkfs.jffs2 的典型用法。 -e 選項確定快閃記憶體的擦除磁區大小(通常是 64 千位元組)。 -p 選項用來在映射的剩餘空間用零填充。 -o 選項用於輸出檔,通常是 JFFS2 檔系統映射 ― 在本例中是 jffs.image。一旦創建了 JFFS2 檔系統,它就被裝入快閃記憶體中適當的位置(引導裝載程式告知內核查找檔系統的位址)以便內核能掛裝它。
tmpfs
當 Linux 運行於嵌入式設備上時,該設備就成為功能齊全的單元,許多守護進程會在後臺運行並生成許多日誌消息。另外,所有內核日誌記錄機制,象 syslogd、dmesg 和 klogd,會在 /var 和 /tmp 目錄下生成許多消息。由於這些進程產生了大量資料,所以允許將所有這些寫操作都發生在快閃記憶體是不可取的。由於在重新引導時這些消息不需要持久存儲,所以這個問題的解決方案是使用 tmpfs。
tmpfs 是基於記憶體的檔系統,它主要用於減少對系統的不必要的快閃記憶體寫操作這一唯一目的。因為 tmpfs 駐留在 RAM 中,所以寫/讀/擦除的操作發生在 RAM 中而不是在快閃記憶體中。因此,日誌消息寫入 RAM 而不是快閃記憶體中,在重新引導時不會保留它們。tmpfs 還使用磁片交換空間來存儲,並且當為存儲檔而請求頁面時,使用虛擬記憶體(VM)子系統。
tmpfs 的 優點包括:
• 動態檔系統大小 ― 檔系統大小可以根據被複製、創建或刪除的檔或目錄的數量來縮放。使得能夠最理想地使用記憶體。
• 速度 ― 因為 tmpfs 駐留在 RAM,所以讀和寫幾乎都是暫態的。即使以交換的形式存儲檔,I/O 操作的速度仍非常快。
tmpfs 的一個 缺點是當系統重新引導時會丟失所有資料。因此,重要的資料不能存儲在 tmpfs 上。
掛裝 tmpfs
諸如 Ext2fs 和 JFFS2 等大多數其他檔系統都駐留在底層塊設備之上,而 tmpfs 與它們不同,它直接位於 VM 上。因而,掛裝 tmpfs 檔系統是很簡單的事:

清單 8. 掛裝 tmpfs
/* Entries in /etc/rc.d/rc.sysinit for creating/using tmpfs */
# mount -t tmpfs tmpfs /var -o size=512k
# mkdir -p /var/tmp
# mkdir -p /var/log
# ln -s /var/tmp /tmp

上面的命令將在 /var 上創建 tmpfs 並將 tmpfs 的最大大小限制為 512 K。同時,tmp/ 和 log/ 目錄成為 tmpfs 的一部分以便在 RAM 中存儲日誌消息。
如果您想將 tmpfs 的一個項添加到 /etc/fstab,那麼它可能看起來象這樣:
tmpfs /var tmpfs size=32m 0 0

這將在 /var 上掛裝一個新的 tmpfs 檔系統。


圖形用戶介面(GUI)選項
從用戶的觀點來看,圖形用戶介面(GUI)是系統的一個最至關重要的方面:用戶通過 GUI 與系統進行交互。所以 GUI 應該易於使用並且非常可靠。但它還需要是有記憶體意識的,以便在記憶體受限的、微型嵌入式設備上可以無縫執行。所以,它應該是羽量級的,並且能夠快速裝入。
另一個要考慮的重要方面涉及許可證問題。一些 GUI 分發版具有允許免費使用的許可證,甚至在一些商業產品中也是如此。另一些許可證要求如果想將 GUI 合併入項目中則要支付版稅。
最後,大多數開發人員可能會選擇 XFree86,因為 XFree86 為他們提供了一個能使用他們喜歡的工具的熟悉環境。但是市場上較新的 GUI,象 Century Software 的 Microwindows(Nano-X)和 Trolltech 的 QT/Embedded,與 X 在嵌入式 Linux 的競技舞臺中展開了激烈競爭,這主要是因為它們佔用很少的資源、執行的速度很快並且具有定制視窗構件的支援。
讓我們看一看這些選項中的每一個。
Xfree86 4.X(帶幀緩衝區支持的 X11R6.4)
XFree86 Project, Inc. 是一家生產 XFree86 的公司,該產品是一個可以免費重複分發、開放源碼的 X Window 系統。X Window 系統(X11)為應用程式以圖形方式進行顯示提供了資源,並且它是 UNIX 和類 UNIX 的機器上最常用的視窗系統。它很小但很有效,它運行在為數眾多的硬體上,它對網路透明並且有良好的文檔說明。X11 為視窗管理、事件處理、同步和客戶機間通信提供強大的功能 ― 並且大多數開發人員已經熟悉了它的 API。它具有對內核幀緩衝區的內置支持,並佔用非常少的資源 ― 這非常有助於記憶體相對較少的設備。X 伺服器支援 VGA 和非 VGA 圖形卡,它對顏色深度 1、2、4、8、16 和 32 提供支援,並對渲染提供內置支援。最新的發行版是 XFree86 4.1.0。
它的 優點包括:
• 幀緩衝區體系結構的使用提高了性能。
• 佔用的資源相對很小 ― 大小在 600 K 到 700 K 位元組的範圍內,這使它很容易在小型設備上運行。
• 非常好的支持:線上有許多文檔可用,還有許多專用於 XFree86 開發的郵遞列表。
• X API 非常適合擴展。
它的 缺點包括:
• 比最近出現的嵌入式 GUI 工具性能差。
• 此外,當與 GUI 中最新的開發 ― 象專門為嵌入式環境設計的 Nano-X 或 QT/Embedded ― 相比時,XFree86 似乎需要更多的記憶體。
Microwindows
Microwindows 是 Century Software 的開放源代碼項目,設計用於帶小型顯示單元的微型設備。它有許多針對現代圖形視窗環境的功能部件。象 X 一樣,有多種平臺支持 Microwindows。
Microwindows 體系結構是基於客戶機/伺服器的並且具有分層設計。最底層是螢幕和輸入設備驅動程式(關於鍵盤或滑鼠)來與實際硬體交互。在中間層,可移植的圖形引擎提供對線的繪製、區域的填充、多邊形、裁剪以及顏色模型的支援。
在最上層,Microwindows 支援兩種 API:Win32/WinCE API 實現,稱為 Microwindows;另一種 API 與 GDK 非常相似,它稱為 Nano-X。Nano-X 用在 Linux 上。它是象 X 的 API,用於佔用資源少的應用程式。
Microwindows 支援 1、2、4 和 8 bpp(每圖元的位元數)的 palletized 顯示,以及 8、16、24 和 32 bpp 的真彩色顯示。Microwindows 還支援使它速度更快的幀緩衝區。Nano-X 伺服器佔用的資源大約在 100 K 到 150 K 位元組。
原始 Nano-X 應用程式的平均大小在 30 K 到 60 K。由於 Nano-X 是為有記憶體限制的低端設備設計的,所以它不象 X 那樣支援很多函數,因此它實際上不能作為微型 X(Xfree86 4.1)的替代品。
可以在 Microwindows 上運行 FLNX,它是針對 Nano-X 而不是 X 進行修改的 FLTK(快速輕巧工具箱(Fast Light Toolkit))應用程式開發環境的一個版本。本文中描述 FLTK。
Nano-X 的 優點包括:
• 與 Xlib 實現不同,Nano-X 仍在每個客戶機上同步運行,這意味著一旦發送了客戶機請求包,伺服器在為另一個客戶機提供服務之前一直等待,直到整個包都到達為止。這使伺服器代碼非常簡單,而運行的速度仍非常快。
• 佔用很小的資源
Nano-X 的 缺點包括:
• 聯網功能部件至今沒有經過適當地調整(特別是網路透明性)。
• 還沒有太多現成的應用程式可用。
• 與 X 相比,Nano-X 雖然近來正在加速開發,但仍沒有那麼多文檔說明而且沒有很好的支持,但這種情形會有所改變。
Microwindows 上的 FLTK API
FLTK 是一個簡單但靈活的 GUI 工具箱,它在 Linux 世界中贏得越來越多的關注,它特別適用于佔用資源很少的環境。它提供了您期望從 GUI 工具箱中獲得的大多數視窗構件,如按鈕、對話方塊、文本框以及出色的“賦值器”選擇(用於輸入數值的視窗構件)。還包括滑動器、捲軸、刻度盤和其他一些構件。
針對 Microwindows GUI 引擎的 FLTK 的 Linux 版本被稱為 FLNX。FLNX 由兩個組件構成:Fl_Widget 和 FLUID。Fl_Widget 由所有基本視窗構件 API 組成。FLUID(快速輕巧的用戶介面設計器(Fast Light User Interface Designer, FLUID))是用來產生 FLTK 源代碼的圖形編輯器。總的來說,FLNX 是能用來為嵌入式環境創建應用程式的一個出色的 UI 構建器。
Fl_Widget 佔用的資源大約是 40 K 到 48 K,而 FLUID(包括了每個窗口構件)大約佔用 380 K。這些非常小的資源佔用率使 Fl_Widget 和 FLUID 在嵌入式開發世界中非常受歡迎。
優點包括:
• 習慣於在象 Windows 這樣已建立得較好的環境中開發基於 GUI 的應用程式的任何人都會非常容易地適應 FLTK 環境。
• 它的文檔包括一本十分完整且編寫良好的手冊。
• 它使用 LGPL 進行分發,所以開發人員可以靈活地發放他們應用程式的許可證。
• FLTK 是一個 C++ 庫(Perl 和 Python 綁定也可用)。面向物件模型的選擇是一個好的選擇,因為大多數現代 GUI 環境都是面向物件的;這也使將編寫的應用程式移植到類似的 API 中變得更容易。
• Century Software 的環境提供了幾個有用的工具,諸如 ScreenToP 和 ViewML 流覽器。
它的 缺點是:
• 普通的 FLTK 可以與 X 和 Windows API 一同工作,而 FLNX 不能。它與 X 的不相容性阻礙了它在許多項目中的使用。
Qt/Embedded
Qt/Embedded 是 Trolltech 新開發的用於嵌入式 Linux 的圖形用戶介面系統。Trolltech 最初創建 Qt 作為跨平臺的開發工具用於 Linux 臺式機。它支援各種有 UNIX 特點的系統以及 Microsoft Windows。KDE ― 最流行的 Linux 桌面環境之一,就是用 Qt 編寫的。
Qt/Embedded 以原始 Qt 為基礎,並做了許多出色的調整以適用於嵌入式環境。Qt Embedded 通過 Qt API 與 Linux I/O 設施直接交互。那些熟悉並已適應了面向物件編程的人員將發現它是一個理想環境。而且,面向物件的體系結構使代碼結構化、可重用並且運行快速。與其他 GUI 相比,Qt GUI 非常快,並且它沒有分層,這使得 Qt/Embedded 成為用於運行基於 Qt 的程式的最緊湊環境。
Trolltech 還推出了 Qt 掌上機環境(Qt Palmtop Environment,俗稱 Qpe)。Qpe 提供了一個基本桌面視窗,並且該環境為開發提供了一個易於使用的介面。Qpe 包含全套的個人資訊管理(Personal Information Management (PIM))應用程式、網際網路客戶機、實用程式等等。然而,為了將 Qt/Embedded 或 Qpe 集成到一個產品中,需要從 Trolltech 獲得商業許可證。(原始 Qt 自版本 2.2 以後就可以根據 GPL 獲得 。)
它的 優點包括:
• 面向物件的體系結構有助於更快地執行
• 佔用很少的資源,大約 800 K
• 抗鋸齒文本和混合視頻的象素映射
它的 缺點是:
• Qt/Embedded 和 Qpe 只能在獲得商業許可證的情況下才能使用。






回頁首



結束語
嵌入式 Linux 開發正迅速地發展著。您必須學習並從引導裝載程式和分發版到檔系統和 GUI 中的每一個事物的各種選項中作出選擇。但是要感謝有這種選擇自由度以及非常活躍的 Linux 社區,Linux 上的嵌入式開發已經達到了新的境界,並且調整模組以適合您的規範從未比現在更簡單。這已經導致出現了許多時新的手持和微型設備作為開放盒,這是件好事 ― 因為事實是您不必成為一個專家從這些模組中進行選擇來調整您的設備以滿足您自己的要求和需要。
我們希望這篇對嵌入式 Linux 領域的介紹性概述能激起您進行試驗的欲望,並且希望您將體會擺弄微型設備的樂趣以滿足您的愛好。為進一步有助於您的專案,請參閱下面的“參考資料”,鏈結到有關我們這裏已經概述的技術的更深入的資訊。

參考資料
引導:
• 您可以參閱本文在 developerWorks 全球站點上的 英文原文.
• 如需獲得對 vmlinux 和 zimage 之間區別的極好解釋,請在 Alessandro Rubini 編寫的“ Kernel Configuration: dealing with the unexpected( Linux Magazine)的一文中找到“Booting your kernel”一節。
小型分發版:
• The Embedded Linux Distributions Quick Reference Guide涵蓋了許多商業的和開放源碼的分發版( Linux Devices,2001 年 8 月)。

• 請查看另一個 詳盡的分發版和有用的工具的清單( Linux-embedded.com)。
工具鏈:
• Wiki 工具鏈頁面包含到本文提到的所有三個工具鏈的鏈結,還有對它們的評論。
設備驅動程式:
• Memory Technology Device (MTD) Subsystem for Linux的目的是簡化記憶體設備(特別是快閃記憶體設備)的驅動程式的創建。

• Vipin Malik 編寫的 The Linux MTD, JFFS HOWTO將幫助您使 MTD 和 JFFS2 一起工作。

• Linux for PowerPC Embedded Systems HOWTO有一個很好的設備驅動程式清單。

• 理解 Linux device drivers有助於理解本篇介紹性文章( Penguin Magazine)。

• 要精通 Linux 設備驅動程式,請閱讀 O'Reilly 的 Linux Device Drivers,第 2 版一書。
有用的工具:
• Binutils、 GCC和 Glibc都可從 Free Software Foundation 下載獲得。

• 許多有用的下載都可從 Netwinder.org獲得,這是一個致力於 NetWinder 平臺上開發工作的志願者站點。

• 請在 Mark Nielsen 寫得非常棒的 How to use a Ramdisk for Linux一文中閱讀有關 Ramdisk 的所有資訊。

• FLNX 是以 FLTK(快速輕巧的工具箱)為基礎的。
檔系統:
• 第二版擴展檔系統 Ext2fs的主頁在 SourceForge。

• Red Hat 英國公司的 David Woodhouse 概述了大量有關 JFFS2:日誌快閃記憶體檔系統,第 2 版的背景知識。

• 您可以在 Linux HeadQuarters 閱讀更多有關 tmpfs的信息。

• Cliff Brake 和 Jeff Sutherland 編寫的 Flash Filesystems for Embedded Linux Systems一文論述了用於快閃記憶體設備的更多檔系統( Embedded Linux Journal)。
GUI:
• Xfree86 是 X 開發的主頁。

• 請查看一篇對 Microwindows 的一些缺點(GNOME gtk 開發人員的郵遞列表)的討論(時間比較長了)。

• 在 Trolltech 上查找有關 Qt/Embedded的更多資訊。

• The Embedded Linux GUI/Windowing Quick Reference Guide中有豐富的鏈結( Linux Devices,2002 年 2 月)。
一般參考資料:
• General Public License 或 GPL確保用戶複製、分發和修改軟體的權利。

• ARM Linux是您瞭解有關 Linux 用於 ARM 處理器的資訊的一個非常好的站點。它由 ARM 的創建者 Russell King 來維護。

• Penguinppc.org是關於 Linux 用於 PowerPC 系列處理器的的主頁。該站點上有一個關於為基於 PPC 的體系結構建立工具鏈的資料豐富的教程。

• Linux Devices是一個非常全面的站點,它包含有關 Linux 和嵌入式開發的出版發行、快速參考、新聞和特色報告等各種資訊。

• Silicon Penguin列表站點上擁有嵌入式 Linux 參考資料的詳盡集合。

• ARMLinux - the book可從 Aleph One 上獲得。您可以定購一本,也可以 線上閱讀。

• 嵌入式 Linux 協會(Embedded Linux Consortium)是一個非贏利的互助協會,它歡迎致力於嵌入式 Linux 領域的開發人員成為會員。

• IBM 的 Linux wristwatch是運行 Linux 的微型嵌入式設備的示例;本文的作者之一,Vishal Kulkarni 也參與了它的研發。請在 本文( FreeOS.com,2001 年 3 月)中閱讀有關它的資訊。

• 在 developerWorks上流覽 更多 Linux 參考資料。

• 在 developerWorks上流覽 更多無線領域的參考資料。

作者簡介

Anand K Santhanam 在印度 Madras 大學獲得電腦科學工學學士學位。自 1999 年 7 月以來他一直在印度為 IBM Global Services(軟體實驗室)工作。他是 IBM Linux 小組的成員,這個小組主要致力於嵌入式系統中的 ARM-Linux、設備驅動程式和電源管理的研究和開發。他感興趣的其他領域是 O/S 本質和聯網。可以通過 mailto:asanthan@in.ibm.com?cc=asanthan@in.ibm.com 與他聯繫。

Vishal Kulkarni 從印度 Maharashtra 的 Shivaji 大學獲得電子工程的學士學位。自 1999 年 3 月以來他一直在印度為 IBM Global Services(軟體實驗室)工作。在此之前,他曾在美國 IBM Austin 工作了一年半多。他是 IBM Linux 小組的成員,這個小組主要致力於嵌入式設備上的 ARM-Linux、設備驅動程式和 GUI。他感興趣的其他領域是 O/S 本質和聯網。可以通過 mailto:kvishal@in.ibm.com?cc=kvishal@in.ibm.com與他聯繫。

2007年8月27日 星期一

Software RAID For Linux

我想大家也聽過RAID 吧! 它能夠保護你的資料, 或是增加讀取的效能,或是把數個硬碟結合在一起。正如大家所知道RAID 也有Hardware RAID 和Software RAID 之分。Hardware RAID 是透過硬體的支援令OS 認為它是一個device。而Software RAID 則是利用OS 的功能來模擬RAID。由於在Linux 下支援的RAID 卡實在不多, 所以在Linux 下要用IDE 作RAID 便只能用Software RAID 的方法了。


RAID 主要分為Linear , RAID 0 to 5 各種Level, 我想大家也很清楚其分別吧, 所以只會簡介一下 : Linear mode 是會把2 個或以上的Harddisk 連起來, 寫完一個再寫一個。RAID-0 和Linear 差不多, 但資料會同時寫在那數個harddisk 上。好處是能夠增進讀寫效能,壞處則是只要其中一個harddisk 有問題則整個RAID-0 的partition 的資料也會不見了(唉~ 筆者家中的電腦舊harddisk 壞了, 所有資料全部失去.. 但和RAID-0 無關 ^^) RAID-1 則會把資料重複寫進harddisk, 好處當然是能夠保護資料, 即使一個harddisk 有問題另一個仍然會保留了應有的資料。 壞處便是效能可能會下降。

至於RAID4 和 5 , 都必須有3個harddisk 以上才能執行。 它們在儲存資料時會同時儲存一寫計算出來的資料。那麼3個harddisk 中其中一個有問題時便能夠靠那寫特點計算的資料重新建立數據。4 和5 的不同之處在於,RAID-4 會把所有計算出來資料存儲在一個 harddisk 上, 但如果所有harddisk 均同速的話那便會拖慢整個RAID-4 partition。而 RAID-5 則會把計算出來的資料分開。

值得一提的是在同一RAID partition 內的harddisk 最好速度一樣, 大小也一樣。除了 Linear mode 外其他level 的RAID 在使用不同速度和大小的 harddisk時都可能會令到效能下降。

另外在RAID-4,5 中我們常常會加進一個spare disks, spare disks 在平常是不會被讀寫的,只有在其中一個harddisk fail 時spare disks 才會代替原有harddisk 的功能。

最後, Swap parition 是不需要RAID 的,因為linux kernel 本身已經能夠同時控制多個 swap parition 的存取來增進效能了。

Kernel Setting

在Linux 中設定Software RAID 其實是十分簡單的,首先你必需重新compile 一個support RAID 的kernel。最新的kernel 2.4.x 已經內建RAID support 了。

你必需要enable 以下的RAID 選項:

Multidevice support ->

Multiple devices driver support (RAID and LVM) -- y
RAID support -- y
Linear (append mode) -- y (如果你用linear mode)
RAID-0 (striping) mode -- y (如果你用RAID - 0)
RAID-1 (mirroring) mode -- y (如果你用RAID - 1)
RAID-4 /RAID-5 mode --y (如果你用RAID 4 或5)


以上的選項如果你的RAID partition 將會是root paritition 的話請必定要選y 而不是 compile 成modules。但如果不是的話(例如只有/home 是RAID paritition),那用modules 也無問題。

然後compile kernel 也不用教吧 ^^
make dep;make bzImage;make modules;make modules_install


設定RAID tools

現在reboot 一下, 看看有沒有問題, 沒有的話便要裝raidtools 了多數的distribution 也附有raidtools 的, 如果沒有的話, 用debian 的請安裝raidtools2 :

apt-get install raidtools2

用RPM 的話便自己到rpmfind.net 下載了並安裝 ,或到ftp 下載sources compile~ (對不起~ 筆者也中了Debian 毒 ^^)

完成安裝了嗎? 那麼便要設定 /etc/raidtab 了,現在你應該沒有這個file 的,但mkraid 預設是會讀取這個設定檔。

Linear mode 的範例設定檔:

raiddev /dev/md0 <--device 名
raid-level linear <--Raidlevel 是linear
nr-raid-disks 2 <--會被加進partition 的總parition 數
chunk-size 32
persistent-superblock 1
device /dev/hde1 <--第0個parition
raid-disk 0
device /dev/hdf1 <--第1個parition
raid-disk 1

至於chunk-size 和persistent-superblock 是什麼呢? chunk-size 是指寫進單一個 partition 的大小, 例如在RAID-0 中把一個file同時寫進兩個或以上parition 時, 會把 file 分成多大才寫進一其中一個partition 呢? (總不能1 bit 寫在這, 1bit 寫在那吧) chunk-size 在linear mode 中也許沒意義, 但在其他level 如RAID-0 對效能是會有影響的。至於persistent-superblock, 加上許是為了令kernel 在開機時能直接detect 到那 partition。

RAID-0 的範例設定檔:

raiddev /dev/md0
raid-level 0
nr-raid-disks 2
chunk-size 32
persistent-superblock 1
device /dev/hde1
raid-disk 0
device /dev/hdf1
raid-disk 1

RAID-1 的範例設定檔:

raiddev /dev/md0
raid-level 1
nr-raid-disks 2
nr-spare-disks 1 <-- 還記得剛才說過的spare-disks 嗎?
chunk-size 4
persistent-superblock 1
device /dev/hde1
raid-disk 0
device /dev/hdf1
raid-disk 1
device /dev/hdh1
spare-disk 0

RAID-4 的範例設定檔:

raiddev /dev/md0
raid-level 4
nr-raid-disks 3 <-- 最少要有3個partition
nr-spare-disks 1
persistent-superblock 1
chunk-size 32
device /dev/hde1
raid-disk 0
device /dev/hdf1
raid-disk 1
device /dev/hdg1
raid-disk 2
device /dev/hdh1
spare-disk 0

RAID-5 的範例設定檔:

raiddev /dev/md0
raid-level 5
nr-raid-disks 3
nr-spare-disks 1
persistent-superblock 1
chunk-size 32
parity-algorithm left-symmetric
device /dev/hde1
raid-disk 0
device /dev/hdf1
raid-disk 1
device /dev/hdg1
raid-disk 2
device /dev/hdh1
spare-disk 0

怎麼樣? 很簡單吧!

寫完你的設定檔後便執行:

mkraid /dev/md0

那麼你的RAID parition 便建立起來了!看一看 /proc/mdstat 吧! ^^

chpapa@power:~$ sudo cat /proc/mdstat
Personalities : [linear] [raid0] [raid1] [raid5]
read_ahead 1024 sectors
md0 : active raid5 hdh1[3] hdg1[2] hdf1[1] hde4[0]
80418048 blocks level5, 32k chunk, algorithm 2 [3/3] [UUU]

unused devices:

跑起來了, 很爽吧!
(順帶一提, 筆者測試是用HPT370 的RAID Card,在Linux Kernel 中選用HPT366 的driver 便能認得出各devices 了)

哈哈~ 但那些沒看完文章便走去mount /dev/md0 的人該打了, 你還未format partition 呀!

mke2fs -b 4096 /dev/md0

(如果是用RAID 4, 5 的話, mke2fs 是有特點options 的: -R stride=8, 為什麼是8? chunksize 除以 blocksize)

假如你的RAID parition 是要在開機時能夠讓Linux 自動Detect (例如是要做root partition) 的話, 你還有一些事情要做的。

首先當然是要有kernel support 吧, 如果是root partition 的話請compile 成內建而不是modules。另外要有persistent-superblock, 剛才便已經有了。最後是每個parition type 都要為Linux raid autodetect。

頭兩項剛才已經列明了做法, 至於要把partition type 轉為Linux raid autodetect...

首先用raidstop 暫停raid partition /dev/md0

power:/# raidstop /dev/md0

power:/# fdisk /dev/hde

The number of cylinders for this disk is set to 5606.
There is nothing wrong with that, but this is larger than 1024,
and could in certain setups cause problems with:
1) software that runs at boot time (e.g., old versions of LILO)
2) booting and partitioning software from other OSs
(e.g., DOS FDISK, OS/2 FDISK)

Command (m for help): p

Disk /dev/hde: 255 heads, 63 sectors, 5606 cylinders
Units = cylinders of 16065 * 512 bytes

Device Boot Start End Blocks Id System
/dev/hde1 * 1 7 56196 83 Linux
/dev/hde2 8 71 514080 83 Linux
/dev/hde3 72 135 514080 82 Linux swap
/dev/hde4 136 5606 43945807+ 83 Linux

跑 t 指令

Command (m for help): t
Partition number (1-4): 4
Hex code (type L to list codes): l
0 Empty 18 AST Windows swa 61 SpeedStor a6 OpenBSD
1 FAT12 1b Hidden Win95 FA 63 GNU HURD or Sys a7 NeXTSTEP
2 XENIX root 1c Hidden Win95 FA 64 Novell Netware b7 BSDI fs
3 XENIX usr 1e Hidden Win95 FA 65 Novell Netware b8 BSDI swap
4 FAT16 <32M 24 NEC DOS 70 DiskSecure Mult c1 DRDOS/sec (FAT-
5 Extended 39 Plan 9 75 PC/IX c4 DRDOS/sec (FAT-
6 FAT16 3c PartitionMagic 80 Old Minix c6 DRDOS/sec (FAT-
7 HPFS/NTFS 40 Venix 80286 81 Minix / old Lin c7 Syrinx
8 AIX 41 PPC PReP Boot 82 Linux swap da Non-FS data
9 AIX bootable 42 SFS 83 Linux db CP/M / CTOS / .
a OS/2 Boot Manag 4d QNX4.x 84 OS/2 hidden C: e1 DOS access
b Win95 FAT32 4e QNX4.x 2nd part 85 Linux extended e3 DOS R/O
c Win95 FAT32 (LB 4f QNX4.x 3rd part 86 NTFS volume set e4 SpeedStor
e Win95 FAT16 (LB 50 OnTrack DM 87 NTFS volume set eb BeOS fs
f Win95 Ext'd (LB 51 OnTrack DM6 Aux 8e Linux LVM f1 SpeedStor
10 OPUS 52 CP/M 93 Amoeba f4 SpeedStor
11 Hidden FAT12 53 OnTrack DM6 Aux 94 Amoeba BBT f2 DOS secondary
12 Compaq diagnost 54 OnTrackDM6 9f BSD/OS fd Linux raid auto
14 Hidden FAT16 <3 55 EZ-Drive a0 IBM Thinkpad hi fe LANstep
16 Hidden FAT16 56 Golden Bow a5 BSD/386 ff BBT
17 Hidden HPFS/NTF 5c Priam Edisk

看來是 fd 吧!

Hex code(type L to list codes): fd

然後跑 w 寫入就成了。

把剛才的做法在每個參與RAID 的partition 都做一次,然後試一下reboot 吧!看一看有沒有開機訊息告訢你已經找到RAID partition 吧!

實例

是次實例是一部原本已經在運行的Server , 它的/ partition 在/dev/hda1, /home 在 /dev/hdb1, 我們假設已經在kernel 設定好RAID5 support 了, 現在會增加四個harddisk 上去並跑RAID5

首先把那些Harddisk 分割好~ 四個harddisk 分別是 /dev/hde , /dev/hdf , /dev/hdg , /dev/hdh
(筆者測試用的電腦是用HPT370 Controller) 打算用 /dev/hde1 作 /boot 開機,用 /dev/hde2 作 /tmp, /dev/hde3 作swap。

首先當然是 fdisk, 相信大家都懂得用fdisk 吧,記緊RAID partition 要差不多size ,也要把partition type 設定為 fd 呀!

安裝raidtools :
apt-get install raidtools2

然後便是篇寫/etc/raidtab 了:

pico /etc/raidtab

raiddev /dev/md0
raid-level 5
nr-raid-disks 3
nr-spare-disks 1
persistent-superblock 1
parity-algorithm left-symmetric
chunk-size 32
device /dev/hde4
raid-disk 0
device /dev/hdf1
raid-disk 1
device /dev/hdg1
raid-disk 2
device /dev/hdh1
spare-disk 0


然後用mkraid 指令...
mkraid /dev/md0

格式化:
mke2fs -b 4096 -R stride=8 /dev/md0

把新的RAID5 mount 作/mnt/newroot:
mount /dev/md0 /mnt/newroot

把舊的資料抄到 /mnt/newroot
umask 0
cp -ax / /mnt/newroot
cp -ax /home /mnt/newroot/ <-- 因為-ax 只會把同一個partition 的資料抄走, 而 /home 現在和/ 在不同partition, 所以要跑兩次, 這是新手常常忘記了的

把/boot 抄到/dev/hde1 來開機
mount /dev/hde1 /mnt/newroot/boot
cp -R /boot /mnt/newroot/boot

chroot到新的harddisk:
chroot /mnt/newroot

設定新的fstab:
pico /etc/fstab (因為已經chroot, 所以現在/ 已經是/mnt/newroot 了)

/dev/md0 / ext2 defaults,errors=remount-ro,usrquota,grpquota 0 0
/dev/cdrom /cdrom iso9660 defaults,ro,user,noauto 0 0
/dev/hde1 /boot ext2 defaults 0 0
/dev/hde2 /tmp ext2 defaults 0 0
/dev/hde3 none swap sw 0 0

設定新的lilo:
pico /etc/lilo.conf

boot=/dev/hde
disk=/dev/hde
bios=0x80
compact
install=/boot/boot-menu.b
delay=1
map=/boot/map
append=""
read-only
default=Linux
image=/boot/vmlinuz-2.4.2
root=/dev/md0
label=Linux


然後執行lilo: /sbin/lilo

重新開機後, 把舊的harddisk 拔出來, 應該可以用/dev/hde 來正常開機了最後別忘了用mkswap format swap parition 呀!

多數用者在設定RAID 都不會遇到問題, 反而是lilo 的設定倒是較麻煩,另外筆者沒有試過直接用RAID 作/boot 來開機, 有興趣的讀者可以試一試, ^o^

raidtools 常用指令介紹

以下為RAID 的常用指令:

raidstart - 開動一個已建立的raid partition
raidstop - 暫停一個已開動的raid partition
raidhotadd - 在RAID 運行時加入一個新Harddisk, 例如在RAID5 中有一個harddisk 壞了, 要更換一個新的上去。
raidhotremove - 和raidhotadd 相反, 是會移除harddisk 的

最後提一提各位讀者, 要更動raid partition 的話, 請先用raidstop 暫停它。

RedHat Linux 9軟體RAID配置

RedHat Linux 9軟體RAID配置
首先請閱讀第3章來瞭解一下 RAID、硬體和軟體 RAID 間的區別、以及 RAID 0、1、和 5 之間的區別。
軟體 RAID 能夠在 Red Hat Linux 的圖形化安裝期間或 kickstart 安裝期間配置。本章討論如何使用 Disk Druid 介面來在安裝期間配置軟體 RAID。
在你創建 RAID 設備之前,你必須首先創建 RAID 分區,然後遵循以下步驟:
1. 在 「磁片分區設置」 螢幕上,選擇 「用 Disk Druid 手工分區」 。
2. 在 Disk Druid 中,選擇 「新建」 來創建一個新分區。
3. 你不能輸入一個掛載點(在你創建了 RAID 設備後你才可以做)。
4. 從 「檔系統類型」 下拉功能表中選擇 「軟體 RAID」 ,如圖10-1所示。


圖 10-1. 創建一個新 RAID 分區
5. 對於 「允許的驅動器」 ,選擇要在其上創建 RAID 的驅動器。如果你有多個驅動器,所有驅動器都會在這裏被選擇,你必須取消選擇你 不想 在上面創建 RAID 的驅動器。
6. 輸入你想要的分區大小。
7. 選擇 「固定大小」 來使物理卷具備指定大小,選擇 「指定空間大小(MB)」 ,輸入以 MB 為單位的大小來給物理卷大小一個範圍,或選擇 「使用全部可用空間」 來使它的大小擴充到填滿整個硬碟的可用空間。如果你有不止一個可擴展的分區,它們會分享磁片上的可用空閒空間。
8. 如果你想讓這個分區成為主分區,選擇 「強制為主分區」 。
9. 如果你想讓安裝程式在格式化硬碟驅動器之前檢查磁片壞塊,選擇 「檢查磁片壞塊」 。
10. 點擊 「確定」 來返回到主螢幕。
重複這些步驟來創建你的 RAID 設置所需的分區。注意,不是所有的分區都必須是 RAID 分區。譬如,你可以僅把 /home 分區配置為軟體 RAID 設備。
一旦你創建了所有所需的 「軟體 RAID」 分區,遵循以下步驟:
1. 在 Disk Druid 的主分區螢幕上(參見圖 10-3 選擇 「RAID」 按鈕。
2. 接著,圖 10-2 就會出現,你可以在這裏製作 RAID 設備。


圖 10-2. 製作 RAID 設備
3. 輸入掛載點。
4. 為分區選擇檔系統類型。
5. 為 RAID 設備選擇設備名稱,如: md0 。
6. 選擇你的 RAID 級別。可供選擇的有: RAID 0 、 RAID 1 、和 RAID 5 。
注記:如果你想把 /boot 製成 RAID 分區,你必須選擇 RAID 級別 1,而且它必須使用前兩個驅動器之一(首先 IDE,其次 SCSI)。如果你不想把 /boot 製成 RAID 分區,但是你要把 / 製成 RAID 分區,它必須是 RAID 級別 1,而且它必須是前兩個驅動器之一(首先 IDE,其次 SCSI)。
7. 你剛剛創建的 RAID 分區會出現在 「RAID 成員」 列表中。從這個列表中選擇要創建 RAID 設備的分區。
8. 如果配置的是 RAID 1 和 RAID 5,請指定備用分區的數量。如果某個軟體 RAID 分區失效了,這個備用的分區會自動被用作替換分區。對每一個你想指定的備用分區,你必須製作一個額外的軟體 RAID 分區(RAID 設備中的分區以外的)。在前一步驟中,為 RAID 設備以及備件選擇分區。
9. 點擊了 「確定」 後,RAID 設備會出現在 「驅動器摘要」 列表中,如圖10-3所示。這時,你可以繼續安裝進程。要獲取進一步說明,請參閱 《Red Hat Linux 安裝指南》 。


圖 10-3. RAID 陣列已創建

SATA RAID的準備與安裝

SATA硬碟跟PATA硬碟幾乎沒有價差,但SATA效能較高一些,而且用來組RAID更加輕鬆方便,不但排線細長較好連接,也沒有Master與Slave設定問題。至於選用第一代SATA( 1.5Gb/s ),或是具備3Gb/s外部傳輸率的SATA II硬碟,基本上是沒有差別的,因為就算組了RAID效能也不一定能破3Gb/s。
選用SATA的另一個重要因素,是PATA硬碟短期內雖不會退出市場,以後也不一定無法買到,但是未來主機對PATA的支援將會越來越少,當你換新主機板時原有RAID系統能否轉移過去也是個問題。
在各種RAID組法中,RAID 5同時具備了效能與安全,容量的浪費也較少,可說是較好的選擇。況且最新的主機板大多開始支援SATA RAID 5的功能,更可看出主流RAID架構的趨勢,因此我們就選擇SATA RAID 5的安裝來做示範。
準備與安裝
1.三顆SATA硬碟(或四顆)
要組磁碟陣列當然要準備硬碟,以RAID 5的架構我們至少要準備3顆硬碟,如果預算允許也能用4顆硬碟來組。而4顆硬碟的SATA RAID也是目前大多主機板的極限了,雖然有些主機板具備額外的RAID控制晶片,可以提供超過4組SATA插槽,但單一控制晶片還是只能管理4顆硬碟。
組成RAID的各顆硬碟最好是同一廠牌、型號,來確保容量、轉速、緩衝區、存取特性等各項規格相同。規格不同的硬碟也是可以組成RAID,但是穩定性可能會較差,而且整個RAID系統的容量與效能,都會遷就其中規格最低的一個硬碟,造成資源的浪費。
2.支援SATA RAID 5的主機板
在主流的主機板中,採用Intel 955X 晶片組的ICH7R南橋,以及AMD平台的NVIDIA nForce4 SLI晶片組,都可以提供「硬體RAID 5」的支援能力,而且最少會提供4個SATA插槽。如果是較舊款的主機板,通常只能支援RAID 0、1、01/10。
某些主機板有附加的RAID控制晶片,可以多提供2個或4個SATA插槽。常見如Silicon Image Sil3132,只提供2個SATA插槽,可想而知一定無法支援需要3顆硬碟的RAID 5。而Silicon Image Sil3114R能控制4個SATA插槽,但對RAID 5只提供軟體支援,必須要在作業系統下以軟體來架構RAID 5,效能與實用性都不理想。
3.軟碟機、軟碟片
平常幾乎完全被人遺忘的軟碟機,在組RAID時卻變成不可或缺,這是因為Windows安裝光碟無法支援RAID、SCSI、SATA等磁碟型式,必須在作業系統安裝時以軟碟片將這些驅動程式「餵」給Windows,否則安裝程式將會完全不認識你的RAID,更別說要把系統裝好了。
舊有的軟碟機通常已積滿灰塵,或是不堪使用,舊的軟碟片也可能都無法讀寫了。如果有這方面問題,花個幾百塊買部新的軟碟機與幾片新軟碟,在整個系統的預算中也只是九牛一毛。
4.空間足夠的機殼
因為要放入3~4顆3.5吋的SATA硬碟,而且還要塞進同為3.5吋外型的軟碟機,所以機殼至少要有「四小」或「五小」的3.5吋設備安裝空間,來安置這麼一堆硬碟。當然,你的硬碟要疊羅漢隨處放著,或是用膠帶整堆綁起來也可以,但是請風險自負。
安裝方式
在舊系統或另一部電腦中,先使用主機板驅動光碟中的「RAID驅動磁片製作程式」,作出一片待會安裝作業系統要用的驅動磁片。

1.製作一片RAID驅動用的軟碟片


2.軟碟片中的驅動檔
在硬體組裝部分,將所有硬碟都掛到機架上固定好,一個個都插上排線與電源,再將一條條排線接到主機板上有提供RAID 5功能的SATA插槽上,不清楚的話請參考主機板的說明書。


3.將SATA排線、電源線都接上


4.將SATA排線接上主機板,順序不重要
確定硬碟都裝好沒問題後,可以先開機進入BIOS中調整相關設定,依照主機板的不同會有不一樣的設定項目,大致上是進入「附加週邊」(Integrated Peripheral)的項目,將主要SATA控制器的模式設為「RAID」,這樣才能開啟主機板的「RAID」功能。

5.進入主機板BIOS作設定


6.將SATA控制器設定為RAID模式
儲存設定後並離開BIOS後,系統會重新開機,如果上個步驟設定正確的話,在BIOS載入過程中應該會出現RAID晶片的提示畫面。這個畫面會列出每顆硬碟的型號、容量等資訊,並提示使用者進入RAID晶片BIOS的組合鍵。這時不要遲疑,趕快按下組合鍵吧。﹙如果錯過的話,就重新開機再來一次就好﹚


7.開機時可以看到RAID提示畫面


8.就是這個快速鍵,按下去就對了
進入RAID設定介面後,通常第一個選項就是「創建新RAID」,進入選項後必須設定RAID的名稱﹙自由輸入﹚、模式﹙選RAID 5或Parity﹚、組成硬碟﹙全選﹚、資料分割大小﹙RAID 5的建議值是64KB﹚、使用容量﹙系統會自動帶出可用容量的最大值,大約是使用硬碟數減一顆的容量總合﹚。


9.組成RAID 5的設定


10.全選所有硬碟


11.根據建議值設定資料分割大小


12.容量自動設為最大值
完成設定後,就可以安裝Windows作業系統了。跟一般安裝類似,先將BIOS的優先開機裝置設為「光碟機」,並記得將含有驅動檔的軟碟片放入﹙BIOS裡也要啟用軟碟機﹚,接著將Windows安裝光碟放進光碟機並重新開機即可。
在安裝光碟載入並開始安裝時,注意螢幕最下方的提示字串,會有一行「Press F6 if you need to install a third party SCSI or RAID driver...」,這邊記得一定要按下「F6」。
安裝到某個階段時,會跳出一個提問畫面,要使用者選擇特定的驅動程式,按下「S」進入並選取要用的RAID控制器名稱,設定完後安裝程式會讀取軟碟中的驅動檔並繼續安裝。


13.看到這行字就按下F6


14.要求選定驅動程式的提示


15.選定要安裝的RAID控制器
後面的步驟就跟一般作業系統安裝相同了,Windows安裝完畢後也可以在視窗環境下安裝RAID的管理程式,可以檢視RAID的組成與狀態,如果不安裝的話也不會影響RAID運作。

磁碟陣列 ( RAID ) 原理及各個階層詳細介紹

前言:

什麼是磁碟陣列?

磁碟陣列的由來:

磁碟陣列,時事所趨:

磁碟陣列有那些優點:

各階層磁碟陣列(RAID)介紹:

RAID 0:Striping/Span (切分/延展)

RAID 1:Mirroring (磁碟鏡射)

RAID 0+1:Mirror + Striping (磁碟鏡射+切分/延展)

RAID 3:Parallel with Parity (平行同位元檢查)

RAID 5:Striping with Rotating Parity (切分/延展+輪轉同位元)

前言:

現在己經有很多主機板都內建了IDE RAID晶片,除了提供ATA/133功能外,也提供了磁碟陣列功能,給使用者一個完整的IDE周邊解決方案。不過,應該還有很多人弄不清楚磁碟陣列是什麼,對磁碟陣列的使用及工作原理也有很多疑問。在這裏我們就來介紹一下磁碟陣列(RAID)的概念與工作原理,相信對各位會有所幫助。

什麼是磁碟陣列?
磁碟陣列簡稱RAID(Redundant Arrays of Inexpensive Disks),有”價格便宜且多餘的磁碟陣列”之意。其原理是利用陣列方式來作磁碟組,配合資料分散排列的設計,提升資料的安全性。磁碟陣列主要針對硬碟,在容量及速度上,無法跟上CPU及記憶體的發展,提出改善方法。磁碟陣列是由很多便宜、容量較小、穩定性較高、速度較慢磁碟,組合成一個大型的磁碟組,利用個別磁碟提供資料所產生的加成效果來提升整個磁碟系統的效能。同時,在儲存資料時,利用這項技術,將資料切割成許多區段,分別存放在各個硬碟上。

磁碟陣列還能利用同位元檢查(Parity Check)的觀念,在陣列中任一顆硬碟故障時,仍可讀出資料,在資料重建時,將故障硬碟內的資料,經計算後重新置入新硬碟中。

磁碟陣列的由來:
由美國柏克萊大學(University of California-Berkeley)在1987年,發表的文章:”A Case for Redundant Arrays of Inexpensive Disks”。文章中,談到了RAID這個字彙,而且定義了RAID的5層級。柏克萊大學研究其研究目的為,反應當時CPU快速的性能。CPU效能每年大約成長30~50%,而硬磁機只能成長約7%。研究小組希望能找出一種新的技術,在短期內,立即提升效能來平衡電腦的運算能力。在當時,柏克萊研究小組的主要研究目的是效能與成本。

另外,研究小組也設計出容錯(fault-tolerance),邏輯資料備份(logical data redundancy),而產生了RAID 理論。研究初期,便宜(Inexpensive)的磁碟也是主要的重點,但後來發現,大量便宜磁碟組合並不能適用於現實的生產環境,後來Inexpensive被改為independence,許多獨立的磁碟組。

磁碟陣列,時事所趨:
自有PC以來,硬碟是最常使用的儲存裝置。但在整個電腦系統架構中,跟CPU與RAM來比,硬碟的速度是PC中最弱的設備之一。所以,為了加速電腦整體的資料流量,增加儲存的吞吐量,進階改進硬碟資料的安全,磁碟陣列的設計因應而生。

硬碟隨著科技的日新月異,現在其容量已達40GB以上,轉速到了1萬轉,甚至15000轉,而且價格實在是很便宜,再加現在企業流行,人力資源規畫(Enterprise Resource Planning:ERP)是每個公司建構網路的主要目標。所以,利用區域網路來傳遞資料,伺服器所使用的硬碟顯得非常重要,除了容量大、速度快之外,穩定更是基本要求。基於此因,磁碟陣列開始廣泛的應用在個人電腦上。

磁碟陣列其樣式有三種,一是外接式磁碟陣列櫃、二是內接式磁碟陣列卡,三是利用軟體來模擬。外接式磁碟陣列櫃最常被使用大型伺服器上,具可熱抽換(Hot Swap)的特性,不過這類產品的價格都很貴。內接式磁碟陣列卡,因為價格便宜,但需要較高的安裝技術,適合技術人員使用****作。另外利用軟體模擬的方式,由於會拖累機器的速度,不適合大資料流量的伺服器。

由上述可知,現在IDE磁碟陣列大行其道的道理;IDE介面硬碟的穩定度與效能表現已有很大的提升,加上成本考量,所以採用IDE介面硬碟來作為磁碟陣列的決解方案,可說是最佳的方式。

磁碟陣列有那些優點:

1.傳輸速率快
2.儲存容量可提升
3.提升I/O每秒的數量
4.增加資料安全性及穩定性
5.大量資料快速及簡易管理
6.增加可用運時間,減少維護

各階層磁碟陣列(RAID)介紹:

磁碟陣列是由2個以上的硬碟,模擬一個邏輯硬碟出現在系統中;使用磁碟陣列控制器以達成其存在,利用不同陣列形式,模擬各種層級。現在我們先來了解磁碟陣列(RAID)到底有幾種模式,一般最常提到及應用的RAID層級分為0、1、0+1、3及5。另外還有一些極少用到的RAID 4及RAID 6在此我們就不提它了。

以下就是各個階層的介紹及圖解:

RAID 0:Striping/Span (切分/延展)

RAID 1:Mirroring (磁碟鏡射)

RAID 0+1:Mirror + Striping (磁碟鏡射+切分/延展)

RAID 3:Parallel with Parity (平行同位元檢查)

RAID 5:Striping with Rotating Parity (切分/延展+輪轉同位元)


RAID 0:Striping/Span (切分/延展)
RAID 0,它是將資料儲存在2個以上的硬碟機,其將全部磁碟機的儲存容量合併,藉由將資料切分到全部的磁碟機上,進行平行讀寫,而達到提高效能增加容量。但是缺點是完全沒有容錯能力,只要有一個磁碟故障,就會導致陣列磁碟的所有資料,毀於一旦無法挽回。

RAID 1:Mirroring (磁碟鏡射)
RAID 1,必須由2個以上的硬碟所組成,由磁碟陣列(RAID)來控制,將資料同時寫入第1個與第2個硬碟,其2組硬碟上的資料完全相同,也就是其中一個硬碟是用來作備份用途;當其中有一個硬碟故障時,系統照常運作正常。RAID 1是所有RAID階層上,經濟效益最好,效能很高,極佳的資料安全性。是所有階層中使用最多最廣最符合當初RAID設計概念的一種。唯一小缺點是,其陣列磁碟容量是全部硬碟容量的一半。


RAID 0+1:Mirror + Striping (磁碟鏡射+切分/延展)
RAID 0+1,是結合了RAID 0與1兩種模式,這個階層須具備4個或以上的雙數硬碟所組成。這個模式是由2個硬碟遵守RAID 0規範,設定成一組,再由每組間遵循RAID 1的規範,使RAID 0+1擁有容錯力及整體讀寫速度與資料安全性。不過,缺點是成本很高。


RAID 3:Parallel with Parity (平行同位元檢查)
RAID 3,最少須3個硬碟或以上,這個階層的磁碟陣列具備了同位元高階智慧型演算法,利用一個硬碟來儲存其運算出來的同位元值的資料。當陣列磁碟中有一個硬碟發生故障時(當然不能是同位元碟),只要換上新硬碟後,磁碟陣列控制器就能利用同位元碟的資料,重新演算得到其舊有資料並回寫建立。因為其同位元檢查資料是將資料切割成數個區段,利用XOR演算法計算出同位元資料;而其區段以Bytes計算時,稱為RAID 3,如果是以Block計算時,就稱為RAID 4。所以RAID 3在整體讀寫效能會較慢較差,但在成本上會比RAID 0+1還省一點,其陣列磁碟整體容量計算公式為N-1。


RAID 5:Striping with Rotating Parity (切分/延展+輪轉同位元)
RAID 5,最少須3個硬碟,其工作原理與RAID 3相似,主要差別是其同位元資料沒有固定在同個硬碟,是以輪流方式儲存在每個硬碟上,故稱輪轉同位元。當磁碟陣列控制器利用XOR演算出同位元檢查資料後,會隨著資料分別寫入各台硬碟上,因此整體讀寫效能比RAID 3要好一些,當然比RAID 0要差。不過在大型資料處理時,需同時讀寫多個硬碟,而同位元檢查是由磁碟陣列控制器的XOR邏輯所控制的,所以資料處理越大越多時,一定會有所遺失,但這個階層的RAID還是可以提供很高的容錯能力。

CentOS 5 yum國內鏡像伺服器 配置檔[CentOS-Base.repo]

/etc/yum.repos.d/CentOS-Base.repo
CentOS5 yum國內鏡像伺服器 配置檔:

[base]
name=CentOS-5 - Base
#mirrorlist=http://mirrorlist.centos.org/?release=$releasever5&arch=$basearch&
repo=os
#baseurl=http://mirror.centos.org/centos/$releasever/os/$basearch/
baseurl=http://mirror.be10.com/centos/5.0/os/$basearch/
http://ftp.iasi.roedu.net/mirrors/centos.org/centos/5.0/os/$basearch/
http://ftp.hostrino.com/pub/centos/5.0/os/$basearch/
gpgcheck=1
gpgkey=http://mirror.centos.org/centos/RPM-GPG-KEY-centos5

#released updates
[update]
name=CentOS-5 - Updates
#mirrorlist=http://mirrorlist.centos.org/?release=4&arch=$basearch&repo=updates
baseurl=http://mirror.be10.com/centos/5.0/updates/$basearch/
http://ftp.iasi.roedu.net/mirrors/centos.org/centos/5.0/updates/$basearch/
http://ftp.hostrino.com/pub/centos/5.0/updates/$basearch/
gpgcheck=1
gpgkey=http://mirror.centos.org/centos/RPM-GPG-KEY-centos5

#packages used/produced in the build but not released
[addons]
name=CentOS-5 - Addons
#mirrorlist=http://mirrorlist.centos.org/?release=4&arch=$basearch&repo=addons
baseurl=http://mirror.be10.com/centos/5.0/addons/$basearch/
http://ftp.iasi.roedu.net/mirrors/centos.org/centos/5.0/addons/$basearch/
http://ftp.hostrino.com/pub/centos/5.0/addons/$basearch/
gpgcheck=1
gpgkey=http://mirror.centos.org/centos/RPM-GPG-KEY-centos5

#additional packages that may be useful
[extras]
name=CentOS-5 - Extras
#mirrorlist=http://mirrorlist.centos.org/?release=4&arch=$basearch&repo=extras

baseurl=http://mirror.be10.com/centos/5.0/extras/$basearch/
http://ftp.iasi.roedu.net/mirrors/centos.org/centos/5.0/extras/$basearch/
http://ftp.hostrino.com/pub/centos/5.0/extras/$basearch/
gpgcheck=1
gpgkey=http://mirror.centos.org/centos/RPM-GPG-KEY-centos5

#additional packages that extend functionality of existing packages
[centosplus]
name=CentOS-5 - Plus
#mirrorlist=http://mirrorlist.centos.org/?release=4&arch=$basearch&repo=centosplus
baseurl=http://mirror.be10.com/centos/5.0/centosplus/$basearch/
http://ftp.iasi.roedu.net/mirror ... tos/5.0/centosplus/$basearch/
http://ftp.hostrino.com/pub/centos/5.0/centosplus/$basearch/
gpgcheck=1
enabled=0
gpgkey=http://mirror.centos.org/centos/RPM-GPG-KEY-centos5

#contrib - packages by Centos Users
[contrib]
name=CentOS-5 - Contrib
#mirrorlist=http://mirrorlist.centos.org/?release=4&arch=$basearch&repo=contrib
baseurl=http://mirror.be10.com/centos/5.0/contrib/$basearch/
http://ftp.iasi.roedu.net/mirrors/centos.org/centos/5.0/contrib/$basearch/
http://ftp.hostrino.com/pub/centos/5.0/contrib/$basearch/
gpgcheck=1
enabled=0
gpgkey=http://mirror.centos.org/centos/RPM-GPG-KEY-centos5

uClinux下Nor Flash的JFFS2檔系統構建


嵌入式系統正隨著Internet的發展而在各個領域得到廣泛的應用,作為嵌入式應用的核心,嵌入式Linux以其自由軟體特性正日益被人們看好。Linux具有內核小、效率高、源代碼開放等優點,還內涵了完整的TCP/IP網路協定,因此非常適於嵌入式系統的應用。而作為專門運行於沒有MMU的微處理器的嵌入式作業系統,uClinux更是得到廣泛應用。
當前的嵌入式系統開發,需要方便靈活的使用Flash。NOR和NAND是現在市場上兩種主要的非易失快閃記憶體技術。Intel于1988年首先開發出NOR flash技術,徹底改變了原先由EPROM和EEPROM一統天下的局面。NOR的特點是晶片內執行XIP eXe-cute In Place,這樣應用程式可以直接在flash快閃記憶體內運行,不必再把代碼讀到系統RAM中。NOR的傳輸效率很高,在1~4MB的小容量時具有很高的成本效益,因此在嵌入式系統得到廣泛的應用。

1 JFFS2檔系統簡介
uClinux通常默認ROMFS作為根檔系統,它相對於一般的EXT2檔系統具有節約空間的優點。但是ROMFS是一種唯讀的檔系統,不支援動態擦寫保存。雖然對於需要動態保存的資料可以採用虛擬ram盤的方法來保存,但當系統掉電後,ram盤的內容將全部丟失,而不能永久保存,因此需要實現一個可讀寫的檔系統。JFFS2檔系統便是一個很好的選擇。
JFFS檔系統是瑞典Axis通信公司開發的一種基於Flash的日誌檔系統,它在設計時充分考慮了Flash的讀寫特性和用電池供電的嵌入式系統的特點,在這類系統中必需確保在讀取檔時,如果系統突然掉電,其檔的可靠性不受到影響。對Red Hat的David Woodhouse進行改進後,形成了JFFS2。主要改善了存取策略以提高FLASH的抗疲勞性,同時也優化了碎片整理性能,增加了資料壓縮功能。需要注意的是,當檔系統已滿或接近滿時,JFFS2會大大放慢運行速度。這是因為垃圾收集的問題。
JFFS2的底層驅動主要完成檔系統對Flash晶片的訪問控制,如讀、寫、擦除操作。在Linux中這部分功能是通過調用MTD(memory technology device記憶體技術設備)驅動實現的。相對於常規塊設備驅動程式,使用 MTD 驅動程式的主要優點在於 MTD 驅動程式是專門為基於快閃記憶體的設備所設計的,所以它們通常有更好的支持、更好的管理和更好的基於磁區的擦除和讀寫操作的介面。MTD相當於在硬體和上層之間提供了一個抽象的介面,可以把它理解為FLASH的設備驅動程式,它主要向上提供兩個介面:MTD字元設備和MTD塊設備。通過這兩個介面,就可以象讀寫普通檔一樣對FLASH設備進行讀寫操作。經過簡單的配置後,MTD在系統啟動以後可以自動識別支援CFI或JEDEC介面的FLASH晶片,並自動採用適當的命令參數對FLASH進行讀寫或擦除。
JFFS2在uClinux中有兩種使用方式,一種是作為根檔系統,另一種是作為普通檔系統在系統啟動後被掛載。考慮到實際應用中需要動態保存的資料並不多,且在Linux系統目錄樹中,根目錄和/usr等目錄主要是讀操作,只有少量的寫操作,但是大量的讀寫操作又發生在/var和/tmp目錄(這是因為在系統運行過程中產生大量log檔和暫存檔案都放在這兩個目錄中),因此,通常選用後一種方式。根檔指的是Romfs、var和/tmp,目錄採用Ramfs,當系統斷電後,該目錄所有的資料都會丟失。
綜上所述,通常在uClinux下採用的檔系統構成如圖1所示。對於本文來說,圖中Romfs和Ramfs兩個檔系統的實現是很方便的,主要需要實現的是Nor Flash的底層MTD驅動,下面就以SST39VF160晶片為例來介紹MTD的驅動設計方法。

2 JFFS2底層MTD驅動設計
本文採用的系統以三星公司的SND-100為母板,CPU為ARM7TDMI晶片S3C4510B,16M的SDRAM,Nor Flash為SST39VF160,容量為1M×16bit,速度為70ns,通過16位元資料匯流排與CPU交換資料,擦寫次數典型值為10萬次。
在\linux-2.4.x\drivers\mtd\maps目錄下,每一個檔都是一個具體的MTD原始設備的相關資訊,包括該MTD原始設備的起始物理位址、大小、分區情況、讀寫函數、初始化和清除程式。設計時,需要對SST39VF160編寫相關的程式,假設為S3C4510B.C。則需要進行以下幾點操作:
(1) 定義SST39VF160在系統中的起始位址、大小、匯流排寬度
#define WINDO DDR 0x1000000|0x04000000 //注意FLASH分區地址必須是non-cacheble
#define WINDOW SIZE 0x200000
#define BUSWIDTH 2
(2) 定義SST39VF160分區
典型的記憶體分區應包括:內核引導區、Linux內核區、應用區。其中內核引導區用來保存內核載入程式,Linux內核區存放的是經過壓縮的uClinux內核,應用區則用來保存用戶的資料和應用程式,該區設為我們要採用的JFFS2檔系統。具體如下:
static struct mtd_partition s3c4510_partitions[]={
{
name: ″bootloader(128K)″,
size: 0x20000,
offset: 0x0000,
mask_flags:MTD_WRITEABLE //設置成唯讀區域
},
{
name: ″uClinux_kernel(832K)″,
size: 0xd0000,
offset: 0x20000,
},
{
name: ″jffs2 (1088K)″,
size: 0x110000,
offset: 0xf0000
}
};
(3) 定義SST39VF160位元組、半字、字的讀寫操作函數。
(4) 初始化SST39VF160函數int_init init_s3c4510b()。
該操作主要包括兩個方面:第一是調用do map probe()檢測搜索MTD設備。通常檢測方式有兩種:cfi probe和jedec probe,這裏採用後一種,該方法在jedec_probe.c檔中定義。另外,jedec probe.c中定義了各種jedec probe類型晶片的資訊,有些linux版本沒有包含SST39VF160,需要手動添加;而操作的第二方面則是調用add_mtd_partitions()以將your_partiton的各個分區加入mtd_table。

3 內核相關配置的設定
3.1 內核配置檔設置
為使內核支持JFFS2,需在內核配置選項功能表裏選擇相關選項。首先把SST39VF160的MTD驅動加入配置功能表。並在mtd/maps/Config.in檔中加入如下程式:
if[″$CONFIG ARM″= ″y″]; then
dep_tristate′CFI Flash device mapped on Samsung S3C4510B′CONFIG_MTD_S3C4510B $CONFIG_MTD_CFI
相應\mtd\maps\Makefile文件加入
obj_$(CONFIG_MTD_S3C4510B)+=s3c4510b.o
其次選擇Menuconfig下的配置選項。
在linux Kernel v2.4.20-uc0 Configuration下
Memory Technology DevicesMTD下
CONFIG_MTD=Y
CONFIG_MTD_DEBUG=Y
CONFIG_MTD_DEBUG_VERBOSE=3
CONFIG_MTD_PARTITIONS=Y
CONFIG_MTD_CHAR=Y
CONFIG_MTD_BLOCK=Y
RAM/ROM/Flash chip drivers下
CONFIG_MTD_CFI=Y
CONFIG_MTD_JEDECPROBE=Y
CONFIG_MTD_CFI_AMDSTD=Y
Mapping drivers for chip access下
CONFIG_S3C4510B=Y
File systems下
CONFIG_JFFS2_FS=Y
CONFIG_JFFS2_FS_DEBUG=2
在uClinux v1.3.4 Configuration下
Flash Tools下
CONFIG_USER_MTDUTILS=Y
CONFIG_USER_MTDUTILS_ERASE=Y
CONFIG_USER_MTDUTILS_ERASEALL=Y
CONFIG_USER MTDUTILS_MKFSJFFS2=Y
BusyBox下選中cat,cp,dd, mount,umount,mkdir工具。
3.2 MTD塊設備配置
下面是修改系統塊設備的主設備號。默認情況下,MTDBLOCK主設備號為31,與BLKMEM的主設備號衝突,因此 修改\mtd\mtd.h中 MTD BLOCK MAJOR的值為30。
接著應添加MTD設備節點到/vender/--你所使用的目的機類型--/Makefile檔中。其中字元設備的主設備號為90,次設備號為0、2、4、6...(奇數次設備號為唯讀設備),塊設備的主設備號為31,次設備號為0、1、2、3。可按以下方式增加DEVICES目標:
mtd0,c,90,0 mtd1,c,90,1 mtd2,c,90,2
mtdblock0,b,30,0 mtdblock1,b,30,1 mtd-block2,b,30,2
做完以上步驟,可以運行內核編譯命令make dep, make 以對內核進行編譯。
當系統啟動時,可以看到以下資訊:
s3c4510b flash device: 200000 at 5000000
Found: SST SST39VF160
number of JEDEC chips: 1
Creating 3 MTD partitions on ″S3C4510B flash de-vice″:
0x00000000-0x00020000: ″bootloader(128K)″
mtd:Giving out device 0 to bootloader(128K)
0x00020000-0x00f0000:″uClinux_kernel(832K)″
mtd: Giving out device 1 to uClinux_kernel(832K)
0x00f0000-0x00200000:″jffs2_usr(1088K)″
mtd: Giving out device 2 to jffs2_usr(1088K)
init_mtdchar: allocated major number 90.
init_mtdblock: allocated major number 31.
……
3.3 創建檔系統鏡像檔
系統會編譯生成JFFS2的輔助工具:mkfs.jffs2、eraseall、erase。其中mkfs.jffs2會產生JFFS2檔系統鏡像的工具,eraseall和erase用來對FLASH晶片的擦除。mkfs.jffs的使用方法如下:mkfs.jffs -d 根目錄 -b| l -e 擦除塊大小 -o 輸出檔 -v 0-9 -q。
另外,為了使系統在啟動時自動掛載建好的JFFS2檔系統,在啟動腳本裏應加入:
mount -t jffs2 /dev/mtdblock2 /mnt4 結束語
本文討論了在uClinux下建立基於Nor Flash的JFFS2的檔系統的一般步驟。Nor Flash的特性決定了它在對資料存儲要求不高的嵌入式系統中有著廣泛的應用,因此JFFS2檔系統對Flash上的資料管理非常方便。對於一些高端的掌上設備來說,Nand Flash更為適合,其單元存儲密度比較高,成本較低,這樣系統可以在不增加成本的情況下擴大存儲容量。目前有一種新型的檔系統YAFFS更適於Nand Flash,本文不再予以討論。

2007年8月26日 星期日

嵌入式Linux檔系統及其存儲機制分析

嵌入式系統與通用PC機不同,一般沒有硬碟這樣的存儲設備而是使用Flash快閃記憶體晶片、小型快閃記憶體卡等專為嵌入式系統設計的存儲裝置,本文分析了嵌入式系統中常用的存儲設備及其管理機制,介紹了常用的基於FLASH的檔系統類型。
1.嵌入式系統存儲設備及其管理機制分析

構建適用於嵌入式系統的Linux檔系統,必然會涉及到兩個關鍵點,一是檔系統類型的選擇,它關係到檔系統的讀寫性能、尺寸大小;另一個就是根檔系統內容的選擇,它關係到根檔系統所能提供的功能及尺寸大小。

嵌入式設備中使用的記憶體是像Flash快閃記憶體晶片、小型快閃記憶體卡等專為嵌入式系統設計的存儲裝置。Flash是目前嵌入式系統中廣泛採用的主流記憶體,它的主要特點是按整體/磁區擦除和按位元組編程,具有低功耗、高密度、小體積等優點。目前,Flash分為NOR, NAND兩種類型。

NOR型快閃記憶體可以直接讀取晶片內儲存的資料,因而速度比較快,但是價格較高。NOR型晶片,位址線與資料線分開,所以NOR型晶片可以像SR

AM一樣連在資料線上,對NOR晶片可以“字”為基本單位操作,因此傳輸效率很高,應用程式可以直接在Flash內運行,不必再把代碼讀到系統RAM中運行。它與SRAM的最大不同在於寫操作需要經過擦除和寫入兩個過程。

NAND型快閃記憶體晶片共用位址線與資料線,內部資料以塊為單位進行存儲,直接將NAND晶片做啟動晶片比較難。NAND快閃記憶體是連續存儲介質,適合放大檔。擦除NOR器件時是以64-128KB的塊進行的,執行一個寫入/擦除操作的時間為5s;擦除NAND器件是以8-32KB的塊進行的,執行相同的操作最多只需要4ms。

NAND Rash的單元尺寸幾乎是NOR器件的一半,由於生產過程更為簡單,NAND結構可以在給定的模具尺寸內提供更高的容量,也就相應地降低了價格。NOR flash佔據了容量為1―16MB快閃記憶體市場的大部分,而NAND flash只是用在8―128MB的產品當中,這也說明NOR主要應用在代碼存儲介質中,NAND適合於資料存儲。

壽命(耐用性),在NAND快閃記憶體中每個塊的最大擦寫次數是一百萬次,而NOR的擦寫次數是十萬次。NAND記憶體除了具有10比1的塊擦除週期優勢,典型的NAND塊尺寸要比NOR器件小8倍,每個NAND記憶體塊在給定的時間內的刪除次數要少一些。

所有嵌入式系統的啟動都至少需要使用某種形式的永久性存儲設備,它們需要合適的驅動程式,當前在嵌入式Linux中有三種常用的塊驅動程式可以選擇。

● Blkmem驅動層

Blkmem驅動是為uclinux專門設計的,也是最早的一種塊驅動程式之一,現在仍然有很多嵌入式Linux作業系統選用它作為塊驅動程,尤其是在uClinux中。它相對來說是最簡單的,而且只支持建立在NOR型Flash和RAM中的根檔系統。使用Blkmem驅動,建立Flash分區配置比較困難,這種驅動程式為Flash提供了一些基本擦除/寫操作。

● RAMdisk驅動層

RAMdisk驅動層通常應用在標準Linux中無盤工作站的啟動,對Flash記憶體並不提供任何的直接支援, RAM disk就是在開機時,把一部分的記憶體虛擬成塊設備,並且把之前所準備好的檔案系統映射解壓縮到該RAM disk環境中。當在Flash中放置一個壓縮的檔系統,可以將檔系統解壓到RAM,使用RAM disk驅動層支援一個保持在RAM中的檔系統。

● MTD驅動層

為了盡可能避免針對不同的技術使用不同的工具,以及為不同的的技術提供共同的能力,Linux內核納入了MTD子系統(memory Technology Device)。它提供了一致且統一的介面,讓底層的MTD晶片驅動程式無縫地與較高層介面組合在一起。
JFFS2, Cramfs, YAFFS等檔系統都可以被安裝成MTD塊設備。MTD驅動也可以為那些支援CFI介面的NOR型Flash提供支援。雖然MTD可以建立在RAM上,但它是專為基於Flash的設備而設計的。MTD包含特定Flash晶片的驅動程式,開發者要選擇適合自己系統的Flash晶片驅動。Flash晶片驅動向上層提供讀、寫、擦除等基本的操作,MTD對這些操作進行封裝後向用戶層提供MTD char和MTD block類型的設備。
MTD char類型的設備包括/dev/mtd0, /dev/mtdl等,它們提供對Flash原始字元的訪問。MTD block類型的設備包括/dev/mtdblock0,/dev/mtdblock1等,MTD block設備是將Flash類比成塊設備,這樣可以在這些類比的塊設備上創建像Cramfs, JFFS2等格式的檔系統。

MTD驅動層也支持在一塊Flash上建立多個Flash分區,每一個分區作為了一個MTD block設備,可以把系統軟體和資料等分配到不同的分區上,同時可以在不同的分區採用不用的檔系統格式。這一點非常重要,正是由於這一點才為嵌入式系統多檔系統的建立提供了靈活性。
2. 基於Flash的檔系統

鑒於Flash存儲介質的讀寫特點,傳統的Linux檔系統己經不適合應用在嵌入式系統中,像Ext2fs檔系統是為像IDE那樣的塊設備設計的,這些設備的邏輯塊是512位元組、1024位元組等大小,沒有提供很好的磁區

擦寫支持,不支持損耗平衡,沒有掉電保護,也沒有特別完美的磁區管理,這不太適合於磁區大小因設備類型而劃分的快閃記憶體設備。基於這樣的原因,產生了很多專為Flash設備而設計的檔系統,常見的專用於快閃記憶體設備的檔系統如下:

● Romfs

傳統型的Romfs檔系統是最常使用的一種檔系統,它是一種簡單的、緊湊的、唯讀的檔系統,不支援動態擦寫保存;它按順序存放所有的檔資料,所以這種檔系統格式支援應用程式以XIP方式運行,在系統運行時,可以獲得可觀的RAM節省空間。uClinux系統通常採用Romfs檔系統。

● Cramfs

Cramfs是Linux的創始人Linus Torvalds開發的一種可壓縮唯讀檔案系統在Cramfs檔系統中,每一頁被單獨壓縮,可以隨機頁訪問,其壓縮比高達2:1,為嵌入式系統節省大量的Flash存儲空間。Cramfs檔系統以壓縮方式存儲,在運行時解壓縮,所以不支援應用程式以XIP方式運行,所有的應用程式要求被拷到RAM裏去運行,但這並不代表比Ramfs需求的RAM 空間要大一點,因為Cramfs是採用分頁壓縮的方式存放檔案,在讀取檔案時,不會一下子就耗用過多的記憶體空間,只針對目前實際讀取的部分分配記憶體,尚沒有讀取的部分不分配記憶體空間,當我們讀取的檔案不在記憶體時, Cramfs檔系統自動計算壓縮後的資料所存的位置,再即時解壓縮到RAM中。

另外,它的速度快,效率高,其唯讀的特點有利於保護檔系統免受破壞,提高了系統的可靠性;但是它的唯讀屬性同時又是它的一大缺陷,使得用戶無法對其內容對進擴充。Cramfs映射通常是放在Flash中,但是也能放在別的檔系統裏,使用loopback設備可以把它安裝別的檔系統裏。使用mkcramfs工具可以創建Cramfs映射。

● Ramfs/Tmpfs

Ramfs也是Linus Torvalds開發的,Ramfs檔系統把所有的檔都放在RAM裏運行,通常是Flash系統用來存儲一些臨時性或經常要修改的資料,相對於ramdisk來說,Ramfs的大小可以隨著所含檔內容大小變化,不像ramdisk的大小是固定的。Tmpfs是基於記憶體的檔系統,因為tmpfs駐留在RAM 中,所以寫/讀操作發生在RAM 中。tmpfs檔系統大小可隨所含檔內容大小變化,使得能夠最理想地使用記憶體;tmpfs駐留在RAM,所以讀和寫幾乎都是暫態的。tmpfs的一個缺點是當系統重新引導時會丟失所有資料。

● JFFS2

JFFS2是RedHat公司基於JFFS開發的快閃記憶體檔系統,最初是針對RedHat公司的嵌入式產品eCos開發的嵌入式檔系統,所以JFFS2也可以用在Linux,uCLinux中。JFFS檔系統最早是由瑞典Axis Communications公司基於Linux2.0的內核為嵌入式系統開發的檔系統。JFFS2是一個可讀寫的、壓縮的、日誌型檔系統,並提供了崩潰/掉電安全保護,克服了JFFS的一些缺點:使用了基於哈希表的日誌節點結構,大大加快了對節點的操作速度;支持資料壓縮;提供了“寫平衡”支援;支持多種節點類型;提高了對快閃記憶體的利用率,降低了記憶體的消耗。這些特點使JFFS2檔系統成為目前Flash設備上最流行的檔系統格式,它的缺點就是當檔系統已滿或接近滿時,JFFS2運行會變慢,這主要是因為碎片收集的問題。
● YAFFS

YAFFS/YAFFS2是一種和JFFSx類似的快閃記憶體檔系統,它是專為嵌入式系統使用NAND型快閃記憶體而設計的一種日誌型檔系統。和JFFS2相比它減少了一些功能,所以速度更快,而且對記憶體的佔用比較小。此外,YAFFS自帶NAND晶片的驅動,並且為嵌入式系統提供了直接訪問檔系統的API,用戶可以不使用Linux中的MTD與VFS,直接對檔系統操作。YAFFS2支援大頁面的NAND設備,並且對大頁面的NAND設備做了優化。JFFS2在NAND快閃記憶體上表現並不穩定,更適合於NOR快閃記憶體,所以相對大容量的NAND快閃記憶體,YAFFS是更好的選擇。

在具體的嵌入式系統設計中可根據不同目錄存放的內容不同以及存放的檔屬性,確定使用何種檔系統。

2007年5月13日 星期日

高稅額扣抵比率公司既賺股利又可節稅

何謂稅額扣抵比率:

股息收入屬於投資人所得的一種,在「兩稅合一」前是包含在27萬元的利息收入裡申報,超過的部份要列入繳稅,但在「兩稅合一」後有了稅額扣抵比率,比率愈高,所得稅可抵稅額就愈高,只要投資人的所得稅率低於參加除權息的稅額扣抵比率,參加除權息不但不用繳稅,還可以領到政府的退稅。

舉例說明:

加東鋼(2006)除息,配息2.59元,100張東鋼可收到25萬9000元現金股息,東鋼2005年度的稅額扣抵比率達36%,若投資人所得稅率是13%,在計算所得稅時,將可以退稅5萬9570元<25萬9000元×(36%-13%)>。相對來說,如果參與除權息的公司稅額扣抵比率低於所得稅率級距,可能會面臨補稅的情況。



資料來源:Smart致富月刊

2007年4月9日 星期一

☆遇見自動千萬富翁(趁年輕,多想想)

遇見自動千萬富翁(趁年輕,多想想)

不知道何時才能退休嗎?細心讀完會有收獲哦

看看下面的故事,嘗試著執行 提前退休不是夢 與您分享 ~~

我永遠忘不了第一次遇上"自動"千萬富翁的情景。

那時候,我二十多歲,在一個社區成人教育推廣班教授投資課程。我班上有位中年男學員名叫吉姆.麥金特,在當地一家電力公司擔任中階經理。他很少和我說話,有一天他在下課後來找我,問我是否可以幫忙評估一下他 和他太太的財務狀況。

這個請求讓我很驚訝。儘管我強烈相信,每個人都應該聽聽合格財務規畫師的理財建議,進而從中獲得裨益,可是吉姆給我的印象全然不是那種會主動求助的人。

我表示非常樂意接受這個邀約,但如果他要聽聽我的意見,他太太必須和他一起過來。
「沒問題,」吉姆微笑說道:「正是蘇珊要我來請教你的。我們兩人都覺得,現在是做點財務規畫的時候了。我正打算下個月退休。」

這下子我真的吃驚了。光聽吉姆在課堂上的幾次發言,我知道他五十歲出頭,在同一家公司工作了三十年,年收入從未超過四萬美元,而且還認為編列預算沒用。我也聽過他形容自己為「超保守派」,因此確信他不可能在股市中發財。

不過,我祖母羅莎.巴哈教過我「人不可貌相」。事情永遠說不準,也許吉姆繼承了大筆遺產。

●提早十三年退休

麥金特夫婦看起來就是那種「勤勞努力、比上不足比下有餘」的人。吉姆身穿胸前有口袋的短袖襯衫,蘇珊頭髮上有幾束亮金色的挑染。蘇珊是美容師,比吉姆年輕好幾歲。

特別的是,麥金特夫婦好像高中生初次約會,手拉著手,興高采烈地聊著。我還沒開口問,吉姆便開始談他的計畫,聊他準備怎樣過退休生活。此時,蘇珊也跟著嚷嚷:「他這麼年輕就能夠退休,多棒呀!好多人要到六十五歲才能夠退休,但吉姆在五十二歲就做到了!」

●平凡無奇的年收入

我就這樣聽了十分鐘,後來不得不打斷一下,說道:「聽到你們這樣說,我也激動起來了。不過,我們先別高興得太快。過去幾年裡,我見過好幾百個想退休的人,可是我得告訴你們,沒有幾個人真的能夠在五十歲出頭退休。」

「通常人們會問我,他們是否能夠退休,」我說道:「不過,你們似乎認為自己能夠退休。你們為什麼這麼確信自己能夠負擔退休生活?」

吉姆和蘇珊對望了一下。然後,吉姆轉過頭來,說道:「你覺得我們不夠有錢,對吧?」
「嗯……我倒不會這樣說。」我回答道:「不過,早早退休的人確實必須有一筆為數不少的錢,而大多數人在你這樣的年紀時還遠遠存不到這麼多。就我對你的了解,我真的很好奇你怎麼會有足夠的錢?」我看進他的眼裡,他也回看我,眼神平靜而沉著。

「吉姆,你才五十二歲。」我說道:「想想看,十個人當中只有一個人能夠在六十五歲退休,且勉強維持就業期間的生活水準。你得承認,在你現在這個年齡退休簡直是個壯舉。」
吉姆頷首默認。「確實如此,」他說著,同時遞給我一大疊文件。其中包括他和蘇珊的退稅和資產證明,詳細列著他們所擁有的和所積欠的金額。

我先看了看他們的退稅單。去年,吉姆和蘇珊合併收入為五三、九四六美元。這不算富裕,但也確實不錯了。
我將資產證明瀏覽一遍,想知道他們欠了多少錢,卻無法找到一條欠債款項。我抬起頭,問道:「你們沒欠債?」

●付清所有貸款

麥金特夫婦再次相視微笑,蘇珊緊握一下丈夫的手,說道:「麥金特夫婦不欠債。」她邊說邊樂呵呵地笑著。「你們的孩子呢?」我問。

「他們?」吉姆回答:「都大學畢業,自立了,托老天的福。」

「哦,那很好。」我說:「讓我看看你們擁有哪些資產。」我重新瀏覽那份資產證明,上面列有兩棟房屋。第一棟是他們現在住的,價值四十五萬美元;第二棟用於出租,價值三十二萬五千美元。

「哇,」我讚歎道:「這兩棟房子現在都沒有貸款?」

「對的。」吉姆回答:「沒有貸款。」

我接著看退休金帳戶。吉姆的四○一(K)帳戶目前結餘為六十一萬美元(注一),而蘇珊的兩個退休金帳戶則總計有七萬兩千美元。另外,他們還擁有十六萬美元的政府債券,以及存在銀行儲蓄帳戶裡的六二、五○○美元。

上述的這些資產加上他們其他的個人財產(包括一艘遊艇和三輛車,款項全部付清),淨資產高達近兩百萬美元。

不論用什麼標準來衡量,麥金特夫婦都是有錢人。他們不僅乾淨俐落地擁有大量資產(有這些就夠讓人欽佩了,何況沒有任何貸款),而且還持續地從投資中獲得股息和利息收入,同時每年還能夠靠出租第二棟房屋,得到兩萬六千美元的收入。另外,吉姆有資格獲得一筆小數目的退休金。至於蘇珊,則因鍾愛美容師的工作,而準備繼續工作到六十歲才退休(儘管她並不需要)。突然間,吉姆的五十二歲退休計畫看起來並不荒唐。這完完全全是可行的,而且讓人振奮不已。

繼承理財知識一般來說,人們不論擁有多少財富,都不至於讓我瞠目結舌,但麥金特夫婦確實有令我印象深刻之處——他們的富裕是看不出來的。他們兩人似乎是不折不扣的平凡人,就像一般友善而勤勞的夫婦。他們怎麼可能在這樣相對較年輕的年紀,就累積了如此一筆財富?

坦白說,我感到有點困惑,但同時也聽得入迷。那時候,二十多歲的我儘管所賺的錢不算少,然而生活也僅僅入能敷出。有幾個月我確實能夠存下一點錢,然而很多時候,我若不是工作太忙,就是開銷劇增,結果一毛錢也沒存。在許多月份裡,我不但無法把錢留給以後,還弄得當月的薪水也不夠花,於是不斷拚命賺錢,以便讓收支平衡。

身為財務顧問的我,專門教別人如何投資,但自己卻經常掙扎求「錢」。更糟的是,我面前的麥金特夫婦在他們收入最多的那些年裡,也未必賺到我一半的收入,可是如今他們已成為千萬富翁,而我卻越來越深陷在欠債的泥淖中。

麥金特夫婦顯然通曉某些我必須學習的理財技巧,我決心去發掘那到底是什麼。普通人如何能夠積蓄到這樣的財富?我心急如焚地想知道麥金特夫婦的祕訣,卻無從入手。於是,我問道:「你們是不是繼承了什麼遺產?」

吉姆捧腹大笑,說道:「我們只繼承了一樣東西,那就是知識。我們的父母教我們一些理財常識,我們照著他們所說的去做,深信這一定可行。很多我們認識的人都是如此。」

聽到這裡,我確實很著迷。麥金特夫婦原本是要向我請教的,如今我倒想向他們求助了。

●真假富翁

我說:「我每週都會見到一些人,他們同樣來上課,情況卻與你們完全相反。這些人看起來很有錢,可是當我們看看他們到底具體地擁有什麼時,就會發現他們不僅不像看起來那麼富貴,甚至窮得叮噹響。

「就以今天早上我會面的一位先生來說,他開全新的保時捷,戴純金的勞力士錶。可是,當我細閱他的資產報告時,卻發現他其實沒剩下多少財產了。他五十多歲,住在一棟有八十萬美元房貸的豪宅裡,個人存款不足十萬美元,信用卡還欠七萬五千美元,連那輛保時捷都是租來的!另外,他還要付贍養費給兩位前妻。

「然而,你們很富有,快活似神仙,婚姻美滿,兩個孩子已讀完大學,而且你們五十多歲就可以退休了!請告訴我,你們究竟有什麼祕訣?這一定有祕訣的,對吧?」

蘇珊著吉姆,問道:「那麼我們再多說個十五分鐘?」吉姆回答道:「十五分鐘算什麼?」

●自動千萬富翁的故事

蘇珊深深吸一口氣,娓娓道來:「當我們開始約會時,他二十一歲,我十九歲,我們在認識三年後結婚。度完蜜月後,兩家的父母親告誡我們必須認真過生活。他們說,我們可以選擇盡畢生精力去工作以儘量賺錢,每個月賺到錢後便全部花光,就像多數人一樣,不過我們也可以選擇讓錢來為我們創造好生活,並且享受人生。他們告訴我們,祕訣就是每賺一塊錢都要保證先付錢給自己。」

決心先付錢給自己吉姆點頭表示贊同,說道:「沒錯,大多數的人領到薪水時,第一個動作就是付帳單,如果付清後還有餘錢,就把錢存起來。也就是說,把錢先付給別人,最後才付給自己。 爸媽說,要在這樣的遊戲中走在前頭,就要把順序顛倒過來,先為自己留些錢,然後才去付帳單。」

蘇珊笑著搖搖頭,說道:「吉姆說得真容易。不過,千真萬確,我們必須學會存錢。起初,我們試著編列預算,可是不知道為什麼,所賺和所花的數目總是算不對,於是我們開始爭吵。我媽媽告訴我,以前她和爸爸也試過編列預算,可是換來的只是沒完沒了的爭吵,於是他們決定把預算表扔到一邊,改成每個月從薪水裡拿出一○%,在沒看到、沒花掉這些錢之前,就先把它們存進儲蓄帳戶。她告訴我:『妳會驚訝地發現,妳很快就能夠適應沒有這一○%的生活。同時,這一○%在銀行裡悄悄地積聚起來。』

「所以我們就這麼做了。最初我們只把收入的四%存起來,然後慢慢增加。現在,我們會存十五%。不過,平均來說,大約占一○%。」「你們怎麼處理這些存款呢?」我問道。

蘇珊回答道:「我們的錢是優先為退休而存的。」

「你也知道,那時候還沒有四○一(K)計畫。」吉姆插話說道:「但是,許多公司,包括我上班的地方,都提供了公司退休金計畫。如果想多存些錢,還可以額外提撥一點錢。很多朋友並未多存一些,但我們做了。」

蘇珊接著說道:「 另外,我們第二個目標就是存錢買自己的房子。我們的父母親都說,他們的房子是他們這輩子最成功的投資,沒有什麼比擁有一棟房子更能夠讓人有自由感和安全感。但關鍵是,要乾淨俐落地擁有房子,也就是說,要盡快付清所有貸款。

「他們告訴我們,當身邊的朋友都在公寓的裝潢上砸錢時,我們應該儘可能注意自己的開銷和儲蓄情況。他們強調,有許多人是在小東西上花掉大筆錢。」

吉姆回應道:「要在理財上走在前頭,並非意味著要過得窮兮兮或苦哈哈,而是要注意小東西——一些戒掉就能讓人變得更寬裕的消費小習慣。

「對我們來說,主要的『小東西』是香菸,我們在吸菸上花了過多的錢。我們以前每天一包,爸媽都對此很厭惡。他們提醒,如果不繼續在香菸上浪費錢,兩年內就能夠存到一棟房子的頭期款,同時還可以挽救健康。」
留意拿鐵因子吉姆身體向前傾,說道:「你在課堂上用『拿鐵因子』概念,教我們不要每天早上花錢買咖啡喝,而要把錢用於投資。」

我點頭。

吉姆說道:「我父親不是這樣稱呼它,可是你們說的是同一回事。或許,他會叫它『不花冤枉錢因子』。他的想法是,如果每天節省幾塊錢,最後就可以省下一棟房子的錢。如果租房子住,會一直做窮鬼,別人將一直賺我們的錢。如果自己買房子,終究能讓自己變得富有。」

「你們就靠戒菸來省錢,而買了房子?」我問道,又看看他們。

他們回我一個微笑,點點頭。「你們怎麼有辦法買兩棟房子,還把貸款全部付清?」

「哎,我們並不是真的擁有兩棟房子,」蘇珊說:「一棟是住宅,另一棟用於出租。這是祕訣的另一部分。」
吉姆接下去說道:「父母親教我們一個早日付清貸款的訣竅。他們說,銀行對這個訣竅深惡痛絕,而我們會對它愛不釋手。他們是對的。現在,用這個訣竅更簡單了,所要做的就是,付貸款時不是每月一次付清款項,而是把這筆款項分成兩半,每兩週就付一次。你如果堅持這種辦法,到年底時就會發現自己不痛不癢地額外付清了一筆錢。如此一來,本來要三十年才能夠付清的房貸,二十三年就能夠清償。我們計算過,依照這個方法,我們二十多歲就可以開始買房子,四十多歲就能夠不拖欠地擁有房子。實際情況更妙。我們持續多付的貸款金額越來越多,結果我們快到四十歲時就已經完全付清房貸了。」

「之後呢?」我問道。

「之後我們再也不需要付貸款,於是每個月多出一筆錢。」吉姆咧嘴朝我笑一笑,接著說道:「我們可以把這筆多出來的錢揮霍掉,或者用來買更好的房子,並將第一棟房子租出去。結果,我們選擇後者。我們用同樣的訣竅,配合快速還款計畫,更快地付清房貸。接下來,我們乾淨俐落地擁有兩棟房子,自己住一棟,租出去一棟,於是又多了一筆穩定可觀的收入。」

「這個計畫真不錯。」我回應道。

吉姆精神來了,說道:「蘇珊的爸媽還教我們另一件事,那就是絕不用信用卡來購物。他們把一條嚴格的紀律傳授給我們,而我們又把它傳授給孩子,那就是不管東西多貴,只用現金買,否則就不買。不過,房子除外,而且盡快付清貸款。雖然這不是永遠都很容易辦到,但這就是規則。」

「重點是,」蘇珊說道:「如果沒有足夠的現金去買東西,就乾脆別買。我們兩人結婚多年,向來都跟信用卡債務無緣。若是刷了卡,就會在當月把錢付清。這是父母親所教的另一個讓銀行恨死而我們愛死的妙計。」有何頂級祕笈?
我向後傾,靠著椅背,不禁對麥金特夫婦簡單的講解感到驚歎。總能找出什麼來刁難他們吧?我想了想,覺得自己找到了,於是問道:「你們說了這麼多,都很有道理。可是,要做到這一切,必然需要強大的意志力。真希望所有的人都像你們一樣,擁有清晰明確的個人原則。可是很不幸地,大多數的人都無法如此。我想,這就是大多數的人不能夠像你們這般致富的緣故吧。」

吉姆和蘇珊再次四目交投,臉上綻開笑容。吉姆以手示意讓妻子做解釋。

不需要意志力和紀律「重點就在這裡,」蘇珊開始說道:「我們並沒有強大的意志力。如果遵循父母親的訣竅是與自我紀律息息相關,我們反而無法完成得那麼好。」

吉姆插嘴說道:「蘇珊是有自我約束力的,但至於我,算了吧!」

這下子我真的糊塗了。我說道:「如果沒有特殊的紀律和原則,你們怎能做得到?畢竟,我們所身處的社會充斥著廣告宣傳、聲色犬馬,它們不停地在誘惑你們違反父母親所傳授的方法。面對種種的誘惑,你們如何抵抗?你們怎樣堅持那些原則?」

我的疑問已不僅僅出於職業好奇心。當時,我只有二十多歲,自己也覺得,要有足夠的自律來約束自己存下該存的錢,實在是比登天還要難。我急於求知的欲望明顯地表現在臉上,逗得吉姆和蘇珊哄然大笑起來。過一會兒,我也跟著笑了。

「大衛,」吉姆笑夠後,對我說:「我們有個女兒,只比你年輕一點點。我們可是非常了解二十多歲的人要約束自己省錢有多麼難。但是,我們所用的方法就是有這點好處,它用不著任何紀律。」

我看了看他,面露疑色。

「看到你這麼懷疑,我一點也不覺得奇怪。」吉姆說道:「其實,道理太簡單、太明顯,以致連你這種對錢這麼內行的人,也要花費點工夫才可以理解這一點。其實,如果你知道自己應該做什麼,卻又擔心自己受到誘惑而去做別的,那麼你怎麼能保證自己會做對呢?」

吉姆看著我,我聳聳肩。

他接著說道:「它是簡單又明顯的。你不要把決定權留在自己手上,要讓該做的事情自動發生。」
「還記得之前說的『先付錢給自己』嗎?」蘇珊加入說明:「我們所做的是,把薪水的一部分安排成自動轉入一個儲蓄帳戶。關鍵是這一切是全自動的。一旦把事情設定好之後,就什麼都不用做。那真的就不會受到我們控制了。」

「是呀,」我說道:「這就像我在課堂上說過的系統性儲蓄和投資計畫。只不過,你把它應用在理財的各個方面了。」

「說得沒錯!」吉姆大聲地表示贊同,並說道:「如果有一件事是你連想都不用想就是要做,那麼你根本不可能會忘記去做,更不可能改變心意而不去做。一旦決定權不在你手上,你就不可能做錯什麼事。」

說做就做,一次就夠「我們爸媽說這叫做『自己防自己』,」蘇珊說道:「我們不需要擔心有沒有特別的意志力,因為除了決定要變得富有的一剎那之外,後來根本不需要再做什麼。由於有所謂『薪水扣款』的幫忙,我們把所有的環節都自動化了。我們就是靠這種傻瓜也懂的自動系統來積聚財富。

「我們讓吉姆的公司從他的薪水中提出一部分金額,撥到他的退休金帳戶。我們在加速支付貸款時,也使用類似的辦法。在銀行剛開辦自動轉帳計畫時,就安排每月的貸款(以及超額還款),直接從支票帳戶中轉帳出去。同樣地,還利用系統性扣款方法,把收入的一部分自動投入共同基金。最後,連捐款也自動化了。我們後來了解到,實行自動化可以使過程變得多麼簡單。」

吉姆說道:「我們不是在說金額很大的錢。最初,我每個月只能從薪水中提出五十美元。但慢慢地,錢確實可以積累起來。」

我低頭掃視麥金特夫婦的千萬資產說明。「你沒開玩笑,」我說道:「這真的是成就卓越啊。」

蘇珊搖搖頭,小聲說道:「這沒什麼了不起。我們能夠做到的,別人也可以。如果年輕時下定決心要變得富有,建立自動系統來累積財富,就不可能會失敗。這就像耐吉的招牌口號加上個小變化。耐吉是『說做就做』( Just do it),我們則是『說做就做,一次就夠』(Just do it...once)。」

吉姆點頭表示贊同,說道:「當我們剛開始這樣做時,自動理財的技術才剛開始啟用,很多朋友都不太相信它。可是今天,它是傻子都會用的東西。我的意思是,現在有那麼多的理財計畫,你只要花幾分鐘,就能夠使理財的任何一個環節變得自動起來。我們的女兒露西在一小時內,就把所有東西都設定好了。」

蘇珊笑道:「可別以為要像我們一樣的土包子才會這樣做。露西可是一位很時髦的小姐。」

「可不是嗎,」吉姆笑逐顏開地說道:「她戴了一只帥奇錶(Swatch),夠時髦的,但也不會貴得離譜。」

「說到重點了,」蘇珊說道:「 這能夠讓你在省錢之餘依然享受人生。想要變得有錢,不需要弄得生活窘困。過去三十年裡,我們玩得很盡興,跟其他朋友一樣,甚至可能比他們還要快活,因為我們的生活裡沒有每天為錢煩惱的壓力。」

麥金特夫婦離開後,我久久坐在桌旁,腦海裡回想著他們所說過的話,特別是他們臨別的那幾句。

他們說,關鍵是要「設計自己的成功」。當你能夠輕鬆致富時,為什麼要把致富弄得困難?我明白他們是對的。只要清楚自己應該做什麼,並且把它們安排成自動執行,每個人都能夠成為自動千萬富翁。

麥金特夫婦的一席話,是我人生的轉捩點。這使我了解到,長期成功理財的一個重要步驟就是:讓理財變得自動。

在向麥金特夫婦學習了一天之後,我也將自己的財務管理自動化了。你知道嗎?這真的很管用。如今,我也是一個自動千萬富翁。

●你也可以成為自動千萬富翁

麥金特夫婦不需要紀律約束,就能緩慢而穩定地累積財富的故事,也會發生在你身上。如果想知道該怎麼做,請翻過這一頁,繼續讀下去吧。再過幾小時,你的理財觀念便會煥然一新,你的血汗錢會在嶄新的管理技巧下熠熠生輝。

現在,你正走在成為「自動千萬富翁」的路途上。

註:美國政府為了鼓勵人們為退休做儲蓄準備,在一九七四年制定《受雇人員退休收入保障法》,其中的四○一(K)條款即是四○一(K)計畫的由來。時至今日,四○一(K)幾乎已經成為退休金計畫的代名詞。富達投資公司的「401k.com」網站提供了這項退休金計畫的詳細說明。

在台灣,勞工退休新制從 二○○五年七月一日起上路,其根本精神與美國四○一(K)制度相似,屬於可攜式的個人帳戶退休金制度。至於台灣勞退新制的詳情,可以參考行政院勞工委員會勞工保險局的網站( www.bli.gov.tw)上的「認識勞退新制」。