终端控制程序例子
作者:互联网
-
终端驱动程序的模式
规范模式:也被称为cooked模式,也是用户最常见的模式。驱动程序将用户输入的数据保存在缓冲区,等待缓冲区满了后或者用户输入了回车之后就会将用户的数据一起发给程序使用。缓冲数据让驱动程序实现基本的编辑功能,例如:删除字符,单词或者整行。这里特殊的按键都在strcut termios的位变量中都可以设置,实用tesetattr和tegetattr函数即可。
非规范模式:当缓冲和编辑的功能本关闭的时候,连接被成为非规范模式。驱动程序还是可以接受特定的字符,例如:ctrl+c等。但是删除键就会被当作普通字符输入了。
raw模式:当所有的处理都被关闭后,连接进入raw模式,驱动程序将用户的输入直接给程序。 -
非阻塞输入
因为我觉得这个比较难点,一些简单的关闭回显,关闭缓冲(即时响应) 后面会贴出代码,但是不在这里细说了。
使用scanf函数的同学就会知道,如果你写了一条scanf语句,那么光标就会在那里等待,直到你输入数据,并回车就会取消阻塞。这个就是我的理解,阻塞就是让程序停在那里,直到你输入了数据才行。好比你遇到了一堵墙(程序被阻塞在这里了),你如果想要过去(程序如果想要继续运行下去),你就的使用钻头将墙弄一个洞,然后你就过去了(程序得到了你输入的数据)。还有阻塞功能的函数还有getchar()函数。如果你使用了getchar函数,势必就会产生阻塞,那么解决方法就是改变文件的属性(阻塞不仅仅是终端连接的属性,还是任何一个文件的属性)。 -
要使用函数的介绍
fcntl有三种“重载”(我不直到这么说对不对)的形式,
int fcntl(int fd,int cmd);
int fcntl(int fd,int cmd,long arg);
int fcntl(int fd,int cmd,struct flock *flock);
还要提到的就是,这里也是可以使用open函数来解决这个问题的。在打开文件的时候,就顺便开启文件描述符的O_NDELAY标志。 -
实现非阻塞模式的超时响应代码
#include<stdio.h>
#include<stdlib.h>
#include<termios.h>
#include<string.h>
#include<signal.h>
#include<fcntl.h>
#define ASK "Do you want another transaction"
#define TRIES 3
#define SLEEPTIME 2
#define BEEP putchar('\a')
void ctrl_c_handler(int);
void tty_mode(int);
void set_cr_noecho_mode();
void set_nodelay_mode();
int get_response(char *,int);
void choose_response(int);
int main()
{
int response;
tty_mode(0);
set_nodelay_mode();
set_cr_noecho_mode();
signal(SIGINT,ctrl_c_handler);
signal(SIGQUIT,SIG_IGN);
response=get_response(ASK,TRIES);
tty_mode(1);
choose_response(response);
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;
}
else if(input=='n')
{
return 1;
}
if(maxtries--==0)
{
//printf("连接超时\n");
return 2;
}
// BEEP;
}
}
int get_ok_char()
{
int c;
while((c=getchar())!=EOF&&strchr("YyNn",c)==NULL)
;
return c;
}
void 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);
}
void tty_mode(int how)
{
static struct termios original_mode;
static int original_flags;
static int stored=0;
if(how==0)
{
tcgetattr(0,&original_mode);
original_flags=fcntl(0,F_GETFL);
stored=1;
}
else if(stored)
{
tcsetattr(0,TCSANOW,&original_mode);
fcntl(0,F_SETFL,original_flags);
}
}
void ctrl_c_handler(int signum)
{
tty_mode(1);
printf("ctrl+c进入,程序回滚\n");
//exit(1);
}
void choose_response(int response)
{
switch(response)
{
case 0:
printf("你的选择是:确认\n");break;
case 1:
printf("你的选择是:否定\n");break;
case 2:
printf("选择超时\n");break;
}
}
- 实现即使响应代码
#include<stdio.h>
#include<termios.h>
#define QUESTION "DO you wanna another transacuion"
void tty_mode(int mode);
void set_crmode();
int get_response(char *);
int main()
{
int response;
tty_mode(0);
set_crmode();
response=get_response(QUESTION);
tty_mode(1);
printf("你的结果是:%d\n",response);
return response;
}
int get_response(char *question)
{
printf("%s(y/n)?",question);
char input;
while(1)
{
switch(input=getchar())
{
case 'Y':
case 'y':return 0;
case 'N':
case 'n':return 1;
case EOF:return 1;
default:
printf("\nconnot nderstand %c",input);
printf("Please type y or no\n");
}
}
}
void tty_mode(int mode)
{
static struct termios original_mode;
if(mode==0)
{
tcgetattr(0,&original_mode);
// printf("c_cc[MVIM]=%d\n",original_mode.c_cc[VMIN]);
}
else
tcsetattr(0,TCSANOW,&original_mode);
}
void set_crmode()
{
struct termios ttystate;
tcgetattr(0,&ttystate);
ttystate.c_lflag&=~ICANON;
ttystate.c_cc[VMIN]=1;
tcsetattr(0,TCSANOW,&ttystate);
}
标签:int,void,控制程序,例子,ttystate,mode,printf,response,终端 来源: https://blog.csdn.net/suliangkuanjiayou/article/details/86666552