unix/linux編程實踐教程:學習stty

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


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章