前言
前一段時間因為工作需要,我對ARM模擬器進(jìn)行了一番調(diào)研。調(diào)研目的是:由于項目參與人員比較多,如果人手一塊ARM開發(fā)板,資源比較緊張,希望能夠用模擬器來代替。
在調(diào)研期間,花費了很多時間去查資料、測試驗證。在實際驗證的時候,發(fā)現(xiàn)一個現(xiàn)象:很多文章雖然給出了或簡單、或詳細(xì)的操作步驟,但是大部分都沒有寫清楚操作的背景、各個軟件的版本,這就導(dǎo)致需要把整個文章看完了、把所有的操作步驟都做了一遍,才明白作者想表達(dá)的是什么意思,操作的目的是什么。
我覺得,任何一篇文章,首先要讓讀者知道為什么要讀這篇文章,或者說讀了這篇文章能夠有什么收獲。
如果是操作性比較強的文章,那么就有必要交代清楚工作平臺的背景是什么,要達(dá)到的目的是什么,總體步驟是怎么樣的。只有這樣,閱讀文章的人在心中首先建立一個宏觀的框架,在理解框架的基礎(chǔ)上,再去實際操作,這樣的話就更容易理解。
當(dāng)然了,每個人的學(xué)習(xí)和閱讀習(xí)慣都不一樣,上面只是我個人的感受,或者說我喜歡這樣比較有條理的文章,這樣才不至于迷茫。
回到Qemu的主題上來,這篇文章主要是把調(diào)研的結(jié)果進(jìn)行梳理、匯總,包括如下內(nèi)容:
為什么需要ARM模擬系統(tǒng)?
Qemu是什么?
Qemu 能做什么?或者說適合做什么?
在 Ubuntu16.04 系統(tǒng)中,利用 Qemu 搭建一個ARM虛擬機操作步驟是什么?
編寫一個HelloWorld程序,放到虛擬機中執(zhí)行。
為什么需要ARM模擬系統(tǒng)
ARM平臺的軟件開發(fā)工作,可以劃分為2類:
應(yīng)用程序的開發(fā)
系統(tǒng)開發(fā)(內(nèi)核、文件系統(tǒng)、驅(qū)動程序)
應(yīng)用程序的開發(fā)
我們在開發(fā)嵌入式項目的時候,一般都是先在x86平臺上把大部分的功能開發(fā)完成,然后再交叉編譯,得到在ARM平臺的可執(zhí)行程序或者庫文件。再通過scp指令或者NFS遠(yuǎn)程掛載的方式,把這些文件復(fù)制到ARM板子上之后執(zhí)行。
一般而言,應(yīng)用程序就是利用硬件產(chǎn)品的各種資源、外設(shè),來完成特定的功能,比如:數(shù)據(jù)采集、控制外部設(shè)備、網(wǎng)絡(luò)傳輸?shù)鹊取V饕奶卣骶褪桥c外部的各種設(shè)備進(jìn)行交互。
系統(tǒng)開發(fā)(BSP)
系統(tǒng)開發(fā)的最終目的是:為應(yīng)用程序的執(zhí)行準(zhǔn)備一個基本的執(zhí)行環(huán)境,內(nèi)容包括:系統(tǒng)引導(dǎo)程序bootloader,內(nèi)核kernel,文件系統(tǒng)rootfs,系統(tǒng)中所有設(shè)備的驅(qū)動程序。在實際的項目開發(fā)中,系統(tǒng)開發(fā)難度更大一些,一旦開發(fā)完成,對于一塊板子來說基本上不會輕易變動,代碼的使用生命周期更長。
以上這兩種分類,主要是從開發(fā)工作的內(nèi)容角度來進(jìn)行劃分的。可以看出:
應(yīng)用程序開發(fā):靈活性更大、需求變動會更多(產(chǎn)品經(jīng)理或項目經(jīng)理經(jīng)常給你改需求)。
系統(tǒng)軟件開發(fā):需求更穩(wěn)定、很多代碼都是官方提供或者開源的,工作內(nèi)容就是進(jìn)行定制、裁剪。
對于系統(tǒng)軟件開發(fā)來說,如果每次編譯出一個bootloader、或者kernel,都上一個ARM開發(fā)板進(jìn)行驗證,的確比較麻煩。如果能有一個ARM模擬系統(tǒng),直接在x86上進(jìn)行模擬,工作效率就會提高很多。
Qemu是什么?
Qemu是一個開源的托管虛擬機,通過純軟件來實現(xiàn)虛擬化模擬器,幾乎可以模擬任何硬件設(shè)備。比如:Qemu可以模擬出一個ARM系統(tǒng)中的:CPU、內(nèi)存、IO設(shè)備等,然后在這個模擬層之上,可以跑一臺ARM虛擬機,這個ARM虛擬機認(rèn)為自己在和硬件進(jìn)行打交道,但實際上這些硬件都是Qemu模擬出來的。

