2012年11月29日 星期四

將 firefox 及 adobe flash 與目前系統隔離完整版


上次寫了將 firefox 執行於 chroot 環境下,用來與目前系統隔離,但由於 chroot 只隔離檔案系統,而核心卻還是共用的,依然沒有很安全,只保護了半套。這篇就直接將 firefox 跑在 kvm 虛擬機器上,畫面及聲音傳回目前桌面系統。

有很多種方法來達到這功能,包括 vnc,nx server,xspice server + spice client,x2go server,ssh x11 forwarding,以及最古早的 X11 access control (xhost),另外還有 dxpc,也就是今天的主角。

但由於 vnc 及 nx server 和 xpice server + spice client 都是出現一個完整的 root window,裡面再有一些應用程式,等於直接操作二台機器,使用上滿不方便的,因此在這邊就不使用。


範例有二台機器,一台是 desktop-host, 另一台為 firefox-host,記憶體給至少 768M 以上,不用啟動 X。


首先介紹最簡單的 ssh x11 forwarding:

ssh x11 forward 是最簡單的,不用安裝額外軟體,直接使用即可。
預設 ssh server 的 x11 forwarding 已經是開啟的,只要直接在本機下指令:
$ ssh -X firefox-host firefox

這時虛擬機器上的 firefox 視窗就會開啟,和平常本機上執行沒二樣,不過檔案就要使用如 sshfs 來分享。
有一點要注意的,就是要先將本機的 firefox 給關掉,若沒關的話,就算是在別台機器開 firefox,也會變成是開啟本機的 firefox,這個功能很奇怪,之前被騙過,下載檔案在別台機器上找不到。

但是,有一個大問題,就是在看 youtube 時 “沒有聲音”,因為是在另一台機器上執行,所以聲音沒傳過來。

沒關係,有功能強大的 pulseaudio 可用,可取代以前的 esd,在本機設定 pulseaudio sound server,由遠端將聲音傳送過來。

on desktop-host 端設定:
$ sudo apt-get install pulseaudio paprefs

$ paprefs
設定 Network Server 標籤,將 Enable network access to localhost sound devices 打抅

然後將 ~/.pulse-cookie 給拷貝到虛擬機器中同樣位置即可。
$ scp -p ~/.pulse-cookie firefox-host:~/.pulse-cookie

若不想這麼麻煩,直接設定同樣 Network Server 標籤下
Don’t require authentication 也打抅,就不用認證即可連接。


 啟動 pulseaudio
$ pulseaudio --start

此時用 netstat -an 可看到 pulseaudio listen tcp port 4713
firewall 記得打開給 firefox-host 連

on firefox-host 端設定:
$ sudo apt-get install pulseaudio

執行:
$ export PULSE_SERVER=desktop-host:4713
$ firefox &

這樣看 youtube 時就有影像及聲音了,從 firefox 下載後也可透過 sshfs 來取得。

當然多開 port 總是不好的,而且聲音流量不大,也可透過 ssh port forwarding 來取代開 port。
將 desktop-host 的 4713 port 由 ssh tunnel 轉到 firefox-host 的 4713 port,這樣在 firefox-host 就可直接將聲音送到 localhost:4713,desktop-host 也就不用防火牆打開 tcp 4713 。

on desktop-host:
$ ssh -X -R 4713:localhost:4713 firefox-host

on firefox-host:
$ export PULSE_SERVER=localhost:4713
$ firefox &

寫個 script start-firefox-ssh-x11-forwarding
#!/bin/bash
export PULSE_SERVER=localhost:4713
firefox &
firefox 下載回來的檔案如何取得,直接安裝 sshfs 掛載起來即可。

簡化上面步驟,一切設定完整後,以後只要下指令:
on desktop-host:
$ ssh -X -R 4713:localhost:4713 firefox-host start-firefox-ssh-x11-forwarding
$ sshfs firefox-host:/home/username/Downloads/ /home/username/Downloads 

即可遠端使用 firefox



使用 x2go server :

x2go server 基本上和 nx server 差不多,之前介紹過,這次就不多做說明。
x2go server 可以單獨執行某一程式,做到 rootless 的功能,只會有一個應用程式的視窗,和本機開啟的看起來一樣。
而聲音部份,x2go 也支援 pulseaudio, arts, esd 等,在設定裡抅好即可,其他的 x2go 會處理,也不用在 desktop-host 上 listen tcp 4713 的設定。
至於檔案分享部份,也在設定裡面直接設定即可,後端也是採用 sshfs。

設定時選擇 Session 標籤 -> 最下方 Session type 改成 single application,並於 Command: 空格中打上 firefox 指令即可,按 ok 關閉視窗。

連接後只會出現 firefox 視窗,而不是整個桌面環境。




最古早的 X11 access control (xhost):

因為直接用 X protocol,沒經過 ssh 什麼的加密,因此是效能最好的,可惜要在本機 desktop-host 上開 tcp 6000 port 給 firefox-host 連,不建議用這個方法,因為這裡是用虛擬機器,基本上是沒出去這台 desktop-host 外面,所以才勉強用看看,若為真實二台機器透過網路連接,千萬不要用這方法。

on desktop-host:
現在預設啟動 X 時,都會自動加上 -nolisten tcp 參數,因此要修改 gdm 類的工具,將這參數拿掉。
若是使用 startx 來啟動 X,則修改:
/etc/X11/xinit/xserverrc
exec /usr/bin/X -nolisten tcp "$@"
改成
exec /usr/bin/X "$@"

這樣在啟動 X 後,就會 listen tcp port 6000
firewall 打開 tcp 6000 給 firefox-host 連

然後設定那幾台機器可以連 X server
$ xhost +firefox-host

on firefox-host:
$ export DISPLAY=desktop-host:0
$ firefox

這樣畫面就會丟過來,而且看 youtube 什麼的,都和原本本機上執行差不多。
聲音一樣使用 pulseaudio,檔案分享一樣用 sshfs。

