使用 Virtual Box Headless 跑 Virtual Machine

VirtualBox 是 Sun (後來被 Oracle 買下) 開發的一套虛擬化軟體。他的 Host OS 可以是 Windows, Linux, MacOS, FreeBSD。除此之外,VirtualBox 可以在 Terminal 下執行,顯示的畫面由 RDP/VNC 輸出,亦即 Headless 模式。要特別注意的是,RDP 輸出僅限於專屬授權版本,OSE (Open Source Edition) 版本是沒有這個功能的。

要使用 VNC 輸出,必須在安裝的時候加入 VNC 支援:

# cd /usr/ports/emulators/virtualbox-ose; make WITH_VNC=yes all install clean

安裝好 VirtualBox 之後,必須再安裝 kernel module:

# cd /usr/ports/emulators/virtualbox-ose-kmod; make install clean

接著把需要的 Kernel Module 載進來:

# kldload vboxdrv; kldload vboxnetadp; kldload vboxnetflt

之前寫在 /boot/loader.conf 會導致開機時 Kernel Panic,但如果開完機手動載入就不會,目前還沒找出原因。

接下來新增一個 Virtual Machine:(以下都可以不需要 root 權限)

% VBoxManage createvm winxp --register

然後設定 VM 的資源需求:

% VBoxManage modifyvm winxp --acpi on --ioapic on --memory 1024 --cpus 2 --nic1 bridged --nictype 82540EM --bridgeadapter1 em1

以上的範例分配了 1024MB (1GB) 的 RAM 與 2 個 Virtual CPU 給 winxp 這個 VM,另外建立了一張虛擬網卡,型號為 Intel 82540EM,橋接到實體的 em1 這張網卡上。

再來建立一個新的 120GB 虛擬硬碟:

% VBoxManage createhd --filename winxp --size 122880

在 VM 裡增加一個 IDE Controller:

% VBoxManage storagectl winxp --name "IDE Controller" --add ide

把硬碟與安裝 ISO 檔連接到 IDE Controller:

% VBoxManage storageattach winxp --storagectl "IDE Controller" --port 0 --device 0 --type hdd --medium winxp
% VBoxManage storageattachwinxp --storagectl "IDE Controller" --port 1 --device 0 --type dvddrive --medium winxp.iso

接著就可以開機了:

% VBoxHeadless -s winxp --vnc --vncport 5900 --vncpass password

執行成功後,可以用 VNC 連入看到安裝 Windows XP 的畫面:

關機、重開機可以使用 VBoxManage 來完成:

% VBoxManage controlvm winxp poweroff

Python 的 GIL (Global Interpreter Lock)

前幾個月在做專案的時候,發現用 mod_wsgi + web.py 寫的程式,理論上支援 multi-thread,應該可以完全利用在多核 CPU Server 的優勢;但實際上跑的時候,會有沒辦法把 CPU Resource 吃完的問題。當時因為時間很趕,想到的解法就是多跑幾個 Process:

<VirtualHost *:80> 
   DocumentRoot “/srv/web/webroot" 
   ServerName python.example.com 
   WSGIProcessGroup pythonexample 
   WSGIDaemonProcess pythonexample processes=16 threads=128 maximum-requests=1024 display-name=%{GROUP}
</VirtualHost>

COSCUPlwhsu 聊到這件事,他講到 CPython 的 GIL,回來查了一下果然就是這個原因。剛好 Web 不需要在每個 thread 之間互相傳資料,所以可以直接用多個 Process 解掉這個問題。

雖然 Python 在執行前就把程式碼轉成 byte code了,但因為這個 Lock 是實做在 CPython 的 Bytecode Interpreter 裡面,所以導致了同時只會有一個 thread 執行 Python bytecode,也因此無法利用到多核 CPU 的優勢 ((Stackoverflow: Python threading and gil))。

除了多跑幾個 Process 之外,也可以用 ctypes 配合用 C 寫的 library 來解決這個問題,不過以 Web 應用來說,寫 C 的機會不高就是了。