怎么知道终端分辨率?

Giu*_*inò 14 less terminal

每次有人为虚拟控制台设置不同的大小时,都会less识别窗口分辨率(我假设......);据此,它改变了它应该可视化的文本行数。该参数是如何计算的?

Jan*_*der 22

如果您正在寻找一种从脚本进行检查的方法,您可以执行以下任一操作:

  • 运行tput colstput lines,正如 manatwork 建议的那样
  • 检查 $LINES 和 $COLUMNS 的值

但是,如果您想要详细信息,请点击此处:

对于虚拟终端(xterm 等),有一个ioctl()系统调用会告诉您窗口的大小。如果可以,请less使用此调用。此外,当您更改窗口大小时,该窗口中运行的任何内容都会收到一个SIGWINCH信号,less告知它应该检查新的窗口大小。例如,我开始less运行(作为进程 ID 16663),使用 连接到它strace,并调整窗口大小。这是我看到的:

$ strace -p 16663
Process 16663 attached - interrupt to quit
read(3, 0xbfb1f10f, 1)                  = ? ERESTARTSYS (To be restarted)
--- SIGWINCH (Window changed) @ 0 (0) ---
rt_sigaction(SIGWINCH, {0x805cf10, [WINCH], SA_RESTART}, {0x805cf10, [WINCH], SA_RESTART}, 8) = 0
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
ioctl(1, SNDCTL_TMR_TIMEBASE or TCGETS, {B38400 opost isig -icanon -echo ...}) = 0
ioctl(1, SNDCTL_TMR_TIMEBASE or TCGETS, {B38400 opost isig -icanon -echo ...}) = 0
ioctl(1, TIOCGWINSZ, {ws_row=40, ws_col=80, ws_xpixel=0, ws_ypixel=0}) = 0
ioctl(2, TIOCGWINSZ, {ws_row=40, ws_col=80, ws_xpixel=0, ws_ypixel=0}) = 0
Run Code Online (Sandbox Code Playgroud)

如果可以的话tput cols,这也是tput lines幕后的事情和做的事情。有关此方法的更多信息,请参阅man tty-ioctl并搜索 TIOCGWINSZ。

但是,对于其他终端,例如连接到串行端口的终端,无法直接获取此信息。在这种情况下,less开始在环境变量中寻找线索。

  • LINES并且COLUMNS通常会设置为终端尺寸。事实上,如果bash或者zsh能找到终端尺寸,它会自己自动设置这些变量,方便不太聪明的程序看到终端尺寸。但是,包括dash和在内的大多数其他 shelltcsh不会设置这些变量。
  • TERM通常设置为终端类型,在这种情况下,terminfo 数据库可能包含终端的预期大小。如果tput rows无法使用 IOCTL(例如,如果您通过串行端口连接),它将回退到此处记录的值。对于大小可以改变的终端,这只是一个猜测,很可能是错误的。

有关更多信息,请参阅man tput控制终端的命令,以及man terminfo您可以告诉终端执行的操作列表。


dai*_*isy 7

如果您查看源代码,您就会知道在 Linux 上检索窗口大小的less调用ioctl()

#ifdef TIOCGWINSZ
    {
        struct winsize w;
        if (ioctl(2, TIOCGWINSZ, &w) == 0)
        {
            if (w.ws_row > 0)
                sys_height = w.ws_row;
            if (w.ws_col > 0)
                sys_width = w.ws_col;
        }
    }
#else
#ifdef WIOCGETD
    {
        struct uwdata w;
        if (ioctl(2, WIOCGETD, &w) == 0)
        {
            if (w.uw_height > 0)
                sys_height = w.uw_height / w.uw_vs;
            if (w.uw_width > 0)
                sys_width = w.uw_width / w.uw_hs;
        }
    }
#endif
Run Code Online (Sandbox Code Playgroud)