ラベル QEMU の投稿を表示しています。 すべての投稿を表示
ラベル QEMU の投稿を表示しています。 すべての投稿を表示

USBストレージから起動するテキストベースLinuxイメージ

標記のひとつにDebian Liveイメージがある。

配布サイト


上記のサイトには各種Linuxディストリビューションのイメージがある。特に好みがなければ、以下のようなstandard版を使う。
  • debian-live-12.5.0-amd64-standard.iso

USBストレージへの書き込み

以下の例では、青色の/dev/sdxがUSBストレージのデバイス。/proc/partitionsやdmsgの出力などから実際に接続しているデバイスを特定してそれに変更する
dd if=debian-live-12.5.0-amd64-standard.iso of=/dev/sdx bs=1M
上記のbs=1Mは、ブロックサイズを1MiBにするオプション。昔、特定の環境でブロックサイズを一定サイズ以上に設定しないと極端に遅いことがあったので習慣として付与している。最近のほとんどのLinux環境では、なくても問題ないと思われる。

おまけ:QEMUの実行例

#!/bin/sh

QEMU=qemu-system-x86_64
IMAGE=debian-live-12.5.0-amd64-standard.iso
MEMORY=2048

${QEMU} \
-cpu host \
-enable-kvm \
-m ${MEMORY} \
-device nec-usb-xhci,id=xhci \
-drive id=DRIVE_ID,format=raw,file=${IMAGE},if=none \
-device usb-storage,bus=xhci.0,drive=DRIVE_ID
上記スクリプトを実行する次のような画面が表示される。
上の画面でLive system (amd64)を選択する(ENTERキーを押す)と、次のようにコンソール画面が表示される。

参考

QEMUでドライブを追加するオプション例

QEMUでLinuxカーネルをGDBでデバッグする

QEMUの起動

以下の2つのオプションを使う
オプション説明
-sTCP 1234番でGDBのリモートコクションをオープンします
-SGDBにアタッチされるまでゲストの実行を待機します。カーネルの起動後にアタッチしても問題ない場合、不要です。

Linuxの起動オプション

QEMUで起動されるLinuxカーネルのコマンドラインオプションにnokaslrを付与する。通常、GRUBなどのブートローダーに指定する。このオプションは、カーネルの関数の配置アドレスのランダム化を抑止する。このオプションを指定しない場合、カーネルのデバッグ情報に記載されているアドレスと、実際のアドレスがことなり、GDBの操作が期待どおりに行われない。

デバッグ情報の入手

ターゲットのカーネルに対応するデバッグ情報ファイルを取得する。

Debianの場合の例

sudo apt install linux-image-5.10.0-22-amd64-dbg
あるいは、APT repositoryから直接取得する。
wget http://ftp.debian.org/debian/pool/main/l/linux/linux-image-5.10.0-22-amd64-dbg_5.10.178-3_amd64.deb
sudo dpkg -i linux-image-5.10.0-22-amd64-dbg_5.10.178-3_amd64.deb

自分でビルドしたカーネルの場合

カーネルのビルドディレクトリにvmlinuxがあるのでそれを使う。ただし、ビルド時、以下の点に留意
  • 以下のCONFIGを有効化
    • CONFIG_DEBUG_INFO_DWARF5、または、CONFIG_DEBUG_INFO_DWARF4
    • CONFIG_GDB_SCRIPTS
    • CONFIG_FRAME_POINTER
  • 以下のCONFIGを無効化
    • CONFIG_DEBUG_INFO_REDUCED
参考: https://docs.kernel.org/dev-tools/gdb-kernel-debugging.html

GDBの起動

デバッグ情報付きのvmlinuxを引数にしてGDBを起動する
gdb /usr/lib/debug/vmlinux-5.10.0-22-amd64
GDB起動後、以下のコマンドを実行する
(gdb) target remote [QEMU起動マシンのアドレス]:1234

グローバル変数の表示例

(gdb) p jiffies
$1 = 4295462764

ブレークポイントの例

do_sys_openにブレークポイントを仕掛けて、ゲストOSでファイルを開く操作をすると以下のようにブレークする
(gdb) b do_sys_open
Breakpoint 2 at 0xffffffff812d6ff0: do_sys_open. (11 locations)
(gdb) c
Continuing.

