利用Ubuntu的字符界面实现虚拟机的最小化内存占用+最快启动

本文介绍了如何通过切换Ubuntu虚拟机到字符界面,结合SSH X11Forwarding功能,实现内存占用最小化和快速启动。通过禁用图形界面、配置自动登录、选择VcXsrv作为Windows下的Xserver,以及开启SSH的X11Forwarding,实现了虚拟机的高效嵌入式开发环境,有效降低了内存占用和提高了启动速度。

目录

需求产生

分析问题

解决问题

切换默认启动到字符界面

选择共享剪切板实现的方式

挑选并启动Windows下的Xserver

开启ssh服务器的X11Forwarding功能

开启SSH客户端的X11Forwarding功能

正确的连接本地虚拟机

效果演示

后记


需求产生

自从业的第三个年头开始,本人的ARM嵌入式开发环境一直都是Windows + Virtualbox +  Ubuntu + Zsh + Tmux + Vim + Putty这几个黄金搭档。每次电脑重启后的统一操作都是 启动Virtualbox -> 等待完全启动 -> 启动Putty -> SSH 远程登录到Ubuntu -> 启动Tmux 开启多个标签页。这个些操作由于过于统一和频繁,因此在很早之前就已经被自动化了(自动化的原理和流程打算后面有空再写一篇文章来专门描述)。由于囊状羞涩,这些年使用的笔记本内存几乎都是统一的8G, Windows启动后默认占用2.4G,虚拟机一般分配2.5G(已经很少了),Chrome一般占用500M,外加一些其他的必须软件,系统基本在开发环境运行时就已经占用了6G,运行一段时间后内存占用一般会到7G,近乎90%的长期占用量,让我这种强迫症患者很是难受。于是在想在不花钱换电脑的情况下有没有办法让内存的占用量降低点,日常使用长期占用率在80%以下那将会大大降低的我对内存的焦虑感。

分析问题

有了想法自然就会心心念念,于是终于在一个闲暇的下午我开始认真的分析了一下这个问题。首先看一下内存的占用情况,Windows的2~3G内存占用一般是不太能动了,花精力各种精简系统也许可以换来500M的节省,但这样做势必会导致windows功能不全,动不动系统就报这个没有那个没有的体验肯定划不来。Ubuntu18.04一般在开机后默认会占用2G以上的空间,因此,实际上2.5G的内存分配量,在系统启动后往往完全空闲的空间就只剩200~300M了(可怜的虚拟机,还没干活就只剩这么点内存了)。Ubuntu之所以一启动就占用2G以上的内存, 一是因为启图形界面占用了大概800M的空间,二是因为启动图形界面过程中载入的大量文件缓存也占用了超过1G的空间。虽然从Ubuntu系统角度上看, 这些文件缓存随时都可以被回收重利用,但从Windows系统上看,这些缓存就是一启动就一直被占用内存空间。而嵌入式开发的实际流程中,Linux虚拟机的存在一般只是用来折腾各种嵌入式开发板的SDK,一个配置的牛逼点的VIM往往可搞定一切开发过程中的源码编辑工作。这么看来如果是纯嵌入式开发,实际上Linux虚拟机的图形界面是可有可无的。实际的情况也的确如此,如果你习惯于使用Putty+SSH登录本地的虚拟机来完成开发任务。那么Ubuntu的图形界面打开使用的概率几乎是不到百分之一。至此就很明显了,如果能干掉这个虚拟机的图形界面,内存占用就可以降低。

解决问题

切换默认启动到字符界面

有了方向就可以着手修改了,简单百度一下,可以知道Ubuntu16.04之后系统改用Systemd作为init管理进程了,在Systemd架构下关闭图形界面直接进入字符界面的配置指令如下:

sudo systemctl set-default multi-user.target # 切换启动目标到多用户的字符界面

该操作后重启系统将自动进入简单的tty1终端,整个图形界面都将不会启动。它的逆操作为:

sudo systemctl set-default graphical.target  # 开启用户图形界面

设置启动到multi-user.target模式后重新启动后将自动跳转到tty1终端的用户登录界面,此时输入用户名+密码即可登录到tty1终端。虽然这个古老到连中文都不能正常显示的tty1终端使用的频率很小,但每次启动后还要手动登录的体验明显不好,我们可以通过如下方法来实现这个tty1终端的自动登录操作:

