本篇出自:虛擬機之家


在 Free Software 的世界中, 除了 Bochs 之外,還有一個以速度號稱的 x86 模擬器 - QEMU。

QEMU 的模擬速度約為實機的 25%; 約為 Bochs 的 60 倍。
Plex86、User-Mode-Linux、VMware 和 Virtual PC 則比 QEMU 快一點,但 Bochs 需要特定的 Kernel Patch;User-Mode-Linux 的 Guest System 必須為 Linux;
VMware 和 Virtual PC 則需要在 Guest System 上安裝特定的 Driver,且它們是針對作業系統而進行模擬,並不能說是完整的模擬器。

所以 QEMU 仍不失為極優秀的 x86 模擬器。

QEMU 所模擬的硬體列表

* i440FX host PCI bridge and PIIX3 PCI to ISA bridge

* Cirrus CLGD 5446 PCI VGA card or dummy VGA card with Bochs VESA extensions (hardware level, including all non standard modes).

* PS/2 mouse and keyboard

* 2 PCI IDE interfaces with hard disk and CD-ROM support

* Floppy disk

* NE2000 PCI network adapters

* Serial port

* Soundblaster 16 card

QEMU 所採用的 PC BIOS 乃取自 Bochs 及 Plex86/Bochs 的 LGPL VGA BIOS。

事前準備

和 Bochs 類似的,在 QEMU 裡,是利用 Image File 來模擬硬碟的;也就是 QEMU 是將一個大大的檔案模擬成一顆硬碟。

我們可以利用 qemu-mkcow 指令來製作這些 Image File,例:

代碼: qemu-mkcow Sarge.cow 2048

這時就會產生一個名為 Sarge.bin 的 COW 檔案。

qemu-mkcow 所產生出來的檔案為取自 User-Mode-Linux 的 Copy On Write (COW) 檔案。 這種檔案的特性是:它只儲存修改過的磁區,所以它是一種會 Growing 的檔案格式。

但它只能存放在 ext2、ext3 之類,有支援 holes 的檔案系統之中。

在使用 ls -l 來檢視 COW 檔案時,
您會發現它的檔案容量就是您所指定的大小;(在上例中,就是 2048 MB) 而只有在使用 ls -ls 來檢視時才會出現它真正所佔用的磁碟空間。

注意:在執行 qemu-mkcow 指令時, 若所指定的檔案已經存在了,或是發生任何問題, qemu-mkcow 幾乎並不會輸出任何的錯誤訊息。使用時請注意。

執行 QEMU

QEMU 並不使用任何的設定檔,它只能以命令列參數來執行; 但是把這些參數寫成一個小小的 script 是輕而易舉的事,所以並不會造成任何的不便。

例: 代碼:
qemu -fda Boot.img -hda Windows95.cow -hdb Source.cow -cdrom CWindows95.iso -boot a -m 64 -enable-audio -localtime -user-net

一般參數(節錄)

-fda file / -fdb file:

指定軟碟機。可在此指定 Image 檔案。

-hda file / -hdb file / -hdc file / -hdd file:

指定硬碟 Image 檔案。請勿指定為光碟 ISO 檔案。

-cdrom file: 指定光碟機。可在此指定 ISO 檔案。它將固定使用 hdc 這個位置,

所以 -hdc 不能和 -cdrom 同時使用。

-boot [a|c|d]:

指定開機磁碟。a 為 floppy,c 為硬碟,d 為 CD-ROM。

-m megs:

指定記憶體大小;單位為 MB。預設為 128 MB。

-enable-audio:

啟用音效卡。預設是關閉的。

-localtime:

使用真實時間。建議使用於 MS Windows / DOS 系統。預設上是使用 UTC 時間。

網路設定參數(節錄)

在 QEMU 裡,有三種網路模式可供選擇:

TUN/TAP 模式(預設模式)

在 Linux 系統中,使用 TUN/TAP 介面來模擬網路界面是很標準的做法。

