日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

使用 qemu 搭建内核开发环境

發(fā)布時(shí)間:2024/4/18 编程问答 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 使用 qemu 搭建内核开发环境 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

本文主要介紹在 MacOS 上使用 qemu 搭建 Linux Kernel 的開發(fā)環(huán)境。(在開始之前需要注意的是,本文中的 Linux 開發(fā)環(huán)境是一個(gè)遠(yuǎn)程服務(wù)器,而 qemu 被安裝在本地的 MacOS 上。通常并不需要這樣折騰,直接將 qemu 安裝在 Linux 中更加方便,而且 qemu 是可以 -nographic 無圖形界面運(yùn)行的。)

1. 為什么需要 qemu?

qemu 是一個(gè)硬件虛擬化程序( hypervisor that performs hardware virtualization),與傳統(tǒng)的 VMware / VirtualBox 之類的虛擬機(jī)不同,它可以通過 binary translation 模擬各種硬件平臺(tái)(比如在 x86 機(jī)器上模擬 ARM 處理器)。而 VirtualBox 等更多是通過虛擬化來進(jìn)行資源隔離,以便在其上運(yùn)行多個(gè) guest os。

基于 qemu 的硬件模擬能力,我們可以輕松搭建指定硬件平臺(tái)的運(yùn)行實(shí)驗(yàn)環(huán)境。

qemu 與 VirtualBox 另一個(gè)不同點(diǎn)在于,在 VirtualBox 上必須安裝一個(gè)完整的操作系統(tǒng)套件,而通過 qemu 我們可以通過參數(shù)直接啟動(dòng)到一個(gè)裸的 Linux Kernel,連 bootloader 都不需要關(guān)心。在此之外,按需配置相關(guān)工具套件與啟動(dòng)好的 Kernel 一起工作即可。

qemu 提供的這種高度可定制化的『白盒』能力,使得我們可以按需構(gòu)建快速、輕量級(jí)的開發(fā)環(huán)境,提供流暢的開發(fā)體驗(yàn)。

2. 環(huán)境準(zhǔn)備

首先,為了進(jìn)行內(nèi)核開發(fā),需要一個(gè)現(xiàn)成的 Linux 操作系統(tǒng)環(huán)境。可以是一個(gè)通過 ssh 工作的遠(yuǎn)程 Linux Server,或者也可以在 MacOS 上通過 VirtualBox (或者使用 qemu 也可以)安裝一個(gè)虛擬機(jī)用于開發(fā)。VirtualBox 的安裝和 Linux Guest OS 的安裝配置此處略過不提。

接下來,安裝 qemu。在 MacOS 上可以使用 Homebrew 包管理工具進(jìn)行安裝(本文使用的 qemu 版本為 2.9.0_2):

brew install qemu

安裝完成后,可以看到系統(tǒng)中有很多個(gè) qemu-system- 開頭的命令,用于模擬各種硬件平臺(tái),比如 qemu-system-x86_64 。運(yùn)行其中一個(gè)命令來驗(yàn)證安裝是否成功:

qemu-system-x86_64

上述命令會(huì)啟動(dòng)一個(gè)類似 VirtualBox 虛擬機(jī)啟動(dòng)時(shí)的窗口。當(dāng)然,由于我們沒有指定任何設(shè)備,最終會(huì)提示找不到可啟動(dòng)設(shè)備。

3. 編譯內(nèi)核

按需編譯內(nèi)核,此處只進(jìn)行簡(jiǎn)單說明(基于內(nèi)核 v4.13)。

3.1 內(nèi)核編譯配置

可以先執(zhí)行 make help 可以查看 make 支持哪些 target。

通常先進(jìn)行內(nèi)核編譯配置:

make menuconfig

會(huì)啟動(dòng)一個(gè)基于文本的配置界面進(jìn)行各種選項(xiàng)、模塊、驅(qū)動(dòng)等配置。或者也可以直接使用目標(biāo)平臺(tái)默認(rèn)的配置,如針對(duì) x86_64 平臺(tái)(后續(xù)平臺(tái)相關(guān)的地方均以 x86_64 為例進(jìn)行說明)可以使用:

make x86_64_defconfig

配置完成后相應(yīng)的配置項(xiàng)會(huì)保存在 .config 文件中。下一次執(zhí)行 make menuconfig 時(shí)可以 load 這份配置文件,在此基礎(chǔ)上進(jìn)行修改。

