QEMUをSSH越しのCUIなどで使用する際に-serial mon:stdio
を指定して仮想マシンのシリアル出力を別GUIではなくqemuのコマンドをたたいたその場所に出力させることがある。この際、QEMUそのものの出力と仮想マシンがシリアル通信ポート (PL011)に書き込んだことによる出力が混在してしまって解析が行いにくい時がある。
-serial
オプションと-chardev
オプションを組み合わせることでシリアル通信用のコンソールとQEMUを立ち上げたコンソールを別々に用意することができる。最新版であるQEMU 8.2.0を使ってこの方法を紹介していく。
chardev/serialのhelp表示
8.2.0におけるhelp表示の関係する部分を確認する。まずは-chardev
に関する箇所は以下のようになっている。
Character device options:
-chardev help
-chardev null,id=id[,mux=on|off][,logfile=PATH][,logappend=on|off]
-chardev socket,id=id[,host=host],port=port[,to=to][,ipv4=on|off][,ipv6=on|off][,nodelay=on|off]
[,server=on|off][,wait=on|off][,telnet=on|off][,websocket=on|off][,reconnect=seconds][,mux=on|off]
[,logfile=PATH][,logappend=on|off][,tls-creds=ID][,tls-authz=ID] (tcp)
-chardev socket,id=id,path=path[,server=on|off][,wait=on|off][,telnet=on|off][,websocket=on|off][,reconnect=seconds]
[,mux=on|off][,logfile=PATH][,logappend=on|off][,abstract=on|off][,tight=on|off] (unix)
-chardev udp,id=id[,host=host],port=port[,localaddr=localaddr]
[,localport=localport][,ipv4=on|off][,ipv6=on|off][,mux=on|off]
[,logfile=PATH][,logappend=on|off]
-chardev msmouse,id=id[,mux=on|off][,logfile=PATH][,logappend=on|off]
-chardev vc,id=id[[,width=width][,height=height]][[,cols=cols][,rows=rows]]
[,mux=on|off][,logfile=PATH][,logappend=on|off]
-chardev ringbuf,id=id[,size=size][,logfile=PATH][,logappend=on|off]
-chardev file,id=id,path=path[,input-path=input-file][,mux=on|off][,logfile=PATH][,logappend=on|off]
-chardev pipe,id=id,path=path[,mux=on|off][,logfile=PATH][,logappend=on|off]
-chardev pty,id=id[,mux=on|off][,logfile=PATH][,logappend=on|off]
-chardev stdio,id=id[,mux=on|off][,signal=on|off][,logfile=PATH][,logappend=on|off]
-chardev braille,id=id[,mux=on|off][,logfile=PATH][,logappend=on|off]
-chardev serial,id=id,path=path[,mux=on|off][,logfile=PATH][,logappend=on|off]
-chardev parallel,id=id,path=path[,mux=on|off][,logfile=PATH][,logappend=on|off]
chardevに関しては-chardev help
で次のような表示が行えるとかかているので実行すると下記が出力された。
qemu-system-x86_64 -chardev help
Available chardev backend types:
ringbuf
mux
pipe
stdio
pty
null
msmouse
socket
braille
vc
parallel
dbus
memory
udp
file
wctablet
serial
testdev
次に-serial
に関する場所をみると下記。
Debug/Expert options:
-compat [deprecated-input=accept|reject|crash][,deprecated-output=accept|hide]
Policy for handling deprecated management interfaces
-compat [unstable-input=accept|reject|crash][,unstable-output=accept|hide]
Policy for handling unstable management interfaces
-fw_cfg [name=]<name>,file=<file>
add named fw_cfg entry with contents from file
-fw_cfg [name=]<name>,string=<str>
add named fw_cfg entry with contents from string
-serial dev redirect the serial port to char device 'dev'
-parallel dev redirect the parallel port to char device 'dev'
-monitor dev redirect the monitor to char device 'dev'
-qmp dev like -monitor but opens in 'control' mode
-qmp-pretty dev like -qmp but uses pretty JSON formatting
-mon [chardev=]name[,mode=readline|control][,pretty[=on|off]]
-debugcon dev redirect the debug console to char device 'dev'
こちらは断片的な情報しかなくこれだけ見てオプションを考えることは難しい(QEMUは他もそうだが)
serial chardev:の使用
この使用例は-serial
のヘルプには書かれていないが下記のようにして使える。
qemu-system-x86_64 \
-chardev socket,id=uart,path=/tmp/qemu.socket,server=on \
-serial chardev:uart \
...
この引数でqemuを起動するとQEMUの出力はそのままのターミナルに流れながら別途で/tmp/qemu.socketにUNIXソケットが生えてくる。別ターミナルで
nc -U /tmp/qemu.socket
もしくは
socat UNIX-CONNECT:/tmp/qemu.socket STDIO
で接続することでこちらは仮想マシンのシリアル出力を確認することができる。
おまけ mon chardev:
下記のようにすると当該chardevはQEMUモニタ用のチャンネルになるらしい。
qemu-system-x86_64 \
-chardev socket,id=monitor,path=/tmp/qemu.socket,server=on \
-mon chardev:monitor \
...
モニタは接続すると次のようなインタラクティブシェルが現れる。
QEMU 8.2.0 monitor - type 'help' for more information
(qemu) x
unexpected end of expression
Try "help x" for more information
(qemu) quit
通常これはQEMU起動したターミナルでCtrl-A+Cで入れるものだがこちらも別ターミナルで操作できるようにしておくことで同じ理由で利便性や何かを自動化するうえでの実現性が増しそうである。このほか、"Debug/Expert options"ヘルプにあるようにgdbの接続なども別ターミナルで行える。