Breakpoint 2.4, do_sys_open (mode=0, flags=557056, filename=0x7f153b8cabe7 "/etc/ld.so.cache", dfd=-100) at fs/open.c:1201
1201    fs/open.c: No such file or directory.
(gdb) bt
#0  do_sys_open (mode=0, flags=557056, filename=0x7f153b8cabe7 "/etc/ld.so.cache", dfd=-100) at fs/open.c:1201
#1  __do_sys_openat (mode=0, flags=557056, filename=0x7f153b8cabe7 "/etc/ld.so.cache", dfd=-100) at fs/open.c:1218
#2  __se_sys_openat (mode=0, flags=524288, filename=139729170115559, dfd=4294967196) at fs/open.c:1213
#3  __x64_sys_openat (regs=<optimized out>) at fs/open.c:1213
#4  0xffffffff818f7e00 in do_syscall_64 (nr=<optimized out>, regs=0xffffc9000027bf58) at arch/x86/entry/common.c:46
#5  0xffffffff81a000a9 in entry_SYSCALL_64 () at /build/linux-ts3hOX/linux-5.10.178/arch/x86/entry/entry_64.S:125

実行中のプロセスのtask_structの表示例

上記のブレーク例は、lsを実行したときのものである。このときのプロセスが確かにlsであることと、そのプロセスIDを確認する。
(gdb) set $curr = (struct task_struct **)($gs_base + (void *)&current_task)
(gdb) p $curr
$2 = (struct task_struct **) 0xffff88803d01fbc0
(gdb) p $curr->comm
$3 = "ls\000h\000\000\000)\000\000\000\000\000\000\000"
(gdb) p $curr->pid
$4 = 552
上記について補足する。実行中のプロセスのtask_struct構造体へのポインタは、CPUごとの変数領域の中にあり、グローバル変数current_taskの値は、その領域におけるオフセットである。また、CPUごとの変数領域の開始位置はGSセグメントレジスタに格納されている。そのため、両者を加算したアドレス位置に実行中のプロセスに関するtask_struct領域へのポインタが格納されている。

参考

QEMUでホストのディレクトリをゲストに9pで共有する

ホスト側

QEMUに起動時に次のオプションを付与する。青字のIDは適宜変更可能。紫のタグについても適宜変更。
-fsdev local,path=$(pwd),security_model=mapped-xattr,id=fsdev1 \
-device virtio-9p-pci,fsdev=fsdev1,mount_tag=tag1

参考

パラメータの詳細

QEMU起動の全体のパラメータ

ゲスト側

tag1の部分は、QEMU起動時にホスト側で指定した文字列と同じものを指定します。
mount -t 9p -o trans=virtio tag1 /mnt/dir_tag1 -oversion=9p2000.L

QEMUでLinux(Ubuntu 22.04)をテキストモード(シリアルコンソール)でインストールする

最近のLinuxのインストーラは、GUIベースのものが多いです。 ただし、サーバにインストールする場合、テキストベースで操作が完結できるとが便利な場合があります。 この記事では、Ubuntu 22.04をQEMUの仮想マシンにテキストモード(シリアルコンソール)でインストールする方法を紹介します。

インストーラISOイメージのダウンロード

wget https://releases.ubuntu.com/22.04.2/ubuntu-22.04.2-live-server-amd64.iso

カーネルとinitrdをファイルとしてアクセスするための準備

以下のようのインストーラのISOイメージをマウントし、その中のカーネルとinitrdを直接ファイルとしてアクセスできるようにします。
mkdir mnt
sudo mount -o ro ubuntu-22.04.2-live-server-amd64.iso mnt
また、インストール終了後、以下のようにアマウントします。
sudo umount mnt

仮想ディスクイメージの作成

qemu-img create -f raw drive1.img 10G
参考: QEMU用の仮想ドライブイメージファイルの作成例

QEMUの起動

