2012年8月1日 星期三

Linux 的 time 指令

Linux 有個很有意思的 time 指令,可以用來查看另一個指令的執行時間,例如執行 time helloworld 會顯示 helloworld 這支程式的執行時間。

time 指令的返回值包含「實際時間 (real time)」、「用戶態 CPU 時間 (user CPU time)」及「核心態 CPU 時間 (system CPU time)」。其中,

  • real time 表示後面所接的指令或程式從開始執行到結束終止所需要的時間。簡單講,當一個程式開始執行瞬間看一下手錶記下時間,當程式結束終止瞬間再看一次手錶,兩次的時間差就是 real time。
  • user CPU time 表示程式在 user mode 所佔用的 CPU 時間總和。多核心的 CPU 或多顆 CPU 計算時,則必須將每一個核心或每一顆 CPU 的時間加總起來。
  • system CPU time 表示程式在 kernel mode 所佔用的 CPU 時間總和。

所以,以下的想法就不一定成立:

一:real time = user CPU time + system CPU time

這裡舉一個比較極端的例子,假設我執行 time sleep 10 這個命令,time 會返回給我的訊息如下:

real    0m10.003s
user    0m0.004s
sys     0m0.000s 

因為動作是「睡 (sleep)」10 秒,從 sleep 指令下達到它結束終止共經過 10 秒,所以 real time 的值是 10 秒。但,sleep 指令在 user mode 及 kernel mode 都沒有佔用 CPU,所以 user CPU time 和 system CPU time 基本上都是「零」。

二:real time > user CPU time + system CPU time

這個式子若是在單核心、單顆的 CPU 上,通常有成立的可能。

但,在多核心或多顆 CPU 的環境,卻往往可能出現 user CPU time + system CPU time > real time 的狀況。甚至我們在編譯大量的程式時,經常執行 time make -j2time make -j4 的指令,往往得到的 user CPU time 值都可能大過 real time 值。

延伸閱讀:

2012年7月31日 星期二

使用 VMware / Android-X86 取代 Android SDK 裡的模擬器

在 "試玩 X86 版本的 Android 4.0.4 (Ice Cream Sandwich branch)" 及 "在 VMware Player 試玩 Android 4.0 幾點筆記" 兩篇文章裡,Android 4.0 在 VMware Player 跑起來了,這要好好感謝網路上許多開發者前輩們的辛苦努力,筆者在 VMware Player 跑 Android 這件事上,花最多時間的大概只是下載程式碼和編譯這兩點吧!

接下來,來看看如何將 Eclipse 裡寫好的 Android 程式安裝到 VMware Player 裡的 Android 4.0 吧!既然網路已經設定妥當了,當然直接想到的就是透過 TCP/IP 來使用 ADB 了。翻一下之前寫的 "How to Use ADB over TCP/IP?" 這篇文章,只要設定 service.adb.tcp.port 這個變數也就搞定了。

確認 service.adb.tcp.port 這個變數設定成 5555 後,重新啟用 adbd,然後在 Windows 端開啟一個 DOS 視窗,執行 adb connect 192.168.245.130 就可以連接裝置了。其中 192.168.245.130 是 VMware Player 裡的 Android 4.0 獲取的 IP 位址。

在 DOS 視窗裡連接裝置後,自然在 Eclipse 也可以藉由 DDMS 使用這個 Android 裝置了。而且,這麼一來比直接開啟 Android SDK 裡的模擬器要快多了。

另外一個不用開啟 DOS 視窗執行 adb connect 指令的方法,就是直接在 Eclipse / ADT 裡,將 DDMS 的設定中指定 ADBHOST 的值,這樣可以跳過上面 DOS 視窗那個步驟,使用上更方便一點點。

在 VMware Player 試玩 Android 4.0 幾點筆記

在 "試玩 X86 版本的 Android 4.0.4 (Ice Cream Sandwich branch)" 這篇文章裡,我使用的是由 cwhuang (黃志偉) 等開發者維護的 Android-x86。由於編譯時選擇了 eeepc 這個項目,所以在 VMware Player 裡初次載入 Android 4.0 後,並不能順利使用設定 eth0 這個網路介面。此時,請將 VMware Player 關閉,修改虛擬機器的 .vmx 檔,將網路卡修改成 vlance,也就是將 ethernet0.virtualDev 修改成 vlance

第二個問題,進入休眠後似乎會造成無法解鎖,使得整個畫面動彈不得,因此建議在「顯示」裡將休眠的功能選擇「永不逾時」。

第三個就是 resolution (分辨率) 的問題,直接使用預設的方式載入 Android,筆者得到的分辨率是 800X552,這比例怪不習慣的。如果要修改分辨率,可以在啟動時修改參數加入 vga=ask 或加入 DPI=240 UVESA_MODE=1280x800

筆者試了好幾次,在 VMware Player 直接採用修改 DPI 及 UVESA_MODE 的方式會比修改成 vga=ask 好用。例如下圖是修改參數成 DPI=240 UVESA_MODE=1280x800 的結果:

試玩 X86 版本的 Android 4.0.4 (Ice Cream Sandwich branch)