3.2 編譯內(nèi)核和模塊

我們構(gòu)建一個(gè)壓縮過的內(nèi)核鏡像:

make bzImage

編譯成功后,bzImage 文件將出現(xiàn)在 arch/x86_64/boot/bzImage。記住文件路徑或者拷貝到一個(gè)方便的路徑,便于后續(xù)啟動(dòng)時(shí)使用。
接下來,編譯在配置階段選擇的內(nèi)核模塊:

make modules

編譯好的內(nèi)核模塊 *.ko 文件存在于模塊對(duì)應(yīng)的源碼目錄中。

4. 啟動(dòng)內(nèi)核

編譯好內(nèi)核以后,我們就可以使用 qemu 啟動(dòng)內(nèi)核了。只需要使用 -kernel 參數(shù)告訴 qemu 內(nèi)核文件的位置即可:

qemu-system-x86_64 \-m 512M \ # 指定內(nèi)存大小-smp 4\ # 指定虛擬的 CPU 數(shù)量-kernel ./bzImage # 指定內(nèi)核文件路徑

上述命令假設(shè)編譯好的 bzImage 內(nèi)核文件就存放在當(dāng)前目錄下。因?yàn)橹熬幾g好的內(nèi)核文件是在 VirtualBox 的虛擬機(jī)中(或者在遠(yuǎn)程服務(wù)器上),而 qemu 在本地 MacOS 上,可以通過 VirtualBox 的 share folder 來共享目錄,或者使用 NFS 共享,甚至簡(jiǎn)單使用 rsync 來在兩者之間同步文件。后續(xù)關(guān)于文件同步與共享不再贅述。

不出意外的話,就可以在啟動(dòng)窗口中看到內(nèi)核的啟動(dòng)日志了。在內(nèi)核啟動(dòng)的最后,會(huì)出現(xiàn)一條 panic 日志:

Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(0, 0)

從日志內(nèi)容可以看出,內(nèi)核啟動(dòng)到一定階段后嘗試加載根文件系統(tǒng),但我們沒有指定任何磁盤設(shè)備,所以無法掛載根文件系統(tǒng)。而且上一節(jié)中編譯出來的內(nèi)核模塊現(xiàn)在也沒有用上,內(nèi)核模塊也需要存放到文件系統(tǒng)中供內(nèi)核需要的時(shí)候進(jìn)行加載。

所以,接下來需要制作一個(gè)磁盤鏡像文件供內(nèi)核作為根文件系統(tǒng)加載。

5. 制作磁盤鏡像

如上一節(jié)所述,需要制作一個(gè)磁盤鏡像文件作為根文件系統(tǒng)供內(nèi)核加載,同時(shí)也用于存放編譯好的內(nèi)核模塊,以及后續(xù)所需的各種配套工具程序。

5.1 創(chuàng)建磁盤鏡像文件

使用 qemu-img 創(chuàng)建一個(gè) 512M 的磁盤鏡像文件:

qemu-img create -f raw disk.raw 512M

現(xiàn)在 disk.raw 文件就相當(dāng)于一塊磁盤,為了在里面存儲(chǔ)文件,需要先進(jìn)行格式化,創(chuàng)建文件系統(tǒng)。比如在 Linux 系統(tǒng)中使用 ext4 文件系統(tǒng)進(jìn)行格式化:

mkfs -t ext4 ./disk.raw

5.2 掛載磁盤鏡像文件

格式化完成之后,可以在 Linux 系統(tǒng)中以 loop 方式將磁盤鏡像文件掛載到一個(gè)目錄上,這樣就可以操作磁盤鏡像文件中的內(nèi)容了。
下面的命令將磁盤鏡像文件掛載到 img 目錄上:

sudo mount -o loop ./disk.raw ./img

5.3 安裝內(nèi)核模塊

現(xiàn)在可以將之前編譯好的內(nèi)核模塊安裝到磁盤鏡像中了。命令如下:

sudo make modules_install \ # 安裝內(nèi)核模塊 INSTALL_MOD_PATH=./img # 指定安裝路徑

執(zhí)行完成后即可在 ./img/lib/modules/ 下看到安裝好的內(nèi)核模塊。

5.4 使用磁盤鏡像文件作為根文件系統(tǒng)

準(zhǔn)備好磁盤鏡像文件后,使用下面的命令再次啟動(dòng) qemu:

qemu-system-x86_64 \-m 512M \-smp 4\-kernel ./bzImage \-drive format=raw,file=./disk.raw \ # 指定文件作為磁盤-append "root=/dev/sda" # 內(nèi)核啟動(dòng)參數(shù),指定根文件系統(tǒng)所在設(shè)備

這一次,內(nèi)核不再報(bào)根文件系統(tǒng)找不到了。但是報(bào)了另一個(gè)錯(cuò)誤:

Kernel panic - not syncing: No working init found. Try passing init= option to Kernel. See Linux Documentation/admin-guide/init.rst for guidance.

這說明內(nèi)核啟動(dòng)已經(jīng)接近完成了,準(zhǔn)備啟動(dòng) 1 號(hào)進(jìn)程,也就是 init 進(jìn)程。但我們的啟動(dòng)參數(shù)里面沒有指定 init 選項(xiàng),而且磁盤鏡像中也沒有相應(yīng)的 init 程序。因此,接下來需要準(zhǔn)備一個(gè) init 程序供內(nèi)核啟動(dòng)。

6. 準(zhǔn)備 init 程序

常用的 init 程序有下面幾種:

  • sysv init:傳統(tǒng) Linux 系統(tǒng)中最常用的 init 程序
  • systemd:目前最流行的 init 程序,很多主流發(fā)行版都已經(jīng)切換到 systemd。systemd 針對(duì) sysv init 啟動(dòng)速度慢、無法并行以及管控能力弱等問題進(jìn)行了重新設(shè)計(jì)。參見 Rethinking PID 1
  • busybox init:通知用在嵌入式等小型系統(tǒng)中。除了 init 程序外,busybox 還包含了很多常用的命令工具,比如 ls、cat 等。busybox 非常輕量級(jí),可以編譯出完全獨(dú)立無依賴的 busybox 套件。

這里選用 busybox 作為 init 程序及其它命令工具的提供者。

6.1 編譯 busybox

下載 busybox 的源碼到 Linux 系統(tǒng)中,準(zhǔn)備進(jìn)行編譯,這里使用的 busybox 版本為 1.27.2。

busybox 的編譯流程與內(nèi)核很像,這里我們基于默認(rèn)配置進(jìn)行編譯。首先,執(zhí)行如下命令讓默認(rèn)配置生效:

make defconfig

接下來,在默認(rèn)配置的基礎(chǔ)上進(jìn)行定制:

make menuconfig

這里有一個(gè)重要的配置,因?yàn)?busybox 將被用作 init 程序,而且我們的磁盤鏡像中沒有任何其它庫(kù),所以 busybox 需要被靜態(tài)編譯成一個(gè)獨(dú)立、無依賴的可執(zhí)行文件,以免運(yùn)行時(shí)發(fā)生鏈接錯(cuò)誤。配置路徑如下:

Busybox Settings --->--- Build Options[*] Build BusyBox as a static binary (no shared libs)

最后,配置完成后執(zhí)行編譯:

make

編譯完成后在當(dāng)前目錄下可以看到 busybox 可執(zhí)行文件,查看大小才 2.5M 左右。整個(gè) busybox 套件只有這一個(gè)可執(zhí)行文件,里面包含了若干工具。比如:

./busybox ls -l ./busybox ps

6.2 安裝 busybox 到磁盤鏡像

編譯好 busybox 之后需要將其安裝到磁盤鏡像中以供使用。執(zhí)行如下命令進(jìn)行安裝:

make CONFIG_PREFIX=<path_to_disk_img_mount_point> install

CONFIG_PREFIX 用于指定安裝路徑,需要指定到之前磁盤鏡像文件的掛載目錄,比如 ./img。進(jìn)入磁盤鏡像掛載目錄查看,常見的文件系統(tǒng)結(jié)構(gòu)已經(jīng)建立起來了。查看 bin 和 sbin 目錄下的命令,可以看到都是鏈接到 bin/busybox 的,busybox 會(huì)根據(jù)執(zhí)行時(shí)的文件名來執(zhí)行不同的功能。

6.3 使用 busybox 作為 init 程序

busybox 安裝完成之后,使用內(nèi)核啟動(dòng)參數(shù) init= 來指定 busybox 作為 init 程序,再次嘗試啟動(dòng)。

qemu-system-x86_64 \-m 512M \-smp 4\-kernel ./bzImage \-drive format=raw,file=./disk.raw \-append "init=/linuxrc root=/dev/sda"