ここでは、以下のシェルスクリプトを作って実行します。もちろん、コマンドラインに直接入力してもよいですが、コマンドラインが長いのでファイルに記載して実行します。 このコマンドラインでは、カーネルをファイルとして直接指定し、カーネルオプションにconsole=ttyS0を渡します。 ttyS0は、シリアルポートデバイスを意味します。これにより、インストーラがシリアルコンソール用に動作します。 また、-nographicオプションは、QEMUを起動した端末(xtermなど)を仮想マシンのシリアルポートとして使用するためののオプションです。
#!/bin/sh

QEMU=qemu-system-x86_64
CD_IMAGE=ubuntu-22.04.2-live-server-amd64.iso
DISK_IMAGE=drive1.img
MEMORY=2048

${QEMU} \
-cpu host \
-enable-kvm \
-m ${MEMORY} \
-drive format=raw,file=${DISK_IMAGE},if=virtio \
-cdrom ${CD_IMAGE} \
-nographic \
-kernel mnt/casper/vmlinuz \
-append console=ttyS0 \
-initrd mnt/casper/initrd
起動すると、以下のようなインストーラの画面が表示されます。
================================================================================
  Serial                                                              [ Help ]
================================================================================
                                                                              
  As the installer is running on a serial console, it has started in basic    
  mode, using only the ASCII character set and black and white colours.       
                                                                              
  If you are connecting from a terminal emulator such as gnome-terminal that  
  supports unicode and rich colours you can switch to "rich mode" which uses  
  unicode, colours and supports many languages.                               
                                                                              
  You can also connect to the installer over the network via SSH, which will  
  allow use of rich mode.                                                     
                                                                              
                                                                              
                                                                              
                                                                              
                                                                              
                                                                              
                                                                              
                          [ Continue in rich mode  > ]                        
                          [ Continue in basic mode > ]                        
                          [ View SSH instructions    ]                        
                                                      
あとは、キーボードで項目を選択したり、ユーザ名を入力するなどGUIのインストーラと同じように操作します。 以下は、インストール完了時に画面です。
================================================================================
  Install complete!                                                   [ Help ]
================================================================================
  ┌──────────────────────────────────────────────────────────────────────────┐
  │            writing etc/fstab                                            ^│
  │            configuring multipath                                         │
  │            updating packages on target system                            │
  │            configuring pollinate user-agent on target                    │
  │            updating initramfs configuration                              │
  │            configuring target system bootloader                          │
  │            installing grub to target devices                             │
  │final system configuration                                                │
  │  configuring cloud-init                                                  │
  │  calculating extra packages to install                                   │
  │  downloading and installing security updates                             │
  │    curtin command in-target                                              │
  │  restoring apt configuration                                             │
  │    curtin command in-target                                             ││
  │subiquity/Late/run                                                       v│
  └──────────────────────────────────────────────────────────────────────────┘

                               [ View full log ]
                               [ Reboot Now    ]

上記でReboot Nowを選択すると、仮想マシンの再起動後に再度インストーラが起動します。そのためCtrl-a xで、QEMUを一旦終了します。

インストールしたLinuxの起動

インストールに使用したQEMUのコマンドラインからインストーラISOイメージドライブとカーネルの指定を除いた以下で、インストールしたLinuxが起動できます。
#!/bin/sh

QEMU=qemu-system-x86_64
DISK_IMAGE=drive1.img
MEMORY=2048

${QEMU} \
-cpu host \
-enable-kvm \
-m ${MEMORY} \
-drive format=raw,file=${DISK_IMAGE},if=virtio \
-nographic

参考記事

仮想マシンのドライブやネットワークインターフェイスカードなどをカスタマイズするには以下の記事を参照。

QEMUでNIC(ネットワークインターフェイスカード)を追加するオプション例

ユーザモードNICの追加

ユーザモードNICは、QEMU内でNATされたネットワークに接続されており、プライベートIPが割り当てられる。NETDEV_IDにはn1やnetdev1など任意の名前を設定可能。
-netdev user,id=NETDEV_ID \
-device virtio-net-pci,netdev=NETDEV_ID
あるいは単純に以下のようにしてもよい。
-nic user,model=virtio-net-pci

ポートフォワーディングの設定

