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 );
}
}