- #include <stdio.h>
- #include <termios.h>
- #include <fcntl.h>
- #include <string.h>
- #define ASK "Do you want again?"
- #define TIMEOUT 6 /* time per try */
- #define BEEP putchar('\a') /* alert user */
- main()
- {
- int response;
- tty_mode(0); /* save current mode */
- set_input_mode(TIMEOUT);
- response = get_response(ASK); /* get some answer */
- tty_mode(1); /* restore orig mode */
- putchar('\n');
- return response;
- }
- get_response( char *question )
- /*
- * purpose: ask a question and wait for a y/n answer or maxtries
- * method: use getchar and complain about non-y/n input
- * returns: 0=>yes, 1=>no, 2=>timeout
- */
- {
- int input;
- //后面采用了清空~ISIG标志位,所以这里就不用信号函数了
- // signal(SIGINT, SIG_IGN); /* ignore kbd signals */
- // signal(SIGQUIT, SIG_IGN);
- printf("%s (y/n)?", question); /* ask */
- fflush(stdout); /* force output */
- while ( 1 ){
- input = tolower(getchar()); /* get next chr */
- if ( input == 'y' )
- return 0;
- if ( input == 'n' )
- return 1;
- if ( input == EOF ) /* timeout */
- return 2; /* sayso */
- BEEP;
- }
- }
- set_input_mode(int timeout)
- /*
- * purpose: put file descriptor 0 into chr-by-chr mode and noecho mode
- * AND set VTIME to 5*timeout
- * See manpage for termios to learn how values of VMIN and
- * VTIME work
- * method: use bits in termios
- */
- {
- struct termios ttystate;
- tcgetattr( 0, &ttystate); /* read curr. setting */
- ttystate.c_lflag &= ~ICANON; /* 设置无缓冲,即输入一个字符就读一个字符,不会等到按回车再处理 */
- ttystate.c_lflag &= ~ECHO; /* 设置不回显,即按下某个键,屏幕不会显示 */
- ttystate.c_cc[VMIN] = 1; /* 最少读取的字符数 */
- ttystate.c_cc[VTIME] = 5*timeout; /* 设置终端超时时间,这里是3秒,5*6=30毫秒,即3秒*/
- ttystate.c_lflag &= ~ISIG; /* 不产生输入信号,即Ctrl+C这样的信号被屏蔽 */
- tcsetattr( 0 , TCSANOW, &ttystate); /* install settings */
- }
- /* how == 0 => save current mode, how == 1 => restore mode */
- /* this version handles termios and fcntl flags */
- tty_mode(int how)
- {
- static struct termios original_mode;
- static int original_flags;
- if ( how == 0 )
- tcgetattr(0, &original_mode);
- else
- tcsetattr(0, TCSANOW, &original_mode);
- }
但是上面这个程序,却在超时后不会自动返回,主要是因为VMIN的设置有问题。
参看下面的解释:
转自
- 情形A:MIN > 0, TIME > 0。TIME说明一个字节间的计时
器,在接到第一个字节时才起动它。在该计时器超时之前,若已接到MIN个字节,则read返回MIN个字节。如果在接到MIN个字节之前,该计时器已超
时,则read返回已接收到的字节(因为只有在接到第一个字节时才起动,所以在计时器超时时,至少返回1个字节)。在这种情形中,在接到第一个字节之前,
调用者阻塞。如果在调用read时数据已经可用,则这如同在read后,数据立即被接收到一样。
- 情形B:MIN > 0 , TIME = = 0。已经接到了MIN个字节时,read才返回。这可以造成read无限期的阻塞。
- 情形C:MIN = = 0,TIME > 0。TIME指定了一个调用read时起动的读计时器。(与情形A相比较,两者是不同的)。在接到1个字节或者该计时器超时时,read即返回。如果是计时器超时,则read返回0。
- 情形D :MIN = = 0,TIME = = 0。如果有数据可用,则read最多返回所要求的字节数。如果无数据可用,则read立即返回0。
所以,在上述程序中把
ttystate
.c_cc
[VMIN
] = 1
; /* 最少读取的字符数
*/
改为
ttystate
.c_cc
[VMIN
] = 0; /* 最少读取的字符数
*/Then it works.
阅读(1040) | 评论(0) | 转发(0) |