ユーザモードネットワークでは、外部から仮想マシンへの通信ができません。 以下のようにhostfwd=...を追加することで、ホストのポートをゲストに転送することができます。以下の例ではホストの5522ポートが、ゲストの22ポートに転送されます。
-netdev user,id=NETDEV_ID,hostfwd=tcp::5522-:22 \
-device virtio-net-pci,netdev=NETDEV_ID
-nicを用いる記述でもポート転送を指定できます。以下の例ではさらに、複数のポートを転送する例を記載します。
-nic user,model=virtio-net-pci,hostfwd=tcp::5522-:22,hostfwd=tcp::5580-:80

ブリッジモードNICの追加

ブリッジモードでは、tapインターフェイスが作成され、ホストOSのブリッジに組み込まれます。ブリッジに組み込むためのスクリプトとしてDebianやUbuntuでは、 /etc/qemu-ifupが使用されます。そのスクリプトでは、デフォルトGWになっているブリッジに作成されたtapインターフェイスが組み込まれます。 次の記事にホストOSでブリッジを作成する方法、および、ブリッジにtapが組み込まれた状態の図が掲載されています。 ブリッジモードでは、mac=で、作成するNICのMACアドレスを指定する必要があります。 他とNICと重複しないように適宜変更します。また、ブリッジモードを使用するにはroot権限でQEMUを実行する必要があります。
-netdev tap,id=NETDEV_ID \
-device virtio-net-pci,mac=02:12:34:56:78:9a,netdev=NETDEV_ID
ブリッジに関しても-nicオプションでより簡潔に記載することが可能。
-nic tap,model=virtio-net-pci,mac=02:12:34:56:78:9a

NICを使用しない場合

上記で説明したオプションを明示しない場合、デフォルトでユーザモードのNICが仮想マシンに作られます。 このデフォルト動作を無効にしてNICのない仮想マシンを作成するには以下を指定します。
-nic none

参考記事

QEMU用の仮想ドライブイメージファイルの作成例

QCOW2

QCOW2は、ドライブの使用量に応じて増加していくので、ホストOS上のストレージサイズ消費量が抑えられる。 例えば、仮想マシン上で、ドイラブのサイズは10GiBに見えても、ホストOS上では、実際の使用量程度である。
$ qemu-img create -f qcow2 drive.img 10G
Formatting 'drive.img', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=10737418240 lazy_refcounts=off refcount_bits=16
ls-sオプションを指定してファイルサイズを見てみる。一番左端の196KiBは、そのファイルのストレージ上に占めるサイズ。 所有者foo fooの右側の193KiBは、そのファイルのサイズ。 両者は、ほぼ同じ(これが一般的)。上記コマンドで10GiBのドライブイメージファイルを作成したが、実際のファイルサイズは初期状態では非常に小さい。
$ ls -lhs drive.img 
196K -rw-r--r-- 1 foo foor 193K Mar 23 20:30 drive.img

RAW

RAW形式は物理的なドライブと同じ形式である。そのため、物理ドライブからddなどで内容を読み出しものは、RAW形式のドライブイメージファイルとしてそのまま使用できる。また、一般的にQCOW2より性能的に優れるとされる。
$ qemu-img create -f raw drive.img 10G
Formatting 'drive.img', fmt=raw size=10737418240
QCOW2の場合と同様にlsでファイルサイズを調べると、上記コマンドで指定したとおり10GiBである。しかし、一番左端の実サイズは非常に小さい。実はRAW形式も、Linuxの多くのファイルシステム(例えばext4)では、スパースファイルと呼ばれる状態のファイルとして作成される。利用に応じて実サイズが増加する。
$ ls -lhs drive.img 
4.0K -rw-r--r-- 1 foo foo 10G Mar 23 20:31 drive.img

関連記事

QEMUの記事一覧

QEMUでドライブを追加するオプション例

VIRTIOドライブ

  • Linux上では、このドライブは/dev/vda[N](N=1,2,3...)に見える
  • VIRTIOは性能がよく、特段の理由がなければ、これがベター
  • DRIVE_IDは、例えばdrive0のような任意の名前でよい。複数指定する場合は重複しないようにする

QCOW2イメージ

-drive id=DRIVE_ID,format=qcow2,file=FILE_NAME.qcow2,if=virtio

RAWイメージ

-drive id=DRIVE_ID,format=raw,file=FILE_NAME.img,if=virtio

SCSIドライブ

