Linux下修改命令行终端显示的分辨率(tty)

以前写过一个Ubuntu下设置自定义桌面的分辨率的文章,使用的是xrandr和cvt,这次碰到的是要在下调整命令行终端的显示。在VMWare中CentOS的命令行终端(tty)默认是很小的(80x25),在偌大的显示屏(1920X1080)中显示出来就中间一小块。所以要解决的问题就是想办法将屏幕展开。

毫不犹豫的使用老方法——尝试xrandr命令,遗憾的是默认是没有的——没有X窗口系统嘛,就连cvt这个命令也没有踪影。

一招不行,再祭一招,修改grub.conf文件!通过修改grub.conf文件中kernel行——在最后加上vga参数,让系统在启动的时候能够自动加载适用的分辨率,如下面这样:

# grub.conf generated by anaconda
#
# Note that you do not have to rerun grub after making changes to this file
# NOTICE:  You have a /boot partition.  This means that
#          all kernel and initrd paths are relative to /boot/, eg.
#          root (hd0,0)
#          kernel /vmlinuz-version ro root=/dev/mapper/vg_mitchell-lv_root
#          initrd /initrd-[generic-]version.img
#boot=/dev/sda
default=0
timeout=5
splashimage=(hd0,0)/grub/splash.xpm.gz
hiddenmenu
title CentOS (2.6.32-431.5.1.el6.i686)
        root (hd0,0)
        kernel /vmlinuz-2.6.32-431.5.1.el6.i686 ro root=/dev/mapper/vg_mitchell-lv_root rd_NO_LUKS rd_NO_MD rd_LVM_LV=vg_mitchell/lv_swap crashkernel=auto LANG=zh_CN.UTF-8 rd_LVM_LV=vg_mitchell/lv_root  KEYBOARDTYPE=pc KEYTABLE=us rd_NO_DM rhgb quiet vga=365
        initrd /initramfs-2.6.32-431.5.1.el6.i686.img
title CentOS (2.6.32-358.el6.i686)
        root (hd0,0)
        kernel /vmlinuz-2.6.32-358.el6.i686 ro root=/dev/mapper/vg_mitchell-lv_root rd_NO_LUKS rd_NO_MD rd_LVM_LV=vg_mitchell/lv_swap crashkernel=auto LANG=zh_CN.UTF-8 rd_LVM_LV=vg_mitchell/lv_root  KEYBOARDTYPE=pc KEYTABLE=us rd_NO_DM rhgb quiet
        initrd /initramfs-2.6.32-358.el6.i686.img

vga=分辨率的编号(Mode ID),这简单了,也妥帖了,写个数字就把你的分辨率搞定,可讲起来非常简单,就是添加个vga参数,加个数值而已,但这个数值是什么呢?网上绝大部分的筒子们都是给出一个列表,类似下面这样的一个表:

Graphics modes 320×200 640×400   640×480 800×600 1024×768 1280×1024
16-color palette       258 (0102h), 106 (6Ah) 260 (0104h) 262 (0106h)
256-color palette   256 (0100h) 257 (0101h) 259 (0103h) 261 (0105h) 263 (0107h)
15-bit (5:5:5) 269 (010Dh)   272 (0110h) 275 (0113h) 278 (0116h) 281 (0119h)
16-bit (5:6:5) 270 (010Eh)   273 (0111h) 276 (0114h) 279 (0117h) 282 (011Ah)
24-bit (8:8:8) 271 (010Fh)   274 (0112h) 277 (0115h) 280 (0118h) 283 (011Bh)

一看,就是找个数字,直接填写个数字作为vga的值就了事,不错!可仔细一看,这个表中竟然没有我要的,这让我情何以堪。在没有参数的情况下,自然就想知道这个数字是怎么出来的,所以接下来,目标就是去找这个列表出来的出处。

谷歌和度娘没少用,可是所有分辨率还是基本都在使用xrandr——这让我清醒的认识到这将是一个多么冷门的想法。。。

