【问题标题】:Terminal window size doesn't update using ioctl终端窗口大小不使用 ioctl 更新
【发布时间】:2018-02-01 17:50:30
【问题描述】:

我在虚拟机中使用香草 Ubuntu。有问题的代码:

#include <sys/ioctl.h>
#include <stdio.h>
#include <unistd.h>

int main(void){
   struct winsize w;

   ioctl(STDOUT_FILENO, TIOCGWINSZ, &w);
   printf("lines %d\n", w.ws_row);
   printf("columns %d\n", w.ws_col);

   printf("\033[8;40;100t");

   ioctl(STDOUT_FILENO, TIOCGWINSZ, &w);
   printf("lines %d\n", w.ws_row);
   printf("columns %d\n", w.ws_col);

   return 0;
}

当我编译并运行它时,会打印出原始终端窗口大小,然后将窗口大小调整为 40x100,但最后的 printf 行不反映新的终端窗口大小。

这里发生了什么,如何获取更新的终端窗口大小信息?

【问题讨论】:

    标签: c terminal size ioctl


    【解决方案1】:

    您的代码中的一个问题很明显,在printf("\033[8;40;100t"); 之后您还没有刷新stdout。因此,当您调用第二个ioctl() 时,这些转义序列仍在stdout 的缓冲区中。

    但是,即使您添加了fflush(stdout);,结果也很可能没有变化。因为存在先调整窗口大小还是先调用下一个ioctl() 的竞争条件。即使添加tcdrain(),情况仍然如此。

    如果您为SIGWINCH 安装信号处理程序,则可以验证这一点。

    #include <sys/ioctl.h>
    #include <stdio.h>
    #include <unistd.h>
    #include <signal.h>
    #include <termios.h>
    #include <string.h>
    
    void winsz_handler(int sig) {
        const char *s = "winsize changed!\n";
        write(STDOUT_FILENO, s, strlen(s));
    }
    
    int main(void){
       signal(SIGWINCH, winsz_handler);
    
       struct winsize w;
    
       ioctl(STDOUT_FILENO, TIOCGWINSZ, &w);
       printf("lines %d\n", w.ws_row);
       printf("columns %d\n", w.ws_col);
    
       printf("\033[8;40;100t");
       fflush(stdout);
       tcdrain(STDOUT_FILENO);
    
       // remove this comment, then it works on my machine
       // However, it's ad hoc because there is no garantee
       //usleep(100000);
    
       ioctl(STDOUT_FILENO, TIOCGWINSZ, &w);
       printf("lines %d\n", w.ws_row);
       printf("columns %d\n", w.ws_col);
       sleep(1);
    
       return 0;
    }
    

    “winsize changed”输出是最后一个。如果评论中的usleep() 被删除,那么它可以在我的机器上运行。当然,这不是一个很好的竞争条件解决方案。

    【讨论】:

    • 有几个函数不应该在信号处理程序中使用。 printf() 是那些不应使用的函数之一。
    猜你喜欢
    • 2020-09-19
    • 1970-01-01
    • 2014-06-15
    • 2011-07-06
    • 1970-01-01
    • 2020-12-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多