ioctlについて調べてみた
Linuxで仮想端末の画面サイズが変更されたとき、fgプロセスやどうやってそれを認識して画面を再描画してるんだろう?
なんとなく疑問におもったのでちょっと調べてみた。
どうやら、プロセスに繋がってる /dev/tty に対して、ioctlシステムコールを投げると端末の属性が設定できたり取得できたりするらしい。
下のプログラムを実行すると、現在の端末サイズ(キャラクタサイズ)が表示される。
tmux等で、1画面でペイン分割している場合は、プログラムを実行したペインのサイズが表示される。
#include <sys/ioctl.h> #include <termios.h> #include <stdio.h> int main( ) { struct winsize size ; FILE *f = fopen( "/dev/tty", "rw" ); int fd = 0; fd = fileno(f); ioctl( fd, TIOCGWINSZ, &size ); printf( "%d - %d\n", size.ws_col, size.ws_row ); fclose(f); return 0; }
また、仮想端末のサイズが変更された場合は SIGWINCH が送られてくるので、
必要に応じて、プログラムでそれを補足して端末サイズの再取得&再描画を行えばいいわけだ。
ついでにキー入力についても調べてみた。
端末に対するキー入力は、/dev/tty に対し、readシステムコールを投げることで取得可能。
デフォルトだとバッファリングモード(Enterを押すとそれまでの入力がまとめて取ってこられるモード)となっている。
1文字ずつ取り込む場合には、read(2)呼び出し前に/dev/ttyの属性をノンバッファリングモードにしてやればよいのだとか*1。
*1:これも端末サイズ取得と同様ioctlを使う