顯示具有 Linux 標籤的文章。 顯示所有文章
顯示具有 Linux 標籤的文章。 顯示所有文章

2009年12月12日 星期六

unix shell script來處理時間

#!/bin/bash

now_sec=$(expr `date +%H` \* 60 \* 60 + `date +%M` \* 60 + `date +%S`) 
echo $now_sec 

time_stamp=$(date +"%H %M %S"); 
now_sec=$(expr $(echo $time_stamp | awk '{print $1}') \* 3600) 
now_sec=$(expr $now_sec + $(echo $time_stamp | awk '{print $2}') \* 60) 
now_sec=$(expr $now_sec + $(echo $time_stamp | awk '{print $3}') ) 
echo $now_sec 

#the MSYS doesn't have bc command 
#now_sec=$(echo "$(date +'%H * 3600 + %M * 60 + %S')" | bc ) 
#echo $now_sec 

now_sec=$(($(date +' 10#%H * 3600 + 10#%M * 60 + 10#%S'))) 
echo $now_sec 


這裡列出如何用linux shell script,算出,現在是一天開始的第幾秒,有四個做法,除了第一個做法有疑慮,其它應該都沒問題,不過這樣的演變是有些心路歷程,所以紀錄一下... 

第一個方法,可以看到使用date指令三次,有一種可能錯誤的狀況,就是當時間為1:59:59,第一次date +%H抓到 1, 第二次好死不死,時間變成2:00:00,所以date +%M變成 00,然後date +%S,也許抓到01或02,所以結果可想而知和事實差了1個小時...所以不太好 

第二個方法,就先把時間的字串紀錄下來,然後再透過awk來各別處理...雖然沒問題,但是有點冗長 

第三個方法是我發現date輸出的格式,可以有些調整,所以加了一些輔助的字元,然後轉向給bc這指令算出... 
其實在考慮bc指令前,我有想過expr指令,不過我發現有些困難... 
首先expr指令的算式,各個operator and operand都需要空白隔開...這應該對shell script熟的人,覺得是常識,我還算菜鳥...CC 
再來這個*的運算符號,必須要這樣\*,前面加個escape符號隔開,否則會告訴你說syntax error... 
然後我想出了這個$(expr `date +'%H \* 360 + %M \* 60 + %S'`) 或者這樣$(expr $(date +'%H \* 360 + %M \* 60 + %S')),結果都是syntax error,我搞了半天,還是參不出道理...結果是放棄,換了bc這指令 

其實搞這些,主要是做些實驗,每隔固定時間,做一些存取動作,然後將結果和時間標記存成.csv的格式,而我是在vmware的linux環境下做的,當我開心的寫好script,開始給它一天時間,去收集資料後,才發現到vmware有個bug,就是vmware下的guest os,時間會不準,所以我那個收集資料的script,就破功了...嗚嗚...我google了一下,好像有解決方法,不過我沒去試,因為我想到,如果某個條件後,就可以停止收集資料,那電腦就會一直開著,直到我發現,然後才有機會關掉電腦,這樣有點不環保,浪費電...而在vmware的linux環境下,雖然有指令可以關機,不過關的是vmware的linux,而不是把電腦關機,所以我選擇在windows上執行這個script,當然,windows認不得這個linux shell script,而我也不太想學windows的shell script,所以弄了個MSYS的東東,用它來解譯我之前寫的linux shell script,同時找出在windows下如何透過cmd下命令,來關機,然後加進我寫的shell scirpt,這樣就蠻順心如意了...哈哈 

可是問題又來了,bc這指令沒有也,雖然我可以找到bc的source code透過MinGW編譯出來,或著用cygwin這個比較完善的unix環境(我想它應該有bc),不過我沒選擇前兩條路,我又在shell script這裡下工夫,我又發現,如果這樣寫$((...)),裡面的...會當作算式處理,然後我一開始時是這樣寫的$(($(date +' %H * 3600 + %M * 60 + %S'))),結果跑一段時間就會停掉,檢查一下,發現是因為如果像是01. 02. 012, 其實是被當八進位處理,所以實際十進位是1. 2. 10, 而如果出現08. 09,就會沒法處理,因為八進位只允許0~7,結果再google一下,發現到只要前面加個10#就會告訴shell interpreter,這個數值就會被用十進位來解釋 

