Understanding Unix/Linux Programming-stty指令练习

先来看一个简单的练习程序:

1 #include <stdio.h>
2 
3 int main()
4 {
5     int c  , n = 0 ;
6     while( (c = getchar() ) != 'Q' )
7         printf("char %3d is %ccode %d
" , n++ , c , c  );
8     return 0 ;
9 }

以上是程序编译后运行的效果啦,可以看到在输入hello之后敲击回车后才运行了该程序,也就是说,在终端中输入的字符实际上是被缓冲的。

另外,回车键本身被识别为换行了,也由该程序识别了,这也与终端的设置有关。

tty驱动程序包含很多对数据的操作:

  1. 输入:驱动程序如何处理来自终端的字符
  2. 输出:驱动程序如何处理流向终端的字符
  3. 控制:字符如何表示——位的个数,位的奇偶性,停止位等等
  4. 本地:驱动程序如何处理来自驱动程序内部的字符

编写终端驱动程序:关于系统调用函数:

  改变终端驱动程序的设置就像改变磁盘文件连接的设置一样:

  1. 从驱动程序获得属性
  2. 修改所要修改的属性
  3. 将修改过的属性送回驱动程序

  通常通过tcgetattr和tcsetattr提供对终端驱动程序的访问。这两个函数在termios结构体中交换设置。

  1 /* stty.c
  2  * show the settings of current tty 
  3  */
  4 #include <stdio.h>
  5 #include <stdlib.h>
  6 #include <termios.h>
  7 
  8 struct flaginfo 
  9 {
 10     int fl_value ;
 11     char * fl_name ;
 12 };
 13 
 14 struct flaginfo input_flags[] =
 15 {
 16     IGNBRK , "Ignore break condition" , 
 17     BRKINT , "Signal interrupt on break" , 
 18     IGNPAR , "Ignore chars with parity errors",
 19     PARMRK , "Mark parity errors",
 20     INPCK , "Enable input parity check",
 21     ISTRIP , "Strip character",
 22     INLCR , "Map NL to CR on input",
 23     IGNCR , "Ignore CR",
 24     ICRNL , "Map CR to NL on input",
 25     IXON , "Enable start/stop control",
 26     IXOFF , "Disable start/stop control",
 27     0 , NULL
 28 };
 29 
 30 struct flaginfo local_flags[] = 
 31 {
 32     ISIG , "Enable signals",
 33     ICANON , "Canonical input(erase and kill)",
 34     ECHO , "Enable echo" ,
 35     ECHOE , "Echo REASE as BS-SPACE-BS" ,
 36     ECHOK , "Echo KILL by starting new line",
 37     0 , NULL 
 38 };
 39 
 40 void show_baud(int thespeed);
 41 void show_some_flags(struct termios * ttyp);
 42 void show_flagset(int thevalue , struct flaginfo * thebitnames);
 43 
 44 int main()
 45 {
 46     struct termios ttyinfo ;
 47     // 从文件中获取当前驱动程序的设置
 48     if(tcgetattr(0 , & ttyinfo ) == -1 )
 49     {
 50         perror("cannot get para about stdin");
 51         exit(1);
 52     }
 53     
 54     show_baud( cfgetospeed( &ttyinfo ) );
 55     
 56     printf("The erase character is ascii %d , Ctrl-%c
",
 57             ttyinfo.c_cc[VERASE] , ttyinfo.c_cc[VERASE] - 1 + 'A') ;
 58     printf("The line kill character is ascii %d , Ctrl-%c
",
 59             ttyinfo.c_cc[VKILL] , ttyinfo.c_cc[VKILL] - 1 + 'A') ;
 60             
 61     show_some_flags(&ttyinfo);
 62     return 0 ;
 63 }
 64 
 65 void show_baud(int thespeed)
 66 {
 67     printf("The baud rate is :");
 68     switch(thespeed)
 69     {
 70         case B300 : printf("300
"); break ;
 71         case B600 : printf("600
"); break ;
 72         case B1200 : printf("1200
"); break ;
 73         case B1800 : printf("1800
"); break ;
 74         case B2400 : printf("2400
"); break ;
 75         case B4800 : printf("4800
"); break ;
 76         case B9600 : printf("9600
"); break ;
 77         default : printf("Fast!
");break ;
 78     }
 79 }
 80 
 81 void show_some_flags(struct termios * ttyp)
 82 {
 83     show_flagset( ttyp -> c_iflag , input_flags ) ;
 84     show_flagset( ttyp -> c_lflag , local_flags ) ;
 85 }
 86 
 87 void show_flagset(int thevalue , struct flaginfo * thebitnames)
 88 {
 89     int i ;
 90     for(i = 0 ; thebitnames[i].fl_name ; i ++ )
 91     {
 92         printf("%s is " , thebitnames[i].fl_name);
 93         if(thevalue & thebitnames[i].fl_value)
 94         {
 95             printf("ON
");
 96         }
 97         else
 98         {
 99             printf("OFF
");
100         }
101     }
102     
103 }

将结构体以及结构体数组的定义提到前面,编译就不会报错了。话说书中例程使用的应该是较老版本的编译器,所以用现在的编译器总是出警告和错误啥的,按照现C++的定义顺序来写就不会有大问题啦。

  

原文地址:https://www.cnblogs.com/NJdonghao/p/5282703.html