端末の解像度をあまり知らないのはなぜですか?


12

誰かが仮想コンソールに異なるサイズを設定するたびにless、ウィンドウの解像度を認識します(私はそれを想定しています...)。それに応じて、視覚化するテキストの行数を変更します。そのパラメーターはどのように計算されますか?


ええと...それでも、実行されたプロシージャはどこにありますか?
GiuseppeCrinò2013年

回答:


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

これは、可能であれば、裏tput colstput lines行うことでもあります。この方法の詳細についてはman tty-ioctl、TIOCGWINSZを参照して検索してください。

ただし、シリアルポートに接続されている端末など、この情報を直接取得する方法はありません。その場合lessは、環境変数で手がかりを探し始めます。

  • LINESそしてCOLUMNS多くの場合、端末の寸法に設定されます。実際には、場合bashzsh、端末の寸法を見つけることができる、それが自動的に、端末サイズを確認するには、それほど巧妙でないプログラムのために簡単にそれを作るために、これらの変数そのものを設定します。ただし、dashおよびを含む他のほとんどのシェルは、tcshこれらの変数を設定しません。
  • TERM通常、端末タイプに設定されます。この場合、terminfoデータベースには、端末の予想サイズが含まれる場合があります。tput rowsIOCTLを使用できない場合(たとえば、シリアルポート経由で接続している場合)、ここで記録された値にフォールバックします。サイズが変化する可能性のある端末の場合、これは単なる推測であり、誤りである可能性があります。

詳細についてman tputは、端末を制御するコマンドと、端末にman terminfo実行するように指示できることのリストを参照してください。


terminfoデータベースは、ここに示されていることを実行しません。情報が少ない@ warl0ckによる答えの方が正確です。
Thomas Dickey

@ThomasDickeyその通りです。それが持っているすべては期待値です。私の答えを修正しました。ありがとう。
ジャンダー

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

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.