[技術] Net-SNMP的mib2c

Written on 5:37 下午 by Yu Lai

今天在搞net-snmp所提供的mib2c tool,
用起來說實在的實在有點難用。
大概是我對它還不太熟的關係吧。
以下是今天弄的一些心得:
(因為開發需求,所以設定prefix為/opt/net-snmp。)

1.
首先,在安裝net-snmp時,需在configure時加入以下參數


$ ./configure --prefix=/opt/net-snmp/ --enable-embedded-perl --enable-shared --with-perl-modules
$ make
$ make test
# make install (should be root)


2.
在確定PATH設定好後,執行mib2c時,
通常會遇到訊息說沒有安裝Perl SNMP Module,
這是因為我們在configure時有設了prefix的關係,
導致perl找不到share library。
解決的方法是將net-snmp的lib目錄設定給ldconfig知道即可。

# echo /opt/net-snmp/lib > /etc/ld.so.conf.d/net-snmp.conf
# ldconfig -v


3.
最後就是mib2c操作方法,
據mib2c的manpage裡說明,
mib2c的功用是產生template code給agent來擴充功能使用。
Usage為
mib2c [-h] -c CONFIGFILE [-I PATH] [-f OUTNAME] [-i][q][-S VAR=VAL] MIBNODE

而mib2c的使用方法是以mib node為parameter來開始生成template code。
所以必須先將mib file放置在$HOME/.mibs/或/opt/net-snmp/share/snmp/mibs,
然後在環境變數中設定MIBS,
export MIBS=+NET-SNMP-TUTORIAL-MIB

接著麻煩的在這裡,
你必須依著你的的mib node來選定所產生的template code的CONFIGFILE。
下面是CONFIGFILE所支援的類型:
如果你要寫些scalars所需的code,請用:
mib2c -c mib2c.scalar.conf MIBNODE

如果你要用int scalars,請用:
mib2c -c mib2c.int_watch.conf MIBNODE


一般來講Table是建議採用MDF:
mib2c -c mib2c.mfd.conf MIBNODE

如果Table Data是在外部時:
mib2c -c mib2c.iterate.conf MIBNODE

如果Table Data是在agent裡:
mib2c -c mib2c.create-dataset.conf MIBNODE

承上,如果還需排序時:
mib2c -c mib2c.array-user.conf MIBNODE


如果是要產生Table上任一Column的header時:
mib2c -c mib2c.column_defines.conf MIBNODE

如果是要產生Column上任一Enum的header時:
mib2c -c mib2c.column_enums.conf MIBNODE


4.
結論,大概就是麻煩吧。
Net-SNMP不像其他商用的SNMP套件一樣提供簡易的開發擴充功能的環境,
像在EMANATE中打一個make就ok了,連型態都自動判斷。
不過也許是我對mib2c還不太熟的關係吧,Orz。

[技術] 製作 ARM9 的 Bootstrap Root Filesystem

Written on 7:40 下午 by Yu Lai

本文出處: www.jollen.org
已取得原作者授權使用

《Jollen的Root Filesystem建置技術系列》

製作ARM9的Bootstrap Root Filesystem

作者/陳俊宏

http://www.jollen.org

更新日期:2007/1/23

在「完整註明出處」的前提下(註明方式說明),您能立即擁有轉貼與引用的授權,且毋需知會作者。

目的

製作 bootstrap root filesystem(base root filesystem)以提供一個最簡單、陽春且可開機的環境;製作完成的系統可開機到shell模式,並可使用 busybox 提供的指令。

準備工作

首先,您必須準備一台 host 開發環境,並安裝好 cross toolchain;接著,由於本文是做實機測試,因此,如果您沒有 ARM9 開發板,可以考慮使用 Qemu 來做模擬測試。

以下的操作示範,只節錄重點指令片段,您可能必須根據自己的整體實作流程,來微調指令的順序,或是參數等。

Step 1:建立工作目錄

建立一個專用的工作目錄,命名為 arm9.so-busybox/:

# mkdir arm9.so-busybox/

# cd arm9.so-busybox/

接著在 arm9.so-busybox/ 目錄下建立 4 個子目錄:

# mkdir src/ install/ mnt/ pub/ build/

實際進行 root filesystem 實作時,我們應該養成將檔案分類擺放的好習慣。以本專案為例,build/ 目錄用來編譯程式,src/ 目錄用來存放原始程式碼,install/ 目錄則用來擺放我們最後的 root filesystem。

Step 2:建立目錄架構

根據 FHS 的目錄架構標準,在 root filesystem 目錄下(install/)建立目錄階層架構:

# cd install/

# mkdir bin/ dev/ etc/ mnt/ proc/ sbin/ usr/

另外還有二個必要的目錄:/var 與 /tmp,由於這二個目錄都需要具備寫入權限,所以在這裡我們是以 ramdisk 的做法來 mount 這二個目錄。

Step 3:建立裝置檔

在 root filesystem 的 dev/ 目錄下建立必要的裝置檔:

crw------- 1 root root 5, 1 1月 1 1970 console

crw------- 1 root root 29, 0 1月 1 1970 fb0

crw------- 1 root root 1, 3 1月 1 1970 null

brw------- 1 root root 1, 0 1月 1 1970 ram0

crw------- 1 root root 5, 0 1月 1 1970 tty

crw------- 1 root root 4, 0 1月 1 1970 tty0

此階段使用 mknod 指令來完成。請先切換到 root filesystem 的 dev/ 目錄下,接著執行以下指令:

# mknod console c 5 1

# mknod fb0 c 29 0

# mknod null c 1 3

# mknod ram0 1 0

# mknod tty c 5 0

# mknod tty0 c 4 0

對於需要產生大量 device file 的場合來說,可以改用 genext2fs 的 ‘-D’ 參數來製作。詳見 Jollen’s Blog:[使用 genext2fs 的 '-D'(device file table)來建立 root filesystem]。

Step 4:加入Busybox

編譯並安裝 Busybox(動態程式庫方式)。將取得的Busybox原始碼解壓縮至 project 目錄裡的 src/ 子目錄下,以下是幾個注意事項:

本教學文件使用 Busybox 1.3.1

Busybox 1.3.0 開始,使用 Linux Kernel 的 Makefile(因為開始支援 CONFIG_DESKTOP)。Cross compile 時,需要修改 Makefile 如下:

ARCH ?= arm

CROSS_COMPILE ?= /opt/crosstool/gcc-3.4.1-glibc-2.3.3/arm-9tdmi-linux-gnu/bin/arm-9tdmi-linux-gnu-

CROSS_COMPILE 的設定是 cross toolchain 的「PREFIX」,視您的 toolchain 而定。您可由 http://www.jollen.org/kit/ 下載本文所使用的 GCC 3.4.1 ARM9 toolchain,以使用與本文完全相同的修改。

Busybox 整合了常用的指令與工具,我們可以設定 Busybox,以勾選我們需要的功能選項。進入 Busybox 的設定選單:

# make menuconfig

請注意,init 與 shell 是必選的項目,請檢查是否有勾選這二個功能。同時,也別忘了設定 Busybox 的安裝路徑,將安裝路徑指到我們 root filesystem 目錄下。

接著直接進行編譯(cross compile):

# make

編譯完成後,將 Busybox 安裝至我們的 root filesystem 目錄(即 Step 2 的 install/ 目錄):

# make install

此時,您應該可以在 root filesystem 目錄下看到 Busybox 所安裝的檔案。

Step 5:加入動態程式庫

編譯完成的 Busybox 已經是給 ARM9 執行的格式了,但我們的編譯設定是將Busybox 編譯成 shared library 架構,因此 Busybox 執行時需要以下的檔案:

˙ libc.so.6:C library標準程式庫。

˙ ld-linux.so.2:Native dynamic loader。

請由 toolchain 將以上二個檔案複製至 root filesystem 的 lib/ 目錄下:

# cd ../../install (切換至root filesystem根目錄)

# cp /opt/crosstool/gcc-3.4.1-glibc-2.3.3/arm-9tdmi-linux-gnu/arm-9tdmi-linux-gnu/lib/ld-linux.so.2 lib/ (複制native dynamic loader。以上命令請勿斷行)

# cp /opt/crosstool/gcc-3.4.1-glibc-2.3.3/arm-9tdmi-linux-gnu/arm-9tdmi-linux-gnu/lib/libc.so.6 lib/ (複製C library。以上命令請勿斷行)

Busybox 會因版本與功能選項設定的差異,而需要更多的程式庫。請使用 cross toolchain 的 objdump 指令來檢查 Busybox 的程式庫相依問題(無法使用 ldd 指令),並將所需的程式庫由 toolchain 複製到 root filesystem 的 lib/ 目錄下。

Step 6:加入系統檔案

加入2個重要的系統檔案於 etc/ 目錄下:

˙ fstab:mount table。

˙ inittab:系統初始表(init table)。

etc/fstab內容如下:

/dev/ram0 / ext2 defaults 1 1

none /proc proc defaults 0 0

/dev/ram1 /tmp ramfs defaults 0 0

/dev/ram2 /var ramfs defaults 0 0

fstab 第一行設定,目的在將 /dev/ram0 重新附掛成 ‘/’(root),此動作用意在於重新指定 ‘/’ 的檔案系統為 ext2。最後二行的目的是為了以 ramfs 來 mount 重要的二個目錄:/var 與 /tmp;如此一來,就算開機沒做 remount root(詳見後文說明),也能對 /tmp 與 /var 目錄做寫入的動作

etc/inittab內容如下:

:0:sysinit:/etc/rc.d/rc.init

:0:respawn:/bin/sh

根據這個 inittab 設定,當系統開機後便會進入 run level 0,在 run level 0 模式下,init process會執行2個動作:(1) 執行 /etc/rc.d/rc.init,此即「init script」;(2) 執行 /bin/sh,即進入 shell 模式。

在此我們並沒有參照 LSB 的標準來設定 run level,而且也沒有使用 getty 來讓使用者登入(多使用者模式)。

Step 7:編寫 Initial Script

根據 inittab 的設定,我們 root filesystem 的 init script 位於 /etc/rc.d/rc.init。以下提供一個供 Embedded Linux 使用的 init script 範本:

#!/bin/sh

# automount (/etc/fstab)

mount -a

# remount root

mount -o remount rw /

#

mkdir /var/lock

mkdir /var/lock/subsys

mkdir /var/run



# start other applications (Running application automatically during

# booting up.

# eg. /bin/thttpd –p 80 –d /var/www

當我們執行「mount –a」後,mount 便會去讀取前一步驟所設定的 fstab,並根據此表格的內容來做 mount 的動作。另外,這裡有一個 remount 的動作:

# mount -o remount rw /

此動作的目的是將 root(’/’)重新 mount 成可讀寫,此動作是選擇性的,若省略不做,請務必保持 /var 與 /tmp 目錄是能寫入的(建議以 ramdisk 方式實作為佳)。

若 root filesystem 未包含 inittab 設定檔,則 Busybox 會使用以下的內建設定:

::sysinit:/etc/init.d/rcS

::askfirst:/bin/sh

::ctrlaltdel:/sbin/reboot

::shutdown:/sbin/swapoff -a

::shutdown:/bin/umount -a -r

::restart:/sbin/init

不過,還是建議編寫自己的 inittab 設定檔。

Step 8:製作 Root Filesystem 映像檔(Image File)

截至目前為止,我們的檔案系統已經擁有基本的系統指令與工具。接下來,我們即可將建置完成的 root filesystem 製作成 ext2 格式的映像檔。

以下提供二種 ext2fs image file 的製作方式:(1) 土方法;(2) 使用 genext2fs 工具。

先說明傳統的土方法。首先,先利用dd指令做出一個空白的檔案,大小為 4M(bytes):

# dd if=/dev/zero of=ext2fs bs=1k count=4096

我們將檔案命名為 ext2fs,接著再將 ext2fs 製作成 ext2 格式的檔案系統:

# mkfs.ext2 ext2fs

mke2fs 1.32(09-Nov-2002)

ext2fs is not a block special device.

Proceed anyway?(y,n)y

選擇y後出現以下畫面:

Filesystem label=

OS type: Linux

Block size=1024(log=0)

Fragment size=1024(log=0)

128 inodes, 1024 blocks

51 blocks(4.98%)reserved for the super user

First data block=1

1 block group

8192 blocks per group, 8192 fragments per group

128 inodes per group



Writing inode tables: done

Writing superblocks and filesystem accounting information: done



This filesystem will be automatically checked every 26 mounts or

180 days, whichever comes first. Use tune2fs -c or -i to override.

到這裡我們已經做好一個檔案格式為 ext2 的空白映像檔,再來只要將先前做好的 root filesystem 全部複製到 ext2fs 映像檔「裡面」即可。

先將 ext2fs 附掛至任一空目錄,例如 mnt/:

# mkdir mnt/

# mount -t ext2 -o loop ext2fs mnt/ (指定檔案系統為 ext2)

複製檔案系統時,我們不使用 cp 指令,而是利用 tar 來完成:

# cd install/

# tar cz * > ../install.tar.gz (將檔案系統做成tarball,同時也備份 root filesystem。)

# cd ..

# cd mnt/

# tar zxvf ../install.tar.gz (再將tarball解至映像檔)

接著將映像檔 umount 並壓縮即可:

# cd ..

# umount mnt/

# gzip -9c ext2fs > pub/ext2fs.gz

最後得到的 ext2fs.gz 即是完成品。請注意,若不使用 tar 來說,也應該使用 cpio 來複製檔案,避免使用 cp 指令。

使用 genext2fs

genext2fs 是一個 ext2 filesystem image file 的製作工具,可以讓我們很方便地將 root filesystem 製作成 image 檔。請由 genext2fs 的官方網站下載原始碼套件:

http://genext2fs.sourceforge.net/

編譯後可以取得 genext2fs 檔案,以下是將 install/ 目錄製作成 ext2fs image 檔的指令:

# genext2fs -b 8192 -i 1024 -d install/ ext2fs

執行後,會得到檔名為 ext2fs 的 image 檔,大小為 8 MB(透過 ‘-b’ 參數指定 image file 大小);接著同樣再用 gzip 將 ext2fs 檔壓縮即可。

Step 9:在 Target 端做測試

