Как получить ширину windows терминала?

Я работаю над встроенной системой, использующей C и linux . Пользователь может подключиться к устройству через SSH или последовательный кабель консоли. Он может сделать это через PuTTY или Tera Term. Мой вопрос, после того как он связан, как я могу узнать ширину его windows? Я пробовал разные подходы, они работают, если я имитирую свою систему на компьютере linux, но никто из них не работает на устройстве:

  1. ioctl()

     struct winsize ws; ioctl(..., TIOCGWINSZ, &ws); 

    Этот метод работает на ПК, но он всегда возвращает 0 на устройство.

  2. tgetnum()

     setupterm((char *)0, 1, (int *)0); CGR_INT columns = tgetnum("co"); 

    Этот метод работает на ПК, но он всегда возвращает 80×24 на устройстве.

  3. getmaxyx()

     CGR_INT xdim; CGR_INT ydim; initscr(); refresh(); getmaxyx(stdscr, ydim, xdim); 

    Этот метод работает на ПК, но он всегда возвращает 0 на устройстве

    Я использую этот код, чтобы напечатать кучу равных знаков в качестве разделителя. Работает на большинстве ящиков / терминов, которые я пробовал. Не знаете, какие устройства вы говорите. Стоит попробовать, я думаю 😉

     #include  #include  #include  int main(int argc, char *argv[]) { struct winsize ws; ioctl(0, TIOCGWINSZ, &ws); int i=0; for(;i<10*ws.ws_col;++i) printf("="); printf("\n"); return 0; } 

    TIOCGWINSZ – это путь. Ваше устройство должно объявить о своем размере, иначе это просто не сработает. Возьмем xterm в качестве примера:

     device —— ttyS driver —— ttyS0 devnode —— screen/minicom xterm —— pty devnode —— pty driver —— pts devnode —— bash 

    xterm делает ioctl (TIOCSWINSZ) при первом запуске, чтобы драйвер tty знал размер windows. bash и программы, порожденные им, могут затем запросить его. Если вы измените размер windows xterm, он скажет драйверу tty новый размер, а xterm также испустит SIGWINCH для его дочернего процесса (в этом случае bash), чтобы уведомить об этом изменение размера.

    Ничто из этого не происходит с устройствами (такими как ваши), которые не знают, с чем они связаны. Также драйвер tty не знает, что с ним связано. (Обычно это не так.) Xterm может указать драйверу размер, потому что он может выдавать ioctl, но ioctls не переносятся, например, через serial port. Теоретически это будет специализированный драйвер ядра, который знает, как связывать изменения размера с вашим конкретным устройством (возможно, протокол поверх серийного, чтобы не требовалось переписывать основной компонент).

    Обратите внимание, что подключенное устройство может даже не иметь концепции фиксированной области – например, принтер может считаться практически бесконечным числом строк.

    ncurses просто предполагает 80×24, если видит 0x0, потому что программист определил его таким образом. Этот размер может быть неправильным, и на практике обычно это происходит не потому, что люди могут изменять размер своих окон (даже если они не могут, например, на tty1, они все равно могут использовать такие вещи, как экран (1), и уменьшают размер до менее чем 80×24 ).

    У последовательной линии нет способа согласовать размер терминала. Запуск реального xterm et.al. через пару TTY / PTY устройство использует TIOCSWINSZ ioctl() TIOCSWINSZ / TIOCGWINSZ для передачи этой информации.

    Традиционно эта информация хранилась в termcap или terminfo о реальных физических терминалах с покрытием из стекла и фосфора, таких как DEC VT220. Это статическая фиксированная firebase database с известными заблаговременно значениями, которая была правильной в то время, когда «терминал» буквально был фиксированным аппаратным обеспечением, но не так хорошо работает в современных терминалах, что это всего лишь часть программы который обращается к фреймбуферу или тому подобному.

    Я бы предположил, что лучшим методом было бы попробовать TIOCGWINSZ , если это не TIOCGWINSZ использовать terminfo tgetnum("co") , и если это не оправдано, предположим, что 80×24.