sudo vi /etc/systemd/system/getty.target.wants/getty@tty1.service

修改

ExecStart=-/sbin/agetty --noclear %I $TERM

ExecStart=-/sbin/agetty -a boddy --noclear %I $TERM

注意:其中的boddy是你真实的用户名。
 

选择共享剪切板实现的方式

通过Putty + SSH + VIM的方式作为开发环境时一个可以在虚拟机和Windows之间完全共享的全局剪切板特性是非常重要的,在我之前"有关VIM的共享剪切板实现"的文章中有提到,这种共享剪切板的实现有两种办法:

1. 通过绑定Xwindow的图形界面到本地(export DISPALY=:0)外加virtualbox提供的增强功能中剪切板共享功能即可实现Linux和Windows之间的剪切板共享。该方法实现原理可以简单描述如下:Virtualbox在给虚拟机系统安装了增强功能后将会在Linux虚拟机中添加并自动启动“/usr/bin/VBoxClient --clipboard”程序,该程序负责连接Xwindow的系统全局剪切板并配合virtualbox本身完成和Windows系统剪切板同步工作。这种方式实现的共享剪切板的桥梁就是那个VBoxClient程序,该程序是在图形界面启动的过程中被自动启动的。

2. Xwindow架构中存在Xserver和Xclient的概念,Xclient一般集成于Linux系统的底层,主要负责管理用户的输入,Xserver可以在本地也可以在远端,负责图形界面的输出,只要Xclient正确和Xserver连接上了,全局剪切板就可以自动实现共享。Xserver的运行可以分为如下几种情况:

        a. 如果启动了本地的图形界面,责一般Xserver直接集成于本地的图形界面中。此时一般会通过"export DISPLAY=:0"环境变量来告知Xclient:你要连接的Xserver在本机。

        b. 如果希望Xclient连接一个远程的Xserver,则可以通过以下两种方式来实现:

            1)通过设置"export DISPlAY=IP_ADDR:0.0"的方式来完成通知Xclient将图形界面相关的请求转发到IP_ADDR所在的Xserver上,其中的IP_ADDR必须配置正确远端IP并在Linux启动之前已经正确的启动了Xserver,否则将很容易导致系统启动时卡死在Xclient初始化阶段!

            2)SSH本身就具备X协议转发的能力,因此,如果通过SSH远程登录,则可以通过开启X11Forwarding特性来实现和SSH客户端所在主机中Xserver的连接。

分析上面三种情况不难看出,方法a可用的前提是本地的图形界面必须启动且正确安装VirtualBox的增强功能,我们连图形界面都没启动,这种方法肯定不适用了,方法b的第一种"export DISPlAY=IP_ADDR:0.0"方法不依赖于本地图形界面的启动,但该方法严重依赖于IP_ADDR的正确设置,一旦该IP配置错误就将导致系统启动卡死,因此也不建议使用。兼容性最强,对系统配置依赖最低的是方法b的第二种情况。下面我们着重来针对该情况来完成共享剪切板的配置过程。

挑选并启动Windows下的Xserver

Windows系统下Xserver的实现目前找到的可用的有 :

1. MobaXterm中自带的X Serever

2.XMing

3.VcXsrv

MobaXterm的Xserver在配合直接使用MobaXterm远程登录时比方便,不过由于我个人平时使用Putty完成远程登录操作,因此没有使用它。XMing是一个很早的项目,目前已经很多年没有维护了,不过依然可用。VcXsrv貌似是微软官方支持的Xserver,从启动界面上看基本上可以确定是就是Xming的借壳重生版本,VcVsrv启动速度快,内存占用少,运行稳定且可以很容易实现静默启动。因此最终就选择它作为Xserver。

VcXsrv的下载安装网上到处都有,因此就不再赘述了,这里重点说一下静默启动VcXsrv的方法:

 1. 启动一次VcXsrv,并正常完成配置,配置截图如下:

 

 

前两个都是默认配置,第三个配置界面需要注意勾选"Disable access control",如不勾选的话远程连接的IP在没有配置许可的情况将总是被拒接,为避免连接被默认拒接,这里勾选就可以了。 最后一个界面中点击“Save configuration”即可将刚刚配置的参数保存到指定的位置(这里假定保存位置为D:\IDE\VcXsrv\config.xlaunch)。