不過,這樣風險滿大的,如果 firefox-host 被入侵,有現成工具(之前在管系統時,有遇到這種後門),可以由 firefox-host 連到 desktop-host 6000 port,並截取所有鍵盤按鍵及畫面,包括密碼什麼的,所以就違反了當初安全的目的。



使用 dxpc 來執行遠端程式,並丟到目前 display 來:

當初 nx server 就是受這套 dxpc 所啟發,而開始發展的。

由於 dxpc 的 client 要先啟動,因此先從 firefox-host 開始
on firefox-host:
$ sudo apt-get install dxpc
$ dxpc &
會 listen tcp port 4000 及 6008 port,4000 是 client 及 server 端溝通的,而 6008 是 X 的 display :8 所用的 port
firefox-host 的防火牆只需要開 tcp port 4000 給 desktop-host 連即可。

將 display 指向 localhost:8
$ export DISPLAY=localhost:8

聲音一樣用 pulseaudio
$ export PULSE_SERVER=desktop-host:4713

等 desktop-host 連結過來後,再來執行 firefox,我的 script 裡面是設定 sleep 5 秒

start-firefox-dxpc
#!/bin/bash
export DISPLAY=localhost:8
export PULSE_SERVER=desktop-host:4713
sleep 5
firefox &

$ start-firefox-dxpc
執行後在5秒內趕快去另一端執行 dxpc


on desktop-host:
$ sudo apt-get install dxpc

$ dxpc firefox-host &

預設 dxpc 和 dxpc 間是用 lzo 來壓縮再傳送,若 cpu 不夠力(如虛擬機器),可以關掉。
$ dxpc -i 0 firefox-host &

通道建立後,就會彈出 firefox 視窗,像平常一樣的使用。
播放 youtube 上 html5 的影片很正常,有點頓就是,應該是機器不夠高檔。不過,好像 flash 及 dxpc 有點不相容,若是去播放 flash 的影片,很容易就將整個 X 都卡住,完全不會動,要按 Ctrl-Alt-F1 回到 console 底下,將 dxpc 給砍了,再按 Alt-F7 回來才正常。

那古早 xhost 方式和這個 dxpc 有什麼不同,其實差很多。
最主要差別在:
xhost 方式是由 desktop-host listen tcp 6000,然後由 firefox-host 連進來
dxpc 是由 firefox-host listen tcp 4000,然後由 desktop-host 連進來,方向不同,自然安全性也不同。當然 dxpc 也可以下 -w 參數,來讓連線方向對調,某些狀況下會用到,如 firefox-host 在 nat 底下。


基本上,這麼多種方法可用,大致上為:
ssh x11 forwarding: 一般使用及瀏覽網頁沒問題,但要看影片滿頓的,手動搭配 pulseaudio 及 sshfs
古早 xhost: 效能最好,但最危險,手動搭配 pulseaudio 及 sshfs
x2go server: 最簡單,看影片滿頓的,聲音及檔案分享都幫你做好
dxpc: 介於中間,安全性不錯及效能勉強可接受,手動搭配 pulseaudio 及 sshfs,不過會 hang,要再多測試看看。

 感覺機器要再高檔些,才有辦法應付影片播放。

2012年11月25日 星期日

以 schroot 在 chroot 環境下執行 firefox

由於前陣子 google 公佈說在 chrome 中執行 flash 已經 “fully sandboxed”(註1),就算 adobe flash 有漏洞,也不容易影響到系統。

但對於 firefox 使用者來說就沒這麼好康了,由於 adobe flash 的安全性一向是滿糟的,在 mozilla 沒做好防護前,只好自己來,這篇是在 debian wheezy 下將 firefox 放到 chroot 底下去執行,以達到隔離目的。

當然最安全的是建立另一台虛擬器,只拿來跑 firefox,但是這樣很麻煩,消耗的系統資源又多,實在不划算。用 lxc 的話也滿不錯,但是只跑 firefox,殺雞焉用牛刀,chroot 就很夠用。

使用 chroot 麻煩地方在於,要掛載原本 root 底下的 /proc、/dev/pts 到 chroot 環境,要有音效,還要掛載 /dev/snd,webcam 的話,就要將整個 /dev 也掛載,就要手動建立 /dev/video0 這個裝置,再將 /dev/shm 也掛載到 chroot 底下才行。

若僅使用一次,那手動掛載沒問題,可是一天要使用幾十次的話,真的會煩死人。因此就要使用 schroot 來做 chroot 的功能,會自動幫忙掛載預先設定好的 filesystem,而且可以一般使用者來呼叫 schroot (因為有 setuid),chroot 則一定要使用 root 才行,在只有單人的桌面系統上使用 schroot 沒什麼問題,多人系統就比較危險了。


首先以 debootstrap 建立一個基本的 chroot 環境:
$ sudo apt-get install debootstrap

$ sudo debootstrap wheezy /media/share/chroots/wheezy http://free.nchc.org.tw/debian

裝上 schroot
$ sudo apt-get install schroot

設定 schroot
/etc/schroot/schroot.conf

[wheezy]
description=Debian Wheezy compiling environment
type=directory
directory=/media/share/chroots/wheezy/
users=john
setup.fstab=mysetup/fstab.wheezy

[iceweasel]
description=Debian Wheezy only run iceweasel
type=directory
directory=/media/share/chroots/iceweasel
users=john
preserve-environment=true
setup.fstab=mysetup/fstab.iceweasel

上面有二個 chroot 的範例,第一台是 wheezy,平常拿來編譯程式用,因為想讓平常的桌面環境乾淨點,沒有裝如 build-essential gcc make 等工具,要編程式,就到 chroot 底下去編譯。

第二個 iceweasel 則是專門用來執行 firefox,而且只執行 firefox,由於 license 的問題,在 debian 中的 firefox 叫做 iceweasel(註2)。