再后来的事情就是看到vga参数可以写成

vga=ask

这个设置是让系统启动的时候,可以显示所有本地显卡支持的分辨率。这可比直接写数字好很多,至少知道有这个方法可以知道本地机器支持的分辨率选项了,即使写数字,通过上面给出的Mode ID,我也能够设置vga参数值了。但如果一直使用ask,问题就是每次系统启动的时候都需要我们做选择,不做选择就回到原来那一小块膏药似的界面上去。这个解决的方法就是每次都按ENTER进入设置咯。如果不愿意,第一次选择好合适的分辨率,通过按a进入对应的kernel行编辑,其实就是将vga=ask修改成对应的Mode ID。

另外一个问题是,这种情况是要在系统启动的时候设置,如果想在系统内设置,就没有办法了。好吧,Mitchell个人更希望能在系统内部直接设置好,虽然上面启动的时候设置已经很好了,继续找找能不能在系统内部设置。

最后,发现vga=ask的时候,启动屏幕的选择列表上有VESA(Video Electronics Standards Association)字样,按图索骥,发现其中的一个VESA的标准是VESA BIOS Extensions(VBE)。——对于菜鸟的我来说,这是多么深奥的一个词!干嘛用的?——不知道。

但在VESA BIOS Extensions的WIKI页面1,看到有SVGA2的也一个页面,查看了SVGA.txt之后,才发现:

This small document describes the "Video Mode Selection" feature which
allows the use of various special video modes supported by the video BIOS. Due
to usage of the BIOS, the selection is limited to boot time (before the
kernel decompression starts) and works only on 80X86 machines.

这... 这节奏的意思就是,要在系统内调用这个菜单设置是完全没有办法了啊!但我要的列表的呢?咋也没有呢?

不甘放弃,后来经过艰苦的寻找(没方向真是艰苦),找到工具hwinfo,这个Linux下的工具可以查找BOIS信息,同时可以通过--framebuffer参数查找到系统支持的分辨率,方法如下:

hwinfo --framebuffer |grep Mode

只需要--framebuffer里面的Mode信息,显示的结果类似下面这样:

  Model: "VMware virtual machine"
  Mode 0x0300: 640x400 (+640), 8 bits
  Mode 0x0301: 640x480 (+640), 8 bits
  Mode 0x0303: 800x600 (+800), 8 bits
  Mode 0x0305: 1024x768 (+1024), 8 bits
  Mode 0x0307: 1280x1024 (+1280), 8 bits
  Mode 0x030e: 320x200 (+640), 16 bits
  Mode 0x0311: 640x480 (+1280), 16 bits
  Mode 0x0314: 800x600 (+1600), 16 bits
  Mode 0x0317: 1024x768 (+2048), 16 bits
  Mode 0x031a: 1280x1024 (+2560), 16 bits
  Mode 0x0320: 320x200 (+320), 8 bits
  Mode 0x0321: 320x400 (+320), 8 bits
  Mode 0x0322: 640x400 (+640), 8 bits
  Mode 0x0323: 640x480 (+640), 8 bits
  Mode 0x0324: 800x600 (+800), 8 bits
  Mode 0x0325: 1024x768 (+1024), 8 bits
  Mode 0x0326: 1152x864 (+1152), 8 bits
  Mode 0x0327: 1280x960 (+1280), 8 bits
  Mode 0x0328: 1280x1024 (+1280), 8 bits
  Mode 0x0329: 1400x1050 (+1408), 8 bits
  Mode 0x032a: 1600x1200 (+1600), 8 bits
  Mode 0x032b: 1792x1344 (+1792), 8 bits
  Mode 0x032c: 1856x1392 (+1856), 8 bits
  Mode 0x032d: 1920x1440 (+1920), 8 bits
  Mode 0x032e: 320x200 (+640), 16 bits
  Mode 0x032f: 320x400 (+640), 16 bits
  Mode 0x0330: 640x400 (+1280), 16 bits
  Mode 0x0331: 640x480 (+1280), 16 bits
  Mode 0x0332: 800x600 (+1600), 16 bits
  Mode 0x0333: 1024x768 (+2048), 16 bits
  Mode 0x0334: 1152x864 (+2304), 16 bits
  Mode 0x0335: 1280x960 (+2560), 16 bits
  Mode 0x0336: 1280x1024 (+2560), 16 bits
  Mode 0x0337: 1400x1050 (+2816), 16 bits
  Mode 0x0338: 1600x1200 (+3200), 16 bits
  Mode 0x0339: 1792x1344 (+3584), 16 bits
  Mode 0x033a: 1856x1392 (+3712), 16 bits
  Mode 0x033b: 1920x1440 (+3840), 16 bits

