终端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个可以更改为任何值。不能更改的是换行符\n和回车符\r。为了进行修改,只要更改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获取实际终端属性与希望的终端属性做对比,判断是否真正的修改成功。
终端IO(上)的更多相关文章
- Linux系统编程@终端IO
Linux系统中终端设备种类 终端是一种字符型设备,有多种类型,通常使用tty 来简称各种类型的终端设备.终端特殊设备文件一般有以下几种: 串行端口终端(/dev/ttySn ) ,伪终端(/dev ...
- 低级终端IO
低级终端IO 程序会需要对输入输出进行比简单的文件操作更为精确的控制.POSX提供了一套接口允许程序控制终端驱动程序的行为,这套接口称为通用终端接口(GIT). 需要改变终端设置的例子 标准输入输出, ...
- linux终端io笔记
简介 终端的两种工作模式:以行为单位的工作模式,以字符数或时间为单位自定义模式 终端判断函数: int isatty(int fd) 终端属性的获取与设置: int tcgetattr(int fd, ...
- linux 终端 查看上一页
问题描述: 我在终端中使用”dpkg -l”命令显示主机中安装的软件时,发现内容很多,而当命令执行完毕后,只显示终端最后一屏的内容.前面的都无法查看,这个是很让人憋屈的.下面就这一个问题说一下我的解决 ...
- commons io上传文件
习惯了是用框架后,上传功能MVC框架基本都提供了.如struts2,springmvc! 可是假设项目中没有使用框架.而是单纯的使用jsp或servlet作为action,这时我们就能够使用commo ...
- 解决 docker.io 上拉取 images Get https://registry-1.docker.io/v2/: net/http: TLS handshake timeout
处理方式 使用如下命令获取 registry-1.docker.io 可用的 ip dig @114.114.114.114 registry-1.docker.io 看到如下输出结果 ; <& ...
- spartan6不能直接把时钟连到IO上
1.问题的提出:spartan6中不允许时钟信号直接连到IO口上面? 2.解决办法: ODDR2的使用 ODDR2Primitive: Double Data Rate Output D Flip-F ...
- Redis持久化磁盘IO方式及其带来的问题 有Redis线上运维经验的人会发现Redis在物理内存使用比较多,但还没有超过实际物理内存总容量时就会发生不稳定甚至崩溃的问题,有人认为是基于快照方式持
转自:http://blog.csdn.net/kaosini/article/details/9176961 一.对Redis持久化的探讨与理解 redis是一个支持持久化的内存数据库,也就是 ...
- debian 7 终端上无法调出输出法
debian 7 终端konsole上无法调出输出法,无法输入汉字的问题解决方案, export GTK_IM_MODULE=fcitxexport QT_IM_MODULE=fcitxexport ...
随机推荐
- delphi StringGrid 表格的复制粘贴
//参考如下代码--uses Clipbrd; function StringGridSelectText(mStringGrid: TStringGrid): string;var I, J: I ...
- Android的Databinding-普通绑定
1. 使用ActivityBasicBinding binding = DataBindingUtil.setContentView(this, R.layout.main);代替之前使用的setCo ...
- virt-manager中为centos 7.2 扩容根分区
1. 打开virt-manager,添加一块磁盘. Add Hardware --> 选中Storage --> Manager (操作参考下图) 点击Manager之后,弹出Choose ...
- WWDC 2018:Swift 更新了什么?
本文转载自:https://juejin.im/post/5b1cb5805188257d507be5d4所有权归原文所有 WWDC 2018 Session 401 What's New in Sw ...
- MySQL -- Innodb的关闭
参数innodb_fast_shutdown控制着innodb的关闭模式,有三种取值: 0: innodb执行slow shutdown,在关闭之前要完成一次full purge和change ...
- node.js中的框架
node.js中的框架 载自: http://nodeframework.com/ MVC frameworks Sinatra-like These frameworks offer rich co ...
- 9.8 翻译系列:数据注解特性之--Required 【EF 6 Code-First系列】
原文链接:https://www.entityframeworktutorial.net/code-first/required-attribute-dataannotations-in-code-f ...
- Docker 管理应用程序数据
1.将Docker主机数据挂载到容器 Docker提供三种不同的方式将数据从宿主机挂载到容器中:volumes , bind mounts 和tmpfs volumes: Docker管理宿主机文件 ...
- Atitit 常见每日流程日程日常工作.docx v4
Atitit 常见每日流程日程日常工作.docx v4 ----早晨 签到 晨会,每天或者隔天 每日计划( )项目计划,日常计划等. mailbox读取检查 每日趋势 推库 -----下午 签退 每日 ...
- CAD技巧之002——如何用Cass内插高程点或者说加密高程点
CAD技巧之002——如何用Cass内插高程点或者说加密高程点 很多同志如果遇到奇葩的Cass内插高程点或者说加密高程点,怎么办,一个个编辑?如果工作量很大,怎么办呢. 今天九天就教您一个好方法! 废 ...