description: 文字說明
type: chroot 種類,可分成 plain(註3), directory, file, loopback, block-device, btrfs-snapshot, lvm-snapshot
directory: 若 type 為 plain 或 directory,則這裡指向 chroot 所在目錄
users: 以哪個身份來執行
setup.fstab: 進入 chroot 要自動掛載哪些 filesystem,檔案在 /etc/schroot 底下,不能指定絕對路徑,否則會失敗。
preserve-environment: 保留目前環境變數,方便執行 chroot 裡的圖形介面程式,否則還要手動 export DISPLAY, xauth 等等。

還有很多其他參數,請自行 man schroot.conf

接著設定進入 chroot 後要掛載的檔案系統
/etc/schroot/mysetup/fstab.wheezy
/proc /proc none rw,bind 0 0
/dev/pts /dev/pts none rw,bind 0 0

/etc/schroot/mysetup/fstab.iceweasel
/proc /proc none rw,bind 0 0
/dev/pts /dev/pts none rw,bind 0 0
/dev/snd /dev/snd none rw,bind 0 0


自動執行 script
schroot 會自動執行 /etc/schroot/setup.d/ 底下所找到的 scripts,當 chroot 啟動時會用檔名順序並且以 「setup-start」選項執行,而離開 chroot 時會用相反順序並以「setup-stop」選項執行。可以在現有的檔案中增加你想進行的動作,也可以自己建立新的 script。


設定好後以指令檢查是否正確:

列出所有 chroots:
$ schroot --list
chroot:iceweasel
chroot:wheezy

檢視某個 chroot 詳細資訊:
$ schroot --info wheezy

檢視所有參數及目前設定值:
$ schroot --config

只執行一行指令就跳出:
$ schroot -c wheezy -- ls /tmp

進入 chroot:
$ schroot -c wheezy

在進入 chroot 後,再安裝其他相關程式
$ schroot -c iceweasel
(iceweasel)$ sudo apt-get install iceweasel xfonts-arphic-ukai xfonts-arphic-uming

以後要執行 chroot 裡的 firefox 就下指令:
$ schroot -c iceweasel iceweasel &

小弟都是用 xbindkeys 熱鍵啟動,放在 ~/.xbindkeysrc 中即可,和在原本的環境中沒二樣。也可自己寫個 desktop file 放在桌面( ~/.local/share/applications/ ),一點擊就啟動,完全忘了是在 chroot 環境中。


要共享下載的東西,也要將 /home/john/Downloads 目錄也加入才行。
/etc/schroot/mysetup/fstab.iceweasel
/home/john/Downloads /home/john/Downloads none rw,bind 0 0


至於更新,將 /var/cache/apt/archives 也掛載到 chroot 中即可,才不用重覆下載更新檔。


schroot 真的是非常好用,讓原本麻煩的 chroot 一下子就變得輕鬆多了,另外還支援 union fs 或 aufs 讓多個 chroot 可共享一個 base,又可同時寫入資料,可節省很多空間。



參考連結:

1. http://thenextweb.com/google/2012/11/13/google-declares-flash-is-now-fully-sandboxed-in-chrome-for-windows-mac-linux-and-chrome-os/

2. 大致上是因為 firefox 官方只支援少數 2,3 個平台 debian 為了支援 10 幾個平台,所以有對 firefox 上了很多 patch,但 mozilla 又不接受 debian 所做的 patch 整合到 firefox 裡,然後 mozilla 不允許 debian 改過的版本還叫 firefox,所以 debian 只好用 fork 出一個 iceweasel。而 thunderbird 則改用 icedove。
http://en.wikipedia.org/wiki/Iceweasel
http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=354622
http://lists.debian.org/debian-legal/2004/12/msg00328.html

3. 基本上 plain 和 directory 是一樣的,差別在於 plain 就和一般 chroot 一模一樣,全部都手動來,而 directory 則會自動幫忙掛載 filesystem 等等。

4. 好用的 chroot
http://novus.pixnet.net/blog/post/29322140

2012年11月15日 星期四

libvirt 搭配 spice 達到 host and guest 桌面剪貼薄 copy and paste 文字及圖片



在 linux 上要使用虛擬化(Virtualization),就我所知,身邊的朋友大部份都是用 virtualbox,因為最容易上手,介面也漂亮,以前也有用過,但是發現 virtualbox 有分成二個版本,一個是 freeware 版,另一個是 ose 版( Open Source Edition),在 debian 中的 ose 版本,是拿掉 usb 功能的,所以從此就改用 kvm。

kvm 程式小,速度快,但使用時,不同 OS 使用的參數並不一樣,如舊的 kernel 2.6.24 以下的 OS 就無法使用 virtio。而虛擬機器上的顯卡及網卡都有好幾個型號可選等等,有太多參數可以調整,若是直接執行 kvm 指令,後面下一堆參數,那久了真的是件辛苦的事。

而且,kvm 有滿多不方便之處,像是無法在 host 及 guest 之間剪貼薄 copy and paste,每次要傳個連結或圖片,都要先存成檔案,再由 host scp 到 guest 中,實在很麻煩。另外,要在 guest 中使用滑鼠,要讓 guest 覇佔去,若要讓滑鼠回到 host 下,還要按 Ctrl+Alt 才行,使用上不方便,還好現在可配合 spice 來達到這功能。

SPICE (Simple Protocol for Independent Computing Environment) 是一種遠端顯示桌面的協定,一開始是由 Qumranet 公司於 2007 年開發,是 closed source。Red Hat 於 2008 年 9 月買下 Qumranet,並於 2009 年 12 月將之開放出來。

SPICE 功能滿多的,其中幾個特點如下,完整版請看下方連結(註1):
傳輸資料使用 openssl 加密。
高品質的影片及3D畫面傳送。
支援遠端聲音錄製及播放。
剪貼薄分享。
在 guest 中裝上 spice agent,以達到 host 及 guest 即時切換,不用按 Ctrl-Alt 來取回滑鼠主控權。


這裡只針對 Clipboard sharing 及 Spice agent 部份稍加介紹。

kvm 可以直接支援 spice,但是一樣要下很多指令,有興趣參考下方連結(註3)。

