1. 終端實際上就是一個文件:
leichaojian@ThinkPad-T430i:~$ tty
/dev/pts/0
leichaojian@ThinkPad-T430i:~$ who > /dev/pts/0
leichaojian :0 2014-08-28 19:54 (:0)
leichaojian pts/0 2014-08-28 20:17 (:0)
leichaojian@ThinkPad-T430i:~$ ll /dev/pts/0
crw--w---- 1 leichaojian tty 136, 0 8月 28 20:38 /dev/pts/0
常用的磁盤文件由字節組成,磁盤文件中的字節數就是文件的大小。設備文件是鏈接,而不是容器。設備文件的i-結點存儲的是指向內核子程序的指針,而不是文件的大小和存儲列表。內核種傳輸設備數據的子程序被稱爲設備驅動程序。
對於tty,136和0被稱爲設備的主設備號和從設備號。主設備號確定處理該設備實際的子程序,而從設備號被作爲參數傳輸到該子程序。
2. 終端驅動程序的模式
#include <stdio.h>
#include <ctype.h>
int main()
{
int c;
while ( ( c = getchar() ) != EOF ){
if ( c == 'z' )
c = 'a';
else if ( islower( c ) )
c++;
putchar( c );
}
}
正常程序運行如下:
leichaojian@ThinkPad-T430i:~$ vim rotate.c
leichaojian@ThinkPad-T430i:~$ cc rotate.c
leichaojian@ThinkPad-T430i:~$ ./a.out
ab<-cd
bc<-de
efg^C
但是,我們使用stty -icanon關閉了驅動程序中的規範模式處理,這時候並沒有緩衝,所以輸入後馬上會顯示結果:
leichaojian@ThinkPad-T430i:~$ stty -icanon; ./a.out
abbcxycdde
effggh^C
leichaojian@ThinkPad-T430i:~$ stty icanon
leichaojian@ThinkPad-T430i:~$ ./a.out
abcdef
bcdefg
^C
3. 使用非阻塞模式實現超時響應
#include <stdio.h>
#include <termios.h>
#include <fcntl.h>
#include <string.h>
#define ASK "do you want another transaction"
#define TRIES 3
#define SLEEPTIME 2
#define BEEP putchar('\a')
int main()
{
int response;
tty_mode( 0 );
set_cr_noecho_mode();
set_nodelay_mode();
response = get_response( ASK, TRIES );
tty_mode( 1 );
return response;
}
int get_response( char *question, int maxtries)
{
int input;
printf("%s(y/n)?", question );
fflush( stdout );
while ( 1 ){
sleep( SLEEPTIME );
input = tolower( get_ok_char() );
if ( input == 'y' )
return 0;
if ( input == 'n' )
return 1;
if ( maxtries-- == 0 )
return 2;
BEEP;
}
}
int get_ok_char()
{
int c;
while ( ( c = getchar() ) != EOF && strchr( "yYnN", c ) == NULL )
;
return c;
}
set_cr_noecho_mode()
{
struct termios ttystate;
tcgetattr( 0, &ttystate );
ttystate.c_lflag &= ~ICANON;
ttystate.c_lflag &= ~ECHO;
ttystate.c_cc[ VMIN ] = 1;
tcsetattr( 0, TCSANOW, &ttystate );
}
void set_nodelay_mode()
{
int termflags;
termflags = fcntl( 0, F_GETFL );
termflags |= O_NDELAY;
fcntl( 0, F_SETFL, termflags );
}
tty_mode( int how )
{
static struct termios original_mode;
static int original_flags;
if ( how == 0 ){
tcgetattr( 0, &original_mode );
original_flags = fcntl( 0, F_GETFL );
}
else{
tcsetattr( 0, TCSANOW, &original_mode );
fcntl( 0, F_SETFL, original_flags );
}
}