若要使用 TUN/TAP 介面,請切換至 /dev 目錄中,執行 代碼:
MAKEDEV tun 來建立 tun 之裝置檔。之後,在執行 QEMU 時,QEMU 便會自行載入 tun 模組並產生一個名為 tun0 的網路介面;之後 Guest System 便能夠藉由這個 tun0 介面和外部連線了。

請參考以下這個 script 來設定 TUN/TAP 介面: (請將 192.168.1.254 替換成一個空的 IP 位址。這個位址將由 tun 介面所使用。) (請將 192.168.1.101 替換成一個空的 IP 位址。這個位址將由 Guest System 使用。)
代碼:
#!/bin/bash
/sbin/ifconfig ${1##/*/} 192.168.1.254
route add -host 192.168.1.101 dev ${1##/*/}

這樣子在 QEMU 啟動時,就會將 tun 裝置設定為 192.168.1.254 了。由於執行這個 Scrip 需要 root 之權限, 所以必須具有 root 身份才能正常啟用這個模式的。且 tun 裝置的 IP 位置和 Guest System 的 IP 位址是寫死在 script 裡的, 所以在使用上並不是很方便。

藉由 TUN/TAP 介面來和網路連線。必須採用固定 IP,但 IP 可以隨意指定;Guest System 可以連線出去,Host OS 也可以和 Guest System 連線, 但外部網路的其它電腦則完全無法連線進來。User-Nat 模式 使用 User Mode Network Stack 來模擬網路界面。Guest System 必須採用 DHCP,且一定會得到 10.0.2.x 的IP,同時,Gateway 會指向 10.0.2.2,DNS 則指向 10.0.2.2。

Guest System 可以連線出去,但 Host OS 和外部網路的其它電腦則完全無法連線進來。

由於 User Mode Network Stack 無法完全支援 ping 指令,所以 Guest System 只能 Ping 到 Host OS,無法 ping 到外部網路的其它電腦。

Dummy Net 模式

並不實地得進行任何網路連線。 網路介面的命令例參數(節錄)

-nics n:

模擬幾個網路介面。預設為 1 個,最多為 6 個。

-n script:

設定 TUN/TAP 網路連線的 script;預設為使用 /etc/qemu-ifup。

-user-net:

使用 User Mode Network Stack。
若未指定或找不到 TUN/TAP 的 script 時,則會採用這個模式。

-dummy-net:

使用虛擬的網路介面。這個網路介面將不會傳送接收任的網路連線。

除錯 / 進階選項(節錄)

-S:

在啟動時暫停 CPU 之運作。使用 c 來繼續執行。

-d item1,...

將 LOG 輸出至 /tmp/qemu.log 中。
使用 -d ? 來查看會產生 LOG 的項目之列表。

-isa:

模擬一個純 ISA 系統;預設上則是模擬成 PCI 系統。

-std-vga:

將顯示卡模擬成一個同時包含了 VESA Bochs 擴充的標準 VGA 卡。
預設則模擬為 CL-GD5446 PCI 顯示卡。

QEMU Monitor(節錄)

在執行 QEMU 後,會出現一個
代碼: (qemu) 的提示。在這個提示下可以輸入一些指令來操作 QEMU。例:
help 或 ? [cmd]

顯示說明文字

info 指令:

顯示系統狀態。例:

★ info network,顯示網路介面狀態

★ info block,顯示儲存裝置狀態

★ info registers,顯示 CPU 的暫存器狀態

★ info history,顯示歷史指令

q 或 quit:

關閉模擬器

eject [-f] device:

退出裝置。使用 -f 來強制退出

change device filename:

更換抽取式媒體。如:軟碟片或是光碟片。

screendump filename:

截取螢幕畫面,儲存成 PPM 影像。

log item1[,...]

將所指定的項目之 LOG 寫入 /tmp/qemu.log 中。

savevm filename:

將整個模擬器狀態儲存至檔案中

loadvm filename:

由檔案中載入模擬器狀態

stop

停止模擬

c 或 cont

繼續模擬

sendkey keys

傳送某個鍵擊給模擬器。使用 - 來連結複合鍵。例:

代碼:
sendkey ctrl-alt-f1

將會傳送 <Ctrl><Alt><F1> 給模擬器。

system_reset

重新啟動系統。

快捷鍵

在 QEMU 的系統裡,可以按下 <Ctrl><Shift> 來跳離 QEMU;
按下 <Ctrl><Shift><f> 來進入全螢幕的畫面。

網路介面解決方案

使用 sudo 來執行 QEMU

如果要使用 TUN/TAP 介面,必須以 root 身份來設定 TUN/TAP 介面才行。

所以建議採用 sudo 的方式執行 QEMU。

☆ 以 root 或是 SUID 或 sudo 來執行任何程式都是大風險,
尤其是使用者可以自行設定 QEMU 呼叫某一個 script 來設定網路, 若 QEMU 以 SUID/sudo 來執行的話,將可能引起極嚴重之安全問題。

* 安裝 sudo 套件。

* 以 visudo 來建立 sudo 的設定檔,並設定不用輸入密碼即可執行 QEMU: (其中的 UserName 和 HostName 請替換成您的系統設定,或設定為 ALL。)
代碼:
Cmnd_Alias QEMU=/usr/bin/qemu
UserName HostName=NOPASSWD: QEMU

* 編輯 .bashrc,讓 qemu 能預設以 sudo qemu 來執行:
代碼:
alias qemu='sudo qemu'

* 執行 qemu,並以 ps aux | grep bochs 來確認 qemu 是否以 root 的身份執行?

讓 TUN/TAP 介面可以和實體網路連線

若依前文所提的方式來設定 TUN/TAP 介面,
則 Guest System 則只能使用固定 IP、
且除了 Host OS 之外,外部網路的其它電腦會完全無法連線至 Guest System。

這種做法並非十全十美。

解決方案之一是將 TUN/TAP 介面和實體網路給 Bind 在一起, 也就是將數個實體網路介面合成一個 Bridge 介面:

設定 Bridge 介面

* 安裝 bridge-utils 套件

* 在 /etc/network/interfaces 加入一段:(在此假設是使用 DHCP 來設定網路的)代碼:
iface bridge inet dhcp

其中的 bridge 名稱可以自訂。

這樣子我們在日後就可以用 ifup、ifdown、ifconfig 等指令來直接操作 bridge 這個介面了。
當然囉,使用 ifconfig、route、dhclient 等指令來手動操作當然也可以;這就全憑個人喜好了。

* 這數個要 Bind 在一起的實體網路介面之 IP 必須為 0.0.0.0,並啟用 promisc 模式:

代碼:
ifconfig eth0 0.0.0.0 promisc up

* 宣告一個名為 bridge 介面的『Bridge';並設定其動作模式:
代碼:
# 建立一個名為 bridge 的 Bridge 介面
brctl addbr bridge
# 轉送延遲時間,Bridge 切換至 listening 及 learning 狀態所需時間。
# Bridge 會花一點時間來記錄每個實體介面的 MAC Address。
brctl setfd bridge 0
# 傳送 STP Hello 封包的頻率。設定為 0 因為我們不使用 STP 這個功能。
brctl sethello bridge 0
# 關閉 spanning tree protocol 功能。用不著...
brctl stp bridge off

* 此時,可以使用 ifconfig -a 來檢視是否出現了 bridge 這個介面。

* 將 eth0 給 Bind 至 bridge 上:
代碼:
brctl addif bridge eth0

* 啟用 bridge 介面:

如果在 /etc/network/interfaces 已設定了 bridge 資訊的話:

ifup bridge

若 bridge 使用 DHCP:

dhclient bridge

手動設定 bridge 參數:

ifconfig bridge 192.168.1.1 netmask 255.255.255.0 up
route add default gw 192.168.1.254

* 檢視 Bridge 的狀況:
代碼:
brctl show

* 由於將數個介面合成了一個 bridge 介面, 而像是 iptables、pppoe 等等設定也必須視情況而有所變更。 而如何設定 iptables 就超過了本篇的範圍之外,在此就略過不加討論了。

關閉 bridge 的方式

* 關閉 bridge 介面:
代碼:
ifdown bridge
ifconfig bridge down

* 解除 Bind 在 bridge 上的 eth0:
代碼:
brctl delif bridge eth0

* 移去 bridge 介面:
代碼:
brctl delbr bridge

* 啟用 eth0:(如果在 /etc/network/interfaces 已設定了 eth0 資訊的話)
代碼:
ifup eth0

這時,eth0 應該就恢後原有的狀態了。

將以上步驟寫成 /etc/init.d/bridge:
代碼:
#!/bin/sh

PATH=/usr/local/sbin:/sbin:/usr/sbin:/usr/local/bin:/bin:/usr/bin

if [ "$(id -u)" != "0" ]; then
echo "$0: To $1 Bridge, you must be root."
exit 1
fi

# Default settings
bridge_interface='bridge'
bind_ethernet='eth0'

case "$1" in
start)
printf "Starting Bridge ... "
ifdown $bind_ethernet
ifconfig $bind_ethernet down
ifconfig $bind_ethernet 0.0.0.0 promisc up
brctl addbr $bridge_interface
brctl setfd $bridge_interface 0
brctl sethello $bridge_interface 0
brctl stp $bridge_interface off
brctl addif $bridge_interface $bind_ethernet
ifup $bridge_interface
echo ""
brctl show
echo ""
;;
stop)
ifdown $bridge_interface
ifconfig $bridge_interface down
brctl delif $bridge_interface $bind_ethernet
brctl delbr $bridge_interface
ifup $bind_ethernet
;;
restart|reload)
$0 stop && $0 start
;;
*)
echo "Usage: $0 {start|stop|restart}"
exit 1
;;
esac

