linux|linux 终端io笔记

简介终端的两种工作模式:以行为单位的工作模式,以字符数或时间为单位自定义模式 终端判断函数:

  • int isatty(int fd)
【linux|linux 终端io笔记】终端属性的获取与设置:
  • int tcgetattr(int fd,struct termios *termptr)
  • int tcsetattr(int fd,int opt,const struct termios *termptr),opt选项如下
    TCSANOW:不等数据传输完毕就立即改变属性。
    TCSADRAIN:等待所有数据传输结束才改变属性。
    TCSAFLUSH:等待所有数据传输结束,清空输入输出缓冲区才改变属性。
终端名称的获取:
  • char *ctermid(char *ptr),如果ptr非空,则将终端名称(/dev/tty)写入到此ptr中并返回;若为空,分配空间写入后返回
终端属性结构:struct termios
struct termios{ tcflag_t c_iflag; tcflag_t c_oflag; tcflag_t c_cflag; tcflag_t c_lflag; cc_t c_cc[NCCS]; };

termios关键字 c_oflag:控制输出格式
  • OPOST:如果屏蔽此关键字,换行后缩进为上一行最后一个字符位置的后一位
c_lflag:本地模式
  • ECHO:回显,如果屏蔽则不显示输入的字符,像输入密码一样
  • ICANON:行模式,屏蔽则变成自定义模式
  • ISIG:使终端产生的信号(ctrl+c/ctrl+z等)起作用,屏蔽则忽略信号
c_iflag:控制输入格式
  • ICRNL:按下回车换行,屏蔽则不换行打印一个^M
  • BRKINT:当在输入行中检测到一个终止状态时,产生一个中断
c_cc:见例2
例子 1.行模式,关闭回显
#include #include #include #include #define MAX_PASS_LEN 8 char * getpass(const char *prompt){ static char buf[MAX_PASS_LEN+1]; char *ptr; struct termios ts,ots; FILE *fp; int c; if((fp=fopen(ctermid(NULL),"r+")) == NULL) return 0; setbuf(fp,NULL); tcgetattr(fileno(fp),&ts); ots=ts; ts.c_lflag &= ~ECHO; tcsetattr(fileno(fp),TCSAFLUSH,&ts); fputs(prompt,fp); //ptr < &buf[x] 两个内存地址比较,最多填充到buf[MAX_PASS_LEN-1] //*ptr=0 在接下来的一位填充0表示结束 ptr=buf; while((c=getc(fp)) != EOF && c != '\n') if(ptr < &buf[MAX_PASS_LEN]) *ptr++ = c; *ptr=0; putc('\n',fp); tcsetattr(fileno(fp),TCSAFLUSH,&ots); fclose(fp); return buf; } int main(){ char *ptr; if((ptr=getpass("Enter password:")) == NULL) perror("getpass word"); printf("passowrd: %s\n",ptr); //先ptr++移到下一位置,接着ptr副本(未移动前的位置)进行*ptr=0 while(*ptr != 0) *ptr++ =0; return 0; }

2.自定义模式
将termios结构中c_lflag字段的ICANON标志关闭就使终端处于非行模式,此时回车换行不作为行结束标识返回
自定义模式下有两种结束标识:
  • c_cc数组中的VMIN变量即c_cc[VMIN]作为最少字符结束标识,字符达到VMIN个就返回,c_cc[VMIN]=0表示不限容量
  • c_cc数组中的VTIME变量即c_cc[VTIME]作为最短时间结束标识,从第一个字符输入开始,经过VTIME时间后就返回,c_cc[VTIME]=0表示不限时间
另外,也可以同时指定上述两个变量,只要有一个变量指定的条件成立就返回
以下为简单自定义模式,字符长度达到10就返回,对SIGINT中断做复位处理
#include #include #include #include #include static struct termios save_termios; static int ttysavefd=-1; int tty_cbreak(int fd){ struct termios buf; if(tcgetattr(fd,&save_termios) <0){ perror("tcgetattr error"); return -1; } buf=save_termios; buf.c_lflag &= ~ICANON; buf.c_iflag &= ~ICRNL; buf.c_cc[VMIN]=10; buf.c_cc[VTIME]=0; if(tcsetattr(fd,TCSAFLUSH,&buf) <0){ perror("tcsetattr error"); return -1; } ttysavefd=fd; return 0; } int tty_reset(int fd){ if(tcsetattr(fd,TCSAFLUSH,&save_termios) <0){ return -1; } return 0; }int main(int argc,char *argv[]){ if(signal(SIGINT,sig_catch) == SIG_ERR) perror("signal error"); if(tty_cbreak(STDIN_FILENO) <0) perror("tty_cbreak error"); char c[11]={0}; int i; puts("cbreak mode,terminate with sigint"); while(i=read(STDIN_FILENO,&c,10)){ printf("\n%s\n",c); } return 0; }

    推荐阅读