看來我希望的目的是達到了...還有一個"date +%s"(小寫),它是給出從1970/1/1到現在的時間秒數,也是可以考慮的時間處理方法 

最後附上windows的關機指令 
關機 shutdown -s 
重開機 shutdown -r 
shutdont -?,查一下,說的很清楚

補充(20091228):
把bash的wildcard(*)關掉,也可以(注意空白)
#!/bin/bash
set -f
now_sec=$(expr $(date +'%H * 360 + %M * 60 + %S'))
echo $now_sec

相關連結:

2008年9月15日 星期一

linux 2.6 模組編譯

在演練Linux driver的過程中,需要一個核心樹來幫助編譯(讓程式可以引用核心function call. struct. type 和 macro等),知道核心提供哪些功能,

在Linux driver聖經版的內容中,作者都建議讀者能編譯一個新核心,給開發系統使用(註一),不過這樣很費時,且CD所附的核心樹常會沒法編譯(kernel-devel-2.6.15-1.2054_FC5.i686.rpm),

在以前linux 2.4的模組的演練上,我會直接從kernel.org 找一個適合的核心(和開發系統最接近的),然後將相關"Inclde 路徑"和 "Define" 設定好,就可以練習了(註二),所以基本上只引用核心樹裡 include/linux 和 include/asm 內的標頭檔,並沒有將開發系統的核心換掉,算是一個省時間且取巧的方法,

不過在linux 2.6上(註三),模組載入進核心,需要透過一個vermagic.o的目的檔去驗證,才可以通過,因此想著,如果可以產生適當的vermagic.o(modinfo所秀出來的資訊),應該就可以騙過核心,載入成功吧,

然而結果是,失敗...,所以只好乖乖的將整個開發系統的核心換掉,才能順利載入和卸載 "Hello world" 的範例,不過這過程也讓我知道核心設定的相關作用,在這裡紀錄一下...

底下是核心設定的細節在FC5上
目標是希望產生的模組,其vermagic : 2.6.15-1.2054_FC5 686 REGPARM 4KSTACKS gcc-4.1,是如此.....
核心盡量在最小的情況下編譯成功,產生所需要的vermagic.o的檔案,讓module可以連結

下載linux-2.6.15.tar.gz
核心設定:

修改核心樹最上層的Makefile(例如/usr/src/linux-2.6.15.1/Makefile),找到 EXTRAVERSION,
修改EXTRAVERSION = -1.2054_FC5

Code maturity level options --->
    [*] Prompt for development and/or incomplete code/drivers (CONFIG_EXPERIMENTAL)
Loadabel module suppoer --->
    [*]Enable loadable module support (CONFIG_MODULES)
為了產生 scripts/mod/modpost

    [*] Module versioning support (EXPERIMENTAL) (CONFIG_MODVERSIONS)
為了 "no version for struct_module found" 的錯誤

    [*] Source checksum for all modules (CONFIG_MODULE_SRCVERSION_ALL)
為了 "srcversion:",在modinfo秀出來

Processor type and features --->
    [*] Use register arguments (EXPERIMENTAL) (CONFIG_PARAM)
為了產生vermagic的 "REGPARAM" 字串

Kernel hacking --->
    [*]Kernel debugging (CONFIG_DEBUG_KERNEL)
        [*] Use 4Kb for kernel stacks instead of 8Kb (CONFIG_4KSTACKS)
為了產生vermagic 的 "4KSTACKS"字串


註一:其實應該說給開發系統和目標系統使用,不過由於是練習,沒有跨平台編譯的問題,所以只提開發系統
註二:linux 2.4的module編譯方法,請參考linux driver 第二版
註三:linux 2.6的module編譯方法,請參考linux driver 第三版


在這裡是參考Gavin's Linux的說明,來做Linux的核心編譯,並置換開發系統的核心
修改核心樹最上層的Makefile,找到EXTRAVERSION,修改EXTRAVERSION = -test

cp -rf /boot/config-2.6.15-1.2054_FC5 /usr/src/linux-2.6.15/.config (用現在使用的核心的設定來覆蓋)

make oldconfig (只對之前沒有的核心選項提問)

make bzImage modules modules-install (這裡很耗時)

make install (將核心的 .config ,map ,vmlinuz 複製到/boot,並增加了grub.conf的選項)

