busybox 的 mdev

mdev 實際上算是 udev 的替代品,代碼看起來很簡單。
下 mdev -s 會 enumerate /sys/class 下的檔案,並據此去建立 /dev 下的 device 檔案。如果 /etc 下有 mdev.conf,它會先參考這裡的設定,來決定 device 的 permission 與 user/group owner。
雖然說是 /sys/class,但是 /sys/class 下的檔案實際上都是 symbolic link,指向 /sys/device 下的檔案。
也可以下這行

echo /sbin/mdev > /proc/sys/kernel/hotplug

,直接讓 kernel detect 到新裝置時,就請 /sbin/mdev 去 /dev 建立新的 device 檔案。
kernel 是怎麼傳遞資訊給 mdev 的呢?答案是透過環境變數,kernel 在執行 /sbin/mdev 之前,會先填好 ACTION、DEVPATH跟SUBSYSTEM 這3個環境變數之後,再去呼叫,所以 mdev 才會知道要做些什麼。這也就是在 shell 下輸入 /sbin/mdev 會印出使用說明的原因,因為沒有這3個環境變數,mdev 就只印出說明了。
kernel mode 下的呼叫,還牽涉到 FIRMWARE 的部份,不過這邊目前沒用到,只有大致看一下。大底來說,就是如果有 FIRMWARE 環境變數時,他會試著去讀取 /lib/firmware/xxx 的 firmware 檔案內容,然後檢查 /sys/$dev/loading 這檔案,有了這檔案以後,再寫入 1,接著再把讀到的內容寫到 /sys/$dev/data 這個檔案裡去,完成載入外部 firmware 的動作。
程式相當的精簡,有空再來看看 udev。

pyexiv2 裡的 Rational 與 GPSCoordinate

要存GPS的相關tag到圖片時,因為某些tag要求存Rational或GPSCoordinate,我不知道該怎麼轉換,所以花了不少功夫查。我基本上是參考 這個老先生的code,他主要是使用 GPS tracker,所以會要讀取 tracker 裡的紀錄,然後以時間跟照片做比對,再把 GPS 位置寫進圖片裡。

可是遇到兩個問題:

  1. 他的 code 是用 surd 處理 Rational,我找不到 surd 了。
  2. 算出來的度、分、秒不準確。

首先是解決Rational問題,python 2.6 已經有內置的 module – Fraction 可以解決了。

def R(f):
"""R(float) - get a Rational number for a float"""
from fractions import Fraction
from pyexiv2 import Rational
r = Fraction.from_float( float(f) )
return Rational( r.numerator, r.denominator )

再來就是轉換的問題,從 Google gear 那邊拿到的經緯度,要轉換成度分秒,我後來是參考 上河文化網站-座標轉換程式與 Google Maps 地圖定位裡的 javascript 來改寫,這才得到正確的度、分、秒:

def d(angle):
"""d(any) - get degrees from a number :eg d(33.41) = 33"""
return math.floor(angle)
def m(angle):
"""m(any) - get minutes from a number :eg d(33.41) = 24"""
return math.floor( (angle-d(angle))*60 )
def s(angle):
"""s(any) - get seconds from a number :eg s(33.41) = 36"""
return round((angle-d(angle)-m(angle)/60)*3600)
def degree2coordinate( lat, lon ):
"""Convert degree to coordinate string."""
latR    = 'N'
lonR    = 'E'
if lat  < 0:
lat = -lat
latR= 'S'
if lon  < 0:
lon = -lon
lonR= 'W'
slat = "%03d,%02d,%02d%s" % (d(lat),m(lat),s(lat),latR )
slon = "%03d,%02d,%02d%s" % (d(lon),m(lon),s(lon),lonR )
return (pyexiv2.GPSCoordinate.from_string( slat ), pyexiv2.GPSCoordinate.from_string( slon ) )

最後,記一下,Tag裡要存的資料型態:

  • Xmp.exif.GPSLatitude、Xmp.exif.GPSLongitude 裡存的是 pyexiv2.GPSCoordinate
  • Xmp.exif.GPSMapDatum、Exif.GPSInfo.GPSMapDatum裡存的是字串,我是用 WGS-84
  • Exif.GPSInfo.GPSLatitude、Exif.GPSInfo.GPSLongitude 裡存的是度、分、秒的tuple,要注意,度、分、秒都要轉成 Rational
  • Exif.GPSInfo.GPSLatitudeRef、Exif.GPSInfo.GPSLongitudeRef 裡存的是度、分、秒的表示字串,如:125.3,67.5,12E

Android 檔案系統用哪個好? ext3 或 ext4?

因為看到有人說 ext4 在 Android 裡的表現比 ext3 好,就想說來試試看。

本來是打算用 Quadrant 來評測,可是跑完以後,他會要上傳數據到網站上才能得到結果,我的 device 沒辦法連上網,所以只能放棄。後來改用 Linux 傳統的 iozone 來做,下載、解開 iozone tarball 以後,用