因此,就需要使用另外的管理介面來輔助,這裡針對的是其中一套,叫 libvirt。

libvirt 的介紹,魏藥大大已有寫了幾篇(註3)(註4),在此就不重覆說明,請參考下方連結,這裡僅針對 host and guest 桌面間的 copy and paste 來做說明。

在開啟 virt-manager 後,找一台原本舊的機器修改設定或新建一台都可以,在 Details 裡,將原本預設的 Display VNC 改成 Display Spice,然後按右下方 Apply 即可,virt-manager 會問說要不要自動新增 Spice agent channels,回答 Yes 後會產生一個 Channel 的項目,檢視內容為:
Channel Device
Device type: spicevmc
Target type: virtio
Target name: com.redhat.spice.0

這樣就完成 spice 在 host 的設定,預設 spice 和  vnc 一樣,也是 listen localhost tcp 5900 port,使用上和原本 vnc 一樣。

另外,若將 Video 改成 qxl 的話,可在虛擬機器中使用較高的解析度,取代原本的 cirrus 或 vga。
要配 xserver-xorg-video-qxl 來使用,在 guest 中要記得安裝。

在 guest 開機進入 OS 後,要裝上 spice agent,若 guest 是 ubuntu 或 fedora 這些,預設應該都已經裝好才是。若是 debian 而沒裝上 desktop environment,則要手動裝上:
$ sudo apt-get install spice-vdagent

裡面有二個執行檔:
/usr/sbin/spice-vdagentd
Spice agent daemon

/usr/bin/spice-vdagent
Spice agent xorg client

在 guest 開機時,要啟動 Spice agent daemon
$ sudo /etc/init.d/spice-agent start

進入 X 之後,要啟動 Spice agent xorg client (只能在 X 中啟動)
將 /usr/bini/spice-vdagent 放到 gnome 或 kde 的啟動中即可,或是放到 /etc/X11/Xsession.d/ 中來啟動。

若正常情況下,便可在 host 及 guest 來 copy and paste 文字及圖片了。
kernel 模組 uinput 應該是使用中才對,若為 0 則是有問題。
$ lsmod | grep uinput
uinput 17440 1

然後 X 的 log 檔中會有訊息,若沒有類似這種訊息,也是不正確
$ cat /var/log/Xorg.0.log
[ 898.310] (II) config/udev: Adding input device spice vdagent tablet (/dev/input/event5)
[ 898.310] (**) spice vdagent tablet: Applying InputClass "evdev pointer catchall"
[ 898.310] (II) Using input driver 'evdev' for 'spice vdagent tablet'
[ 898.310] (**) spice vdagent tablet: always reports core events
[ 898.310] (**) evdev: spice vdagent tablet: Device: "/dev/input/event5"
[ 898.310] (--) evdev: spice vdagent tablet: Vendor 0 Product 0
[ 898.310] (--) evdev: spice vdagent tablet: Found 3 mouse buttons
[ 898.310] (--) evdev: spice vdagent tablet: Found scroll wheel(s)
[ 898.310] (--) evdev: spice vdagent tablet: Found relative axes
[ 898.310] (--) evdev: spice vdagent tablet: Found absolute axes
[ 898.310] (--) evdev: spice vdagent tablet: Found x and y absolute axes
[ 898.310] (--) evdev: spice vdagent tablet: Found absolute touchscreen
[ 898.310] (II) evdev: spice vdagent tablet: Configuring as touchscreen
[ 898.310] (II) evdev: spice vdagent tablet: Adding scrollwheel support
[ 898.310] (**) evdev: spice vdagent tablet: YAxisMapping: buttons 4 and 5
[ 898.310] (**) evdev: spice vdagent tablet: EmulateWheelButton: 4, EmulateWheelInertia: 10, EmulateWheelTimeout: 200
[ 898.310] (**) Option "config_info" "udev:/sys/devices/virtual/input/input5/event5"
[ 898.311] (II) XINPUT: Adding extended input device "spice vdagent tablet" (type: TOUCHSCREEN, id 10)
[ 898.311] (WW) evdev: spice vdagent tablet: touchpads, tablets and touchscreens ignore relative axes.
[ 898.311] (II) evdev: spice vdagent tablet: initialized for absolute axes.
[ 898.312] (**) spice vdagent tablet: (accel) keeping acceleration scheme 1
[ 898.312] (**) spice vdagent tablet: (accel) acceleration profile 0
[ 898.312] (**) spice vdagent tablet: (accel) acceleration factor: 2.000
[ 898.312] (**) spice vdagent tablet: (accel) acceleration threshold: 4


在 debian 中,若 spice-vdagentd 及 spice-vdagent 都有執行,但是還是無法 copy and paste,就要檢查看看是否有裝 libpam-ck-connector,因為小弟一開始沒裝桌面環境,結果一直無法正常運作,裝上 gnome-desktop 後,就會動,後來很辛苦的一個個找才找到是這個 consolekit 的 pam 模組的問題。
$ sudo apt-get install libpam-ck-connector

注意,裝好後,一定要登出再登入,或重新開機才會生效。


SPICE 目前主要是用在虛擬機器上,而不是在實體機器,所以要取代 vnc 及 freenx 也不是在短期內能做到,不過未來的前景很看好,不但可傳輸影像、聲音,還有 3D 畫面。在 debian 中有看到一個 xserver-xspice 的 xserver,想必就是用在實體機器上的,不過還沒測過,不知道實際運作起來如何,有沒有可能完全取代 vnc 及 freenx 就要再測試。

SPICE 真的是非常的強大,配合 kvm 來做虛擬化,不但效能好,而且功能也越來越完整了,希望越來越多人使用 kvm。真要感謝 redhat 在 linux 上所做的努力,今天才有這麼棒的虛擬化環境。


參考文件:

1. SPICE features:
http://www.spice-space.org/features.html

2. SPICE 官方網站:
http://www.linux-kvm.org/page/SPICE