修改/boot/grub/grub.conf, default=0 (因為它會插到最前面)

reboot,uname -r後,秀出 2.6.15-test,完成


相關連結: The Complete Fedora Kernel Headers
註:可惜太晚才找到這文章,這招也可以試試...

2008年7月31日 星期四

VMware 的網卡驅動

VMware 所模擬的網卡是AMD PCnet32,在linux-2.4.20 有包含這個driver,

linux-2.4.20的核心設定
General setup --->
[*] PCI support (CONFIG_PCI)
(Any) PCI access mode (CONFIG_PCI_GOBIOS)
[*]PCI device name database (CONFIG_PCI_NAMES)
因為這個網卡是接在PCI bus上

Network device support --->
[*] Network device support (CONFIG_NETDEVICES)
Ethernet (10 or 100Mbit) --->
[*] Ethernet(10 or 100Mbit) (CONFIG_NET_ETHERNET)
[*] EISA, VLB, PCI and on board controllers (CONFIG_NET_PCI)
[*] AMD PCnet32 PCI support (CONFIG_PCNET32)

這樣在開機時,Linux會自動偵測出網卡,然後利用ifconfig 和route 設定 IP 和 GATEWAY 的位址, DNS 可以利用resolv.conf 設定,但要注意 NSS (Name Service Switch) 如何提供


練習一下module的設置,

linux-2.4.20 核心設定
Loadable module support --->
[*] Enable loadable module support
[*] Set version information on all module symbols
[*] kernel module loader

其他和上面一樣,只有一個不一樣
<M> AMD PCnet32 PCI support (CONFIG_PCNET32)
對,就是這個設為module,有點廢話...

make moudles
會將設置為 <M>的選項,以modules的編譯參數編譯起來

make INSTALL_MOD_PATH=要建立root的絕對路徑 modules_install
將module放在"root的絕對路徑"/lib/module/`uname -r`/中,並產生一個叫modules.dep的檔案,,是用來告訴modprobe,要載入pcnet32.o前要先載入mii.o,語法有點像make,
其他相關的modules.XXX,都是空的,不過有一個叫modules.pcimap有些東東,還沒找到相關資料來了解其用途,
註:在做跨平台編譯,或者Linux最小化時,這個INSTALL_MOD_PATH要注意,是絕對路徑而沒法是相對路徑,是指向自己要建立root 的filesystem,
註: `uname -r` ==> 2.4.20

在/etc/下要有一個modules.conf,內容如下
alias eth0 pcnet32

還有busybox的module相關指令要加入, modprobe depmod lsmod insmod rmmod modinfo

因此當ifconfig eth0 192.168.8.19 up 時, 由於核心沒有eth0網路設備,就叫modprobe來載入module,首先modprobe檢查modules.conf,知道eth0的driver是pcnet32,然後再檢查modules.dep,得知要載入pcnet32.o前要先載入mii.o,來處理這個相關性,如此核心就知道怎樣處理eth0這個網路設備,完成這個連鎖反應....

其實一般PCI介面有所謂PnP的功能,這樣我們可以存著許多網卡driver,然後利用這機制得知到底要用哪一個driver,這樣才user friendly吧...
不過現在的工作主要在embedded linux,主要以精簡為目標,我想以後有機會再了解吧!!!

2008年7月24日 星期四

udhcp and route 設定 for linux

在busybox-1.00-pre7,已經包含了udhcp 的client 和 server,
在udhcpc的script裡需要ifconfig和route指令(需要在busybox裡設定),還有一些相關的核心設定參數,在這裡紀錄一下
由於我的 embedded linux 有兩個網路介面(再加一個lo),所以也實驗了Router的設定

linux-2.4.20 核心設定
Code maturity level options --->
[*] Prompt for development and/or incomplete code/drivers (CONFIG_EXPERIMENTAL)
這個選項開放一些新的的功能或著實驗的選項,讓使用者可以選擇

General setup --->
[*] Networking support (CONFIG_NET)
這樣才有Networking Options ---> 和 Network device support ---> 這兩大選項
[*] Sysctl support (CONFIG_SYSCTL)
可以讓/proc下出現sys的子目錄,當然proc這個檔案系統要先開啟

