Linux - 终端

C语言编写简单的菜单程序

工作过程分析
getchoice()
显示程序介绍信息greet及样本菜单choices
让用户选择初始字符
main()中的do循环体
通过getchar()获取用户输入,直到接收到一个与菜单数组某个选项的首字符匹配的字符为止

规范模式与非规范模式

规范模式
按回车键后,才能读到终端输入
基于行处理
在输入行完成前,终端接口负责管理所有用户键盘输入,包括退格键,应用程序读不到用户输入的任何字符
非规范模式
应用程序对用户输入字符的处理拥有更大的控制权

换行符的处理

Linux
行结束标志:换行符LF
回车符的输入要由Linux终端处理部分负责完成
优点
对文本文件及二进制可执行文件无任何实际区别
在对终端、打印机或绘图仪进行输入输出时,才需要对回车进行处理
其他操作系统
行结束标志:回车符CR(0D)+换行符LF(0A)
对前例换行符的处理

输出重定向处理

正常情形
所有数据都被重定向到文件,对用户不可见
一般需求
让用户看到提示信息,而看不到其他输出内容
判断标准输出是否被重定向
isatty()
检查底层文件描述符是否关联到一个终端
如果打开的文件描述符关联到一个终端,则返回1
否则返回0
只能对文件描述符操作
需通过fileno()将文件流和文件描述符关联

与终端对话

基本需求
不希望程序中与用户交互部分被重定向,但允许其他的输入和输出被重定向
解决思想
将与用户交互部分与stdout、stderr分离
实现途径
直接对终端进行读写
特殊设备文件:/dev/tty
该设备始终指向当前终端或者当前登录会话

终端驱动程序基本控制功能

行编辑
是否允许使用退格键进行编辑
缓存
立即读取字符,还是等一段可调配的延迟
回显
允许显示控制字符
回车/换行(CR/LF)
如何在输入/输出时映射回车/换行符
如打印“\n”时该如何处理
线速
当用PC电脑作为控制台时,很少使用该功能
但使用调制解调器或者串行线连接的终端很重要

termios结构

POSIX规范的标准结构
通过设置termios类型变量和使用一组函数调用,可对终端接口进行控制
termios.h需要链接到curses库
编译时需在末尾加上-lcurses
支持的操作模式分类
输入模式
输出模式
控制模式
本地模式
特殊字符控制

头文件
#include <termios.h>
函数原型
int tcgetattr(int fd, struct termios *termios_p);
int tcsetattr(int fd, int actions, const struct termios *termios_p);
actions参数说明
TCSANOW:立即对变量值进行修改
TCSADRAIN:等当前输出完成后修改
TCSAFLUSH:等当前输出完成后修改,但丢弃还未从read调用返回的当前可用输入

输入模式

功能
控制输入数据(终端驱动程序从串行口或键盘接收到的字符)在被传递给程序之前的处理方式
通过termios中的c_iflag成员的标志对其控制
BRKINT: 当收到break 时产生一个中断
IGNBRK: 忽略break 
ICRNL: 将回车符转换成换行
IGNCR: 忽略回车符
INLCR: 将换行符转换成回车符
IGNPAR: 忽略有校验错的字符
INPCK: 对接收到的字符执行校验
PARMRK: 标记校验错误
ISTRIP: 条块化所有输入字符(设置成7位)
IXOFF: 在输入上启用软件流控制
IXON: 在输出上启用软件流控制

输出模式

功能
控制输出字符(程序发出的字符)在传递到串行口或者屏幕之前的处理方式
大多处理方式与输入模式相反,但有几个用于慢速终端的额外标志
通过设置c_oflag来控制
OPOST: 打开输出处理
ONLCR: 将任何输出换行符转换成回车符/行输入对
OCRNL:将任何输出回车符转换成换行符
ONOCR: 在输出的0列不包含回车符
ONLRET: 换行也执行回车符
OFILL: 发送结束符来提供延迟
OFDEL: 使用DEL作为结束符,而不使用 NULL
NLDLY: 换行延迟选择
CRDLY: 回车延迟选择
TABDLY: Tab键延迟选择
BSDLY: Backspace延迟选择
VTDLY: 垂直tab延迟选择
FFDLY: 表单(Form feed)延迟选择

