QEMU 模拟器(一)
安裝
安裝 比較簡單, 有幾種方案.
- 遠(yuǎn)程倉庫安裝
- 官網(wǎng)下載可執(zhí)行文件(Windows 平臺適用)
- 通過源碼自己編譯
可只裝指定平臺, 如 ARM: sudo apt-get install qemu-system-arm
u-boot 仿真
下載 uboot 源碼 這里以版本u-boot-2018.09.tar.bz2 為例
- -M 指定了主板類型, 和上面編譯的 uboot 主板參數(shù)一致
- -m 表示主板的 DRAM 大小
- -kernel 后面的可執(zhí)行文件會被QEMU直接加載到內(nèi)存并執(zhí)行, 這里等效于 -device loader,file=u-boot,cpu-num=0
- -nographic 表示不啟動(dòng)圖形界面
[注]: 先按 Ctrl-A 進(jìn)入QEMU的功能選擇模式, 然后按 x 退出.
[提示]: Ctrl-A 后按 ? 可查看有哪些功能選項(xiàng).
Linux kernel 仿真
下載 kernel 源碼, 這里以5.17版本為例
在 kernel 根目錄執(zhí)行
export ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- # 設(shè)置編譯平臺和工具鏈 make vexpress_defconfig # 加載板子的配置信息 make zImage dtbs -j8 # 編譯目標(biāo)在新版內(nèi)核中,需要給內(nèi)核生成對應(yīng)的 dtb,因此目標(biāo) dtbs 是需要的
編譯后在 arch/arm/boot 生成 zImage, 在 arch/arm/boot/dts 生成 vexpress-v2p-ca9.dtb 可將它們拷貝出來使用, 后面將默認(rèn)它們已經(jīng)拷貝出來放在同一路徑了
直接加載內(nèi)核到QEMU
load.sh 文件:
- -dtb 告訴QEMU將文件用作設(shè)備樹二進(jìn)制(DTB)映像,并在引導(dǎo)時(shí)將其傳遞給內(nèi)核。
執(zhí)行上面腳本后, QEMU將運(yùn)行Linux內(nèi)核鏡像, 內(nèi)核顯示許多引導(dǎo)消息,然后它將報(bào)告: not syncing: VFS, 表示沒有找到根文件系統(tǒng)
制作簡單的根文件系統(tǒng), 并在內(nèi)核初始化時(shí)執(zhí)行 Hello World 程序
hello.c
編譯 hello 程序
arm-linux-gnueabi-gcc -static hello.c -o hello- -static 表示靜態(tài)編譯, 靜態(tài)編譯會將所有庫都鏈接在一個(gè)二進(jìn)制文件中
[注] 引入無限循環(huán)是因?yàn)楫?dāng)Linux執(zhí)行根文件系統(tǒng)中的第一個(gè)程序時(shí),它預(yù)計(jì)該程序不會退出
制作基于內(nèi)存的初始根文件系統(tǒng) (initramfs), 參考
Linux 支持把一段內(nèi)存用來充當(dāng)臨時(shí)的文件系統(tǒng), 這樣做是因?yàn)樵趦?nèi)核啟動(dòng)完成后很可能硬盤等設(shè)備并未初始化完成, 將內(nèi)存作為臨時(shí)根文件系統(tǒng), 并在該根文件系統(tǒng)下執(zhí)行用戶程序, 由用戶程序來完成初始化工作并掛載在硬盤上的真正的根文件系統(tǒng)
我們使用cpio工具創(chuàng)建一個(gè)簡單的文件系統(tǒng):
echo hello | cpio -o --format=newc > rootfscpio 工具輸入一個(gè)文件列表, 輸出一個(gè)文件. 這里指明輸出的文件格式是 newc, 它是 initramfs 文件系統(tǒng)格式,Linux內(nèi)核可以識別.
load.sh
qemu-system-arm \-M vexpress-a9 \-m 256M \-nographic \-kernel zImage \-dtb vexpress-v2p-ca9.dtb \-initrd rootfs \-append "root=/dev/ram init=/hello console=ttyAMA0"- -initrd QEMU可以使用initrd參數(shù)將 initramfs 文件系統(tǒng)二進(jìn)制映像傳遞給內(nèi)核;
- -append 用于向內(nèi)核傳遞參數(shù), 內(nèi)核還必須知道根文件系統(tǒng)將位于RAM中(因?yàn)檫@是QEMU寫入initrd二進(jìn)制文件的位置),并且指明第一個(gè)啟動(dòng)的程序是我們的測試可執(zhí)行文件hello
- console=ttyAMA0 是將輸出定向到串口, 否則需要去掉 -nographic 才能查看
上面的shell 腳本執(zhí)行后將會看到屏幕上顯示Hello World, 并且內(nèi)核停留在 while 循環(huán).
initrd vs initramfs
initrd 是 Linux 2.6 版本以前制作內(nèi)存根文件系統(tǒng)的方法了, 該方法已經(jīng)過時(shí). 這是因?yàn)?initrd (initial ram disk 初始化內(nèi)存磁盤) 是把內(nèi)存當(dāng)做一塊磁盤, 內(nèi)核需要先創(chuàng)建 ramdev 塊設(shè)備, 然后將 initrd 拷貝到塊設(shè)備,最后掛載.
同時(shí) initrd 內(nèi)的文件系統(tǒng)還需要驅(qū)動(dòng)支持, 如果是 ext2 則必須在內(nèi)核中編譯 ext2 驅(qū)動(dòng)程序. initrd 最大的缺點(diǎn)是占用較大內(nèi)存,不可伸縮. 參考官方文檔
下面演示如何制作 initrd
新版本 kernel 默認(rèn)不再支持內(nèi)存塊設(shè)備支持, 需要手動(dòng)打開:
在內(nèi)核目錄執(zhí)行 grep BLK_DEV_RAM .config 查看 BLK_DEV_RAM 是否被編譯進(jìn)去, 若沒有則需要使用 make menuconfig 進(jìn)入設(shè)置后按 / 查找 BLK_DEV_RAM 并到對應(yīng)區(qū)域打開該功能
重新編譯內(nèi)核后拷貝出 zImage 執(zhí)行下面的腳本
qemu-system-arm \-M vexpress-a9 \-m 256M \-nographic \-kernel zImage \-dtb vexpress-v2p-ca9.dtb \-initrd rootfs.img \-append "root=/dev/ram0 init=/hello console=ttyAMA0"新版的 initramfs 直接把內(nèi)存作為文件系統(tǒng), 因?yàn)閮?nèi)核總是內(nèi)置 tmpfs 文件系統(tǒng) (initramfs就是tmpfs的實(shí)例), 可以直接掛載不需要設(shè)備和額外的文件系統(tǒng)驅(qū)動(dòng)程序.
根文件系統(tǒng)在外部設(shè)備
現(xiàn)代的高級的系統(tǒng)引導(dǎo)程序, 往往都直接支持文件系統(tǒng), 在初始化磁盤后可以識別文件系統(tǒng), 并將參數(shù)傳遞給內(nèi)核從哪個(gè)外部設(shè)備掛載根文件系統(tǒng). 制作外部設(shè)備的根文件系統(tǒng)鏡像和制作 initrd 是一樣的, 因?yàn)樗鼈兤鋵?shí)本質(zhì)都是包含文件系統(tǒng)的鏡像文件, 因此可以直接使用上一節(jié)的 rootfs.img 來使用, 只是它們被放到了真正的磁盤, 而 initrd 則是內(nèi)存虛擬的磁盤. 例如, 我們把它虛擬成sd卡, 讓 QEMU 的引導(dǎo)程序傳遞給內(nèi)核
load.sh
總結(jié)
以上是生活随笔為你收集整理的QEMU 模拟器(一)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 魔方 大模拟
- 下一篇: html div背景自动居中显示,网站背