• 终端IO(上)


    一、综述

      终端IO有两种不同的工作方式:

    • 规范方式输入处理。在这种方式中,终端输入以行为单位进行处理。对于每个读要求,终端驱动程序最多返回一行。
    • 非规范方式输入处理。输入字符不以行为单位进行装配

      如果不做特殊处理,则默认方式是规范方式。vi编辑程序使用非规范方式,其原因是其命令是由不以换行符终止的一个或几个字符组成。
      POSIX.1定义了11个特殊输入字符。其中9个可以改变
      终端设备一般位于内核中的终端驱动程序所控制的。每个终端设备有一个输入队列,一个输出队列,见下图:
      

      对此图要说明以下几点:

    • 如果需要回送,则在输入队列和输出队列中间有一个隐含的连接。
    • 输入队列的长度MAX_INPUT是有限值,当一个特定设备的输入队列已填满,各系统实现有所不同,大多数UNIX系统会送响铃字符。
    • 图中没有显示另一个输入限制MAX_CANON,它是一个规范输入行中的最大字节数。
    • 虽然输出队列通常也是有限长度,但是程序不能存取定义其长度的常数。这是因为当输出队列要填满时,内核使写进程睡眠直至写队列中有可用的空间,所以程序无需关心该队列的长度。

      大多数UNIX系统在一个称为终端行规程(terminal line discipline)的模块中进行规范处理。它是位于内核类属读、写函数和实际设备驱动程序之间的模块,见下图
      

      所有我们可以检测和更改的终端设备特性都包含在termios结构中。该结构在头文件<termios.h>中定义。

    struct termios {
        tcflag_t    c_iflag; /* input flag */
        tcflag_t    c_oflag; /* output flags */
        tcflag_t    c_cflag; /* control flags */
        tcflag_t    c_lflag; /* local flags */
        cc_t        c_cc[NCCS]; /* control characters */
    };

      粗略而言,输入标志由终端设备驱动程序用来控制输入特性(剥除输入字节第8位,允许输入奇偶校验等等),输出标志则控制输出特性(执行输出处理,将新行映照为CR/LF等),控制标志影响到RS-232串行线(忽略调制解调器的状态线,每个字符的一个或两个停止位等等),本地标志影响驱动程序和用户之间的界面(回送的开或关,可试的擦除符,允许终端产生的信号,对后台作业输出的控制停止信号等)。
      类型tcflag_t的长度是以保持每个标志值。它经常被定义为unsigned long。c_cc数组包含了所有可以更改的特殊字符。NCCS是该数组的长度,POSIX.1定义为11,咯实现有所不同。cc_t类型的长度足以保持每个专用字符,典型的是unsigned char。
      下表列出了所有可以更改以影响终端设备特性的终端标志。
      

      下表列出了POSIX.1定义对终端设备进行操作的各个函数。
      

      对终端设备,POSIX.1没有使用ioctl,而使用了上表中列出的12个函数。这样做的理由是:对于终端设备的ioctl函数,最后一个参数的数据类型随执行动作的不同而不同。
      上表中12个函数之间的关系见下图:
      

    二、特殊输入字符

      POSIX.1定义了11个在输入时做特殊处理的字符。SVR4 另外加了6个特殊字符,4.3+BSD则加了7个。下表列出了这些字符
      

      11个特殊字符中,9个可以更改为任何值。不能更改的是换行符 和回车符 。为了进行修改,只要更改termios结构中c_cc数组的相应项。该数组中的元素都用名字作为下标进行引用,每个名字都以字母V开头。

    三、获取和设置终端属性

      使用函数tcgetattr和tcsetattr可获得/设置termios。这样就可以检测和修改各种终端选择标志和特殊字符,以使终端按我们所希望的方式进行操作。

    #include <termios.h>
    int tcgetattr(int filedes, struct termios *termpptr);
    int tcsetattr(int filedes, int opt, const struct termios *termpptr);
    返回值: 成功为1,出错为-1

      因为这两个函数只对终端设备进行操作,所以若filedes并不引用一个终端设备则出错返回,error设置为ENOTTY
      tcsetattr的参数opt使我们可以指定在什么时候新的终端属性才起作用。opt可以指定为以下常数中的一个:

    • TCSANOW 更改立即发生
    • TCSADRAIN 发送了所有输出后更改才发生。若更改输出参数则应使用此选择项
    • TCSAFLUSH 发送了所有输出后更改才发生。更进一步,在更改发生时未读的所有输入数据都被删除(刷清)。

      tcsetattr函数的返回值易于产生混淆。如果执行了任意一种所要求的动作,即使未能执行所有要求的动作,它也返回0(表示成功)。如果函数返回0,则我们有必要调用tcgetattr获取实际终端属性与希望的终端属性做对比,判断是否真正的修改成功。

  • 相关阅读:
    打开网页总结
    学期总结
    总结
    Sprint3
    Sprint2团队贡献分
    6.14
    典型用户与场景
    5种创建型模式
    JAVA 将接口的引用指向实现类的对象
    Java里的接口
  • 原文地址:https://www.cnblogs.com/orlion/p/6527746.html
Copyright © 2020-2023  润新知