less如何知道终端分辨率?

less如何知道终端分辨率?

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

答案1

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

  • 按照 manatwork 的建议运行tput colstput lines
  • 检查 $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

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

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

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

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

答案2

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

#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

答案3

我不确定这是否是您正在寻找的信息。我猜想less注册了一个信号处理程序SIGWINCH。当终端尺寸发生变化时,它会收到SIGWINCH信号并探测终端当前尺寸的tty信息。 http://www.gnu.org/software/libc/manual/html_node/Miscellaneous-Signals.html

相关内容