我设置了一个虚拟机,除了自动调整大小功能似乎不一致之外,它运行良好。我让它随机工作了几次,但它也随机停止工作。它目前不工作,我不确定我需要做什么才能让它可靠地工作(比如 VirtualBox 自动调整大小)。请参阅下面的配置。
设置
Host: Ubuntu 16.10
Guest: Ubuntu 16.04.2, et. al (I've tried with other Linux distros with similar results)
Guest: created using virt-manager
Guest: installed spice-vdagent
Guest: virt-manager > View > Scale Display > Auto resize VM with window (checked)
香料
user@ubuntu:~$ ps aux | grep spice
root 805 0.0 0.0 30568 260 ? Ss 08:59 0:00 /usr/sbin/spice-vdagentd
user 1365 0.0 0.0 35124 2360 ? Ss 08:59 0:00 /usr/bin/spice-vdagent
user 1933 0.0 0.0 21292 1020 pts/17 S+ 09:00 0:00 grep --color=auto spice
青霞
user@ubuntu:~$ sudo lshw -c Video
*-display
description: VGA compatible controller
product: QXL paravirtual graphic card
vendor: Red Hat, Inc.
physical id: 2
bus info: pci@0000:00:02.0
version: 04
width: 32 bits
clock: 33MHz
capabilities: vga_controller rom
configuration: driver=qxl latency=0
resources: irq:10 memory:f4000000-f7ffffff memory:f8000000-fbffffff memory:fc058000-fc059fff ioport:c040(size=32) memory:c0000-dffff
我缺少什么来正确启用 qemu/kvm 的自动调整大小?
答案1
gnome 桌面,mutter,有一些处理调整大小的热插拔代码。
如果您有任何其他桌面,例如 xfce4 或 KDE,或者像我一样运行 compiz 的裸 .xinitrc 文件,那么您会遇到很多困难,但我想我终于找到了一个优雅而简单的解决方案。
xrandr --output Virtual-0 --auto
将从 vdagent 中获取大小并应用。所需的只是一个触发器。
这是触发器以及处理它的方法。
udev
将调整大小事件公开为如下所示的drm
设备:change
UDEV [10758.537471] change /devices/pci0000:00/0000:00:02.0 `drm/card0 (drm)
要让您的桌面对其做出反应,请创建一个udev
规则并引用脚本来调整大小:
规则/etc/udev/rules.d/50-x-resize.rules
:
ACTION=="change",KERNEL=="card0", SUBSYSTEM=="drm", RUN+="/usr/local/bin/x-resize"
/usr/local/bin/x-resize 中的脚本:
#! /bin/sh
PATH=/usr/bin
export DISPLAY=:0.0
xrandr --output "$(xrandr | awk '/ connected/{print $1; exit; }')" --auto
您可能需要根据您的情况定制该 shell 脚本。
我发现在 debian 10 和 Ubuntu 20.04 上我甚至不需要重新启动任何东西;它会立即恢复。
更新:2021-03-17
我最近发现我必须获得权限才能允许该脚本运行。我将其更改为:
#! /bin/sh
PATH=/usr/bin
desktopuser=$(/bin/ps -ef | /bin/grep -oP '^\w+ (?=.*vdagent( |$))') || exit 0
export DISPLAY=:0
export XAUTHORITY=$(eval echo "~$desktopuser")/.Xauthority
xrandr --output $(xrandr | awk '/ connected/{print $1; exit; }') --auto
答案2
我使用 Debian 10 和 icewm 作为客户虚拟机。当 spice-vdagent 运行时,我可以使用以下命令手动调整屏幕尺寸xrandr --output Virtual-1 --auto
使用 xev 也可以观察到显示尺寸的变化:
joe@l1:~$ xev -root -event randr
RRScreenChangeNotify event, serial 18, synthetic NO, window 0x3af,
root 0x3af, timestamp 39153, config_timestamp 82137
size_index 65535, subpixel_order SubPixelUnknown
rotation RR_Rotate_0
width 1320, height 949, mwidth 348, mheight 250
RRNotify event, serial 18, synthetic NO, window 0x3af,
subtype XRROutputChangeNotifyEvent
output Virtual-1, crtc 63, mode 1320x949 (1320x949)
rotation RR_Rotate_0
connection RR_Connected, subpixel_order SubPixelUnknown
使用它作为触发器似乎比使用 udev 更少干扰,特别是在同一个 VM 中使用不同的桌面环境或窗口管理器时。
joe@l1:~$ cat /home/joe/.xsession
#!/bin/sh
if [ -x /usr/bin/spice-vdagent ] ; then
/usr/bin/spice-vdagent
/home/joe/.icewm/xrandr-loop &
fi
exec /usr/bin/icewm-session
joe@l1:~$ cat /home/joe/.icewm/xrandr-loop
#!/bin/sh
sleep 2
xrandr --output "$(xrandr | awk '/ connected/{print $1; exit; }')" --auto
xev -root -event randr | \
grep --line-buffered 'subtype XRROutputChangeNotifyEvent' | \
while read foo ; do \
xrandr --output "$(xrandr | awk '/ connected/{print $1; exit; }')" --auto
done
joe@l1:~$
答案3
我很难让我的客户虚拟机支持分辨率大于 1080p 的两个显示器。事实证明,这是因为默认的 QXL 内存缓冲区 16 mib 不够大。如果您的两个显示器都只有 1080p,您可能不会遇到此问题。但如果是,则需要heads=2
通过属性设置并增加内存缓冲区vgamem
(在我的情况下,32 mib 有效)。
在我的系统上,我必须手动编辑 libvirt XML 配置才能进行此更改。为此,请查找属性vgamem
。它可能具有默认值16384
(即 16 mib)。要增加它,例如 32 mib,请将属性值更改为32768
。在我的系统上,以下修改后的 XML 片段来自:
<video>
<model type="qxl" ram="65536" vram="65536" vgamem="16384" heads="1" primary="yes"/>
<address type="pci" domain="0x0000" bus="0x00" slot="0x01" function="0x0"/>
</video>
到:
<video>
<model type="qxl" ram="65536" vram="65536" vgamem="32768" heads="2" primary="yes"/>
<address type="pci" domain="0x0000" bus="0x00" slot="0x01" function="0x0"/>
</video>
如果您不确定实际使用的值,您可以通过查看qemu
命令行参数来找出答案。在 Unix/Linux 系统上,启动客户机,然后运行ps -ef | grep qemu
... 并查找 QXL 设备。它可能看起来像-device qxl-vga,id=video0,ram_size=67108864,vram_size=67108864,vram64_size_mb=0,vgamem_mb=32,max_outputs=2,bus=pcie.0,addr=0x1
。vgamem_mb的价值三十二才是最重要的。
正确设置 QXL 驱动程序后,更改客户机分辨率应该很容易。您可以使用图形显示配置器,也可以xrandr
通过命令行使用。就我而言,我选择使用以下脚本自动执行该过程:
#!/bin/bash
if [ `xrandr | grep --extended-regexp --count "Virtual-0 connected|Virtual-1 connected"` == 2 ]; then
xrandr --newmode "1920x1200_60.00" 193.25 1920 2056 2256 2592 1200 1203 1209 1245 -hsync +vsync
xrandr --addmode Virtual-0 "1920x1200_60.00"
xrandr --addmode Virtual-1 "1920x1200_60.00"
xrandr --output Virtual-0 --mode "1920x1200_60.00" --panning 1920x1200+0+0 --output Virtual-1 --mode "1920x1200_60.00" --panning 1920x1200+1920+0
elif [ `xrandr | grep --extended-regexp --count "qxl-0 connected|qxl-1 connected"` == 2 ]; then
xrandr --newmode "1920x1200_60.00" 193.25 1920 2056 2256 2592 1200 1203 1209 1245 -hsync +vsync
xrandr --addmode qxl-0 "1920x1200_60.00"
xrandr --addmode qxl-1 "1920x1200_60.00"
xrandr --output qxl-0 --mode "1920x1200_60.00" --panning 1920x1200+0+0 --output qxl-1 --mode "1920x1200_60.00" --panning 1920x1200+1920+0
elif [ `xrandr | grep --extended-regexp --count "Virtual-0 connected"` == 1 ]; then
xrandr --newmode "1920x1200_60.00" 193.25 1920 2056 2256 2592 1200 1203 1209 1245 -hsync +vsync
xrandr --addmode Virtual-0 "1920x1200_60.00"
xrandr --output Virtual-0 --mode "1920x1200_60.00" --panning 1920x1200+0+0
else
xrandr --newmode "1920x1200_60.00" 193.25 1920 2056 2256 2592 1200 1203 1209 1245 -hsync +vsync
xrandr --addmode qxl-0 "1920x1200_60.00"
xrandr --output qxl-0 --mode "1920x1200_60.00" --panning 1920x1200+0+0
fi
请注意,这是针对 1920x1200 的设置。还值得注意的是,根据您的显示服务器、内核版本和驱动程序设置等,显示适配器可能会显示为“qxl-#”或“Virtual-#”。
要将上述脚本用于 1920x1200 以外的分辨率,您需要使用适当的模式行。要获取正确的模式行,请使用cvt
命令行工具。例如,如果您想要的是 4k(又称 2160p)显示器的模式行,您可以运行cvt 3840 2160 60
(假设刷新率为 60hz)。这将为您提供模式行:
# 3840x2160 59.98 Hz (CVT 8.29M9) hsync: 134.18 kHz; pclk: 712.75 MHz
Modeline "3840x2160_60.00" 712.75 3840 4160 4576 5312 2160 2163 2168 2237 -hsync +vsync
现在获取“Modeline”之后显示的值:
"3840x2160_60.00" 712.75 3840 4160 4576 5312 2160 2163 2168 2237 -hsync +vsync
并替换值:
"1920x1200_60.00" 193.25 1920 2056 2256 2592 1200 1203 1209 1245 -hsync +vsync
在上面的示例脚本中。
几点说明。也就是说,引号内的文本实际上是“标签”...因此您需要将引用替换为"1920x1200_60.00"
新模式行的标签。还值得注意的是,您可以在调用时省略刷新率cvt
,它会猜测...但如果您在客户系统内运行它,那么猜测可能会出错。为避免此问题,您可能需要在主机上调用cvt
。在这种情况下,您可以省略刷新率,并cvt
通过查看硬件来确定正确的值。
答案4
如果您使用的桌面环境(例如 Xfce)本身不支持动态屏幕调整大小(https://gitlab.xfce.org/xfce/xfce4-settings/-/issues/142),您可以运行一个脚本,该脚本xrandr -s 0
在 udev 每次通知drm
子系统发生变化时调用,以实现类似的功能。
对于易于打包/安装的易于使用的解决方案,您可能有兴趣尝试以下操作:https://gitlab.com/Apteryks/x-resize/,它将安装一个自动启动脚本并记录屏幕变化~/.local/state/x-resize.log.1
:
2023-12-30 04:31:58 (INFO): x-resize started; logging to /home/guest/.local/state/x-resize.log
2023-12-30 04:33:41 (INFO): screen 0 resized from 1024x768 to 1918x1010
2023-12-30 04:33:48 (INFO): screen 0 resized from 1918x1010 to 958x1010
2023-12-30 04:34:27 (INFO): screen 0 resized from 958x1010 to 958x470
它在 GNU Guix 中可用,可以通过 进行安装guix install x-resize
。