您可以考慮讓這個 script 在開機時自動執行:(在此時設定其啟動編號為 13)

代碼:
update-rc.d bridge start 13 0 2 3 4 5 6 .

這樣就可以在開機時就自動產生 bridge 這個介面囉。

設定 TUN/TAP 介面的 script

而 QEMU 設定 TUN/TAP 介面的 script 也要改成:(建議寫入 /etc/qemu-ifup 中)
代碼:
#!/bin/bash

ifconfig ${1##/*/} 0.0.0.0 promisc up
brctl addif bridge ${1##/*/}

這樣子,只要 QEMU 一啟動,在 QEMU 裡的 Guest System 就可以傳送接收 DHCP、Windows Login 等封包,外部網路的其它電腦也可以自由連線至 Guest System 了。

小技巧

如果在無線網路卡上啟動 Bridge 可能會遭遇到困難, 這時您可以在啟動 Bridge 之前先啟動無線網路卡, 很可能可以解決這個困擾哦!

另外,因為 Bridge 介面很可能會用到 iptbale 裡的 ipt_physdev 模組。
請自行參考 iptables 之說明。

而這個方式也適用於 User-Mode-Linux 及 Bochs 等等用得到 TUN/TAP 介面的程式哦!

設定 Guest System 小技巧

MS Windows 95/98/Me

在 QEMU 裡執行 MS Windows 95/98 時,將使得 CPU 的 Loading 永遠維持在 100%。 您可以到 AMN Software 下載並安裝 Amn Task Manager 來解決這個問題。

另外,Windows 95/98/ME 在安裝完成後, 在該顯示遊標的地方只會出現一個大大的白色方塊。(可能是一個 Bug...),所以建議使用 -std-vga 參數來暫時避開這個問題。

MS Windows 2000

可能暫時無法在 QEMU 裡安裝。會出現『磁碟空間不足』之錯誤訊息。

GNU/Linux

在安裝時,不管是 Woody 或是 Sarge 都能夠自動驅動 QEMU 所模擬的 NE2000 PCI 網路卡。

若想使用 X Window,顯示卡模組請採用 vesa 或是 cirrus 模組;色深建議採用 16 bit。

若想使用 Kernel 2.6.x,
因為 Kernel 2.6.x 會精確得檢查電腦硬體時鍾的時間,而這是 QEMU 無法模擬的。請在開機時加上 clock=pit 參數來避開這個問題。

創作者介紹

胖虎的祕密基地

idobest 發表在 痞客邦 PIXNET 留言(0) 人氣()