存档

2012年7月 的存档

如何使用 QEMU 中的虚拟串口

2012年7月25日 8 条评论

QEMU 具有模拟 串口并口 的能力, 在 QEMU 的命令行接口, 提供了 -serial 参数供用户设置把虚拟的串口重定向到哪里.

本文档主要介绍如何使用这个虚拟串口, 接下来会从代码方面描述 QEMU 如何模拟 一个串口.

不使用串口

$ qemu-kvm ArchLinux.img -serial none

不管是 Linxu 还是 Window, 在 QEMU 里面禁用了串口, 但是用一些硬件检测 工具还是能检测到串口的存在. 用一段简单的代码来检测是否串口可以使用

#!/usr/bin/python
import serial
try:
    s = serial.Serial('/dev/ttyS0')
    print "Find serial port on /dev/ttyS0"
except:
    print "Cant found serial port on /dev/ttyS0"

重定向到虚拟控制台

$ qemu-kvm ArchLinux.img -serial vc:800x600 # 或者 vc:80Cx24C

实际上, 默认 启动 QEMU 的时候如果不加参数的话, 会自动创建四个控制台, 分别用 Ctrl + Alt + number 来切换, number 为 1, 2 或 3, 4 其中 1 是 QEMU 的图形终端, 2 是 QEMU 的 Monitor 终端(QEMU 的 Monitor 稍候会介绍), 3 是 Serial 终端, 4 是并口终端.

重定向到一个伪终端

$ qemu-kvm ArchLinux.img -serial pty

然后会发生什么呢? QEMU 会自动创建一个伪终端设备(/dev/pts/3) 之类的, 然后 用 screen 之类的工具就可以操纵这个终端了.

PS. 这东西 Linux only 哟

重定向到 null

$ qemu-kvm ArchLinux.img -serial null

这和重定向到 none 有什么区别呢? 区别就是 -> none QEMU 不会虚拟串口设备, 但是 -> null 会虚拟一个串口设备, 丢弃所有的输出: 如以下的代码. 至于输入? 需要输入吗?

static int null_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
{
    return len;
}

重定向要真实串口设备

$ qemu-kvm ArchLinux.img -serial /dev/ttyS0

但是虚拟串口的硬件参数需要和真实串口符合

PS. Linux only 哟

重定向到并口

$ qemu-kvm ArchLinux.img -serial /dev/parportN

重定向到第 N 个并口

PS. Linux only 哟

重定向到一个文件

$ qemu-kvm ArchLinux.img -serial file:/tmp/serial.out

不过从打开文件的方式看来, QEMU 只是把串口的输出写入文件, 而并不支持串口的 输入.

TFR(fd_out = qemu_open(qemu_opt_get(opts, "path"),
                       O_WRONLY | O_TRUNC | O_CREAT | O_BINARY, 0666));

重定向到 stdio

$ qemu-kvm ArchLinux.img -serial stdio

把串口重定向到标准输入输出, 这给调试 Guest OS(其实我说的是 Linux OS, 你要调试 Window OS? 你吃饱了撑的?)提供了方便.

重定向到管道

$ qemu-kvm ArchLinux.img -serial pipe:/tmp/serial:

不过这玩意还比上面的复杂, 根据 QEMU 打开这类设备的代码, 需要手动创建 /tmp/serial.in 和 /tmp/serial.out 两个管道文件

snprintf(filename_in, 256, "%s.in", filename);
snprintf(filename_out, 256, "%s.out", filename);
TFR(fd_in = qemu_open(filename_in, O_RDWR | O_BINARY));
TFR(fd_out = qemu_open(filename_out, O_RDWR | O_BINARY));
$ mkdir fifo /tmp/serial.in
$ mkdir fifo /tmp/serial.out

怎么使用呢? cat /tmp/serial.out 会看到 Linux 登录的一堆信息, 最后停在 virt-debian login: 这里等待输入, 用

$ echo your_username >> /tmp/serial.in
$ echo your_password >> /tmp/serial.in

再打开 cat /tmp/serial.p.out 就可以看到内容已经变成 root@virt-debian:~# 这样的东西了.

所以这玩意对我用处不大

重定向到 udp 端口

$ qemu-kvm ArchLinux.img -serial udp::3333

将 QEMU 的串口重定向到 3333 端口, 使用 nc 访问这个端口 (当然可以自己编写 socket 访问). 这对远程管理很有帮助

$ nc -u -l -p 3333

重定向到 tcp 端口

$ qemu-kvm ArchLinux.img -serial tcp::3333,server,nowait

可以使用 telnet 来访问该端口

$ telnet localhost 3333

重定向到 telnet

几乎 TCP 是一样的

$ qemu-kvm ArchLinux.img -serial telnet::3333,server,nowait

重定向到 Unix socket

$ qemu-kvm ArchLinux.img -serial unix:/tmp/serial.sock,server,nowait

用 socat 连接

$ socat  /tmp/serial.sock STDIO

同时定向到串口和 mon 控制台

$ qemu-kvm ArchLinux.img -serial mon:telnet::3333,server,nowait

这将同时定向串口到 TCP 3333 端口的同时, 可以使用 Ctrl + a 然后按 c 访问 Monitor 终端

定向到 braille

这个太强大了, 相关 google braille

msmouse

重来没有使用过

分类: QEMU 标签:

在主机和虚机之间共享文件的N中方法

2012年7月15日 没有评论

以下是我常用的在主机的虚拟机间通信(共享文件)的常用方法(未完待续):

通过内建的 Samba 服务器

很少有人知道 QEMU 内置了一个 Samba server, 按如下方式启动 QEMU, 即可启用 它.

$ qemu-kvm -net nic -net user,smb=shared_directory ~/Image/XP.img

或者在旧的 QEMU 中版本中.(未来可能被失效)

$ qemu-kvm -smb shared_directory ~/Image/XP.img

之后 GUEST 就可以用 10.0.2.4(默认) 上访问这个文件夹, 例如在 Windows Explorer 中, 可以用 \\10.0.2.4, 在 gnome nautilus 中可以用 smb://10.0.2.4 访问.

更过的细节:

static int slirp_smb(SlirpState* s, const char *exported_dir,
                     struct in_addr vserver_addr)
{
    // ......
    /* s->smb_dir: "/tmp/qemu-smb.QEMUPID-0" */
    mkdir(s->smb_dir, 0700);
 
    /* smb_conf: "/tmp/qemu-smb.QEMUPID-0/smb.conf" */
    f = fopen(smb_conf, "w");
    fprintf(f,
            "[global]\n"
            "private dir=%s\n"
            "socket address=127.0.0.1\n"
            "pid directory=%s\n"
            "lock directory=%s\n"
            "state directory=%s\n"
            "log file=%s/log.smbd\n"
            "smb passwd file=%s/smbpasswd\n"
            "security = share\n"
            "[qemu]\n"
            "path=%s\n"
            "read only=no\n"
            "guest ok=yes\n",
            s->smb_dir,
            s->smb_dir,
            s->smb_dir,
            s->smb_dir,
            s->smb_dir,
            s->smb_dir,
            exported_dir
            );
    fclose(f);
 
    /* smb_cmdline: "smbd -s /tmp/qemu-smb.QEMUPID-0/smb.conf" */
    snprintf(smb_cmdline, sizeof(smb_cmdline), "%s -s %s",
             CONFIG_SMBD_COMMAND, smb_conf);
 
    slirp_add_exec(s->slirp, 0, smb_cmdline, &vserver_addr, 139);
 
    // ...... 
}

通过主机的 Samba Server

这种方式很简单, 把主机的 Samba server 打开, 在 Guest 里面就可以用 10.0.2.2 访问

$ /etc/init.d/samba start

通过主机SSH

同上, 在 Guest 中, 用 ssh 协议访问 10.0.2.2(Host IP) 这个 IP 地址

通过客户机 SSH(主机的端口转发)

$ qemu-kvm -m 1024 -redir tcp:3456::22 ~/Image/ArchLinux.img

QEMU 将会在 3456 端口监听, 收到数据后把所有端口转发到 Guest 的 22 端口.

在 Guest 上启动 ssh server, 然后在主机上就可以用下列的指令访问了.

$ ssh IP_Address_Of_Host -p 3456

qemu-nbd

qemu-nbd 是一个能使用 NBD 协议将 QEMU Image 导出的工具.

加载 nbd 驱动

某些版本的 linux 不加 max_part 参数会导致没有没有设备节点 /dev/nbd0p{1,2,3,4…} 等. 用 kpartx 也不行.

$ sudo modprobe nbd max_part=8

连接 qemu-nbd

$ sudo qemu-nbd -c /dev/nbd0 path/to/image/file # 注意要写绝对路径
$ fdisk -l /dev/nbd0 # 列出分区类型
$ mount /dev/nbd0p3 /mnt # 挂载虚拟磁盘的分区到本机

libgustfs

libgustfs 是一个想要一统天下的虚拟机镜像查看/修改工具, 号称支持几乎所有 类型的虚拟机镜像, 在它面前 qemu-nbd 弱爆了. 分析它显然超出了这篇文档的范围. 过后将会专门写一篇文章来分析它, 以下简单的提供一种利用 libguestfs 来访问 虚拟机镜像的方法.

首先, 安装它

# 在 Gentoo中, 使用
$ sudo emerge libguestfs
# 在 redhat 家族的发行版中, 使用
$ yum install libguestfs libguestfs-tools*

然后使用以下指令启动 guestfs 的命令行,

# --rw 参数表示挂载后对镜像具有读写权限, 可能有点慢, 需要
# 等待, 注意对运行中的虚拟机, 有必要使用 --ro 只读挂载
$ guestfish --rw -i -a path/to/image/file
 
# 创建一个临时挂载点, guestfs 的命令行接口可以执行命令
# 命令前面加 ! 就可以了
$ !mkdir /tmp/mnt
 
# 导出镜像文件到 /tmp/mnt, 导出后需要执行 mount-local-run
$ mount-local /tmp/mnt 
 
# 进入 mount loop, 类似于 glib 的 g_main_loop_run
# 卸载镜像后这个 loop 自动结束
$ mount-local-run

打开另外一个终端, 在 /tmp/mnt 里面就可以看到导出的文件了, 由于是读写方式的挂载, 可以在里面像在本地一样的读写文件, 完成后 使用下面指令卸载

$ fusermount -u /tmp/mnt

执行后, 上面的 loop 就会结束

启动虚拟机后, 所有的更改都会生效.

分类: libguestfs, QEMU 标签: ,