Networking options --->
[*] Packet Socket (CONFIG_PACKET)
udhcpc 需要這個選項
[*]Unix domain sockets (CONFIG_UNIX)
使用netstat可以看到 Active UNIX domain sockets (w/o servers) 的列表,udhcpd 需要這個選項
[*] TCP/IP networking (CONFIG_INET)
可以在/proc/sys/下出現net/ipv4的子目錄,例如 echo "1" > /proc/sys/net/ivp4/net_ipforward ,linux才有路由的功能, 還有會擁有 lo 這個 loopback 網路裝置, 可以ping 自己!!!

Network device support --->
[*] Network device support (CONFIG_NETDEVICES)
基本上這個大選項,是在選擇網卡的dirver,不過在一些SOC的embedded system中,雖然廠商已經porting好了相關網路驅動,且放置在和晶片相關的選項中(廠商所分出的一個大選項),不過上面的 (CONFIG_NETDEVICES)還是要選,不然掛udhcpd會失敗,

udhcp 介紹:
udhcpc: 需要一個 script file, 注意是一個可執行的檔,不是設定檔,udhcpc利用shell 變數和 script file 做互動
udhcpd: 需要一個設定檔,這個設定檔可以指定相關的資訊的儲存檔案路徑
關於這些設定檔的參考,udhcpd可以參考 udhcpd.conf , udhcpc 可以參考這網站內的S50default

相關連結:
參考一

2008年7月11日 星期五

MTD 測試

MTD 裝置通常是用來當作是Flash的裝置,若是系統沒有Flash可以測試,也可以用記憶體來模擬MTD裝置,以下紀錄核心, /dev, mtd-utils 的選擇和設定

linux 2.4.20 Kernel 設定
進入Memory Technology Devices (MTD) --->
[*] Memory Technology Devices (MTD) support (CONFIG_MTD)
[*] Direct char device access to MTD devices (CONFIG_MTD_CHAR)
[*] Caching block device access to MTD devices (CONFIG_MTD_BLOCK)
進入Self-contained MTD device drivers --->
[*]Test driver using RAM (CONFIG_MTD_MTDRAM)
(1024) MTDRAM device size in kiB (CONFIG_MTDRAM_TOTAL_SIZE)
(128) MTDRAM erase block size in kiB (CONFIG_MTDRAM_ERASE_SIZE)


/dev/mtdblock0 b 31 0
/dev/mtdblock1 b 31 1
/dev/mtdblock2 b 31 2
依序類推...
/dev/mtd0 c 90 0
/dev/mtd1 c 90 2
/dev/mtd2 c 90 4
依序類推...

mtd-utils-1.0.0 下載

發現一個問題:
mkfs.jffs2 -d test -o test.bin
dd if=test.bin of=/dev/mtdblock0
mount -t jffs2 /dve/mtdblock0 /mnt/flash
在最後一個步驟後會有錯誤訊息,研究一下,終於了解.....

既然是模擬Flash memory,有一個參數很重要,那就是 CONFIG_MTDRAM_ERASE_SIZE,所以使用mkfs.jffs2指令來產生image檔案時,必須 "mkfs.jffs2 -e0x20000 -d ./root -o test.bin",如此才能吻合RAM所模擬的FLASH memory

註: mkfs.jffs2 的參數 -e "size" 代表erase block的大小

一般實際有Flash的系統上,會利用CFI去偵測FLASH得到這些資訊

mtd-utils-1.0.0 裡,試過mkfs.jffs2. flash_erase. flash_eraseall 這三個命令

flash_eraseall 作用在 /dev/mtd0 會有問題.看一下flash_eraseall.c, grep bbtest=1,改成bbtest=0就可以了,這個修改是讓程式跳過bad block的檢查,我想應該是核心的MTD子系統沒有建置bad block check的機制,了解不多,不過至少可以用了.... :-)

2008年6月26日 星期四

busybox & /etc/passwd group


一般linux套件會利用glibc的 Name Service Switch (NSS) 來讀取 /etc/passwd 和 /etc/group,像是ls -l 列出檔案的擁有者和群組,若是沒有這些lib,則只能顯示uid和gid的號碼,
busybox-0.60.5 可以設定直接讀取 /etc/passwd group,而不需要透過 NSS, 因此可以省掉些library建置

在Makefile裡找到USE_SYSTEM_PWD_GRP,然後改成 USE_SYSTEM_PWD_GRP=false