3. 基於 KVM 與 libvirt 的虛擬化叢集系統-Debian 篇
http://www.openfoundry.org/tech-column/8448

4. 基於 KVM 與 libvirt 的虛擬化叢集系統-儲存空間的配置
http://www.openfoundry.org/tw/tech-column/8539-the-clustered-virtualization-system-based-on-kvm-and-libvirt-chapter-of-debian-storage-allocation

2012年11月3日 星期六

使用 qemu 來模擬 Raspberry Pi

由於有些時候,Raspberry Pi 不在身邊或開發 Raspberry Pi 程式時,可利用 qemu 來模擬 arm 系統,執行開發的程式,除錯用。

在 windows 平台上也可以,請各位自行研究,小弟對 windows 實在沒興趣。
http://sourceforge.net/projects/rpiqemuwindows/

在 linux 上,裝上 qemu(是老大哥 qemu,不是 kvm)。
$ sudo apt-get install qemu

裝好後,系統上就有一堆平台的模擬器
$ ls /usr/bin/qemu-system-*
/usr/bin/qemu-system-alpha
/usr/bin/qemu-system-arm
/usr/bin/qemu-system-cris
/usr/bin/qemu-system-i386
/usr/bin/qemu-system-lm32
/usr/bin/qemu-system-m68k
/usr/bin/qemu-system-microblaze
/usr/bin/qemu-system-microblazeel
/usr/bin/qemu-system-mips
/usr/bin/qemu-system-mips64
/usr/bin/qemu-system-mips64el
/usr/bin/qemu-system-mipsel
/usr/bin/qemu-system-ppc
/usr/bin/qemu-system-ppc64
/usr/bin/qemu-system-ppcemb
/usr/bin/qemu-system-s390x
/usr/bin/qemu-system-sh4
/usr/bin/qemu-system-sh4eb
/usr/bin/qemu-system-sparc
/usr/bin/qemu-system-sparc64
/usr/bin/qemu-system-x86_64
/usr/bin/qemu-system-xtensa
/usr/bin/qemu-system-xtensaeb

因為 Raspberry Pi 是 arm,所以模擬 Raspberry Pi 就要用 qemu-system-arm
執行 qemu-system-arm 有幾個參數是必要的:
1.kernel
2.disk image

所以到 Raspberry Pi 官方網頁去下載最新的 disk image
http://www.raspberrypi.org/downloads
下載這個最新的 435M,解開後為 1.9G
2012-10-28-wheezy-raspbian.zip

由於 qemu 和真實的 raspberry pi 還是有些不同,因為無法使用 2012-10-28-wheezy-raspbian.zip 裡面提供的 kernel 來開機,須要自行編出 qemu 用的 kernel。

自己編出 qemu 用 kernel 說明
http://xecdesign.com/compiling-a-kernel/

但是網路上有人真的是佛心來的,已經幫忙編好了,再加上自己懶,用現成的就好,不過裡面會不會藏什麼怪東東,請小心使用。
http://elinux.org/File:ZImage.7z
抓下面那個 3.2.27 版的,上面 3.6.1 的不知道為什麼沒畫面


由於是 .7z ,用 7za 來解,若沒 7za 裝上
$ sudo apt-get install p7zip-full


解開後得到 zImage 檔
$ 7za x  20121016173340\!ZImage.7z


執行模擬器
$ qemu-system-arm -M versatilepb -cpu arm1176 -kernel zImage -m 512 -append root=/dev/sda2 -net nic -net user -hda 2012-10-28-wheezy-raspbian.img

-M 是 Machine type
-cpu 是 cpu type
-kernel 核心
-m 為記憶體大小
-append 開機時的 kernel 參數
-net nic -net user  這樣是一對,代表這台機器有一張網卡,而網路模式是 user mode
-hda 第一顆硬碟

在這邊使用最簡單的 user mode 網路,一開好就會有網路可用,但缺點是無法用 icmp(不能 ping) 及無法由 host 機器連入虛擬機器。

執行這指令後,應該就會有一個視窗彈出,並看到樹莓派的 logo 了。
不過若使用 elinux.org 的 kernel,開機中間會有一些錯誤訊息,找不到模組什麼的,這是因為我們只提供 kernel,而這個 kernel 是 3.2.27 版,而 2012-10-28-wheezy-raspbian.zip image 裡的是 3.2.27+ 版,不符合,所以此時無法載入任何模組,要解決此問題,只有自己編 kernel 了。反正沒那些模組一樣可以開機完成,對於僅測試來說是夠用的。

另外,若想要能用網路從 host 和虛擬機器溝通,能用的方式有很多種,比較簡單是用 bridge mode.

我們需要 tunctl 執行檔
$ sudo apt-get intall uml-utilities

建立一張網卡 tap0,讓你的使用者可存取,因此 your_normal_user 要改為你的登入帳號
$ sudo tunctl -t tap0 -u your_normal_user

新增一個 bridge 介面 br0
$ sudo apt-get intall bridge-utils
$ sudo brctl addbr br0

$ sudo ifconfig br0 up

$ sudo brctl addif br0 eth0 tap0

$ qemu-system-arm -M versatilepb -cpu arm1176 -kernel zImage -m 512 -append root=/dev/sda2 -net nic -net tap,ifname=tap0 -hda 2012-10-28-wheezy-raspbian.img

-net nic -net tap,ifname=tap0 有一張網卡,設定為使用 host 機器的 tap0

用這種模式,就可以直接 ssh 到 qemu 虛擬機器裡了。


以使用者 pi ,  密碼 raspberry 登入
第一次會開啟選單做設定

如果在選單中鍵盤無法設定,結束選單直接修改
edit /etc/default/keyboard
XKBLAYOUT="us"
then
$ sudo /etc/init.d/keyboard-setup restart


開始體驗 Raspberry Pi  :-)

2012年11月1日 星期四

Raspberry Pi 樹莓派使用場合及時機



在買了 Raspberry Pi 後,到底能拿來做什麼事情呢?有幾個想法一起分享

