# 2019q1 Homework7 (riscv) contributed by < `zodf0055980` > ###### tags: `Linux 核心設計` # 自我檢查清單 - [ ] riscv-emu 原始程式碼中多次出現 virtio,這樣的機制對於 host 和 guest 兩端有何作用?在閱讀 Virtio: An I/O virtualization framework for Linux 一文後,對照原始程式碼,你發現什麼? 要了解 virtio,首先要了解完全虛擬化和半虛擬化。 全虛擬化:允許未經修改的 Guest OS 隔離運行在 VMM 上,並對Guest OS 隱藏了真實的硬體。所有硬體特徵像是指令集、中隊都對應到虛擬機上。所以我們電腦可以直接運行的軟體都可以直接運行在虛擬機上,不用修改。然而 VMM 必須捕捉這些請求並模擬硬體的行為,雖然有彈性但是造成效率低落。例如:以前常用的 Oracle VM VirtualBox。 半虛擬化:則要求對 Guest OS 做出必要的更改,以適應 VMM 提供的半虛擬化API。而且 Guest OS 運行時知道自己是運行在虛擬化的機器上, 並自己包含驅動程序的前端驅動,而 VMM 為後端驅動。而 Virtio 前後端的溝通提供標準化接口以提高效率。 ![](https://i.imgur.com/rJ74ym3.gif) Virtio 所提供的 API 透過簡單的 buffer 來把對 Guest OS 的命令做封裝傳輸,並提供兩個層來幫助 Guest OS 與 VMM 的通訊,其中頂層使用 Queue 作為虛擬接口連接前後端,也被稱為 virtio。 ![](https://i.imgur.com/Jof9LQH.gif) virtio_driver : 代表 Guest OS 的前端驅動程序。與此驅動程序匹配的設備由 virtio_device 封裝。 virtio_config_ops : 定義配置virtio設備操作的結構 virtqueue : 引用 virtio_device。使用 Queue 做資料結構。virtqueue_ops : 定義 virtqueue 中 Queue的基本操作。 - [ ] 透過 $ temu root-riscv64.cfg, 我們在 RISCV/Linux 模擬環境中,可執行 gcc 並輸出對應的執行檔,而之後我們則執行 riscv64-buildroot-linux-gnu-gcc,這兩者有何不同? 當我們一般在 linux 使用 gcc 來編譯某個程式,程式只能執行相同指令集的電腦上,而我們要使用虛擬機模擬 RISCV 架構,就不能使用 電腦上的編譯器去編譯。而透過 Cross Compiler 可以編譯出執行在不同指令集的程式,因此我們程式要在 RISCV 的虛擬機上執行,便要透過 riscv64-buildroot-linux-gnu-gcc 去編譯。 - [ ] 在 Guest 端透過 $ dmesg | grep 9pnet 命令,我們可發現 9P2000 字樣,這和上述 VirtFS 有何關聯? 嘗試執行: ``` [root@localhost ~]# dmesg | grep 9pnet [ 0.278541] 9pnet: Installing 9P2000 support ``` 把上面一一拆解,[dmesg](http://www.runoob.com/linux/linux-comm-dmesg.html) 用來顯示開機訊息, kernel 會把開機訊息存在 ring buffer 和 /var/log 中 dmesg 的文件。 而 grep 可以搜尋要找的字串,所以上述指令是在開機訊息中尋找 9pnet。 >9P(又名九號計劃檔案系統協定或Styx),是貝爾實驗室九號計劃分散式作業系統所開發的網絡協定,作用在於連結九號計劃系統內的元件。在九號計劃第四版中,9P被更名為9P2000,也增加了一些基礎上的改進。 > 在文章中可知在 guest 和 host 的 OS 中設置 VirtFS ,使的資料夾可以共享。 >VirtFS (Plan 9 folder sharing over Virtio - I/O virtualization framework) > - [ ] 在 root-riscv64.cfg 設定檔中,有 bios: "bbl64.bin" 描述,這用意為何? bbl 全名是 the Berkeley Boot Loader。文章中提到為了避免把硬體的假設寫入映像檔,使用兩種抽象機制: 1. 設備樹(device tree): 一種現代系統用來描述硬體資源的結構,這指定了記憶體映射,系統中配置以及所有靜態分配的設備。它通過 bootloader 將硬體資源傳給 kernel,使得 kernel 和硬體資源描述相對獨立。 >Documentation for device trees, a data structure by which bootloaders pass hardware layout to Linux in a device-independent manner, simplifying hardware probing. > 2. supervisor binary interface (SBI) : supervisor 的機器二元碼介面,允許由較低優先權的 stack 提供的接口寫入 supervisor。 而在 RISC-V supervisor-mode 中,設備樹和 SBI 都由 machine-mode 的 bbl 提供。 - [ ] 為何需要在 host 端準備 e2fsprogs 工具呢?具體作用為何呢? e2fsprogs(又稱為e2fs programs)是用以維護ext2,ext3和ext4檔案系統的工具程式集。 # 實驗 客製化 buildroot,將 kilo 編輯器加入到 build image 參考 [Buildroot Manual]( https://buildroot.org/downloads/manual/manual.html#adding-packages),在 /package 中創建 kilo 資料夾,並參考寫出 `Config.in`: ```clike config BR2_PACKAGE_KILO bool "kilo" help Kilo is a small text editor in less than 1K lines of code (counted with cloc). https://github.com/sysprog21/kilo ``` 以及 `kilo.mk` : ``` ################################################################################ # # kilo # ################################################################################ KILO_VERSION = af3919d68cb2e70a3d9a2309596cf290cf6bc1ac KILO_SITE = $(call github,sysprog21,kilo,$(KILO_VERSION)) KILO_LICENSE = BSD-2-Clause define KILO_BUILD_CMDS $(MAKE) $(TARGET_CONFIGURE_OPTS) -C $(@D) all endef define KILO_INSTALL_TARGET_CMDS $(INSTALL) -D -m 0755 $(@D)/kilo $(TARGET_DIR)/usr/bin endef $(eval $(generic-package)) ``` 在 Buildroot Manual 有寫到: LIBFOO_VERSION, mandatory, must contain the version of the package. Note that if HOST_LIBFOO_VERSION doesn’t exist, it is assumed to be the same as LIBFOO_VERSION. It can also be a revision number or a tag for packages that are fetched directly from their version control system. Examples: a version for a release tarball: LIBFOO_VERSION = 0.1.2 a sha1 for a git tree: LIBFOO_VERSION = cb9d6aa9429e838f0e54faa3d455bcbab5eef057 而觀看 [github.com/sysprog21/kilo/](https://github.com/sysprog21/kilo/commit/af3919d68cb2e70a3d9a2309596cf290cf6bc1ac) 發現最新 commit 檔案為 af3919d68cb2e70a3d9a2309596cf290cf6bc1ac 將此作為 KILO_VERSION。 以及 [加入git檔案](https://buildroot.org/downloads/manual/manual.html#github-download-url)的說明,他有提供工具可以從 github 下載檔案,因此 `KILO_SITE = $(call github,sysprog21, kilo, $(KILO_VERSION))`。 更改 package/Config.in 把 kilo 加入 menu "Text editors and viewers",接著執行 make menuconfig 就能看到 kilo 出現在選單中。 ![](https://i.imgur.com/qrHqAKM.png) 可以看到 package/Config.in 有這段 ``` if BR2_PACKAGE_BUSYBOX_SHOW_OTHERS source "package/vim/Config.in" endif ``` 得知如果我們沒有預設文字編輯器的話,會自動用 vim。 之後在 diskimage-linux-riscv-2018-09-23 資料夾中建立 test64.cfg,因為如果在 /tmp 資料夾下如果重開機,檔案會自動做清除。(被這個害慘,下載檔案下載好多次 .......)因此把檔案移到 home 目錄下作實驗,把 test64.cfg 修改為 ``` { version: 1, machine: "riscv64", memory_size: 128, bios: "bbl64.bin", kernel: "kernel-riscv64.bin", cmdline: "console=hvc0 root=/dev/vda rw", drive0: { file: "/home/yuan/buildroot-riscv-2018-10-20/output/images/rootfs.ext2" }, fs0: { tag: "/dev/root", file: "/tmp" }, eth0: { driver: "user" }, } ``` 之後執行 temu test64.cfg ,進到模擬器中,因為我們已經把預設的文字編輯器改成 kilo,直接輸入 kilo XXX ,便能出現 kilo 做處理了。 ![](https://i.imgur.com/HkSl0Ul.png) 在 [8.10. Graphing the filesystem size contribution of packages](https://buildroot.org/downloads/manual/manual.html#_graphing_the_filesystem_size_contribution_of_packages) 提到能利用 $ make graph-size 去顯示大小,下面做小小測試: ```shell= yuan@yuan-X555LF:~/buildroot-riscv-2018-10-20$ make graph-size You need python-matplotlib to generate the size graph Makefile:737: recipe for target 'graph-size' failed make: *** [graph-size] Error 1 ``` 發現需要 python-matplotlib 的套件,透過執行 $sudo apt-get install python-matplotlib 安裝套件 最後在執行一次,會在 buildroot-riscv-2018-10-20/output/graphs/graph-size.pdf ![](https://i.imgur.com/0nGDcz8.png) 接著想要移除 vi,讓ext2 image 變得更精簡 輸入$ make busybox-source 和$ make busybox-menuconfig 把 busybox-menuconfig 中 editer 的 vi 給取消。 ![](https://i.imgur.com/RdHLEMP.png) 發現大小並沒有改變,應此跑去更改 buildroot-riscv-2018-10-20/package/busybox/busybox.config 把 CONFIG_VI=y 改成 CONFIG_VI=n ,並重新編譯看看。 ![](https://i.imgur.com/5QIPPda.png) 發現檔案大小確實減少了,去觀察 package 得狀況: ![](https://i.imgur.com/LP0BBv8.png) 發現 bustbox的大小減少了一點。