在PVE 的KVM - Option 中將Qemu Agent 改為Yes (Enable). 3. 啟動VM 並安裝作業系統 ... 節省哥跟網路上其他人在介紹Proxmox VE的防火牆時,都是用VM的虛擬機器。 ... <看更多>
qemu介紹 在 [閒聊] 教學:如何在Linux上玩LOL - 英雄聯盟| PTT遊戲區 的美食出口停車場
我們將藉由libvirt的協助使用QEMU/KVM在linux上建立虛擬機,並藉由GPU ... 用libvirt建立一台虛擬機器(Virtual Machine,VM)。qemu提供Guest OS一張QXL ... ... <看更多>
qemu介紹 在 [教學] 用qemu + chroot 編譯與測試Linux Kernel 的美食出口停車場
用 qemu + chroot 編譯與測試 Linux Kernel
聽說有人光是編譯 Linux Kernel 就編譯了 4 個小時,
也就是說若以 10/28 為 deadline 各位只剩下 42 次
修改檔案的機會...。
-- 來自地下室的哀號
序言
我個人非常不喜歡編譯 kernel,因為 kernel 是作業系統當中最重要
的部分。如果 kernel 編壞了可能無法開機,而且可能弄亂原有的作業
系統。
如果萬不得已要自己編譯,我通常會使用 fakeroot make-kpkg 之類
的指令把 kernel 編譯成 Debian 套件,再用 dpkg -i 安裝。日後要
移除也比較容易。
然而我日常的作業系統就是 Ubuntu,我不希望 OS Project 1 染指我
每天要使用的系統。而且一直重新開機測試修改成果也非常累,所以
我還是比較想要使用虛擬機器 (Virtual Machine)。
我這次要介紹二個工具:qemu-kvm 與 chroot,這二個工具都是用來
創造和原本作業系統相互隔離的環境,也各有長處與短處,所以我的
攻略會交互使用二個工具。
- qemu / qemu-kvm
這是一個虛擬機器,就像 VMWare, Virtual Box, Virtual PC 等軟體,
可以用來模擬一台虛擬的電腦。
qemu 是使用 Dynamic Recompilation 模擬 CPU,不過這種技術執行速
度約為 Host CPU 的 20%。而 qemu-kvm 使用 paravirtualization,會
利用 Intel/Amd CPU 提供的虛擬機制加快模擬速度,執行速度約為 50~
80%。
- chroot
這個是 Linux 之下的一個程式,可以幫我們把根目錄替換成另一個目錄,
就好像使用不同的 Linux(gcc、bash 甚至是 mv cp 等指令都會被換掉)。
在 chroot 環境下執行程式與一般環境執行程式無異,所以速度是 100%。
然而 chroot 不能完全隔離所有操作,所以要小心使用(避免使用 root
身分,或者是 sudo),以免影響原有的作業系統。
準備工作
1. 先有一套 Linux(推薦使用 Ubuntu Linux 或 Debian Linux)
以便使如 qemu-kvm 與 chroot
2. 準備一份 Linux 安裝光碟映像檔(我自己是用 Ubuntu 10.10)
3. 取得 qemu 與 qemu-kvm,在 Ubuntu Linux 之下,可以使用以
下指令取得:
$ sudo apt-get install qemu qemu-kvm
4. 取得一份 Linux Kernel source code(我是用 2.6.36)
https://www.kernel.org/pub/linux/kernel/v2.6/linux-2.6.36.tar.bz2
準備子系統
1. 建立虛擬機器的硬碟檔案(至少要 10Gb)
$ dd if=/dev/zero of=disk.img bs=1 count=1 seek=10737418239
稍微說明一下:為了使用 chroot,我們不使用 qemu 特有可以動
態成長的硬碟格式。不過這裡還是使用了一個小技巧:直接把檔
案 seek 到 10Gb - 1byte 的地方,寫入一個 byte 以節省時間。
2. 用 qemu 開啟子系統
$ qemu -hda disk.img -m 1024 \
-cdrom ubuntu10.10.iso -boot d
參數說明:
-hda 以此檔案為主硬碟
-cdrom 以此檔案為光碟映像檔
-boot 開機選項 (c) 硬碟 (d) 光碟
-m 虛擬機器要有多少記憶體 (MB)
3. 依指示安裝作業系統。不過要注意:在割硬碟的時候,把整塊都割
給 root (/),不要留 swap。(要選「專家模式」然後手動切割)
4. 關機時,要我們取出光碟,此時就可以把 qemu 關掉了!
5. 重新開機
$ qemu -hda disk.img -m 1024
6. 在子系統安裝必要的軟體(打開「應用程式->附屬應用程式->終端機」)
\> sudo apt-get build-dep linux # 編譯 linux 必備
\> sudo apt-get install libncurses5-dev # menuconfig 必備
7. 關機
在主系統掛載子系統的分割區
我想在主系統編譯 kernel,所以我要把子系統的分割區掛載到主系
統上,再使用 chroot 把 root 切換到這一個分割區。
1. 先檢查分割表計算分割區的 offset:
$ sudo losetup /dev/loop0 disk.img
$ sudo fdisk /dev/loop0
Command (m for help): p # 用 p 列出分割表的資訊
Disk /dev/loop0: 8589 MB, 8589934592 bytes
255 heads, 63 sectors/track, 1044 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes
Sector size (logical/physical): 512 bytes / 512 bytes # 記住 sector 的大小
I/O size (minimum/optimal): 512 bytes / 512 bytes
Command (m for help): x # 進入專家模式
Expert command (m for help): p # 再列出分割表的資訊
Disk /dev/loop0: 255 heads, 63 sectors, 1044 cylinders
Nr AF Hd Sec Cyl Hd Sec Cyl Start Size ID
1 80 32 33 0 86 53 993 2048 15955968 83 # 記住 start
Expert command (m for help): q
$ sudo losetup -d /dev/loop0
透過以上步驟,我們知道一個 sector 的大小是 512byte,另外
子系統的 root partition 是在 2048 個 sector,所以 offset
是 512 * 2048 = 1048576 (請根據你自己的情況加以修改)
2. 掛載子系統的 root 分割區
$ mkdir partition
$ sudo losetup --offset 1048576 /dev/loop0 disk.img # 把檔案當 loop device
備註:如果這一步有問題,可以試不同的 loop device:loop0 ~ loop7。
$ sudo mount /dev/loop0 partition # 掛載檔案系統
備註:如果這一步有問題,大概是你的 offset 算錯了!
3. 解壓縮 Linux Kernel 的原始碼
$ sudo chown username:username partition/usr/src
備註:暫時修改資料夾的權限。username 是你主系統檔中
uid 為 1000 的使用者。一般來說應該就是你自己。
$ tar jxf linux-2.6.36.tar.bz2 -C partition/usr/src
說明:解壓縮 Linux Kernel source code 到 partition/usr/src
資料夾之下。
$ sudo chown root:root partition/usr/src
備註:把權限改回來。
編譯 linux 核心
1. 使用 chroot 進入子系統。要小心,chroot 的隔離不是絕對
安全的!只要有 root 權限,隨時可以離開 chroot 的隔離
環境,所以要避免使用 root。
$ sudo chroot partition env -i TERM=xterm su username
參數說明:partition 是子系統的根目錄,也就是我們要切換
的目標,後面是緊接著要執行的指令。
env -i 會把不相關的環境變數清掉。而 TERM=xterm 是因為
menuconfig 需要這個環境變數。
su 是把使用者切換成 username。這個 username 是子系統的
user,應該是你安裝子系統時填入的名字。
2. 複製 Linux Kernel 設定檔
\> cp /boot/config-2.6.35-22-generic .config
3. 執行 menuconfig。不用調整任何選項,直接 Exit 就可以了。
\> make menuconfig
4. 開始編譯 Kernel 與模組
\> make -j4 bzImage modules
備註:根據每個人電腦的不同,要使用不同的 -jN。我的電
腦是雙核心的 cpu,所以我覺得 -j4 很適合我。大家的電腦
應該都比我好,可以用更大的數字(但適量就好,並不是越大
越快)。
備註:用筆電的人記得把電源接上,讓 CPU 可以全速工作。
備註:在我的筆電上這一步大概要 50 分鐘到 1 小時。
安裝新核心
編譯完成之後,我們要安裝核心。不過要安裝核心,必需要有 sudo
的權限,所以在 chroot 的環境下不太安全,所以我們還是要改用
qemu 開機。
1. 離開 chroot 環境,並卸載子系統的分割區。
\> exit # 離開 chroot 環境
$ sudo umount partition # 卸載檔案系統 (這可能會有一點久)
$ sudo losetup -d /dev/loop0 # 解除檔案與 loop device 之間的關連
2. 使用 qemu 開機
$ qemu -hda disk.img -m 1024
3. 開啟終端機,依序執行以下指令
\> cd /usr/src/linux-2.6.36
\> sudo make modules_install install
\> sudo mkinitramfs -o /boot/initrd.img-2.6.36 2.6.36
4. 修改 grub2 設定檔,在 GRUB_HIDDEN_TIMEOUT=0 的前面加上 '#'。
\> sudo vi /etc/default/grub
:%s/GRUB_HIDDEN_TIMEOUT=0/#GRUB_HIDDEN_TIMEOUT=0/g
:wq
5. 更新開機選單
\> sudo update-grub2
6. 重新開機
小結
我們使用了二種創造隔離環境的方法:(1) 使用 qemu 當做我們的
虛擬機器 (2) 使用 chroot 隔離主系統與子系統。前者比較安全,
不過比較慢;後者比較快,但是比較不安全。
另外,一般我們要進入 chroot 的環境,我們要 losetup、mount、
chroot,使用完必之後,要再 exit、umount、losetup -d。程序
很煩鎖,而且如果沒有 umount、losetup -d,就執行 qemu 就會
有很可怕的結果(很可怕不要問)。所以我寫了一個 shell script
自動執行這些步驟:
https://w.csie.org/~b97073/B/enter-partition.sh.txt
下載後,修改 USERNAME、PARTITION_OFFSET 再 chmod +x,即可
使用 ./enter-partition.sh.txt。看到 leaving successfully
才是正常結束。
修改作業系統與重新安裝
1. $ ./enter-partition.sh # 進入 chroot
2. \> cd /usr/src/linux-2.6.36 # 進入 source code 的資料夾
3. 修改 kernel 的 source code。
(1) kernel 資料夾之下建立 myservice.c 這個檔案,並輸入
助教給的程式:
#include <linux/linkage.h>
#include <linux/kernel.h>
asmlinkage int sys_myservice(int arg1) {
printk("my service is invoked!\n");
return arg1 * 10;
}
(2) 打開 arch/x86/include/asm/unistd_32.h 找到最後一個 #define __NR_...
在它的最面加上 #define __NR_myservice 341 。然後把下面的 NR_syscalls
改成 342。
(3) 打開 arch/x86/kernel/syscall_table_32.S,直接移到
最後一行,加上 .long sys_myservice
(4) 打開 include/linux/syscalls.h,移到最後,#endif 之前,加上
asmlinkage int sys_myservice(int arg1);
(5) 打開 kernel/Makefile,在一開始的地方加上
obj-y += myservice.o
4. \> make -j4 bzImage modules
備註:如果有修改 arch/x86/include/asm/unistd_32.h,
那幾乎所有的 source code (bzImage 與 modules) 都要重
新編譯,又是一個小時... ,所以要儘量避免。
備註:如果只改 kernel/myservice.c kernel/signal.c
include/linux/syscalls.h 重新編譯的時間不超過 10 分鐘。
備註:沒事千萬不要 make clean!!
5. \> exit # 離開 chroot
6. $ qemu -hda disk.img -m 1024
7. \> cd usr/src/linux-2.6.36
\> sudo make modules_install install # 安裝新的 os
\> sudo update-initramfs -u -k 2.6.36 # 更新 initramfs
\> sudo reboot
8. 寫一個測試用的程式:
#include <stdio.h>
#include <stdlib.h>
#define _GNU_SOURCE
#include <unistd.h>
#include <sys/syscall.h>
#define __NR_myservice 341
int main(int argc, char *argv[])
{
int num = (argc > 1) ? atoi(argv[1]) : 1234;
printf("%d\n", (int)syscall(__NR_myservice, num));
return EXIT_SUCCESS;
}
然後懷著敬畏的心情,compile 並執行它!祝你好運!
9. Project 1 的部分,就如投影片所說,要在 SYSCALL_DEFINE2(kill
加料,而 sent signal 可以在 __send_signal 加料。
Q & A
Q: 喂 logan,我裝了 qemu-kvm 之後,Virtual Box 就壞掉了,
你要負責!
A: qemu-kvm 相衝!所以如果你要用 Virtual Box 必需要把
qemu 與 qemu-kvm 移除。
$ sudo apt-get purge qemu qemu-kvm
Q: 怎麼看 printk 的結果?
A: sudo dmesg | tail -n 10
Q: 為什麼我按下 Alt-F4 之後,qemu 就關掉了,我要關的是裡面的
視窗呀!
A: 按下左方的 Ctrl+Alt 可以鎖定鍵盤還有滑鼠。
結語
這份作業蠻有趣的!
如果有人在結報上提到這篇文章我會很高興的。 ^^
\
--
※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 140.112.30.131
※ 編輯: LoganChien 來自: 140.112.30.131 (10/22 06:19)
... <看更多>