make CC=/opt/arm-2009q1/bin/arm-none-linux-gnueabi-gcc GCC=/opt/arm-2009q1/bin/arm-none-linux-gnueabi-gcc LDFLAGS=-static linux-arm

就可以編譯出來了。(我的ARM toolchain 放在 /opt/arm-2009q1 下)

丟到 device 上執行的時候跑了好幾次,都沒成功,只能降低最大 record size 跟最大 file size,然後就行了。我用的指令如下:

/bin/iozone -R -a -q 2048 -g 4096

從最後得到的報告看起來 ext4 是略優於 ext3 的,但是使用上的感覺並不是很明顯,可能是因為沒有用大檔案的關係吧,以後再仔細試試看。

電影流水帳(2010/7/26~2010/8/9)

生產力是什麼?可以吃嗎??

  • Solomon Kane(IMDB, Wikipedia),中譯:所羅門傳奇。原本我以為是小時候看的故事,所羅門王的寶藏,看了之後才知道不是,是改編自 Robert E. Howard 的系列小說。故事就是描述Solomon如何踏上除魔之路的故事,坦白說,電影不怎麼樣,小說可能會比較好看吧~
  • The A-Team(IMDB, Wikipedia),中譯:天龍特攻隊。翻拍自小時候很熱門的影集,不過小時候沒什麼在看台視,所以對裏面故事沒什麼印象,對霹靂遊俠倒是比較有印象。故事類型類同於 Mission impossible,就是團隊協同出任務的故事,電影裡多了計中計的鋪陳,The A-Team收到委託,並且算是成功地完成任務,卻被判刑、入獄。後來CIA幫助他們逃獄,讓他們洗刷恥辱,但卻想不到原來CIA就是幕後的黑手,幫他們逃出來,只是幫CIA找到黑吃黑的人。電影拍的不錯,很流暢,沒有冷場,愛看動作片的人,不要錯過。

XMP and Cell ID 之二

在之後打算要寫入 geotagging 到圖片的時候,才發現 python XMP toolkit 的不足,於是又踏上尋覓的路程。後來找到 pyexiv2,這個 library 更好用,不僅可以讀,也能寫,用法也不會太複雜。唯一的缺點是,ubuntu 10.04 包的是 1.x 版,好在,有人包了最新的版本在ppa裡
安裝:

sudo apt-add-repository ppa:pyexiv2-developers/ppa
sudo apt-get install python-pyexiv2

讀取跟寫入,基本上參考官方的tutorialAPI 文件就行了。Cell ID 資訊在這幾個tag裡:

  • Xmp.cell.mcc
  • Xmp.cell.mnc
  • Xmp.cell.lac
  • Xmp.cell.cellid

XMP and Cell ID

去年就看到這篇文章:Cell ID Photo PC Tool 0.3,想試試看了。因為是c#寫的,照理來說,Linux 上的 mono 應該可以用才對,哪知道卻發現他用了 System.Windows.Media.Imaging 這個 mono 沒實作的類別庫。
沒辦法,於是就想說用 python 寫一個好了,當作練習。
首先遇到的問題就是 cell id 怎麼取得,原本以為是在 exif 裏面,用了 PIL 去撈,卻沒撈到。胡亂找了一陣,才知道這是放在 XMP metadata 裏面,得用 XML toolkit sdk 來撈才行,python 也是有 binding:Python XMP toolkit,只是得另外裝,ubuntu 沒有包進去。

是故,得先裝 libexempi3 (sudo apt-get install libexempi3),再下載 Python XMP toolkit,解開後,執行 sudo python setup.py install 來安裝。這樣就大功告成了。

程式很簡單,簡單到爆:

#!/usr/bin/env python
import sys
from libxmp import file_to_dict
CELL_NS="http://developer.sonyericsson.com/cell/1.0/"
if __name__ == '__main__':
xmp = file_to_dict( sys.argv[1] )
for prop_name, prop_value, prop_options in xmp[CELL_NS]:
print prop_name, prop_value

就這樣就可以把 Cell ID 相關的資訊都撈出來了。

電影流水帳(2010/7/8~2010/7/25)