保存完配置后,找到的VcXsrv安装目录下的xlaunch.exe文件,右键对其"创建快捷方式"并修改快捷方式的属性中的"目标” 为 “D:\IDE\VcXsrv\xlaunch.exe -run D:\IDE\VcXsrv\config.xlaunch”(个人的VcXsrv安装在D:\IDE\VcXsrv目录下)。此后只要双击这个lnk快捷键文件就可以实现静默启动了。如果希望XcXsrv随系统自启动, 只需要简单的将这个lnk快捷键复制到C:\Users\xxx\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup目录下即可(其中xxx是你的用户名)。

开启ssh服务器的X11Forwarding功能

实际上Ubuntu上的ssh-server(通过 sudo apt install openssh-server即可完成安装)在安装后的默认配置就已经打开了X11Forwarding功能,不过为了说明原理,这里还是需要说明一下配置位置的。

通过 sudo vi /etc/ssh/sshd_config即可打开ssh服务器的主配置文件,其中默认的"X11Forwarding yes"配置即表示开启了X11Forwarding功能,另外一个值得注意的地方是在X11Forwarding yes配置的下一行还有一个默认被注释掉了的"# X11DisplayOffset 10", 该注释说明了ssh服务器在设置X11Forwarding功能时默认转发的显示位置偏移是10。开启X11Forwarding时,当SSH服务器在和SSH client连接时ssh server将负责自动的设置DISPLAY环境变量为"localhost:10.0", 这一点在成功完成SSH登录后使用 "env|grep DISPALY" 可以得到验证:

 这里你应该已经注意到了参数中的10.0,其中10就来自于X11DisplayOffset的默认值。

开启SSH客户端的X11Forwarding功能

Windows下SSH客户端有很多,主流的有SecurceCRT、Xshell、Putty和MobaXterm,个人日常总是习惯于使用Putty做SSH远程登录客户端(选择Putty作为SSH客户端理由实际上有很多,后面我会专门写一篇文章来描述它),SecureCRT做为嵌入式开发板的调试客户端。因此下面以Putty为例来说明X11Forwarding的配置。

Putty的X11Forwarding功能的开启只需要一个配置即可,对应配置截图如下:

 勾选截图中的“ Enable X11 forwarding”即可开启X11Forwarding,"X display location在留空时默认配置应该也是localhost:10.0,因此在没有修改ssh服务器的X11DisplayOffset参数的情况下是可以留空不配置的。如果你参考了某些教程添加了该配置,那么默认应该要设置为localhost:10.0,注意其中10很重要,该值必须要X11DisplayOffset配置保持一致,否则将导致Xserver连接失败。

正确的连接本地虚拟机

如果使用SSH远程登录一个不在本地的远程服务器,那么唯一的方法自然是使用对外网卡的IP实现登录。但如果你登录的是运行在本地的virtualbox虚拟机,那么使用host-only网卡将是更加便捷高效的选择。

当你安装了virtualbox或者vmware到Win10上时, 他们都会自动在你的Win10的网卡列表中添加一个虚拟机的host-only网卡,以virtualbox为例,它长这样:

 这个网卡实际上是使用文件实现的一张虚拟网卡,该网卡有如下特点:

1. 无论何时,它总是自动的和virtualbox连接,连接状态不会因为你拔了网线就断了。

2. 由于该虚拟网卡底层实际是使用文件实现的,因此它的通讯速度非常快,如果你用的固态硬盘,那么它的通讯带宽可以轻松达到万兆。

3. 该虚拟网口的IP默认总是192.168.56.1,永远不会变

综上所述不难看出,这个host-only网卡本身就是为本地ssh客户端登录本地虚拟机量身定制的方案。因此我们必须用起来,使用要点记录如下:

要使用host-only网卡,我们首先需要为自己的虚拟机额外添加一张网卡并配置为host-only类型,配置截图如下:

我这里直接将虚拟机的第一张网卡就配置成了host-only,足以说明我对它的重视。

 默认情况下,虚拟机启动后这个网卡的IP由virtualbox负责动态分配,为了获得一个完全稳定的虚拟机登录地址,这里我们应该将其修改为静态分配,Ubuntu的网卡的静态分配方法就不再赘述了,直接上截图:

 

 截图中的第一张网卡enp0s3就是的我host-only网卡,这里我将其配置成固定的192.168.56.101。

 至此,我们就获得了一个高速通讯、永不掉线、IP地址固定的SSH连接到本地虚拟机的方式。任何时候通过192.168.56.101这个IP地址我们都将可以迅速的连接到本地虚拟机,以下是Putty的SSH登录固定配置截图:

效果演示

通过上面的各种配置后,我们将得到一个占用内存小,启动速度快的字符界面Linux虚拟机。该虚拟机任何时候都可以通过一个固定 IP完成本地SSH连,SSH登录后可以完成99%的日常开发工作。X11Forwarding功能的开启将会为我们提供一个Linux和Windows之间的共享剪切板,同时VcXsrv也为我们提供了一个完整的Xserver。

让我们演示一下最终的改造效果吧。

首先,我们实现了一个每次可以上电自动静默启动的VcXsrv。正确的配置自动后,每次Windows系统重启后X标记将自动出现在你的任务栏。

 接着你应该通过手动或自动的方式完成virbualbox虚拟机的启动,启动后Ubuntu虚拟机将自动进入字符界面并自动登录,由于没有启动图形界面,这个过程将从常规的10S以上缩短到5S,登录后界面截图如下:

 接着你需要使用开启了X11Forwarding功能的SSH客户端远程登录这个本地的虚拟机,登录后的默认内存占用量降低到200M左右,文件缓存和降低到600M,启动初始总占用低于1G:

 Windows下的初始占用量也来到5G(这还是在在开启了chrome等必要软件的情况下):

注意:由于虚拟机没有启动图形界面,对CPU的算力消耗也随之下降,日常使用时笔记本散热口的温度也也低了很多,啊,我的强迫症终于得到了根治!

登录后你还将获得一个拥有共享剪切功能的SSH终端。vim的*和+剪切板将自动变得可用:

此后你在windows下复制复制到剪切板的内容都将自动同步到vim的*和+号剪切板中。在vim中对*和+号剪切板的复制操作也将自动同步到windows剪切板上。以下是Dotto历史剪切板中显示的正确同步的剪切板内容:

为了方便的使用共享剪切板, VIM的一个必不可少的配置是配置VIM使用*和+剪切板作为默认操作的剪切(set clipboard=unnamedplus,unnamed),该配置完成后y和p等操作都将默认使用*和+剪切板:

X11Forwarding功能除了带来共享剪切板功能外还可以实现直接在windows上启动一些纯Xwindow框架实现的Linux应用,比如Wireshark:

 注意:上面的wireshark是通过SSH客户端启动的,但最终的图形界面是直接通过VcXsrv的Xserever功能完成展示的。

该功能理论上可以直接支持所有使用纯Xwindow架构实现的图形应用,可惜的是Ubunutu默认的多数应用使用的都不是纯Xwidndow框架,因此在图形界面没有启动的情况下,直接运行诸如gnome-control-center这些系统组件,将导致界面显示异常。

最后还需要知道的一点是,虽然系统默认启动进入了tty1字符终端。但这并不代表我们想要重新切换回图形界面时只能使用sudo systemctl set-default graphical.target操作。嵌入式开发中99%的时间都不需要用到完整的Ubuntu图形界面,如果真的遇到必须使用图形界面才能完成的操作,可以通过在tty1终端中输入sudo init 5 来实现临时切换到图形界面来完成:

        

注意:进入图形界面后,我们还可以通过sudo init 3或重启来重新回到tty1字符终端界面。 

后记

关于这个X11Forwarding的实现原理的个人理解: 

SSH Server端通过设置DISPLAY环境变量到localhost:10.0来完成对Xclient端对Xserver数据通讯的捕获,此后所有发送到Xserver的数据都将被SSH服务器通过ssh连接转发给ssh客户端,ssh客户端,默认情况下ssh客户端将忽略这些发送到Xserver的数据,在开启了SSH客户端的X11Forwarding功能后,ssh客户端将负责转发Xsever数据到指定的Xserver,默认的localhost:10.0位置描述了Xserver在本地,通过ssh客户端向localhost本地转发Xserver数据,本地运行的VcXsrv将可以正确的收到和Xserver通讯的数据。反向VcXsrv发送数据到Xclient原理类似。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值