.........more................

 这个出来的结果符合我的期望,这样就能直接在系统内部进行设置vga参数了,为了偷懒,写了个脚本,来提取信息:

###################################################
##
## Linux system terminal resolution utility
## Create by MitchellChu @2014.05.10
##
###################################################
#get system type
SysType=`cat /etc/issue|awk 'FNR==1{print tolower($1)}'`
#get hardware's framebuffer data and filter framebuffer information, then format it.
sudo hwinfo --framebuffer 2>/dev/null |grep "Mode\s*0x" | awk 'BEGIN{print "ModeID:Resolution-depth\t\tModeID:Resolution-depth"} {
output = (substr($2, 1, 6)+0)":"$3"-"$5$6
if(FNR%2==0) printf "%s\n", output; else printf "%s\t\t", output;}'
read -p "Please enter your mode id:" resolutionModeId
read -p "you choiced mode id is:$resolutionModeId, are you sure (y|n)?:" uconfirm
if [ "${uconfirm,,}" = 'y' ]; then
  case $SysType in
    "ubuntu") echo "ubuntu system..."
      sudo sed -i "s/^\s*linux\s.*$/& vga=$resolutionModeId/" /boot/grub/grub.cfg;;
    "centos") echo "CentOS system..."
      sudo sed -i "s/^\s*kernel\s.*$/& vga=$resolutionModeId/" /boot/grub/grub.conf;;
    "debian") echo "Debian system..."
      sudo sed -i "s/^\s*linux\s.*$/& vga=$resolutionModeId/" /boot/grub/grub.cfg;;
    *) echo "undetected system..."
      echo "the script unsupported current system.";;
  esac
else
  echo "Not file be updated."
fi
echo "script works done. you can reboot to enable new config."

这样将代码保存为脚本,在需要修改分辨率的时候,运行脚本就能获取系统支持的系统分辨率。

到此,总算不是很完美的达到了在系统运行的时候设置vga参数。为什么说不完美?因为CentOS下是没有hwinfo的,为了实现这个我们必须要手动去安装hwinfo(或者其他类似工具)。个人开始是希望从内存中直接读取BIOS的数据来获取显卡支持的分辨率,下面是个尝试之一:

sudo dd if=/dev/mem bs=1K skip=768 count=256 2>/dev/null | strings -n 8

但是由于不知道这些设置在内存中的位置,也不清楚BIOS在内存中的格式——个人猜想每个系统里BIOS保存的内存地址应该也会有差别。因此只能作罢。

 

TIPS:本文仅是个人作为对系统分辨率修改的一种尝试,菜鸟一枚,欢迎大家拍砖!

同时也注意,在某些情况下设置vag参数并不能达到我们需要的效果,比如参考文章4中提及的情况。

 

参考文章: 

 1. VESA BIOS Extensions

2. SVGA

3. VESAFB

4. How to set the resolution in text consoles

Sunday, May 11, 2014 | Unix & Linux

文章评论

No comments posted yet.

发表评论

Please add 4 and 7 and type the answer here:

关于博主

  一枚成分复杂的网络IT分子,属于互联网行业分类中的杂牌军。