本地模式

功能
控制终端的各种特性
设置c_lflag标志
ECHO: 允许本地回显输入字符
ECHOE: 接收到ERASE 执行Backspace, Space, Backspace组合
ECHOK: 接收到KILL字符时执行删除行
ECHONL: 回显换行字符
ICANON: 启用规范输入处理
IEXTEN: 允许实现特定功能
ISIG: 支持信号
NOFLSH: 使队列上的flush失效
TOSTOP: 尝试通过写方法向后台进程发送信号

特殊控制字符

termios结构的c_cc数组成员将各种特殊字符映射到对应的支持函数
根据终端是否设置成标准模式(即c_lflag是否设置了ICANON标志),该数组有两种差别很大的用法
标准模式下的数组下标
VEOF: EOF字符
VEOL: EOL字符
VERASE: ERASE字符
VINTR: INTR字符
VKILL: KILL字符
VQUIT: QUIT字符
VSUSP: SUSP字符
VSTART: START字符
VSTOP: STOP字符
非标准模式下的数组下标
VINTR: INTR字符
VMIN: MIN值
VQUIT: QUIT字符
VSUSP: SUSP字符
VTIME: TIME值
VSTART: START字符
VSTOP: STOP字符

TIME与MIN值说明

功能
只能用于非标准模式
控制对输入的读取
控制程序试图读取与某终端关联的文件描述符时将发生的情况
参数设置说明
MIN=0,TIME=0
read调用立即返回
有等待字符,返回该字符;否则返回0
MIN=0,TIME>0
只要有可处理字符或者经过TIME个1/10秒的时间间隔,read调用返回
MIN>0,TIME=0
read调用一直等待,直到有MIN个字符可以读取时才返回
MIN>0,TIME>0
read调用在接收到第一个字符及后续的每个字符后,启动一个字符间隔定时器(若已运行,将重新启动)
当有MIN个字符或者两个字符之间时间间隔超过TIME个1/10秒时,read调用返回

在命令提示符下设置终端模式

终端速度
函数原型
speed_t cfgetispeed(const struct termios *);
speed_t cfgetospeed(const struct termios *);
int cfsetispeed(struct termios *, speed_t speed);
int cfsetospeed(struct termios *, speed_t speed);
终端速度
speed参数设置
B0: 挂起终端
B1200: 1200波特率
B2400: 2400波特率
B9600: 9600波特率
B19200: 19200波特率
B38400: 38400波特率

其他函数

int tcdrain(int fd);
让调用程序一直等待,直到所有队列的输出都发送完毕
int tcflow(int fd, int flowtype);
暂停或者重新开始输出
int tcflush(int fd, int in_out_selector);
用于清空输入、输出或者两者都清空

获取光标移动功能标志cup

通过tigetstr函数可以获得xterm类型终端的cup值
返回参数化结果\E[%p1%d;%p2%dH
cup标志所需参数
光标要移动到的行号和列号
这两个坐标都是从0开始计算,表示左上角
tparm用实际数值替换功能标志中的参数
一次最多可替换9个参数,并返回一个可用escape序列

函数原型
#include <term.h>
char *tparm(char *cap, long p1, long p2, ..., long p9);

说明
返回的escape转义序列不能通过printf发送到终端

tputs函数说明

功能
为不能通过stdout访问终端时准备
允许指定一个用于输出控制字符的函数
函数原型
int tputs(char *const str, int affcnt, int (*putfunc)(int));
参数说明
str
待输出字符
affcnt
表明受变化影响的输出行数,一般为1
putfunc
控制输出字符串,返回值类型必须与putchar相同
返回值
用户指定的函数putfunc()的返回结果
说明
putp(string)等价于tputs(string, 1, putchar)

虚拟控制台

功能
一组终端设备共享PC电脑的屏幕、键盘和鼠标
Linux典型安装中将配置12个虚拟控制台
表示方法:/dev/ttyN
查看方法
who:显示目前登录到系统的用户的信息
pe –e:显示当前使用的虚拟终端控制台及其运行的程序

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。