正因為Qemu是純軟件實現(xiàn)的,所有的指令都要經(jīng)過它的轉(zhuǎn)換,所以性能非常低。所以在生產(chǎn)環(huán)境中,大多數(shù)的做法都是配合KVM來完成虛擬化工作,因為KVM是硬件輔助的虛擬化技術(shù),主要負(fù)責(zé)比較繁瑣的CPU和內(nèi)存虛擬化,而Qemu則負(fù)責(zé)I/O虛擬化,兩者合作各自發(fā)揮自身的優(yōu)勢,相得益彰。這部分不是重點,就不具體深入介紹了。
Qemu的兩種模式
Qemu有兩種執(zhí)行模式:
- 用戶模式(User mode):利用動態(tài)代碼翻譯機制來執(zhí)行不同主機架構(gòu)的代碼,例如:在x86平臺上模擬執(zhí)行ARM代碼,也就是說:我們寫一條ARM指令,傳入整個模擬器中,模擬器會把整個指令翻譯成x86平臺的指令,然后在x86的CPU中執(zhí)行。

- 系統(tǒng)模式(System mode):模擬整個電腦系統(tǒng),利用其它VMM(Xen, KVM)來使用硬件提供的虛擬化支持,創(chuàng)建接近于主機性能的全功能虛擬機。

Qemu 能做什么?或者說適合做什么?
因為Qemu是使用純軟件模擬的,它的強項是模擬那些不涉及到外部的具體硬件設(shè)備的場景,比如:
想學(xué)習(xí)如何定制bootloader;
想在Arm系統(tǒng)中進(jìn)行文件系統(tǒng)的裁剪,學(xué)習(xí)文件系統(tǒng)的掛載過程;
想體驗一下如何配置、裁剪linux kernel;想學(xué)習(xí)Linux系統(tǒng)中的設(shè)備樹;
...
以上這些場景中,都非常適合使用Qemu來模擬ARM系統(tǒng)。
在 Ubuntu16.04 系統(tǒng)中,利用 Qemu 搭建一個ARM虛擬機
使用Qemu虛擬機的幾種選擇
利用Qemu來運行ARM虛擬機,你有2個選擇:
- 簡單方式:直接下載別人編譯好的映像文件(包含了內(nèi)核,根文件系統(tǒng)),直接執(zhí)行即可。
缺點是:別人編譯好的也許不適合你的需求,沒法定制。- 復(fù)雜方式:自己下載內(nèi)核代碼、根文件系統(tǒng)代碼(例如:busybox),然后進(jìn)行編譯。
優(yōu)點是:可以按照自己的實際需求,對內(nèi)核、根文件系統(tǒng)機型裁剪。
在第2種復(fù)雜模式中,又可以有2個選擇:
2-1. 內(nèi)核代碼、根文件系統(tǒng)代碼全部自己手動編譯,最后把這些編譯結(jié)果手動組織在一個文件夾中,形成自己的根目錄;
2-2. 利用 buildroot 整個框架,只需要手動進(jìn)行配置(比如:交叉編譯器在本機上的位置、輸出路徑、系統(tǒng)的裁剪),然后就可以一鍵編譯出一個完整的系統(tǒng),可以直接燒寫到機器!
以上這幾種操作方式的選擇,可以根據(jù)自己的實際需要來選擇。如果對構(gòu)建系統(tǒng)的整個流程已經(jīng)非常熟悉了,就利用buildroot工具;如果是想更徹底的學(xué)習(xí)制作一個系統(tǒng),那就手動一步一步的實際編譯、操作一遍,多練幾次,你就變成大牛了。
下面,我們就按照2-2的方式,進(jìn)行實際操作一遍。所有的指令部分,我都直接貼代碼,不用截圖,這樣方便復(fù)制。
測試平臺
我的工作電腦是Win10,通過VirtualBox安裝了Ubuntu16.04虛擬機,64位系統(tǒng)。
下面的操作在Ubuntu16.04虛擬機中可以順利編譯,當(dāng)然,一些基本的工具(例如:build-essential, make等基礎(chǔ)工具軟件這里就不詳述了)。
安裝交叉編譯器
交叉編譯器的作用就不需要詳細(xì)解釋了,因為我們是在x86平臺上進(jìn)行編譯,而運行的平臺是ARM系統(tǒng),這2個平臺的指令集不一樣,所以需要交叉編譯得到ARM系統(tǒng)上可以執(zhí)行的程序。
sudo apt-get install gcc-arm-linux-gnueabi
驗證安裝結(jié)果
dpkg -l gcc-arm-linux-gnueabi
顯示如下:

有些文章建議自己下載交叉編譯器,然后手動設(shè)置環(huán)境變量。我實際操作了一下,手動下載的交叉編譯工具鏈在編譯內(nèi)核的時候報錯,所以還是建議直接用apt-get直接安裝。
編譯內(nèi)核kernel
內(nèi)核kernel的作用也是不言而喻的,就相當(dāng)于我們的Windows操作系統(tǒng),沒有這個操作系統(tǒng),硬件就是一堆廢鐵。當(dāng)系統(tǒng)啟動的時候,會把內(nèi)核加載到內(nèi)存中,然后從內(nèi)核的入口地址開始執(zhí)行。
-
下載內(nèi)核版本:linux-4.14.212.tar。在文末,我會列出所有的軟件包下載地址。
-
使用現(xiàn)成的vexpress開發(fā)板子的config文件
make CROSS_COMPILE=arm-linux-gnueabi- ARCH=arm vexpress_defconfig
這個操作,會把vexpress_defconfig作為配置文件保存為.config,下面在編譯內(nèi)核時就根據(jù)這個config中的配置進(jìn)行編譯。
如果需要對內(nèi)核進(jìn)行裁剪,執(zhí)行:
make menuconfig
根據(jù)自己的實際需要,對內(nèi)核進(jìn)行定制。比如:可以配置網(wǎng)絡(luò)和NFS,在系統(tǒng)啟動的時候就自動掛載宿主機中的某個目錄。
- 編譯內(nèi)核
make CROSS_COMPILE=arm-linux-gnueabi- ARCH=arm
編譯得到內(nèi)核文件arch/arm/boot/zImage,Qemu啟動時需要指定使用這個映像文件。
制作根文件系統(tǒng)
內(nèi)核在啟動之后、執(zhí)行到最后步驟時,需要掛載根文件系統(tǒng),然后執(zhí)行文件系統(tǒng)中指定的執(zhí)行程序,例如:/etc/rc.local。
如果沒有跟文件系統(tǒng),那么內(nèi)核在執(zhí)行到最后就提示:panic...。
-
下載busybox
版本:busybox-1.20.2.tar.bz2。
-
創(chuàng)建rootfs根目錄
mkdir -p rootfs/{dev,etc/init.d,lib}
- 把busybox-1.20.2中的文件復(fù)制到rootfs根目錄下,主要是一些基本的命令
cp busybox-1.20.2/_install/* -r rootfs/
- 把交叉編譯工具鏈中的庫文件復(fù)制到rootfs根目錄的lib文件夾下
sudo cp -P /usr/arm-linux-gnueabi/lib/* rootfs/lib/
- 制作根文件系統(tǒng)鏡像根文件系統(tǒng)鏡像就相當(dāng)于一個硬盤,就是把上面rootfs根目錄中的所有文件復(fù)制到這個硬盤中。
(1) 生成512M大小的磁盤鏡像
qemu-img create -f raw disk.img 512M
(2) 把磁盤鏡像格式化成ext4文件系統(tǒng)
mkfs -t ext4 ./disk.img
(3) 將rootfs根目錄中的所有文件復(fù)制到磁盤鏡像中操作步驟是:創(chuàng)建掛載點-掛載-復(fù)制文件-卸載。
mkdir tmpfs
sudo mount -o loop ./disk.img tmpfs/
sudo cp -r rootfs/* tmpfs/
sudo umount tmpfs
(4) 使用file指令檢查一下
file disk.img

利用Qemu啟動ARM虛擬機
1.啟動虛擬機
這個命令有點長,測試時建議直接復(fù)制、粘貼。
qemu-system-arm -M vexpress-a9 -m 512M -kernel ./linux-4.14.212/arch/arm/boot/zImage -dtb ./linux-4.14.212/arch/arm/boot/dts/vexpress-v2p-ca9.dtb -nographic -append "root=/dev/mmcblk0 rw console=ttyAMA0" -sd disk.img
2.停止虛擬機在Ubuntu另一個終端窗口中,通過killall指令來停止。
killall qemu-system-arm
當(dāng)然,也可以用ps指令找到qemu-system-arm的進(jìn)程號,然后通過kill -9來停止虛擬機。
測試HelloWorld應(yīng)用程序
- 在Ubuntu任意一個目錄,編寫HelloWorld可執(zhí)行程序hello.c:
int main()
{
printf("HelloWorld!
");
return 0;
}
- 交叉編譯hello.c,得到可執(zhí)行程序hello:
arm-linux-gnueabi-gcc hello.c -o hello
通過file指令,查看一下hello程序:
file hello

-
通過kill命令停止虛擬機。
-
把hello可執(zhí)行程序復(fù)制到磁盤鏡像disk.img中操作步驟是:掛載-復(fù)制文件-卸載。
sudo mount -o loop ./disk.img tmpfs/
cp hello tmpfs/
sudo umount tmpfs
- 執(zhí)行hello程序再次啟動虛擬機,此時可以在根目錄下面看到hello文件,直接執(zhí)行即可看到輸出結(jié)果。
總結(jié)
在以上的操作步驟中,我們把一個ARM系統(tǒng)在啟動應(yīng)用程序之前,所需要的程序都手動編譯、操作了一遍。看一遍很容易就明白,親手操作一遍印象會更深刻。
這里的操作過程有些還需要繼續(xù)深入,比如:在系統(tǒng)啟動之后,自動掛載宿主機(Ubuntu系統(tǒng))中的某個文件夾,這樣就可以把hello等可執(zhí)行程序復(fù)制到掛載目錄中,然后在ARM系統(tǒng)中直接執(zhí)行了,而不用再執(zhí)行下面在一連串的操作(停止虛擬機-掛載磁盤鏡像-復(fù)制文件-卸載-啟動虛擬機)。
最后,希望這篇總結(jié)能給你帶來小小的收獲和提升!
軟件下載地址
1. linux-4.14.212.tar.xz
鏈接:https://pan.baidu.com/s/1d8RxjMkYQhPtbZgiybD8Gw
提取碼:b6ft。
2. busybox-1.20.2.tar.bz2
鏈接:https://pan.baidu.com/s/1oPeH7juEWuFR6y1Qpna_BA
提取碼:9kh6
審核編輯 :李倩
-
ARM
+關(guān)注
關(guān)注
134文章
9310瀏覽量
375125 -
應(yīng)用程序
+關(guān)注
關(guān)注
38文章
3322瀏覽量
58747 -
qemu
+關(guān)注
關(guān)注
0文章
57瀏覽量
5628
原文標(biāo)題:一步步教你:在x86平臺,如何用Qemu來模擬ARM系統(tǒng)
文章出處:【微信號:zhuyandz,微信公眾號:FPGA之家】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。
發(fā)布評論請先 登錄
聚徽廠家視角——X86 架構(gòu) vs. ARM 架構(gòu):工控一體機的算力、功耗與成本差異解析
龍芯處理器支持WINDOWS嗎?
ARM與x86:架構(gòu)對比及其應(yīng)用

Arm主板與x86主板的區(qū)別

KiCon演講回顧(八):KiCAD 賦能 x86 系統(tǒng)擴展板

英特爾和AMD組建x86生態(tài)系統(tǒng)咨詢小組
英特爾將攜手AMD共同捍衛(wèi)x86生態(tài)
ARM 架構(gòu)工控機與 X86 架構(gòu)工控機:差異究竟在哪?

就服務(wù)器而言,ARM架構(gòu)與X86架構(gòu)有什么區(qū)別?各自的優(yōu)勢在哪里?
樹莓派是x86還是arm
X86架構(gòu)處理器有哪些優(yōu)點和缺點
X86架構(gòu)和ARM架構(gòu)有什么區(qū)別
鴻道Intewell工業(yè)操作系統(tǒng)ARM平臺生態(tài):飛騰E2000Q

探索RISC-V二進(jìn)制翻譯,openKylin成功在SG2042平臺運行X86架構(gòu)軟件!

ElfBoard技術(shù)貼|如何將libwebsockets庫編譯為x86架構(gòu)

評論