satumaimoの備忘録

個人的なメモ中心

PythonでQEMUとシリアル通信を行う方法の考察

こちらの記事の続きで、QEMUの起動/停止やQEMUモニタの操作と合わせてQEMUとのシリアル通信もPythonで自動化したいと考えています。

そこで、PythonQEMUとシリアル通信を行う方法を考えた結果をメモします。

QEMUからのシリアル通信デバイスの種類

公式ドキュメントによると、シリアル通信のデバイスとして概ね以下の種類が挙げられます。

これらの方法のうち、

  • ptyは割り当てられる仮想端末がQEMUを実行する度に異なる

  • /dev/XXXはroot権限が必要

  • stdioはQEMUモニタで使用する予定

といった理由から、telnetでシリアル通信を行う方法を採用したいと思います。

QEMU側の起動コマンド

qemu-system-aarch64 -cpu cortex-a57 -machine virt -kernel out.img -montor stdio -serial telnet::60000,server,nowait -nographic

telnetの使用するポートはプライベートなものを指定します。

Python側のコード

#!/usr/bin/python3

import telnetlib

host = "localhost"
port = "60000"

tn = telnetlib.Telnet(host=host, port=port)

tn.write(b"foo\r\n")

print(tn.read_until(b"ok\n", timeout=1).decode('ascii'), end="")

数行でtelnetを通してシリアル通信を行うプログラムが書けました。

なお、telnetの出力を読み出す関数としてread_until()以外にもread_some()read_eager()read_lazy()などがありましたが、

  • read_some()は読み出せる文字の数が不安定

  • read_eager()read_lazy()は何故か出力を読み出せなかった(環境の問題?)

といった理由で(少なくとも自分の環境では)使えないので、今回の場合はタイムアウトを指定しつつread_until()を使うのが適切だと思われます。

参考サイト

QEMU Emulator User Documentation

qemu: pyhtonでゲストとシリアル通信 - φ(・・*)ゞ ウーン カーネルとか弄ったりのメモ

telnetlib --- Telnet クライアント — Python 3.10.4 ドキュメント

Pythonでtelnet接続してみる | BTY備忘録