SCSIインターフェイスを1つ作成
-device virtio-scsi-pci
次いでドライブを作成
  • 複数のドライブが必要な場合、以下の2行をidを変えて繰り返す
  • 以下ではドライブイメージがqcowの場合を示しています。rawの場合は上記を参照
  • これらのドライブはLinuxは、/dev/sda[N](N=1,2,3...)に見える
-drive id=DRIVE_ID,format=qcow2,file=FILE_NAME.qcow2,if=none \
-device scsi-hd,drive=DRIVE_ID

USBドライブ

xHCIインターフェイスを1つ作成
-device nec-usb-xhci,id=xhci
次いでドライブを作成。
  • 複数定義する場合、SCSIドライブと同様に以下の2行をidを変えて繰り返す。
-drive id=DRIVE_ID,format=raw,file=FILE_NAME.raw,if=none \
-device usb-storage,bus=xhci.0,drive=DRIVE_ID

参考

QEMUの記事一覧

QEMUのnographicモードでモニタに移行する

モニタ画面への移行

  • Ctrl-a c

すると以下のようなモニタ画面が表示される

QEMU 7.2.0 monitor - type 'help' for more information
(qemu) 

シリアルコンソールへの復帰

モニタへの移行と同じキー操作

実行中に強制終了

  • Ctrl-a x

関連記事

QEMUの基本的な使用方法

QEMUは、ハイパーバイザー型の完全仮想化ソフトウェアです。Linuxでは、Virt-Manager経由で利用されることもしばしばあります。 しかし、QEMUの持つ機能を直接使用したり、よりシンプルに利用する場合、QEMUを直接起動するほうが便利です。 この記事では、基本的な起動方法を紹介します。

なお、x86_64アーキテクチャでは、LinuxのKVMという仮想化支援機能を用いて高い実行性能を実現しています。 そのめ、QEMU/KVM、あるいは、単にKVMと呼ばれることもあります。

基本形

QEMUのコマンドラインは、仮想マシンの構成を含むためやや長くなりがち。そのため、以下ではシェルスクリプトとして起動コマンドを記載する例を示す。下記の内容を適当なファイル名(例: launch-qemu.sh)で保存し、実行すればよい。
#!/bin/sh

QEMU=qemu-system-x86_64
DISK_IMAGE=disk1.raw
MEMORY=1024

${QEMU} \
-enable-kvm \
-cpu host \
-m ${MEMORY} \
-drive format=raw,file=${DISK_IMAGE},if=virtio \
-nic user,model=virtio-net-pci
上記の実行により、次のようなWindowが起動する。

ドライブを追加する(SCSI接続のドライブ追加やUSBドライブの接続を含む)

以下の記事を参照

NICをブリッジモードに変更したり、ユーザモードで外部からアクセスする

上記の-nic userは、QEMU内でのNATを行うNICを追加する。 10.0.2.0/24のプライベートアドレスが仮想マシンに割り当てられる。 仮想マシン内から外部へのアクセスは行えるが、以下の制約がある。
  • pingで外部のノードと通信できない
  • 外部ノードから仮想マシンにアクセスできない(例えば、sshやnginxを仮想マシンで起動しても外部からアクセスできない)
これらが問題となるなる場合、ブリッジモードにするか、ユーザモードでポートフォワーディングの設定をする。 設定方法については、以下の記事を参照。

シリアルコンソールで起動する

X11を使っていない場合や、GUIのWindowが不要な場合、-nographicオプションを追加すると、 コマンドを起動した端末をシリアルコンソールにすることができる。
-nographic
nographicモードでシリアルコンソールとなった端末から復帰する方法については以下を参照

カーネルを直接起動する

冒頭のコマンド例では、物理マシンと同じように仮想ドライブ内に格納されているブートローダーが、同じく仮想ドライブ内のLinuxカーネルを起動する。QEMUは、ホストOS上の(仮想ドライブ内にない)Linuxカーネルを直接起動できる。以下に追加するコマンド例を示す。 -appendはカーネルの起動オプションである。
-kernel vmlinuz \
-append root=PARTUUID=a99825a2-e759-4e41-9c4c-b4804d050caa console=ttyS0 \
-initrd initrd.gz

参考