根據 "ReleaseNote 4.0-RC2" 這篇文章,下載 Ice Cream Sandwich 的程式碼:

$ repo init -u http://git.android-x86.org/manifest -b ics-x86
$ repo sync 

編譯:

$ lunch eeepc-eng
$ make iso_img 

接著請耐心等待它編譯完成。

編譯完成後,可以得到 out/target/product/eeepc/eeepc.iso 這個檔案。接著,可以利用 VMware Player 或 Virtualbox 建立一個虛擬機器,並執行這個 ISO 檔。

順利載入 Android 的第一個畫面:

接下來,要先設定它的網路,能上網才方便繼續玩耍下去呀!先找到 Terminal 程式,然後執行 su 這個指令,它會取得 root 權限:

接著就可以設定網路裝置了。我在 VMware Player 裡設定網路使用 NAT 模式,所以可以讓 eth0 藉由 DHCP 取得 IP,不過 DNS 仍然要手動鍵入,因此執行以下的指令:

# netcfg eth0 dhcp
# setprop net.dns1 8.8.8.8 

打開瀏覽器看看,可以上網囉!

2012年7月17日 星期二

sfdisk: The Scriptable fdisk

在玩 Beagleboard 時接觸到 sfdisk 這個指令,一開始還沒怎麼弄明白,不過爬了些文章後,試了試發現 sfdisk 這指令真的很有意思。只要將想建立的 partition 資訊「餵」給它,就會將磁碟建立出對應的 partition。所以,可以在腳本裡利用 echo 和 sfdisk 配合,來建立需要的 partition。

在反覆試了幾次,我試著改了一個 mkmmc.sh 的腳本出來:

#!/bin/bash

echo "[Unmounting all existing partitions on the device ]"
umount $1*

echo "[Partitioning $1...]"

DRIVE=$1
SIZE=`fdisk -l $DRIVE | grep Disk | awk '{print $5}'`
  
echo DISK SIZE - $SIZE bytes
 
CYLINDERS=`echo $SIZE/255/63/512 | bc`
 
echo CYLINDERS - $CYLINDERS
{
 echo ,17,0x0C,*
 echo ,130,,-
 echo ,130,,-
 echo ,,0x0C,-
} | sfdisk -D -H 255 -S 63 -C $CYLINDERS $DRIVE &> /dev/null

echo "[Making filesystems...]"

mkfs.vfat -F 32 -n boot "$1"1 &> /dev/null
mkfs.ext3 -L rootfs "$1"2 &> /dev/null
mkfs.ext3 -L extend "$1"3 &> /dev/null
mkfs.vfat -F 32 -n data "$1"4 &> /dev/null 

經過這個腳本,可以建立出如下的 partition:

Disk /dev/sdb: 3965 MB, 3965190144 bytes
255 heads, 63 sectors/track, 482 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0x00000000

   Device Boot      Start         End      Blocks   Id  System
/dev/sdb1   *           1          17      136521    c  W95 FAT32 (LBA)
/dev/sdb2              18         147     1044225   83  Linux
/dev/sdb3             148         277     1044225   83  Linux
/dev/sdb4             278         482     1646662+   c  W95 FAT32 (LBA)

延伸閱讀:

  1. sfdisk: The Scriptable fdisk

2012年5月12日 星期六

在少於 2GB 記憶體的虛擬機裡編譯 Android 4.0 (ICS)

先前偶爾會在虛擬機器裡編譯 Android,這兩天也試在稍早安裝的 Debian (32bit) 上嘗試編譯 Android 4.0 (ICS),首先遇上的問題是記憶體的部份。首先我將虛擬機器裡的記憶體設定成 1GB,所以編譯時遇上了這個問題:

target Dex: core
Error occurred during initialization of VM
Could not reserve enough space for object heap
Could not create the Java virtual machine.
make: *** [out/target/common/obj/JAVA_LIBRARIES/core_intermediates/noproguard.classes-with-local.dex] Error 1 

這個容易處理,修改 core/definitions.mk 這個檔案是可以解決的,修改方式如下:

diff --git a/core/definitions.mk b/core/definitions.mk
index b678158..b83b299 100644
--- a/core/definitions.mk
+++ b/core/definitions.mk
@@ -1525,7 +1525,7 @@ define transform-classes.jar-to-dex
 @echo "target Dex: $(PRIVATE_MODULE)"
 @mkdir -p $(dir $@)
 $(hide) $(DX) \
-    $(if $(findstring windows,$(HOST_OS)),,-JXms16M -JXmx2048M) \
+    $(if $(findstring windows,$(HOST_OS)),,-JXms16M -JXmx1024M) \
     --dex --output=$@ \
     $(incremental_dex) \
     $(if $(NO_OPTIMIZE_DX), \ 

但,最後卻在編譯 qemu 時又出現錯誤,爬了文之後,在 "Build android ICS on ubuntu 32 bits" 這串討論文章裡看到以下這麼一段:

Indeed, with the emulator moving to 64-bit, building on 32-bit hosts is not an option any more (not even unsupported).

噗~~~既然我主要的環境都是 64 位元,而且在 32 位元的 Debian GNU/Linux 上也只是順手試試,那麼就先暫時到這裡吧! XD