這裡有初學者教學的影片,非常值得一看。
http://www.youtube.com/user/RaspberryPiBeginners


1. 插上擴充卡,DIY 或教學。

當然最主要用法,插上 GPIO 卡,接上麵包板,拉一些電路,控制 LED 來顯示些什麼,或是生產啤酒 (http://forum.talkonly.net/viewthread.php?tid=15049) 等等,似乎是主要的用法。


2. 放在客廳看影片(mpeg4) 及播放藍光 DVD。

但是我對麵包板實在沒什麼興趣,沒關係 Raspberry Pi 還有其他特點:
1) 省電
2) 不佔空間
3) 能看影片(mpeg4) 及播放藍光 DVD

由於 Raspberry Pi 有內建 mpeg4 壓縮及解壓縮晶片,所以對我們一般人來說,拿來放在客廳接上大螢幕看影片及藍光 DVD 是最適合的,不會像一般電腦或準系統那麼大台,放在客廳幾乎忘了他的存在,不會很礙眼。


3. 在偏遠學校,每人一台小 Raspberry Pi 當 thin client。

在偏遠地區學校經費不足,可為每個小朋友都準備一台 Raspberry Pi,裝上 linux,寫程式,也可當 thin client 連上 X server 或 vnc server 及 freenx server,不過可能要另外買 hdmi to dvi 的轉接頭就是。


4. 開發 QT 應用程式。

除了 rasbian,  arch 以外,在官方 www.raspberrypi.org 上還有另一個可裝在 raspberrypi 的 distribution 叫做 QtonPi (Qt on Pi)
直接將 Qt on Pi dd 到 sdcard 上放到 raspberrypi 開機,就有一個完整的 QT 開發環境。不但跨平台,還可以寫 meego 應用程式,放上 nokia 商店賣錢。對未來 jolla 的  sailfish 開賣後,應該會有些幫助。

所以就算窮到沒錢買一、二萬元的電腦來開發程式賺錢,只要花 35 美金買一台樹莓派,裝上 QtonPi,就可以開始開發程式賺錢了 :-)
http://qt-project.org/wiki/Qt-RaspberryPi



5. 由於省電,拿來取代小路由器,24 小時開機。

由於 Raspberry Pi 很省電,才 3.5W,因此拿來取代家中 IP 分享器最適合,24 小時開機。一般買的產品,功能都滿少的,限制又多。若刷成 dd-wrt 或 openwrt 雖然不錯用,但通常儲存空間都很小,還是不如一台 linux 系統來得完整好用。而且之前尋找 vpn 產品,價格都偏高,至少 NT$3000 起跳,不如買台 Raspberry Pi 裝上 openvpn 或 ipsec 來取代。


6. 插上 webcam 放在外面租的房子中錄影,以防外人入侵。

若搭配上 webcam,則能做的事又多了一些。

裝上錄影軟體,架在外面租的房子中錄影,以防小偷,不過要設定好圖片上傳到網路上才行,不然整台搬走,連錄下來的資料或截圖都會不見。


7. 插上 webcam 當嬰兒或老人的觀察系統,有問題可即時處理。

若家裡有小嬰兒或行動不便老人,可放一台在旁邊,就算在別的房間或外面,一樣能注意到。


8. 插上 webcam 拿去 open source 聚會做直播 :-)

串流影像沒問題,但聲音的話,還要再想辦法。


9. 插上 webcam 將各地風景即時影像串流到網路上。

可將 webcam 對準風景或小動物,串流到網路上去做分享。


10. 打雷神之鎚3

在 Raspberry Pi 上抓回 source 照著下面網頁修改並編譯,約一小時即可編好,由於有用到 gpu,超順的。
http://www.raspbian.org/RaspbianQuake3


目前大概就想到這些,而我個人則最想拿來取代之前的 openwrt,因為上面儲存空間才 8M,放幾個檔就滿。由於最近有為 wheezy 編一些 deb 檔,如 italc,opennx,freenx等等,若用一般電腦或 notebook 24 小時開機,一個月下來也多了不少電費,吃不消。

現在是 2012/11/01,要播放 mpeg4 的影片,僅能使用 omxplayer 來播放才有使用到硬體解壓。
quake3 有支援 gpu,效能很棒,但其他像 openarena 還沒支援。
可以修改 /boot/cmdline.txt 來開外接 usb 硬碟上的系統,但是 sdcard 還是一定要有才可以開機。
使用外接硬碟時,若硬碟無外接電源,恐怕 Raspberry Pi 無法供那麼多電,可以改用有外接電源的 usb hub。

樹莓派的出現,真是全世界的一項福音,沒想到 35 美金的電腦就能夠做到如此的功能,又環保省電。

雖然目前 Raspberry Pi 上的 X server 是用 framebuffer 的 xserver-xorg-video-fbdev,效能並不好,所以要拿來充當 desktop 用還真的有困難,頓頓的。不過最近 broadcom 釋出了上面 gpu 的 VideoCore driver code,相信再過幾個月就會更好用了,到時候使用小的 window manager 加上 midori 或 dillo 等小瀏覽器,就可將 Raspberry Pi 拿來當省電的 desktop 使用。

介紹如何在 debian wheezy amd64 上 cross compile Raspberry Pi 執行檔


 以三個方式來編 ffmpeg-dmo 這支程式,比較時間上的差異。

1. 直接在 Raspberry Pi arm 上編譯
2. 在 debian wheezy amd64 上裝上 cross compiler (raspberrypi-tools) 編譯出 arm 上的 binary。
3. 在 debian wheezy amd64 上裝上 cross compiler (raspberrypi-tools) 並加上 distcc,而 Raspberry Pi 上也裝上 distcc,控制自己和其他電腦共同幫忙編譯。

以 ffmpeg-dmo 來當範例,下載原始碼:

$ wget http://ftp.tw.debian.org/debian-multimedia/pool/main/f/ffmpeg-dmo/ffmpeg-dmo_1.0.orig.tar.gz
$ wget http://ftp.tw.debian.org/debian-multimedia/pool/main/f/ffmpeg-dmo/ffmpeg-dmo_1.0-dmo2.diff.gz
$ wget http://ftp.tw.debian.org/debian-multimedia/pool/main/f/ffmpeg-dmo/ffmpeg-dmo_1.0-dmo2.dsc


一、直接在 Raspberry Pi 上編譯:


解開並加上 patch
$ dpkg-source -x ffmpeg-dmo_1.0-dmo2.dsc

$ cd ffmpeg-dmo-1.0

正常程序即可
$ ./configure
$ make -j 8

通常單顆 cpu 是不需要用 -j 8 的,但為了統一,三種編譯方式全部都用 -j 8,減少變數。

在 Raspberry Pi 上,沒超頻,以 700MHz 來編,參數是 -j 8,花了約 153 分鐘完成。



二、於 debian wheezy amd64 裝上 cross compiler 來編譯:


Raspberry Pi 的 cpu 有點慢,所以拿來編譯程式,滿沒有效率的。既然有 desktop 比較快,可以先在 i386 或 x86_64 的 desktop 或 notebook 上將程式編好,再拷貝到 Raspberry Pi 上去執行。

第一步先在 desktop 裝上 raspberrypi-tools。
由於 raspberrypi-tools 是 32bits 的,所以在 debian wheezy amd64 要裝上 32bits 的程式庫。
$ sudo apt-get install libc6-i386 lib32stdc++6 lib32z1

下載 Raspberrypi-tools:
https://github.com/raspberrypi/tools

$ cd /tmp
$ sudo tar zxvf raspberrypi-tools-9c3d7b6.tar.gz
$ sudo mv raspberrypi-tools-9c3d7b6 /opt/cross

裝好後,試試看指令能不能執行
$ /opt/cross/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian/bin/arm-linux-gnueabihf-gcc
arm-linux-gnueabihf-gcc: fatal error: no input files
compilation terminated.

這樣 no input files 就是正常可執行的狀況

-bash: /opt/cross/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian/bin/arm-linux-gnueabihf-gcc: No such file or directory

若出現 No such file or directory 則應該是 32bits 程式庫沒裝好,再用 ldd 檢查一下。

接著拿 hello.c 來測試看看
$ cat > hello.c << EOF
#include
int main() {
printf("Hello, world!\n");
return 0;
}
EOF

會產生一個 hello.c 檔

編看看
$ /opt/cross/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian/bin/arm-linux-gnueabihf-gcc -o hello hello.c
若沒問題會產生一個 hello 執行檔

$ ./hello
-bash: ./hello: cannot execute binary file

$ file hello
hello: ELF 32-bit LSB executable, ARM, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.26, BuildID[sha1]=0x2c11b259c80ffd4ceccb9a2a0622fb12571858f7, not stripped

無法執行,因為是 arm 的執行檔,將 hello 拷貝到 Raspberry Pi 中去執行即可。


接下來編一個比較大的程式,ffmpeg-dmo:

解開並加上 patch
$ dpkg-source -x ffmpeg-dmo_1.0-dmo2.dsc

$ cd ffmpeg-dmo-1.0

加上剛才裝的 raspberrypi-tools 路徑
$ export PATH=/opt/cross/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian/bin:$PATH

配置時指定打開 cross compile,目的平台為 arm,目的 os 為 linux,cross compiler 的前綴字首為 arm-linux-gnueabihf-
$ ./configure --enable-cross-compile --arch=arm --target-os=linux --cross-prefix=arm-linux-gnueabihf-

因為剛才設定 PATH 地方的檔案如下:
$ ls /opt/cross/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian/bin/
arm-linux-gnueabihf-addr2line arm-linux-gnueabihf-gfortran
arm-linux-gnueabihf-ar arm-linux-gnueabihf-gprof
arm-linux-gnueabihf-as arm-linux-gnueabihf-ld
arm-linux-gnueabihf-c++ arm-linux-gnueabihf-ld.bfd
arm-linux-gnueabihf-c++filt arm-linux-gnueabihf-ld.gold
arm-linux-gnueabihf-cpp arm-linux-gnueabihf-ldd
arm-linux-gnueabihf-ct-ng.config arm-linux-gnueabihf-nm
arm-linux-gnueabihf-elfedit arm-linux-gnueabihf-objcopy
arm-linux-gnueabihf-g++ arm-linux-gnueabihf-objdump
arm-linux-gnueabihf-gcc arm-linux-gnueabihf-pkg-config
arm-linux-gnueabihf-gcc-4.7.2 arm-linux-gnueabihf-pkg-config-real
arm-linux-gnueabihf-gcc-ar arm-linux-gnueabihf-ranlib
arm-linux-gnueabihf-gcc-nm arm-linux-gnueabihf-readelf
arm-linux-gnueabihf-gcc-ranlib arm-linux-gnueabihf-size
arm-linux-gnueabihf-gcov arm-linux-gnueabihf-strings
arm-linux-gnueabihf-gdb arm-linux-gnueabihf-strip
arm-linux-gnueabihf-gdbtui

所有執行檔都是以 arm-linux-gnueabihf- 為開頭,後面再加上原本的 gcc 、ar 之類的指令,所以前綴字要設定成 arm-linux-gnueabihf-

configure 完成後,直接 make 即可
$ make -j 8

若是在 configure 沒有指定 --arch,則在 make 時要加參數
$ make ARCH=arm -j 8

這個 ffmpeg-dmo 在我的 hp 6530b core 2 duo 2.26 G 上用 -j 8 來編譯,花了約 30 分鐘完成,這樣比起 Raspberry Pi 來得有效率多了,所以 cross compile 真的滿好用。




三、於 debian wheezy amd64 裝上 cross compiler 並配合 distcc 多台一起來編譯:


到目前為止,不管是 Raspberry Pi 、desktop 或 notebook 都只是在一台機器上編譯,再強的電腦能縮短的時間也是有限,若你剛好有很多台電腦呢?