PS:若是使用的(cross)compiler,是參照到uClibc而不是glibc,也可以不需要使用任何NSS的files和libraries

相關連結:http://busybox.net/downloads/BusyBox.html

2008年5月25日 星期日

Linux系統最小化

目標是利用initrd的機制,使用ramdisk當作root filesystem,看看kernel可以裁減到多小,root filesystem 至少需要哪些檔案

工作平台: x86, Red Hat 9

Linux Kernel 2.4.20
必要選項:
General setup --->Kernel support for ELF binaries(CONFIG_BINFMT_ELF)
註:因為所有linux的binary執行檔都用這種格式,以前是用a.out的格式,
例如windows的執行檔是用PE的格式

Character devices --->Virtual terminal(CONFIG_VT)

Character devices --->Support for console on virtual terminal(CONFIG_VT_CONSOLE)

File systems --->/proc file system support(CONFIG_PROC_FS)
註:很多工具命令需要,像是 ps.reboot....

Console drivers --->VGA text console(CONFIG_VGA_CONSOLE)
註:在 make menuconfig 環境下,Character devices -->Virtual terminal(CONFIG_VT)勾選之後,才能看到

root filesystem:
/bin /dev /etc /lib /mnt /proc /sbin /usr
mknod /dev/console c 5 1
mknod /dev/tty1 c 4 1


BusyBox工具集:(版本-0.60.5)
/bin/busybox
/linuxrc
註:若kernel傳參數時,有加入root=/dev/ram0,這個連結檔可以砍掉
/sbin/init
其他工具...

若使用靜態連結,可以不用考慮shared library的相依性
若使用動態連結,可以用ldd指令來查binary執行檔的相依性,不過只要檢查busybox檔的相依性,因為其它的都是連結檔!!!


GNU工具集:(直接從Red Hat 9.0 複製過去)
/sbin/init
/bin/bash
/bin/nash
/linuxrc
註:若kernel傳參數時,有加入root=/dev/ram0,這個檔就不需要,若無法傳遞參數給kernel,可以寫成如下:

#!/bin/nash
echo Mounting /porc filesystem
mount -t proc /proc /proc
echo 0x0100 > /proc/sys/kernel/real-root-dev

這樣算是等同於busybox自動產生的linuxrc連結檔!!!

nash 是個命令解譯器,有很多特殊的內建命令,用來適合initrd的任務,細節請參考man或者相關連結,雖然這個命令稿有用到echo. mount的指令,不過這些都是nash內建的,建議就用nash當作指令稿的解析器,
若用bash會有其它要解決的問題,例如mount,除了是外部命令,還有函式庫相依性,還有 ...

還有kernel的核心設定要多加一項
General setup --->sysctl support(CONFIG_SYSCTL)
這樣子,/proc下才有/sys這個子目錄

其他工具...

由於都是從Red Hat 9.0複製過來,所以一定要考慮執行檔相依性,像是moount. echo. bash. ...
可以用 type '命令',知道命令的位置,也可以用ldd '命令', 知道命令相依哪些函式庫:-)

相關連結
雲上的老鼠 西莎雜記
酷!學園 簡單日誌 skywalker_nick的技術專欄 Checko's Blog
Jamyy's Weblog
IT技術-賽迪網 資安論壇

2008年5月13日 星期二

initrd 的建立方式

Linux2.6 内核的 Initrd 机制解析
這裡面講解了Linux2.6 & Linux2.4 initrd 的不同,有一個地方,以為是錯誤,結果卻不是,

之前以為目錄之間的複製,如果包含了裝置檔,是不能用cp的指令,因為如果裝置檔的major & minor, 如果剛好match系統中的某個裝置檔的major & minor,則cp指令會觸發系統裝置的驅動程式,而不是在複製裝置檔,所以會有很多奇怪的現象

結論是,如果只複製一個裝置檔會有問題,如果使用cp -r 就可以...
註: -r 是遞迴的拷貝,包括目錄和次目錄下的所有檔案

紀錄一下之前覺得安心的做法:
(cd initrd; tar -cf - *) | (cd ram0; tar -xf -)

(cd initrd; find . | cpio -p ../ram0)

相關連結:
Hangle的學習筆記
[藍森林-自由軟件]