上述命令通過 init=/linuxrc 指定了 init 程序?yàn)楦夸浵碌?linuxrc,實(shí)際上是一個(gè)指向 busybox 的軟鏈接。

這一次內(nèi)核成功找到了 init 程序并且創(chuàng)建出 init 進(jìn)程,但是 init 執(zhí)行過程中出現(xiàn)如下報(bào)錯(cuò):

can't run '/etc/init.d/rcS': No such file or directorycan't open /dev/tty3: No such file or directory can't open /dev/tty4: No such file or directory

看樣子,init 程序需要一些配置才能正常運(yùn)行起來。

6.4 配置 busybox init

參考 busybox 代碼中的 文檔 可知,init 啟動(dòng)后會(huì)掃描 /etc/inittab 配置文件,這個(gè)配置文件決定了 init 程序的行為。而 busybox init 在沒有 /etc/inittab 文件的情況下也能工作,因?yàn)樗心J(rèn)行為。它的默認(rèn)行為相當(dāng)于如下配置:

::sysinit:/etc/init.d/rcS ::askfirst:/bin/sh ::ctrlaltdel:/sbin/reboot ::shutdown:/sbin/swapoff -a ::shutdown:/bin/umount -a -r ::restart:/sbin/init tty2::askfirst:/bin/sh tty3::askfirst:/bin/sh tty4::askfirst:/bin/sh

參考文檔,我們提供一份 /etc/inittab 配置文件如下:

::sysinit:/etc/init.d/rcS ::askfirst:/bin/ash ::ctrlaltdel:/sbin/reboot ::shutdown:/sbin/swapoff -a ::shutdown:/bin/umount -a -r ::restart:/sbin/init

并且根據(jù)配置,我們創(chuàng)建可執(zhí)行文件 /etc/init.d/rcS,內(nèi)容如下(暫時(shí)什么事都不做):

#!/bin/sh

配置完成以后再次嘗試啟動(dòng),這次將成功啟動(dòng),并且出現(xiàn)如下提示:

Please press Enter to activate this console.

按提示按下 Enter 鍵之后將會(huì)啟動(dòng) shell,進(jìn)行到我們熟悉的環(huán)境,可以執(zhí)行各種常用命令了。

6.5 掛載 /dev, /proc, /sys 文件系統(tǒng)

查看當(dāng)前系統(tǒng)環(huán)境,會(huì)發(fā)現(xiàn)當(dāng)前文件系統(tǒng)結(jié)構(gòu)是不完整的。比如沒有 /dev, /proc 以及 /sys 掛載點(diǎn)。這樣我們無法通過 /dev 查看系統(tǒng)中的設(shè)備,如果執(zhí)行 df 命令也會(huì)因?yàn)闆]有 /proc 掛載點(diǎn)而報(bào)錯(cuò):

df: /proc/mounts: No such file or directory

因此,我們需要手工創(chuàng)建 /dev, /proc, /sys 這三個(gè)目錄。/dev 目錄創(chuàng)建完成后重啟系統(tǒng)即可工作,但 /proc 和 /sys 需要執(zhí)行掛載才可工作,可以將 /proc 和 /sys 的掛載動(dòng)作放到 /etc/init.d/rcS 中,每次系統(tǒng)啟動(dòng)時(shí)自動(dòng)掛載。修改 /etc/init.d/rcS 內(nèi)容如下:

#!/bin/sh mount -t proc proc /proc mount -t sysfs sysfs /sys

重新啟動(dòng)系統(tǒng)查看,可以看到 /dev, /proc, /sys 掛載點(diǎn)都相應(yīng)有了內(nèi)容。

7. 小結(jié)

本文介紹了通過 qemu 作為模擬器,自己動(dòng)手編譯內(nèi)核,并從頭配置 init 進(jìn)程,構(gòu)建出一個(gè)最小的可運(yùn)行系統(tǒng),可用于驗(yàn)證對(duì)內(nèi)核的改動(dòng)。
通過這次開發(fā)環(huán)境搭建,對(duì)系統(tǒng)的啟動(dòng)過程有了一個(gè)粗略的了解。但這只是邁出了第一步,后續(xù)還有長(zhǎng)路漫漫。

同步發(fā)布:https://hellogc.net/archives/121

總結(jié)

以上是生活随笔為你收集整理的使用 qemu 搭建内核开发环境的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。