本步驟以 Jollen-Kit! 為例,Jollen-Kit! 是由 www.jollen.org 所推出的 ARM9 training board,詳細介紹請參考 [http://www.jollen.org/kit/]。請注意,本階段的操作,視 target device 的不同而不同,因此以下示範只適用於 Jollen-Kit! 或是其他的 SMDK2410 平臺。

步驟 8 所得到的 ext2.gz 必須再包裝成 U-Boot 的格式,才能透過 U-Boot 載入到 RAM,以成為 kernel 的 initial ramdisk(initrd):

# mkimage -A arm -O linux -T ramdisk -C none -a 0x30800000 -e 0x30800000 -n ramdisk -d ext2fs.gz urootfs.img

執行後可得到 urootfs.img 檔案,在測試階段為了方便起見,我們可以直接將 urootfs.img 載到 RAM 做測試;U-Boot 指令如下:

jollen.org # tftpboot 32000000 urootfs.img; tftpboot 30F00000 uimage.img; bootm 30F00000 32000000

urootfs.img 是我們製作的 root filesystem,uimage.img 則是給 Jollen-Kit! 使用的 Linux kernel(pre-built)。

[技術] 學習使用SkyEye仿真

Written on 9:08 上午 by Yu Lai

[轉自Experiences of Code (http://blog.csdn.net/zblue78)]

學習使用SkyEye仿真

--------------------------------------------------------------------------------


SkyEye是一個可以運行嵌入式操作系統的硬件仿真工具,這樣就可以在沒有硬件條件下來進行嵌入式系統的開發。

以下操作均在Fedora Core 1.0里通過。

Skyeye項目資源列表
http://gro.clinux.org/projects/skyeye/


文檔摘要:
1、什麼是SkyEye?
2、SkyEye可以做什麼事情?
3、安裝SkyEye
4、安裝arm-elf交叉編譯器
5、測試你的arm-elf-gcc編譯器
6、執行你的hello程序
7、編譯並運行uClinux-dist-20030909.tar.gz
8、加入網絡功能
9、安裝完成SkyEye後,下一步將做什麼?


1、什麼是SkyEye?

SkyEye是開源軟件的一個項目,SkyEye的目標是在Linux和Windows操作系統裡提供一個完全的仿真環境。SkyEye仿真環境相當於一個嵌入式計算機系統,你可以在SkyEye裡運行一些嵌入式Linux操作系統,如ARMLinux,uClinux,uc/OS-II(ucos-ii)等,並能分析和調試它們的源代碼。

如果你想知道關於SkyEye和嵌入式系統更詳細的信息,請訪問下面的站點:
www.SkyEye.org
http://www.skyeye.org/index_cn.html

通過SkyEye能仿真下面的硬件:
CPU核心:ARM7TDMI, ARM720T, ARM9, StrongARM, XScale
CPU: Atmel AT91/X40, Cirrus CIRRUS LOGIC EP7312, Intel SA1100/SA1110, Intel XScale PXA 250/255, CS89712, samsung 4510B, samsung 44B0(還不全)
內存: RAM, ROM, Flash
周邊設備: Timer, UART, ne2k網絡芯片, LCD, 觸摸屏等

目前能在SkyEye上運行下面的操作系統和系統軟件:
uC/OSII-2.5.x(支持網絡)
uClinux(基於Linux2.4.x內核, 支持網絡)
ARM Linux 2.4.x/2.6.x
lwIP on uC/OSII
基於uC/OSII, uClinux, ARM Linux的應用程序


2.SkyEye可以做什麼事情?
1. 通過SkyEye可以幫助促進嵌入式系統的學習,在不需要額外硬件的情況下學習和分析uclinux操作系統和其它嵌入式操作系統,如ucosII等。
2. SkyEye可用於嵌入式系統的教學。
3. 希望通過skyeye促進操作系統的研究,如ucosII,uclinux+RTAI,uclinux2.5.x等。
4. 可以基於SkyEye進行仿真特定硬件模塊的研究。
5. SkyEye可以作為嵌入式集成開發環境開發嵌入式系統(當然需要對SkyEye做大量的工作)。
註:引自陳渝《SkyEye Project FAQ》


3、安裝SkyEye

到http://gro.clinux.org/projects/skyeye/下載skyeye-0.7.0.tar.bz2包:

tar jxvf skyeye-v0.7.0.tar.bz2

進入解壓後的skyeye目錄,如果SkyEye的版本低於0.6.0,則運行下面的命令:

./configure --target=arm-elf --prefix=/usr/local --without-gtk-prefix --without-gtk-exec-prefix --disable-gtktest

如果SkyEye的版本高於0.6.0,則運行下面的命令:

./configure --target=arm-elf --prefix=/usr/local

接下來執行:

make
make install

安裝完成後執行skyeye

注意:
a.如果你使用的是Mandrake Linux發行版,那麼你在編譯SkyEye時遇到錯誤,並且錯誤與readline, ncurse, termcap等有關,你可以試試下面的方法:

ln -s /usr/include/ncurses/termcap.h /usr/local/include/termcap.h

接著再make和make install看能否成功!
b.如果你的Linux發行版是Debian Linux,那麼不要使用gcc 2.95或是gcc 3.0,請使用gcc 3.2+
c.gcc的版本要在2.96或以上
d.如果SkyEye的版本大於0.6.0,那麼使用LCD仿真需要在Linux系統裡安裝GTK軟件。


4、安裝arm-elf交叉編譯器

下載arm-elf-tools-20030314.sh
ftp://166.111.68.183/pub/embed/uclinux/soft/tools/arm
或到
ftp://166.111.8.229/OS/Embeded

執行:
chmod a+x arm-elf-tools-20030314.sh
然後:
./arm-elf-tools-20030314.sh

ls /usr/local/bin/

你應能看到以arm-elf開頭的可執行文件,其中arm-elf-gcc就是用來編譯你目標平台的編譯器的,當然還有一些小工具,後面將一一講來。


5、測試你的arm-elf-gcc編譯器

先寫一個小程序hello.c


#include

int main(void)
{
int i;

for(i = 0; i < 6; i++){

printf("i = %d ",i);

printf("Hello, embedded linux!\n");
}

return 0;
}


然後執行:

arm-elf-gcc -Wl,-elf2flt -o hello hello.c

-elf2flt參數是將elf文件格式轉為flat文件格式,這個工具是在你安裝交叉編譯器產生的。

或者你可以寫個Makefile文件,執行:

make

這裡是我的Makefile文件,僅供參考:

# begin

CC = arm-elf-gcc

CFLAGS = -D__PIC__ -fpic -msingle-pic-base -O2 -pipe -Wall -g
LDFLAGS = -Wl,-elf2flt

LIBS =
OBJS = hello.o

all: hello

hello: $(OBJS)
$(CC) $(CFLAGS) $(LDFLAGS) -o hello $(OBJS) $(LIBS)

clean:
rm -rf *.o *.elf *.gdb hello

# end


如果編譯通過,就會產生hello可執行文件。用下面的命令:

file hello

你會發現,它是BFLT(binary FLAT),你目標平台所支持的文件格式。


6、執行你的hello程序

這裡,我們將借助genromfs這個小工具來完成測試,這個工具就是你在安裝交叉編譯器時產生的,你可以直接使用它。

到http://gro.clinux.org/projects/skye...0.4.tar.bz2包:

tar jxvf skyeye-binary-testutils-1.0.4.tar.bz2

cd testsuits/at91/uclinux2(當然你還可以用別的)

mkdir romfs(建一個目錄,後面用)

mount -o loop boot.rom /mnt/xxx

cp -r /mnt/xxx/* romfs

另外,把你編譯好的可執行程序拷貝到/romfs/bin目錄裡,這裡就是hello了!

genromfs -f boot.rom -d romfs/

註:可以用genromf -h來獲得幫助!

OK!執行下面的命令:

skyeye linux

(skyeye)target sim

(skyeye)load

(skyeye)run

kernel start.....

很熟悉了吧。。。

cd /bin

hello

可以看到結果了嗎?

其實到了這一步,你就可以開發自己的程序了!


7、編譯並運行uClinux-dist-20030909.tar.gz

到ftp://166.111.68.183/pub/embed/uclinux/soft/
或到ftp://166.111.8.229/OS/Embeded/uclinux/pub/uClinux/dist下載
uClinux-dist-20030909.tar.gz

假設把它下載到/usr/src/目錄下,然後依次執行下面的命令:

tar zxvf uClinux-dist-20030909.tar.gz
cd uClinux-dist/

在圖形方式下可用命令make xconfig

在命令行方式下用命令make menuconfig

vendor/product中選擇GDB/ARMulator
kernel版本選擇2.4
然後save and exit

運行下面這兩條命:
make dep
make

此時在/usr/src/uClinux-dist/linux-2.4.x目錄下會生成可執行文件linux
在/usr/src/uClinux-dist/images/會生成romfs.img等文件

在uClinux-dist目錄下建立仿真AT91的skyeye配置文件skyeye.conf,內容如下:
cpu: arm7tdmi
mach: at91
mem_bank: map=M, type=RW, addr=0x00000000, size=0x00004000
mem_bank: map=M, type=RW, addr=0x01000000, size=0x00400000
mem_bank: map=M, type=R, addr=0x01400000, size=0x00400000, file=images/romfs.img
mem_bank: map=M, type=RW, addr=0x02000000, size=0x00400000
mem_bank: map=M, type=RW, addr=0x02400000, size=0x00008000
mem_bank: map=M, type=RW, addr=0x04000000, size=0x00400000
mem_bank: map=I, type=RW, addr=0xf0000000, size=0x10000000


這個時候就可以用skyeye來調試運行kernel了,在/usr/src/uClinux-dist執行如下命令:

skyeye linux-2.4.x/linux

(skyeye)target sim

(skyeye)load

(skyeye)run

kernel start.....

注意:
要在skyeye.conf所在目錄下執行skyeye linux-2.4.x/linux


8、加入網絡功能
a.用root用戶進行操作。
b.你要看你的/lib/modules/'uname -r'/kernel/drivers/net/目錄裡有沒有tun.o
如果沒有的話你就需要編譯你的linux內核來獲得tun.o了。
c.(1)運行tun設備模塊:

#insmod /lib/modules/'uname -r'/kernel/drivers/net/tun.o

如果你沒有該設備,那你就要用下面的命令來創建它:

#mkdir /dev/net
#mknod /dev/net/tun c 10 200

(2)運行vnet(虛擬集線器)設備模塊(這一步不是必需的):
獲取vnet的源碼,然後創建設備:

#mknod /dev/net/vnet c 10 201
#chmod 666 /dev/net/vnet

創建vnet.o
#make vnet.o

插入模塊vnet.o
#insmod vnet.o

進入test目錄,用test來測度vnet.o
#cd test
#make
#./testvnet1

d.配置skyeye.conf文件

cpu: arm7tdmi
mach: at91
mem_bank: map=M, type=RW, addr=0x00000000, size=0x00004000
mem_bank: map=M, type=RW, addr=0x01000000, size=0x00400000
mem_bank: map=M, type=R, addr=0x01400000, size=0x00400000, file=images/romfs.img
mem_bank: map=M, type=RW, addr=0x02000000, size=0x00400000
mem_bank: map=M, type=RW, addr=0x02400000, size=0x00008000
mem_bank: map=M, type=RW, addr=0x04000000, size=0x00400000
mem_bank: map=I, type=RW, addr=0xf0000000, size=0x10000000
# format: state=on/off mac=xx:xx:xx:xx:xx:xx ethmod=tuntap/vnet hostip=dd.dd.dd.dd
net: state=on, mac=0:4:3:2:1:f, ethmod=tun, hostip=10.0.0.1


下面將對上面的一些參數作下說明:
state=on/off意思是仿真的NIC(網絡接口板)是有線的還是無線的;
mac=仿真適配器的MAC地址;
ethmod=tuntap/vnet在主機環境裡使用的虛擬設備;
hostip=意思是主機環境與keyeye交互用的IP
格式: state=on/off mac=xx:xx:xx:xx:xx:xx ethmod=tuntap/vnet hostip=dd.dd.dd.dd

For example:
#set nic info state=on/off mac=xx:xx:xx:xx:xx:xx ethmod=tuntap/vnet hostip=dd.dd.dd.dd
net: state=on, mac=0:4:3:2:1:f, ethmod=tun, hostip=10.0.0.1

net: state=on, mac=0:4:3:2:1:f, ethmod=vnet, hostip=10.0.0.1

注意:
如果你想在同一時刻運行兩個或更多的skyeye,那麼請為每一個skyeye使用不同的skyeye.conf

e.運行skyeye linux-2.4.x/linux

9、安裝完成SkyEye後,下一步將做什麼?

1、對於嵌入式操作系統的初學者和入門者和入門的學生而言,他們可以先看一些有關操作系統和嵌入式操作系統方面的教材和書籍,如與uC/OS、Minix、uClinux、Linux相關的書籍等。然後可以在Skyeye上開發一些簡單的應用程序例子(如進程間通信、進程優先級、死鎖情況、網絡應用等),對某些操作系統功能(如進程調度、內存管理、網絡子系統、文件子系統等)進行簡單的修改和擴展,並通過Skyeye進行運行和調試,看看會發生什麼情況。

2、對於有一定經驗的軟件工程師而言,在SkyEye上完成一定的應用系統原型開發是值得一做的事情。比如移植或開發一個文件子系統或網絡子系統到一個特定的操作系統中,相信比在一個真實的開發板上開發要容易一些。在Skyeye上進行一些操作系統的移植和開發(如移植RTLinux、RTAI等其它操作系統到Skyeye上)也是很有挑戰性的工作。

3、對於硬件工程師而言,對Skyeye進行擴充,設計新的硬件仿真(如USB、IDE硬盤等)使得Skyeye的硬件仿真功能更加強大,支持更多功能的軟件,是很有意義的事情。

參考:
SkyEye項目站點裡的一篇中文文檔;
陳渝《SkyEye Project FAQ》;
skyeye-0.7.0中的README文檔。

後記:
為了讓大家能快速上手,進行實際的開發工作,我趕湊了一篇文檔,很粗糙。但我堅信隨著更多的有經驗的人的加入;隨著我們自己水平的提高,一定會出現更多、更好的文章來。就讓我們快點行動起來吧!

最後,我再次建議大家看一下《嵌入式Linux技術與應用》這本書。

可以到http://www.skyeye.org/document.htm或是
ftp://166.111.68.183/pub/embed/skyeye/document/或是
http://www.huihoo.org/mirrors/skyeye/
下載文檔,可以獲得更多有關skyeye和嵌入式Linux開發的知識和經驗。

[技術] 一步一步教你在skyeye上運行uboot

Written on 9:00 上午 by Yu Lai

[轉自Experiences of Code (http://blog.csdn.net/zblue78)]

一步一步教你在skyeye上運行uboot
by faif

1. 簡介

skyeye是一個很好的,基於各種ARM系列CPU的,SOC和主板級的模擬器。uboot是一個可以在各種cpu(arm,mips,powerpc)的主板上運行的引導程序,相當於PC機的BIOS但是又遠遠的強於普通的BIOS,比如支持網絡引導,引導各種內核,甚至一個簡單的shell,等等。他們兩個都是基於GPL的開源自由軟件。

這篇文章教你怎樣在最少量的修改代碼的情況下,用skyeye模擬EP7312並在上面運行uboot,給接觸嵌入系統的新手一個感性的認識。

2. 建立開發環境

2.1 skyeye模擬器的安裝

開發環境是建立在Linux上的。首先下載安裝skyeyes-0.8.5.1的源代碼包,解壓,按照裡面的readme安裝,注意你的linux要有gtk的支持。安裝的時候要以root的身份。在各種linux發行版下的安裝注意事項參照論壇的相關帖子。安裝成功以後,把skyeye的目標目錄加入你的路徑,這樣你就可以在任何目錄下執行skyeye模擬器了。

2.2 交叉編譯器的安裝

交叉編譯器是運行在主機上編譯另外一種體系結構的編譯器。比如,我的主機是linux在x86上,我現在要編譯基於ARM的代碼,所以我就不能用普通的編譯器而需要交叉編譯器。我曾經試過自己從gcc的源代碼構建交叉編譯器,很麻煩和耗時。uboot的作者同樣也開發了一個很好的交叉編譯器叫ELDK(Embedded linux development kit)。我就使用這個,當然你也可以使用其他嵌入式公司提供的。你可以從以下的網址查看提供ELDK的鏡像:

ELDK Availability: http://www.denx.de/twiki/bin/view/DULG/ELDKAvailability

ELDK有三個版本分別編譯MIPS,PPC和ARM。我從下面的鏡像下載了基於ARM的交叉編譯器:

http://sunsite.utk.edu/ftp/pub/linux/eldk/3.1/arm-linux-x86/iso/

文件為"arm-2004-11-09.iso",它支持ARM7, ARM9, XScale, AT91RM9200 and other ARM based systems。

安裝交叉編譯器,我將交叉編譯器安裝到自己的目錄「/opt/x86-arm/」裡面:
/mnt/cdrom/install -d /opt/x86-arm/

等待安裝結束以後設置好用戶環境:


export PATH="${PATH}:/opt/x86-arm/usr/bin:/opt/x86-arm/bin"
export CROSS_COMPILE=arm-linux-

這樣你在任何目錄也可以訪問交叉編譯器了。

測試:

arm-linux-gcc -o testarm test.c
file testarm
testarm: ELF 32-bit LSB executable, ARM, version 1 (ARM), for GNU/Linux 2.2.5, dynamically linked (uses shared libs), not stripped.

說明你編譯好的文件是ARM上的代碼了。你可以用arm-linux-gcc來編譯你的文件了。

3. 修改Uboot

從uboot的網站上可以下載到最新的uboot源代碼,你可以從以下的網址下載

http://u-boot.sourceforge.net/
ftp://ftp.denx.de/pub/u-boot/

uboot的源碼結構清晰,註釋詳細,是學習嵌入系統的很好的例子。我下載的是最新的U-Boot-1.1.2。因為我們要模擬EP7312的芯片,而uboot已經支持一個基於EP7312的板子了,所以我們只要對uboot裡面有關EP7312的板子的配置略作修改就可以了。uboot裡面有關主板的配置文件都在"include/configs/.h"下,所以我們找到include/configs/ep7312.h,對它進行修改。

找到
#define CONFIG_DRIVER_CS8900 1
改為
#define CONFIG_DRIVER_CS8900 0

找到
#define CONFIG_COMMANDS (CONFIG_CMD_DFL | CFG_CMD_JFFS2)
改為
#define CONFIG_COMMANDS (CONFIG_CMD_DFL) /*Skyeye doesn't have jffs2*/


然後回到uboot的根目錄下,配置,編譯:

make ep7312_config
make all

等待結束以後我們會發現u-boot.bin和u-boot兩個文件,其中u-boot.bin是raw的二進制文件。u-boot是ELF格式的。

4. 配置skyeye,並運行uboot

首先,新建一個目錄代表你的EP7312的主板。這樣也可以保持文件的清潔和有序。

mkdir board01

將你剛才編譯成功的u-boot.bin拷貝到這個目錄下來。skyeye支持raw binary和ELF的格式,這裡我們用raw binary的格式。

編輯skyeye.conf,這個文件是用來配置主板的,詳細說明見skyeye的相關文檔。我的skyeye.conf如下:

#skyeye config file for uboot
cpu: arm720t
mach: ep7312

mem_bank: map=I, type=RW, addr=0x80000000, size=0x00010000

#skyeye for uboot flash 16M bank 1
mem_bank: map=M, type=RW, addr=0x00000000, size=0x01000000, file=./u-boot.bin,boot=yes

#skyeye for uboot sdram 16m bank 1
mem_bank: map=M, type=RW, addr=0xc0000000, size=0x01000000

注意這裡的內存的地址和容量的分配都是根據uboot裡面的ep7312的配置文件調整的。這樣也可以是我們對uboot的代碼修改做到最小。

這時候你的skyeye-ep7312主板就配置好了。你可以試著運行了。在你現在的目錄下打入:
skyeye

然後在skyeye的界面下打入:

target sim
run

這時候你可以看到uboot的啟動界面,和提示符,如果你鍵入「hlep」,可以查看所有uboot支持的命令,鍵入「version」可以查看當前uboot的版本,等等。

5. 進一步的工作

由於本文是最基本的介紹性的一步一步的指導。有很多工作還要去嘗試。比如:

× 由於現在skyeye還不支持flash內存,所以我們是不是可以修改uboot上ep7312相對flash的代碼來臨時滿足我們的需要,不然的話,對於在uboot上面的環境參數的設置,我們只能去修改源碼裡面的缺省參數。

× Uboot支持8019AS的以太網控制器,skyeye也支持了這個硬件的模擬,我們要進一步的使uboot的網絡也在skyeye上用起來?

× 對於模擬flash的開發也可以用uboot來測試。uboot裡面各種板子有大量的flash驅動程序。

還望各位高手指教,我進一步修改和提高。

[技術] 學習嵌入式Linux的筆記和體會

Written on 8:53 上午 by Yu Lai

[轉自Experiences of Code (http://blog.csdn.net/zblue78)]

為大家學習的方便,我把這篇文章從基礎版貼過來了。裡面的東西滿有趣的,大家可以試試!


以下是我初次學習嵌入式linux的筆記和體會,製作了軟盤minicom應用,在此基礎上也清楚了軟盤Linux的實現,並利用busybox實際製作了軟盤上的Linux系統。希望能給新手一些幫助和啟發,同時也請高手批評指正。
yihui, eazi@163.com 2004年2月12日

一個典型的桌面Linux系統包括3個主要的軟件層---linux內核、C庫和應用程序代碼。
內核是唯一可以完全控制硬件的層,內核驅動程序代表應用程序與硬件之間進行會話。內核之上是C庫,負責把POSIX API轉換為內核可以識別的形式,然後調用內核,從應用程序向內核傳遞參數。應用程序依靠驅動內核來完成特定的任務。
在設計嵌入式應用的時候,可以不按照這種層次,應用程序越過C庫直接和內核會話,或者把應用和內核捆綁在一起,甚至可以把應用寫為內核的一個線程,在內核中運行,雖然這樣在移植上帶來了困難,但考慮嵌入式系統對尺寸要求小的特點,是完全可行的。不過我們使用三層軟件結構的模式來學習嵌入式linux將會是我們認識更清晰,簡單可行並使應用具有彈性。

快速入門,最簡單的建立嵌入式Linux應用的方法就是從我們使用的桌面Linux入手,安裝一個喜愛的版本,把我們的某個應用作為初始化的一部分,框架就算完成了。當然,嵌入式linux應用遠比我們的桌面版本功能簡單專一,它也許就是一個用於足彩的終端機,或是一個數碼音頻播放器,這些系統除了使用嵌入式CPU外,僅僅再需要一個串口,網口等少量的輸入輸出接口就可以完成它們特定的應用了。在軟件上,它可以按照三層的概念由內核裝載器,定制的內核和較少的為特定任務設計的靜態連接的應用程序組成。之所以使用靜態連接的應用程序,是因為少量的靜態連接程序所要的存儲空間,比同樣數量的動態連接的程序所佔的空間小,這個平衡點需要我們在實際開發中去獲取。也許你正在設計的是個PDA,它的應用程序較多,那麼你很可能就要使用動態連接程序來減少存儲空間。在你的/bin或者/sbin目錄下,用廠列表看看bash,ifconfig,vi...,也許只用幾十K,當你運行 ldd /bin/bash 時,你會看到它們都和好幾個庫文件相連。好了,這樣看來,我們得把PC想像成一個嵌入式硬件平台,再重新製作一個特定功能的嵌入式linux。

再進行實際操作之前,先來搞清楚幾個基礎知識。
內核裝載器Loader,它的作用是把內核從外部存儲器,移動到內存中。它只作這個事情,一旦完成了調入內核的工作,Loader就跳轉到內核位置開始執行。不同架構有不同的Loader,在x86結構的PC上,通常使用的loader有LILO,GRUB,syslinux,syslinux在嵌入式linux中也同樣工作。其他非x86架構的應用中,你必須使用專門的loader,或者自己編寫loader來裝入內核。也有不使用loader的情況,系統加電以後,內核直接從燒錄有映像的Flash上開始執行。
內核,一旦內核開始執行,它將通過驅動程序初始化所有硬件,這可以從我們的pc機監視器的輸出看出來,每個驅動程序都打印一些有關它的信息。初始化完成後,計算機就準備運行嵌入式應用。也許一個,也許是多個應用程序組成了嵌入式應用,但通常首先調用的是init(通過loader 向核心傳入init=/program 可以定制首先運行的程序)。桌面linux中,init會讀取/etc/inittab文件,來決定執行級別和哪些腳本和命令。嵌入式應用中,可以根據實際的情況決定是否使用標準的init執行方式,也許這個init是個靜態程序,它能夠完成我們的嵌入應用的特定任務,那完全不用考慮inittab了。
initrd文件系統,initrd以一種把內核從存儲介質裝入到內存的相同的機制來裝入一個小型文件系統。這個文件系統最好是以壓縮的方式存儲在介質上的,解壓縮到RAM盤上。通過使用initrd,包含有核心驅動和啟動腳本的小文件系統,就可以直接從介質上和內核一起啟動起來,內核屆壓縮這個文件系統,並執行這個文件系統上叫做/linuxrc的腳本文件,這個腳本通常會把啟動過程中所需要的驅動程序裝入。腳本退出以後,initrd文件系統也卸下了,啟動過程進入真正初始化過程。對於嵌入式來講,可以將需要的應用軟件都運行在這個initrd文件系統上,只要/linxrc文件不結束,內核啟動過程的其他部分就不會繼續。
做個試驗:


cp /boot/initrd-2.4.20.img /tmp
cd /tmp
mv initrd-2.4.2-.img initrd.img.gz
gunzip initrd.img.gz
mount -o loop initrd.img /mnt
cd /mnt
ls
cat linuxrc
可以看到裡面執行了加載了兩個模塊的操作,你在啟動linxu的時候會看見屏幕打印信息。

入門試驗,製作一個簡單的應用:我們使用一張軟盤啟動一台假象的只有一個串口,鍵盤輸入,顯示輸出的x86架構的linux系統,執行的特定應用就是運行minicom,通過串口撥號。需要軟件: minicom-xx.src.tar.gz 和 syslinux-xx.tar.gz,xx代表版本號 ,開始之前,在主目錄建立一個目錄,來釋放這兩個軟件包:

cd
mkdir -p project/minilinux
cd project/minilinux
tar zxvf minicom-xx.src.tar.gz
tar zxvf syslinux-xx.tar.gz


1、裁減linux內核(需要系統安裝內核文件包)

配置內核的時候,我們需要選擇這些:摸塊編入內核,386處理器、物理內存off、支持ELF、標準PC軟盤、支持RAM盤(4096)、支持initial RAM disk (initrd)、虛你終端、虛擬終端控制台、標準串口、ext2文件系統、控制台驅動,VGA text console、DOS FAT、MSDOS文件系統,其他的都可以不要,這樣內核編出來較小。
步驟:

cd /usr/src/linux
make mrproper
make xconfig
make dep && make bzImage

得到 /usr/src/linux/arch/i386/boot/目錄的內核文件bzIamge。

2、編譯一個靜態的minicom ,把它作為將來的linuxrc

cd minicom-xx/src
vi Makefile
修改下面這行
minicom: $(minicom_OBJECTS) $(minicom_DEPENDENCIES)
rm -f minicom 下面的行加上 -static,連接為靜態程序
(LINK) -static $(minicom_LDFLAGS) $(minicom_OBJECTS) $(minicom_LDADD) $(LIBS)

vi minicom.c
找到 if (real_uid==0 && dosetup==0 ) 刪除這個判斷條件語句,主要是用於權限判斷的,因為這個嵌入應用不關注權限問題,否則會出錯。
make
得到可執行程序,用ldd 檢查一下是不是靜態程序。


3、準備initrd壓縮文件image.gz

dd if=/dev/zero of=image bs=1k count=4096
losetup /dev/loop0 image
mke2fs -m 0 /dev/loop0
mounmt -t ext2 /dev/loop0 /mnt/
mkdir -p /mnt/dev
mkdir -p /mnt/usr/share/terminfo/l/
cd /dev
cp -a consle null tty tty0 zero mem /mnt/dev
cp -P /usr/share/terminfo/l/linux /mnt/usr/share/terminfo/l/linux
cp ~/project/minilinux/mincom/src/minicom /mnt/linuxrc
umount /mnt
losetup -d /dev/loop0
sync
gzip -9 image


4、製作軟盤引導,並拷貝文件 bzimage image.gz 到軟盤

A.使用grub

fdformat /dev/fd0
mke2fs /dev/fd0
mount /mnt/fd0 /mnt/floppy
mkdir -p /mnt/floppy/boot/grub
cp /boot/grub/stage1 /boot/grub/stage2 /mnt/floppy/boot/grub
執行 grub,在軟盤上創建引導
grub > root (fd0)
grub > setup (fd0)
grub > quit

cp /usr/src/linux/arch/i386/boot/bzImge /mnt/floppy
cp ~/porject/minilinux/image.gz /mnt/floppy

編輯 /mnt/floppy/boot/grub/grub.conf
default =0
timeout-=10
title minilinux
root (fd0)
kernel /bzImage
initrd /image.gz

卸下軟盤
umount /mnt/floppy



B. 使用syslinux

fdformat /dev/fd0
mkfs.msdos /dev/fd0
mount -t msdos /dev/fd0 /mnt/floppy

cp /usr/src/linux/arch/i386/boot/bzImge /mnt/floppy
cp ~/porject/minilinux/image.gz /mnt/floppy

cp syslinux-xx/ldlinxu.sys /mnt/floppy
cat > /mnt/floppy/syslinux.cfg
LABEL linux
KERNEL bzimage
APPEND initrd=image.gz

umont /mnt/floppy
syslinux-xx/syslinux /dev/fd0
sync


5、用軟盤啟動計算機,如果幸運,minicom的運行畫面出現在屏幕上。

到此,我們的單應用嵌入式linux做好了,但它還很簡陋,沒有什麼實際用途,但通過這個實驗,可以瞭解嵌入式系統的大致結構和開發過程。在進行實際的嵌入式開發時,通常要在PC機上借助嵌入式linux開發工具包,如:uclinux,bluecat等,對相應的硬件平台(目標機)進行軟件編寫編譯,調試成功後,將內核及應用程序寫入到目標機的存儲器中,從而完成整個應用。

[折紙] KERORO紙模型

Written on 12:47 上午 by Yu Lai

轉自ookkk.blogspot.com









[閒聊] 假期結束了

Written on 11:55 下午 by Yu Lai

結束了為期十二周的國防役新訓,
這中間的過程有歡笑也有衝突。
但無論怎樣都過去了,
該是拿起行李走向下一階段囉。

這一周本來是有時間上來寫寫這十二周的心得的,
但光是忙著把球感練回來就沒時間了。
至於心得嘛,過陣子有心情&時間再來寫吧。

明天要開始上班了,
公司那邊之前也去過一個月了,
所以應該不會有什麼適應上的問題,
而這個blog也會開始繼續有文章囉。

[工具] 碩、博士論文致謝詞產生器

Written on 11:47 下午 by Yu Lai

http://tfanalysis.zooserver.net/jotting/acknowledge.php

哎呀,好物啊~當初在寫論文時怎麼沒有這種東西可以用啊?

[技術] FreeBSD/Linux的Booting from network

Written on 3:08 下午 by Yu Lai

最近要搞在Mips的板子上搞Embedded Linux,
要透過網路開機來啟動,所以有了幾下的研究。

其概念為client開機時透過網卡的設定呼叫dhcp或bootp取得ip,
並向server以tftp的方式將boot image檔載入執行開機的動作。

在FreeBSD/Linux上可以透過網路開機,
設定的方法依照機器的網路卡功能的支援不同而有所不一樣。
以下是常見的幾種方式和設定方法:
(PS: 以下設定以Linux為主,FreeBSD則會有些許的不同。)

1. rboot
先介紹rboot
1.1 取得rbootd
如果你的網卡支援rboot開機的話,你必須有台Server來負
責handle boot request,所以首先你必須安裝rbootd。

1.2 設定rbootd
安裝完rbootd後需設定rbootd.conf來設定rbootd。
一般而言rbootd會位於/etc/rbootd.conf
設定範例如下:

# ethernet addr        boot file           comments
08:00:09:87:e4:8f lifimage_715 # PA/Linux kernel for 715/33
08:00:09:70:04:b6 lifimage_720 # PA/Linux kernel for 720
1.3 安裝boot file
將在rbootd.conf裡設定的boot file置於rbootd的目錄,一般是/var/lib/rbootd。

2. dhcp/tftp
這是最常見的一種方式,也是目前主流的diskless system建置的方法。

2.1 取得dhcp/tftp
先透過rpm或apt-get等方式來安裝server必要的檔案。
rpm: dhcp tftpd
(FreeBSD可以用Ports安裝/usr/ports/net/isc-dhcp3-server即可)

2.2 設定dhcp/tftp
1.修改/etc/inetd.conf或/etc/xinetd.d/tftp
inetd.conf中加入:
tftp           dgram   udp     wait    nobody  /usr/sbin/tcpd /usr/sbin/in.tftpd /tftpboot
xinetd.d/tftp:
service tftp
{
disable = no //yes改成no
socket_type = dgram
protocol = udp
wait = yes
user = root
server = /usr/sbin/in.tftpd
server_args = -c -s /tftpboot //加上-c參數
per_source = 11
cps = 100 2
flags = IPv4
}
改完後接著重新啟動inetd或xined。
(FreeBSD則是改/etc/inetd.conf並在/etc/rc.conf中啟動inetd。)
這邊要注意的是我們必須將開機用的檔案放置於/tftpboot中。
2. 參考man 5 dhcpd.conf來修改dhcpd.conf,範例如下:
allow bootp;
default-lease-time 600;
max-lease-time 7200;
# This will tell the box its hostname while booting:
use-host-decl-names on;

subnet 192.168.1.0 netmask 255.255.255.0 {
option routers 192.168.1.1;
option domain-name "foo.com";
option domain-name-server 192.168.1.4;
}
host tatooine {
hardware ethernet 00:40:05:18:0c:dd;
fixed-address 192.168.1.22;
filename "lifimage-tatooine";
option root-path "/exports/tatooineroot";
}
3. bootp/tftp
這是和dhcp/tftp類似,主要是dhcp已經將bootp的功能包含在一起的關係。
但由於網路架構的關係(e.g. 已有dhcp server),也是個常見的採用方式。

3.1 取得bootp/tftp
先透過rpm或apt-get等方式來安裝server必要的檔案。
rpm: bootp tftpd
(FreeBSD皆已內建其中)

3.2 設定bootp/tftp
1.修改/etc/inetd.conf或/etc/xinetd.d/tftp
inetd.conf中加入:
tftp dgram udp wait nobody /usr/sbin/tcpd /usr/sbin/in.tftpd /tftpboot
bootps dgram udp wait root /usr/sbin/bootpd bootpd -i -t 120
xinetd.d/tftp和xinetd.d/bootps:
service tftp
{
disable = no //yes改成no
socket_type = dgram
protocol = udp
wait = yes
user = root
server = /usr/sbin/in.tftpd
server_args = -c -s /tftpboot //加上-c參數
per_source = 11
cps = 100 2
flags = IPv4
}
service bootps
{
disable = no //yes改成no
socket_type = dgram
protocol = udp
wait = yes
user = root
server = /usr/sbin/bootpd
server_args = -i -t 120
per_source = 11
cps = 100 2
flags = IPv4
}
改完後接著重新啟動inetd或xined。
(FreeBSD則是改/etc/inetd.conf並在/etc/rc.conf中啟動inetd。)
這邊要注意的是我們必須將開機用的檔案放置於/tftpboot中。
2. 參考man 5 bootptab來修改/etc/bootptab,範例如下:
vodka:hd=/tftpboot:\
:rp=/usr/src/parisc/:\
:ht=ethernet:\
:ha=080069088717:\
:ip=140.244.9.208:\
:bf=lifimage:\
:sm=255.255.255.0:\
:to=7200:

[技術] Tomcat的OutOfMemory issue

Written on 10:00 上午 by Yu Lai

最近在幫Pinter弄系統,發現Tomcat偶爾會噴OutOfMemory
的Exception出來,而在Console中也沒有辦法Trace出怎麼發生的。
Survey了一下才發現,原來除了存取大量的資料外,在Tomcat中使用
Singleton Pattern會有這類問題。

原因如下:
Hard references to classes can prevent the garbage collector from reclaiming the memory allocated for them when a ClassLoader is discarded. This will occur on JSP recompilations, and webapps reloads. If these operations are common in a webapp having these kinds of problems, it will be a matter of time, until the PermGen space gets full and an Out Of Memory is thrown.

而解決方法有三種:
Workaround 1: Move the class to another classloader
This workaround is for the case this class should be shared between webapps, or if the server will contain only one webapp. That is, we need to use the same instance across several webapps in the same server, or there is no need to worry about it. In this case, the class will need to be deployed on a shared classloader. This means this class must be in the shared/lib or shared/classes directory.

This way, the class will be loaded by a parent classloader, and not by the webapp classloader itself, so no resources need to be reclaimed on webapp reloadings.

This workaround may not always fit well with your code or design. In particular, care must be taken to avoid the singleton to keep references to classes loaded through the webapp classloader, because such references would prevent the classloader from being deallocated. A servlet context listener could be used to get rid of those references before the context is destroyed.

Workaround 2: Use commons-discovery
If you need to have a singleton instance for each webapp, you could use commons-discovery. This library provides a class named DiscoverSingleton that can be used to implement singletons in your webapp.

For using it, the class to be used as singleton will need to implement an interface (SPI) with the methods to be used. The following code is an example of usage of this library:

MyClass instance = DiscoverSingleton.find(MyClass.class, MyClassImpl.class.getName());
It is important, for this library to work correctly, to not keep static references to the returned instances.

Just by using this syntax, you get the following advantages:

Any class could be used as a singleton, as long as it implements an SPI interface.

Your singleton class has been converted into a replaceable component in your webapp, so you can "plug-in" a different implementation whenever you want.

But only this does not make for a workaround. The most important advantage is the DiscoverSingleton.release() method, that releases all references to instantiated singletons in the current classloader. A call to this method could be placed into a ServletContextListener, into its contextDestroyed() method.

That is, with a ServletContextListener simple implementation like the following:

public class SingletonReleaser implements ServletContextListener {
public contextInitialized(ServletContextEvent event) { }

public contextDestroyed(ServletContextEvent event) {
DiscoverSingleton.release();
}
}
we could release all cached references to the instantiated singletons. Of course, this listener should be registered on the web.xml descriptor before any other listener that could use a singleton.

Workaround 3: Use ServletContext attributes
This refactoring will work well provided the ServletContext instance is available, as a local variable or as a parameter.

It will be more efficient than using commons-discovery, but has the disadvantage of making your code depend on the web layer (ServletContext class). Anyway, I have found out that, in some cases, it is a reasonable approach.

There are many ways to do this refactoring, so I will just present one implementation that works well for me:

Create the following ServletContextListener:

public class SingletonFactory implements ServletContextListener {
public static final String MY_CLASS = "...";

/**
* @see ServletContextListener#contextInitialized(ServletContextEvent)
*/
public void contextInitialized(ServletContextEvent event) {
ServletContext ctx = event.getServletContext();
ctx.setAttribute(MY_CLASS, new MyClass());
}

/**
* @see ServletContextListener#contextDestroyed(ServletContextEvent)
*/
public void contextDestroyed(ServletContextEvent event) {
ctx.setAttribute(MY_CLASS, null);
}

/**
* Optional method for getting the MyClass singleton instance.
*/
public static MyClass getMyClassInstance(ServletContext ctx) {
return (MyClass)ctx.getAttribute(MY_CLASS);
}
}
Register the listener in the web.xml descriptor

Replace the calls to MyClass.getInstance() by:

MyClass instance = (MyClass)ctx.getAttribute(SingletonFactory.MY_CLASS);

/* or, if implemented:
MyClass instance = SingletonFactory.getMyClassInstance(ctx);
*/

[閒聊] 玻璃渣跟南方公園合作的影片

Written on 10:44 下午 by Yu Lai

http://www.youtube.com/watch?v=IFN_ceKOcbU&mode=related&search=
一共三集...真是太好笑了...lololol
看著南方公園的畫面..背景是阿拉希戰場的音樂...好惡搞啊...XD
還惡搞B社的員工跟老闆..自己開發的..卻都沒有遊戲角色帳號....
搶車那一段..應該是惡搞GTA系列吧...還蠻像的...cc
不過最後那一把神兵怎麼沒有靈魂綁定啊...=.=

[閒聊] 偽基百科

Written on 2:02 下午 by Yu Lai

http://zh.uncyclopedia.info/

PS: 個人覺得內容還蠻腦殘的啦..

[閒聊] 英文的數字單位

Written on 11:29 上午 by Yu Lai

今天剛好有聊到,想說就做個筆記吧。


yotta = 1024
zetta = 1021 十垓
exa = 1018 百京
peta = 1015 千兆
tera = 1012
giga = 109 十億
mega = 106 百萬
kilo = 103

mini = 10-3
micro= 10-6
nano = 10-9

PS: 毫微奈的記憶法可以用"好無奈"來幫助記憶..XD

[技術] 解決samba的charset問題

Written on 11:28 上午 by Yu Lai

就在9/11那天所po的"[技術] 在FreeBSD上掛載smbfs"中,其實有個問題沒有被提到,而是最近才解決的,那就是charset的問題。

在那台Linux上是採用zh_TW.Big5的編碼,其檔案系統也是採用Big5來儲存檔名。而在FreeBSD那台是採用zh_TW.UTF-8,自然的透過mount_smbfs來掛載會出現亂碼的問題,在經過測試,發現mount_smbfs -E的選項可說是無效..XD

所幸,解決的方法是根據samba的The Official Samba-3 HOWTO and Reference Guide中的
Chapter 30. Unicode/Charsets裡提到的:
As of Samba-3, Samba can (and will) talk Unicode over the wire. Internally, Samba knows of three kinds of character sets:

unix charset
This is the charset used internally by your operating system. The default is UTF-8, which is fine for most systems and covers all characters in all languages. The default in previous Samba releases was to save filenames in the encoding of the clients for example, CP850 for Western European countries.

display charset
This is the charset Samba uses to print messages on your screen. It should generally be the same as the unix charset.

dos charset
This is the charset Samba uses when communicating with DOS and Windows 9x/Me clients. It will talk Unicode to all newer clients. The default depends on the charsets you have installed on your system. Run testparm -v | grep "dos charset" to see what the default is on your system.

也就是只要將unix charset和display charset皆設為配合系統設定的Big5的CP950,然後在dos charset設為UTF-8,這樣透過mount_smbfs來掛載時就會自動轉成UTF-8的編碼了。而目前的成果自然就是FreeBSD上的pure-ftp (with utf-8 support)可以多很多東西囉。

[技術] BT備用Tracker列表

Written on 7:27 下午 by Yu Lai

雖然不一定有用,但勉強加入看看吧。

http://tracker.so-ga.net/announce
udp://tracker.bitcomet.net:8080/announce
udp://bt.lanspirit.net:2710/announce
http://btfans.3322.org:6969/announce
http://btfans.3322.org:8080/announce
http://tracker.prq.to/announce.php
http://tracker.prq.to:80/announce.php
http://tracker.prq.to/announce
http://tracker.prq.to:80/announce
http://bt.cnxp.com:8080/announce
http://bt.cnxp.com:6969/announce
http://privatetracker.limitedivx.com:2710/announce.php
http://tracker.torrentz.info:42426/announce
http://tracker.torrentportal.com:6969/announce
http://tracker1.desitorrents.com:6969/announce

[技術] 在FreeBSD上掛載smbfs

Written on 12:36 上午 by Yu Lai

最近,在弄lab的ftp整合計畫。
要將另一台Linux的資料透過samba的方式來掛載到ftp那台FreeBSD上。
以下則是在弄的過程所得到的一些Notes。

首先,我們可以透過以下的指令來察看有提供連線的資料
smbutil view

掛載時則使用
mount_smbfs //[username]@[host]/[service] [mountpoint]

若要加入 /etc/fstab 使開機後自動mount,請先編輯 /etc/nsmb.conf
加入[host:user]的 section,注意! host及section都必須為"大寫",既使平常輸入的是小寫!
然後在該section加入
password=[encrypted_password] (由smbutil crypt算出)

最後,在 /etc/fstab 裡加上:
//[username]@[host]/[service] [mountpoint] smbfs rw,-I=xxx.xxx.xxx.xxx,-N,-u=[uid],-g=[gid] 0 0

要測試是否成功可以用:
mount -a
來觀看結果。

[技術] 解決Blogger下IE顯示問題

Written on 5:40 下午 by Yu Lai

IE在判斷charset時,會先判斷html檔內的文字編碼,
再去判斷Web Server所提供的charset資訊。
一般而言,這樣是不會有什麼大問題。
但問題就出在判斷html檔內的<meta>資訊前,如果先遇到
<title>時會自動去判斷charset而不理會<meta>所設定的charset。

也就是說如果在Blogger下使用UTF-8編碼,IE會因為這樣的Bug而導致畫面一片空白。
遇到這樣的問題,解決的方法進到Blogger裡的範本修改一下囉。
將<head>裡的
<title><$BlogPageTitle$></title>
<$BlogMetaData$>
順序改一下,將<title>往後調,讓IE先讀取<meta>的資訊即可解決。

[技術] 在Linux上掛載FreeBSD的UFS

Written on 6:19 下午 by Yu Lai

Linux從Kernel 2.6.x開始對FreeBSD的UFS有著良好的支援,
對於FreeBSD的Slice也可以對應良好,但在mount時有些參數
仍需注意一下。

以下是在Linux上要mount UFS的一些注意的地方:
首先先用dmesg找到UFS所在的device node,
e.g.
hdc: ST380021A, ATA DISK drivehdc: max request size: 128KiB
hdc: 156312576 sectors (80032 MB) w/2048KiB Cache, CHS=65535/16/63, UDMA(33)
hdc: hdc1
hdc1: <bsd: hdc5 hdc6 hdc7 hdc8 hdc9 >
然後再執行mount指令來掛載ufs,因為要掛載slice,所以要在options中加入ufstype=ufs2。
# mount -t ufs -o ufstype=ufs2,ro /dev/hdc9 /mnt

[紀念] 偶畢業啦

Written on 11:08 下午 by Yu Lai

就是今天,就是今天。
今天拿到畢業證書,辛苦兩年終算有結果了。
恭喜自己一下 ^____^

[技術] 寫AppleScript叫Mail自動轉寄信件

Written on 12:58 上午 by Yu Lai

相信大家都有用到Forward的功能吧,
而一些好文章也都會轉來轉去的吧。
但如果是一堆mail就會按forward再打
mail address等同樣的動作弄到煩吧.. XD

身為懶人的我,找了一下網路,寫了這樣功能的AppleScript。

tell application "Mail"
set theMessages to the selection
repeat with thisMessage in theMessages
set newMessage to make new outgoing message at end of outgoing messages
tell newMessage
set content to thisMessage's content
set subject to thisMessage's subject
make new to recipient with properties {address:"blahblah@blahblah.org"}
end tell
send newMessage
delete thisMessage
end repeat
end tell