現在一天只能看20分鐘左右,所以一部片要花一星期才能看完,這完完全全是讓我把電影當小說來看呢~

  • Ghost Town(IMDB, Wikipedia),中譯:超感應妙醫/通靈牙醫。這是我某天在HBO上看到的片子,劇情雖然是有點老套,但是男主角的演技讓人不會覺得無聊,我覺得很好看。男主角是個牙醫,因為麻醉的緣故有了短暫死亡的體驗,這導致他可以看到鬼魂。鬼魂都有未完的願望所以逗留在人間,正巧他可以看到他們,能跟他們溝通,所以大家就都跑去找他。可是男主角是個孤僻的人(這也許是我對這角色產生共鳴的原因),不希望跟人(鬼)有所接觸,因此通通拒絕,可是鬼魂還是糾纏著他,後來,女主角的丈夫(一開始就變成鬼)出來當說客,只要男主角幫他,他就願意讓他一勞永逸地不用再跟其他鬼接觸。男主角就出來幫他讓女主角遠離另外一個男人,可是他也因此墜入情網。最後結局是皆大歡喜的,男主角終於打開心防,願意幫助人(鬼),也因此跟女主角有更進一步的交流。
  • The Bad Lieutenant: Port of Call – New Orleans(IMDB, Wikipedia),中譯:爆裂警官。
    有點悶的片子。男主角一開始因為救人而有背傷,所以導致他後來依賴毒品來擺脫疼痛。他為了一件滅門慘案,展開調查,這件案子跟毒品有關係,他的前途也因為要買毒品、養女人而陷入困境,後來他不得已要跟毒梟合作,但想不到這卻是計中計,他反將了毒梟一軍,也因此獲得晉升。小悶歸小悶,但故事本身算是還不錯,可以看看的。
  • The Book of Eli(IMDB, Wikipedia),中譯:奪天書。很悶的片子,說是動作片,覺得又還好,我覺得不好看。故事發生在大災難之後,世界各地因為太陽變成荒漠,人們白天只能帶著太陽眼鏡,靠著地下水過日子,人類也變得很稀少。男主角因為上帝的聲音,所以獨自帶著聖經西行。西行的時候,途經一個城鎮,城鎮的老大是個識貨的人,所以知道他帶著是聖經以後,下手搶奪。後來是搶奪到手了,可卻是盲人版,男主角則是跟女主角到了San Francisco 的 Alcatraz Island,那兒是人類最後保存知識的地方,在那裡,他把內容都默了出來,原來他記下了整本聖經…

Json.Net serialization/deserialization

Json.Net 的 serialization/deserialization 其實不難,因為都內建了,我被卡到的原因,是因為我沒仔細看文件。我的類別裡有日期時間的屬性,但我一直以為不需要特別處理,但我錯了。


在用 JsonConvert.SerializeObject 時,得傳入 new IsoDateTimeConverter () 才行,要不然會導致之後 JsonConvert.DeserializeObject 時無法轉換日期時間。

var items = new List<Item>();
// other stuffs
File.WriteAllText (m_filename, JsonConvert.SerializeObject (items, Formatting.Indented, new IsoDateTimeConverter () ));
List<Item> objs = JsonConvert.DeserializeObject<List<Item>>(File.ReadAllText (m_filename));

另外一件重要的事情就是你的類別必須有 default constructor,如果沒有的話,JsonConvert.DeserializeObject 也會丟例外出來給你。

initrd+busybox

kernel source 的 Documentation/initrd.txt 裡,把 initrd 、開機順序跟必要的程序講的很清楚,依法施為,大致就沒問題了。

雖然如此,我還是花了快一天的時間。這邊紀錄一下我的作法,我是用文件裡提到的 loop device 方法,也就是先用 dd if=/dev/zero of=initrd bs=4M count=1 製作出 initrd,再用 mke2fs 格式化,接著用 mount -o loop 把這檔案掛為檔案系統。

然後我 build BusyBox,參考 BusyBox 原始碼的 examples/bootfloppy/mkdevs.sh 裡的 code,把我要的 device 都建起來,然後把 BusyBox 的相關檔案放進去,再把 examples/boot/floopy/etc 放進去。接著修改 etc/init.d/rcS, etc/fstab, etc/inittab,調整成我要的樣子以後,就差不多了。

因為這份 initrd 在開機後,我就拋棄了,所以 etc/init.d/rcS 最後得掛上真正的 device,並且切換過去:

# mount your device to /newroot.
mkdir /newroot
mount -t ext3 /dev/your_device /newroot
cd /newroot
mkdir /initrd
/sbin/pivot_root . initrd
exec /usr/sbin/chroot . /init </dev/console >/dev/console 2>&1

最後,umount,再用 gzip -9 壓縮得到 initrd.gz 之後,大致上就是這樣子。

VirtualBox的VM啟動不了兒

好久沒啟動公司的VirtualBox OSE,就想說啟動起來,打算開個新VM,裝個Debian來玩玩兒,結果不知道是不是太久沒啟動,他鬧了脾氣,出現這樣的錯誤訊息:

VirtualBox can’t operate in VMX root mode. Please disable the KVM kernel extension, recompile your kernel and reboot.

這真是一個糟,所以我立馬就把所有視窗都關掉(天知道我關了多少),然後重新開機,再試試,居然還是不行。拜請Google大神,果然早有人回報到 https://bugs.launchpad.netBug #292588 in virtualbox-ose (Ubuntu): “VirtualBox can’t operate in VMX root mode.”
照看起來,只要用這指令 workaround 一下就行了:sudo modprobe -r kvm-intel
我想應該是昨天裝了 qemu 的關係,因為印象中有裝 qemu-kvm,應該跟他有關係。Bug #292588後面的 comment 也有人提到這點,不過看起來,這 bug 真的很久了啊~