這時就可配合 distcc 來做多台電腦同時編譯一套程式,預設 distcc 是用在同一平台上編程式,使用很廣泛,如 gentoo、chakra 等等由原始碼編成的 distribution,使用 distcc 就很適合。

但若我們在每台都裝上 cross compiler,就可以用 distcc 來做 cross compile。

我們拿二台來當例子,一台 Raspberry Pi arm (192.168.1.105),另一台 hp6530b x86_64 (192.168.1.123)
在 hp6530b 上剛才已經裝好 arm cross compiler,在二台機器都裝上 distcc


於 hp6530b (amd64 desktop):

$ sudo apt-get install distcc

$ sudo vi /etc/default/distcc
STARTDISTCC="true"
預設 distcc 是不啟動的,要在這裡改成 true 才會啟動

ALLOWEDNETS="192.168.1.105"
允許 192.168.1.105 連過來 (Raspberry Pi)

LISTENER="192.168.1.123"
預設只 listen 127.0.0.1,若要全部介面都能連,設成 0.0.0.0

最後面加上 cross compiler 路徑
PATH=/opt/cross/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian/arm-linux-gnueabihf/bin/:\
/opt/cross/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian/libexec/gcc/arm-linux-gnueabihf/4.7.2:\
${PATH}

儲存後啟動 distcc
$ sudo /etc/init.d/distcc start

防火牆記得打開 tcp port 3632 給 Raspberry Pi (192.168.1.105) 連過來。

觀察 distcc log Raspberry Pi 是否有連過來。

$ sudo tail -f /var/log/distccd.log
distccd[21702] (dcc_job_summary) client: 192.168.1.105:58440 COMPILE_OK exit:0 sig:0 core:0 ret:0 time:2477ms gcc libavutil/mathematics.c
distccd[21817] (dcc_job_summary) client: 192.168.1.105:58442 COMPILE_OK exit:0 sig:0 core:0 ret:0 time:779ms gcc libavutil/time.c

這時還不會有連線過來,等會從 Raspberry Pi 上開始編譯後才會有訊息,若有在動 log 大概長這樣。


於 Raspberry Pi:

在 Raspberry Pi 也裝上 distcc
$ sudo apt-get install distcc

當然可以二台 機器都透過 distccd 去編譯,但由於我們是在 Raspberry Pi 上編的,所以本機不要透過 distccd 而直接編效率會更好,因此,在 Raspberry Pi 上的 distccd 不用啟動,只要安裝好即可。

為了更乾淨些,將剛才的編譯的目錄砍了重新由原始碼解開
$ rm -rf ffmpeg-dmo-1.0

解開並加上 patch
$ dpkg-source -x ffmpeg-dmo_1.0-dmo2.dsc

$ cd ffmpeg-dmo-1.0

設定 /usr/lib/distcc 在路徑最前面,這樣在執行編譯指令時,會呼叫到 distcc 來運作
export PATH=/usr/lib/distcc:$PATH

$ ls -l /usr/lib/distcc/
lrwxrwxrwx 1 root root 16 Oct 25 21:52 c++ -> ../../bin/distcc
lrwxrwxrwx 1 root root 16 Oct 25 21:52 c89-gcc -> ../../bin/distcc
lrwxrwxrwx 1 root root 16 Oct 25 21:52 c99-gcc -> ../../bin/distcc
lrwxrwxrwx 1 root root 16 Oct 25 21:52 cc -> ../../bin/distcc
lrwxrwxrwx 1 root root 16 Oct 25 21:52 g++ -> ../../bin/distcc
lrwxrwxrwx 1 root root 16 Oct 25 21:52 g++-4.7 -> ../../bin/distcc
lrwxrwxrwx 1 root root 16 Oct 25 21:52 gcc -> ../../bin/distcc
lrwxrwxrwx 1 root root 16 Oct 25 21:52 gcc-4.7 -> ../../bin/distcc
lrwxrwxrwx 1 root root 16 Oct 25 21:52 x86_64-linux-gnu-g++ -> ../../bin/distcc
lrwxrwxrwx 1 root root 16 Oct 25 21:52 x86_64-linux-gnu-g++-4.7 -> ../../bin/distcc
lrwxrwxrwx 1 root root 16 Oct 25 21:52 x86_64-linux-gnu-gcc -> ../../bin/distcc
lrwxrwxrwx 1 root root 16 Oct 25 21:52 x86_64-linux-gnu-gcc-4.7 -> ../../bin/distcc

設定在使用 distcc 編譯時,有哪些成員
export DISTCC_HOSTS="192.168.1.123 localhost”


~/.distcc/hosts
192.168.1.123
localhost

注意,localhost 在這裡除了是本機外,還有額外意義的,寫成 localhost 告訴 distcc 直接執行編譯動作,而不要透過 distcc 去和本機的 distccd 溝通,這樣效率會更好些,所以,本機的 distccd 是不用啟動的。

機器列表是有順序的,比較快的電腦放在最前面,由於 Raspberry Pi 比較慢,放在最後面,一般來說,若主控機器 CPU 的效能不到全部機器加總效能的 1/5,最好從列表中拿掉,只讓其他機器編譯就好,由主控台全力做分配及連結的動作,不然會因此而拖垮整體效能。

前面設定完成後,這邊就一如往常的編就好:
$ ./configure
$ make -j 8

這次編 ffmpeg-dmo 透過 distccd 在 Raspberry Pi 及 hp6530b 上用 -j 8 來編譯,花了約 45 分鐘完成,雖然比起單用 6530b 一台編還慢些,但比起在 Raspberry Pi 上直接編要 153 分鐘還是來得有效率。

因為是從 Raspberry Pi 當主控者,而主控者要做的事比較多,除了分配資料給其他機器編譯外,完成的資料要做連結,所以主控者要用最強那台才對。也因為才二台,看不大出來差別,若是拿個 5 台來,相信時間會縮更短的。