这周把一块RK3588板子塞进了一个工业机柜做上位机,现场没有给配显示器,连HDMI都没接。改完内核驱动想验证一下QT界面的实际显示效果,才发现自己一直在“盲改”——编译过了、进程起来了,但屏幕上是啥样完全靠猜。后来花了一个多小时把x11vnc配好,终于做到“板子上显示什么,我远程看到的就是什么”,这中间踩了不少坑,把完整过程和经验教训一起整理出来。
这篇文章适合手里有RK3588开发板、跑Ubuntu桌面系统,但又没有外接显示器的朋友——不管你是做嵌入式应用的,还是像我一样临时要调试GUI程序,x11vnc这套方案都能帮你少走弯路。核心解决两个问题:一是怎么在没有显示器的情况下通过VNC远程看到真实桌面,二是怎么让这个远程画面和板子本地输出保持完全同步,而不是各看各的。
1. 为什么“真同步”才是RK3588远程桌面的正确打开方式
1.1 无显示器场景下的两个典型状态
很多人一提到“无显示器远程桌面”,第一反应是装个VNC Server,然后远程连上去。但这里有个容易被忽略的问题:RK3588板子的“无显示器”其实分两种情况。
第一种情况是板子本身是带桌面系统的,比如Ubuntu Desktop或者Debian加个LXDE,只是因为部署位置没有显示器可接。这种情况下X服务其实已经在运行,桌面环境也起来了,只是没有物理屏幕输出。你说的“远程桌面”,本质上是要把这个已经存在的X11会话共享出去。
第二种情况是板子被当成纯服务器使用,压根没装桌面,系统启动后直接进命令行。这种情况下没有X会话,想远程看图形界面就必须自己先搞一个X服务出来。
x11vnc能解决的主要是第一种场景,而且它的核心优势就是“真同步”。它不像tigervnc那样会创建一个全新的、单独的虚拟桌面,而是直接去抓当前正在运行的X11桌面,把画面实时转发给VNC客户端。换句话说,你在远程看到的画面和HDMI接口输出的画面是同一个——改一个窗口、弹一个提示框,远程和本地同时都能看到。
这一点对调试太重要了。我见过不少人在板子上跑了一个OpenGL程序,用tigervnc新建一个会话去测试,结果发现画面渲染不正常,排查了半天才发现是两个不同的X display,硬件加速根本没落到同一个会话里。用x11vnc就没有这个烦恼。
1.2 x11vnc与其它远程桌面方案的取舍
在RK3588这种arm64平台上,可选的远程桌面方案其实不少,但各有利弊。
- tigervnc-standalone-server:会创建独立的X display,适合做“多用户远程桌面”,但和本地屏幕不同步,调试GUI应用时会遇到画面不一致的问题。
- vino:GNOME自带的VNC服务,配置简单,但默认只支持加密连接,很多Windows客户端连起来麻烦,而且性能调优空间小。
- xrdp:用RDP协议,Windows自带客户端直接连,体验流畅,但它默认也是创建新会话,不是镜像当前桌面,而且arm64上编译配置稍微麻烦一点。
- x11vnc:直接共享当前X11会话,延迟低、可控参数多、部署简单,缺点是只能镜像当前登录的桌面,不能提供独立的“多人会话”。
从我的实际体验来看,RK3588这种板子性能虽然比树莓派强不少,但也没到跑虚拟机或容器虚拟显示的地步,用x11vnc把现有桌面共享出去,是最省资源也最符合直觉的方案。
我整理了一个简单的对比表,方便你按需选型:
| 方案 | 是否镜像当前桌面 | 客户端兼容性 | 是否适合RK3588 | 典型问题 |
|---|---|---|---|---|
| x11vnc | 是,完全同步 | 所有VNC客户端 | 非常适合 | 需要X11运行、Wayland不支持 |
| tigervnc | 否,创建新会话 | 所有VNC客户端 | 可以用 | 和本地桌面不同步 |
| xrdp | 否,创建新会话 | Windows远程桌面客户端 | 可以 | 配置稍复杂,资源占用高 |
| vino | 是,镜像当前桌面 | 所有VNC客户端 | 一般 | 加密配置麻烦,性能调优弱 |
2. 环境准备:确认X11在跑,再谈x11vnc
2.1 先确认系统架构和桌面会话
我用的板子是RK3588加一块官方评估底板,系统刷的是官方提供的Ubuntu桌面镜像,内核是6.1的。拿到手之后第一件事,先把系统架构和桌面会话类型搞清楚,因为x11vnc依赖X11,如果系统跑的是Wayland,那后面全白搭。
这一步很简单,SSH登录板子后执行:
uname -m echo $XDG_SESSION_TYPE echo $DISPLAY ps aux | grep -E "xorg|wayland" | grep -v grep我的板子输出是这样的:
aarch64 x11 :0 root 1234 0.0 0.3 123456 1234 tty1 Ss 10:02 0:00 /usr/lib/xorg/Xorg看到XDG_SESSION_TYPE是x11,DISPLAY是:0,心里就踏实了——Xorg在跑,x11vnc有东西可以抓。
如果你执行完发现XDG_SESSION_TYPE是wayland,那x11vnc大概率是没法用的,因为Wayland的合成器不暴露X11的共享接口。这时候要么改登录桌面的会话类型(让GDM或者SDDM默认走Xorg),要么换用wayvnc这种专门适配Wayland的工具。我个人建议能换Xorg就换Xorg,因为Wayland环境下很多嵌入式场景的窗口管理行为差异很大。
2.2 安装x11vnc并完成基础配置
在RK3588的Ubuntu上安装x11vnc非常简单,官方源里就有arm64的包,直接apt装就行:
sudo apt update sudo apt install x11vnc安装完之后先设置访问密码。x11vnc的密码文件可以用它自己带的工具生成,也可以复用VNC的passwd格式:
x11vnc -storepasswd执行后会提示你输入密码,默认会保存在~/.vnc/passwd。这里有个细节:如果目录不存在,它会提示你先创建。手动创建一下:
mkdir -p ~/.vnc x11vnc -storepasswd /home/你的用户名/.vnc/passwd注意,x11vnc的密码文件权限要求比较严格,如果权限太开放,它会拒绝启动。改一下权限:
chmod 600 ~/.vnc/passwd提示:如果你用的是root账号跑桌面,密码文件位置就是在
/root/.vnc/passwd。很多人习惯所有操作都在root下搞,这时候别在普通用户目录里找密码文件。
到这里,基础准备就完成了。下一步是启动x11vnc试跑一次,确认它真的能把当前桌面抓起来,再做服务化配置。
3. 把x11vnc跑成稳定服务:systemd服务化与真同步配置
3.1 首次试运行与参数含义
先手动起一次x11vnc,确认能正常工作。我用的命令是:
x11vnc -display :0 -auth guess -forever -shared -rfbauth /home/你的用户名/.vnc/passwd -rfbport 5900 -o /tmp/x11vnc.log逐个解释这些参数,因为后面做服务化配置还会继续用到:
-display :0:指定要共享的X display,默认就是:0,但显式写出来能避免一些奇怪的权限问题。-auth guess:让x11vnc自动猜测Xauthority文件的位置。在Ubuntu桌面版上,这个文件通常在/run/user/1000/.mutter-Xwaylandauth.XXX或者/home/用户名/.Xauthority,用guess最省心。-forever:默认x11vnc在第一个客户端断开后就退出了,加上forever会持续监听,等着下一个客户端连接。-shared:允许多个客户端同时连接。调试的时候我经常要用手机和电脑同时看画面,这个参数很有用。-rfbauth:指定密码文件。-rfbport 5900:监听端口。VNC默认是5900,不需要改。-o:输出日志文件,排障的时候靠它。
启动后看日志:
cat /tmp/x11vnc.log如果看到类似The VNC desktop is: board-ip:0或者是PORT=5900这样的输出,说明已经监听起来了。
然后到电脑上用VNC客户端连接试试。我平时用TigerVNC的客户端,也试过RealVNC,都没问题。连接地址是板子IP:5900,输入刚才设置的密码,如果能看到桌面画面,说明这一轮成功了。
3.2 systemd服务配置与开机自启
手动启动虽然有-forever参数,但板子一重启就没了。生产环境必须做服务化,让x11vnc跟着开机自启,并且崩溃后自动拉起。
创建systemd服务文件:
sudo nano /etc/systemd/system/x11vnc.service内容如下:
[Unit] Description=x11vnc Remote Desktop Server After=multi-user.target [Service] Type=simple User=你的用户名 Environment=DISPLAY=:0 ExecStart=/usr/bin/x11vnc -display :0 -auth guess -forever -shared -rfbauth /home/你的用户名/.vnc/passwd -rfbport 5900 -o /var/log/x11vnc.log Restart=on-failure RestartSec=3 [Install] WantedBy=multi-user.target这里几个关键点:
User=必须指定成跑桌面的那个用户。如果你指定成root,然后桌面是普通用户启动的,x11vnc抓取X会话时很可能会提示权限不足或者直接黑屏。
Environment=DISPLAY=:0是给服务进程注入DISPLAY环境变量。有些情况下忽略这个变量,x11vnc也能靠-display :0参数工作,但加上更稳妥。
Restart=on-failure保证x11vnc意外崩溃后能在3秒后自动拉起。
配置文件写好后,重新加载并启用:
sudo systemctl daemon-reload sudo systemctl enable x11vnc sudo systemctl start x11vnc sudo systemctl status x11vnc如果你看到状态是active (running),并且日志里没有异常,这一步就完成了。
注意:如果出现
Can't open display: :0之类的错误,多半是X服务还没起来,或者是socket权限问题。RK3588的Ubuntu镜像默认Xorg绑定在/tmp/.X11-unix/X0,检查一下这个文件是否存在,以及当前用户是否有权限访问。执行ls -la /tmp/.X11-unix/,如果看不到X0,说明X服务根本没起来,不关x11vnc的事。
3.3 远程连接的客户端选择
服务端配好了,客户端的选择也挺关键。Windows上我用的是TigerVNC的Windows版客户端,体积小、连接快、对x11vnc的兼容性好。手机上用的是bVNC,紧急情况下用手机连上去看一眼状态非常方便。
连接时的参数一般不需要额外设置,但有一个可以留意:颜色深度。x11vnc默认会根据客户端协商调整色彩模式,有些客户端默认用低色深,导致画面颜色发灰。如果你有强迫症,可以在客户端里强制指定24位色彩,画面效果会好很多。
我一般会先在电脑上用TigerVNC连接测试画面是否正常、鼠标是否流畅、键盘输入是否跟手,确认无误后再开始调性能参数。别一上来就调性能,先保证基础功能可用,这是排障的基本思路。
4. 性能调优:让远程桌面不卡、不清、不闪
4.1 x11vnc的性能参数与效果对比
x11vnc默认参数在局域网内其实已经很流畅了,但如果你的使用场景是跨网络(比如从办公室远程到家里板子),或者板子负载很高,就需要做性能调优。
常见的调优手段有三个方向:压缩、帧率、编码。
压缩方面,x11vnc支持-compress参数,取值范围是0到9,默认是6。我实测下来,在RK3588上开高压缩会明显增加CPU占用,因为板子要花更多算力去压缩画面,而省下来的带宽在千兆局域网内感知不明显。如果你的网络环境不太好,可以试试-compress 9配合-quality 6。-quality控制JPEG图像质量,取值范围0到9,默认也是6。
我做了一组简单对比,板子CPU是RK3588,网络是千兆有线直连:
| 参数配置 | 1080p画面帧率 | 板子CPU占用 | 主观观感 |
|---|---|---|---|
| 默认参数 | 约25FPS | 25%左右 | 流畅,偶尔画面撕裂 |
| -compress 9 -quality 3 | 约35FPS | 45%左右 | 画面有轻微模糊 |
| -compress 6 -quality 9 | 约20FPS | 30%左右 | 画面精细,但帧率低 |
| -compress 9 -quality 9 | 约30FPS | 55%左右 | 画面和流畅度平衡较好 |
这里没有绝对最优,完全取决于你的网络和想要的主观体验。我自己的方案是局域网内用默认参数,跨网络的时候加-compress 9 -quality 4,兼顾流畅度和清晰度。
还有几个参数值得关注:
-wait:设置服务器检查屏幕变化的间隔,单位是毫秒,默认是50。改成-wait 10可以提升画面刷新率,但会显著增加CPU占用和网络流量。调试动效多一点的界面时我会临时加这个参数,平时保持默认。-defer:设置更新发送的延迟,单位是毫秒,默认是40。调低能减少画面延迟感,但更容易出现掉帧。-framebuffer:这个参数和显示内存有关,RK3588的Mali GPU显存和系统内存统一编址,一般不需要手动指定。有几次设置不当导致画面花屏,后来干脆不用它。
4.2 视频播放、OpenGL场景下的特殊处理
如果你和我一样,需要在远程桌面里看视频或者跑OpenGL渲染的界面,会发现一个尴尬现象:画面区域黑屏,或者只有视频控制条在动。
这是因为video overlay和GPU direct rendering的缓冲区和X11的framebuffer不是同一个。x11vnc默认抓取的是X11的framebuffer内容,而视频播放器或者OpenGL渲染出来的画面可能直接走了GPU的硬件overlay或者EGL路径,不会出现在X11 framebuffer里。
解决这个问题有一个常用参数:
-display :0 -xrandr -use_xrender-use_xrender强制x11vnc通过XRender扩展抓取合成后的画面,能在很多场景下抓到overlay和部分GPU合成的输出。不过它也能显著增加CPU占用,而且不是所有驱动都支持。
还有一个更简单粗暴的办法:把视频播放器的硬件加速关掉,让它用软件渲染。比如mpv加--vo=x11,浏览器视频播放时在设置里关闭硬件加速。这样一来,画面输出就会落到X11 framebuffer里,x11vnc自然就能抓到了。
如果你需要在远程桌面里跑OpenGL程序,建议在程序里设置环境变量LIBGL_ALWAYS_SOFTWARE=1,强制使用软件渲染。虽然性能会打折,但至少画面能传过来,方便你确认界面布局和交互逻辑。硬件渲染留给本地屏幕去跑,毕竟远程调试阶段主要看的是逻辑和界面状态。
5. 常见问题与排查技巧实录
5.1 连接失败问题速查表
这个表是我反复踩坑之后总结出来的,遇到问题对着查很有效:
| 现象 | 直接原因 | 排查命令/操作 |
|---|---|---|
| 客户端提示connection refused | x11vnc没起来,或端口被防火墙挡了 | sudo systemctl status x11vnc;`ss -tlnp |
| 连接后黑屏 | Xauthority权限不对,抓不到X会话 | 用-auth guess;检查~/.Xauthority权限 |
| Can't open display: :0 | X服务没启动,或DISPLAY设置错误 | `ps aux |
| 密码正确但不断弹认证框 | 密码文件格式不兼容或损坏 | 用x11vnc -storepasswd重新生成 |
| 画面极其卡顿,鼠标都挪不动 | 客户端和服务端色彩深度协商失败 | 客户端强制24位色深 |
| 连接上后立刻断开 | 已有一个连接且没开-shared | 加上-shared参数重启服务 |
| 远程看到桌面,但是键盘鼠标没反应 | VNC客户端没开启输入转发,或服务端用户权限受限 | 检查客户端设置;确认x11vnc进程User是否为桌面用户 |
| 手机能连,电脑连不上 | 局域网可能有设备隔离,或电脑防火墙拦截 | 在电脑上telnet 板子IP 5900测试端口通不通 |
遇到问题不要慌,先看日志。x11vnc的日志信息非常丰富,默认会打印出每一步操作和错误原因。我把日志路径统一放到/var/log/x11vnc.log,每次出问题第一件事就是:
sudo tail -50 /var/log/x11vnc.log80%的问题在日志里都有直接线索。
5.2 黑屏、断线、Wayland冲突等典型问题深挖
第一个想展开说的是黑屏问题。前期配置x11vnc时遇到黑屏,十有八九是Xauthority的问题。X11的安全机制要求访问X display必须有对应的授权文件。x11vnc用-auth guess自动查找,但某些系统上猜不到正确位置。这时候可以手动指定:
x11vnc -display :0 -auth /run/user/1000/.Xauthority注意不同系统的路径不完全一样,用find / -name ".Xauthority" 2>/dev/null搜一下最稳妥。
我自己遇到过一种比较怪的情况:明明Xauthority路径正确,但x11vnc还是黑屏。查了很久才发现是User=配错了,systemd服务里用的是root,而X会话是普通用户启动的。root进程去读普通用户的X authority,就算路径对也会被SELinux或者AppArmor拦下来。改成User=你的用户名之后再启动,问题立刻消失。
第二个常见问题是断线后重新连接失败。如果你没有加-forever参数,x11vnc在第一个客户端断开后就会退出。但有些时候加了-forever依然连不上,检查一下是不是还有残留进程占着端口:
ss -tlnp | grep 5900如果有个僵死进程占着5900,把它杀掉再重启服务就好。
第三个是Wayland冲突问题。前面提过,x11vnc只认X11。如果你板子刷的镜像默认用Wayland(比如较新的Ubuntu桌面版会默认切到Wayland),那这个过程会是另一个局面。我的一个朋友在RK3588上刷了某发行版的新版镜像,聚会时问我为什么vnc连不上,我远程看了下发现整个会话是Wayland的,后来让他换装了Xorg会话才解决。
RK3588的Ubuntu桌面切换Xorg的方式一般是:编辑/etc/gdm3/custom.conf,把WaylandEnable=false取消注释并重启GDM。但不同桌面管理器配置位置不太一样,搜一下自己的桌面管理器 + disable wayland基本都能找到。
还有一个冷门但很重要的坑:如果你在RK3588上跑的是Ubuntu镜像,而且系统里同时装了gdm3和lightdm,会导致X服务启动异常混乱。我自己遇到过开机后X起不来,查了半天发现是lightdm和gdm3在争抢显示管理器。直接用startx手动启动X是不行的,因为搞不清谁是权威。最后卸掉一个,只保留gdm3,世界才清净。
5.3 输入体验优化的小技巧
远程桌面光能看还不行,鼠标键盘操作必须跟手。x11vnc默认的输入体验在局域网内已经很接近本地了,但有几个细节能进一步优化体验。
第一个是鼠标加速度问题。VNC连接后,远程鼠标的灵敏度往往比本地高很多。可以在客户端里关掉鼠标加速度,或者在板子的系统设置里把鼠标加速调整到舒适档位。这个纯看个人习惯,有需要就调。
第二个是键盘布局问题。远程桌面连接后,如果本地键盘是美式布局,板子系统默认是德语或其他布局,输密码时就会发现符号对不上,特别折腾。解决方法是提前在板子的桌面设置里把键盘布局改成和客户端一致的布局,或者改x11vnc启动参数,让x11vnc尝试保持客户端传来的键盘状态。后者配置起来略麻烦,我一般直接改板子的键盘布局,一劳永逸。
第三个是触摸屏支持。RK3588的板子很多会接触摸屏,如果你要用远程桌面调试触摸程序,x11vnc默认会把鼠标点击转换成触摸事件,但多点触控手势是传不过去的。这个限制目前VNC协议无解,只能忍,或者远程调试时用鼠标模拟单点操作。
结语:最后一点实用建议
我在实际配置过程中最大的体会是:远程桌面的“真同步”不只是画面同步,还包含会话同步和输入同步。x11vnc能把这三者都做到,是因为它完全基于现有的X11会话工作,不搞虚拟显示器、不创建新会话,所以RK3588上跑的什么,你远程看到的就是什么。
最后再分享一个小技巧:RK3588板子如果在没有显示器的情况下启动Xorg,部分镜像会因为检测不到显示设备而自动降低分辨率或切换虚拟输出。遇到这种问题但又不想插一个假HDMI头的时候,可以看看内核cmdline里有没有video=参数可以设置,比如video=HDMI-A-1:1920x1080@60,强制指定Xorg的输出分辨率。这个参数不治本,但对不少RK3588板卡是很有效的兜底方案。
配置好x11vnc之后,我至少不用再为“本地到底显示什么样”猜来猜去了。编译完一个界面程序,远程连上去截图、录屏、操作,直接一步到位。如果你也经常和RK3588的GUI调试打交道,这套方案值得一试。