Linux笔记五(终端)

8 篇文章 0 订阅

终端

对终端进行读写

标准模式与非标准模式

规范模式标准模式
按下回车键才会把键入的数据传递给程序。

非标准模式
应用程序对用户输入字符的处理拥有更大的控制权。

规范的英文:canonical

处理重定向输出
#include <unistd.h>
int isatty(int fd);

将文件描述符传递给isatty,它就可以判断该描述符是否连接到一个终端。如果是则返回1,不是则返回0。

与终端进行对话

Linux和UNIX提供特殊设备 /dev/tty,这个设备始终是指向当前终端或当前的登录会话。可以用一般文件的操作方式来对/dev/tty进行读写。

终端驱动程序和通用终端接口

可以通过一组函数调用( 通用终端接口,GTI )来 控制 终端,这组函数调用与用于读写数据的函数是分离的,这就使得读写数据的接口非常简洁。

能够控制的主要功能:
行编辑:是否允许用退格键进行编辑。
缓存:是立即读取字符,还是等待一段可配置的延迟之后再读取它们。
回显:允许控制字符的回显,例如读取密码时。
回车/换行(CR/LF):定义如何在输入/输出时映射回车/换行符,比如打印\n字符时应该如何处理。
线速:这一功能少用于PC控制台,但对调制解调器或通过串行线连接的终端就很重要。

termios结构

termios是在POSIX定义的标准接口。通过设置termios类型的数据结构中的值和使用一小组函数调用,就可以对终端接口进行控制。termios数据结构和相关函数调用都定义在头文件 termios.h 中。

调用termios.h中的函数时,需要与一个正确的函数库链接,可能是标准的C函数库,也可能是curses函数库。连接curses函数库时,编译命令加上 -lcurses,有些是加 -lncurses(n表示new)。

可以被调整来影响终端的值按照不同的模式被分成如下几组:
输入模式输出模式控制模式本地模式特殊控制字符

#include <termios.h>
struct termios {
	tcflag_t c_iflag;	//输入模式
	tcflag_t c_oflag;	//输出模式
	tcflag_t c_cflag;	//控制模式
	tcflag_t c_lfalg;	//本地模式
	cc_t	c_cc[NCCS];	//特殊控制字符
};
/*
获取与一个终端(fd文件描述符指向的文件)对应的termios结构(存入到termios_p中)。
*/
#include <termios.h>
int tcgetattr(int fd, struct termios *termios_p);
#include <termios.h>
int tcsetattr(int fd, int actions, const struct termios *termios_p);
参数 actions 取值说明
TCSANOW立刻对值进行修改
TCSADRAIN等当前的输出完成后再对值进行修改
TCSAFLUSH等当前的输出完成后再对值进行修改,但丢弃还未从read调用返回的当前可用的任何输入

程序结束时应恢复终端状态,这是码农的职责。

输入模式

控制输入数据在被传递给程序之前的处理方式。

参数 c_iflag 取值说明
BRKINT当在输入行中检测到一个终止状态(连接丢失)时,产生一个中断
IGNBRK忽略输入行中的终止状态
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制表符延时选择
BSDLY退格符延时选择
VTDLY垂直制表符延时选择
FFDLY换页符延时选择
控制模式

控制终端的硬件特性。

参数 c_cflag 取值说明
CLOCAL忽略所有调制解调器的状态行
CREAD启用字符接收器
CS5发送或接收字符时使用5比特
CS6发送或接收字符时使用6比特
CS7发送或接收字符时使用7比特
CS8发送或接收字符时使用8比特
CSTOPB第个字符使用两个停止位而不是一个
HUPCL关闭时挂断调制解调器
PARENB启用奇偶校验的生成和检测功能
PARODD启用奇校验而不是偶校验
本地模式

控制终端的各种特性。

参数 c_lflag 取值说明
ECHO启用输入字符的本地回显功能
ECHOE接收到ERASE时执行退格、空格、退格的动作组合
ECHOK接收到KILL字符时执行行删除操作
ECHONL回显新行符
ICANON启用标准输入处理
IEXTEN启用基于特定实现的函数
ISIG启用信号
NOFLSH禁止清空队列
TOSTOP在试图进行写操作之前给后台进程发送一个信号
特殊控制字符

对字符组合(如ctrl+c)采取一些特殊的处理方式。

标准模式

可使用下标说明
VEOFEOF字符
VEOLEOL字符
VERASEERASE字符
VINTRINTR字符
VKILLKILL字符
VQUITQUIT字符
VSUSPSUSP字符
VSTARTSTART字符
VSTOPSTOP字符

非标准模式

可使用下标说明
VINTRINTR字符
VMINMIN值
VQUITQUIT字符
VSUSPSUSP字符
VTIMETIME值
VSTARTSTART字符
VSTOPSTOP字符
字符说明
INTR该字符使终端驱动程序向与终端相连的进程发送SIGINT信号。
QUIT该字符使终端驱动程序向与终端相连的进程发送SIGQUIT信号。
ERASE该字符使终端驱动程序删除输入行中的最后一个字符。
KILL该字符使终端驱动程序删除整个输入行
EOF该字符使终端驱动程序将输入行中的全部字符传递给正在读取输入的应用程序。如果输入行为空,read调用将返回0,就好像在文件结尾调用read一样
EOL该字符的作用类似行结束符,效果和常用的新行符相同
SUSP该字符使终端驱动程序向与终端相连的进程发送SIGSUSP信号。如果你的UNIX系统支持作业控制功能,当前应用程序将被挂起
STOP该字符的作用是“截流”,即阻止向终端的进一步输出。它用于支持XON/XOFF流控,通常被设置为ASCII的XOFF字符,即组合键ctrl+s
START该字符重新启动被STOP字符暂停的输出,它通常被设置为ASCII的XON字符

TIME和MIN值:
只用于非标准模式。
等待TIME个十分之一秒或接收到MIN个字符。如果两个都为0,read调用总是立刻返回,如果有一个以上不为0,只看不为0的条件。

通过shell访问终端模式:

$ stty -a

在这里插入图片描述如果不小心把终端设置为非标准状态,可以用以下几种方法:
(1)使用如下命令。

$stty sane

(2)用命令 stty -g 将当前的stty设置保存到某种可以重新读取的形式中。

$ stty -g > save_stty
$ stty $(cat save_stty)

如果回车键和新行符的映射关系丢失了,可以用 ctrl+j(对应新行符)。

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

$ stty -icannon min 1 time 0
$ stty -echo
终端速度
#include <termios.h>
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);

termios结构提供的最后一个功能是控制终端速度,但termios结构中 并没有与终端速度对应的成员 ,它是通过函数调用来进行设置的。

参数 speed 取值说明
B0挂起终端
B12001200波特
B24002400波特
其他函数
#include <termios.h>
//让调用程序一直等待,直到所有排除的输出都已发送完毕
int tcdraint(int fd);
//暂停或重新开始输出
int tcflow(int fd, int flowtype);
//清空输入、输出或者两者都清空
int tcflush(int fd, int in_out_selector);

直接对文件描述符进行操作,不需要读写termios结构。

终端的输出

终端类型

不同的制造厂商生产了大量的各种类型的硬件终端。虽然它们几乎都用 escape转义序列 来控制光标的位置和终端的其他属性——比如黑体和闪烁等,但在具体实现手段上并没有统一的标准。

$ echo $TERM

查看自己正在使用的终端是何种类型。

terminfo软件包包含了一个由大量不同类型终端的功能标志和escape转义序列等信息构成的数据库,并且为使用它们提供了一个统一的编程接口。一个使用这个软件包的程序能够随着数据库的扩展来适应未来的终端类型,对不同类型终端的支持不再需要由应用程序自身来提供。

terminfo的功能标志由属性描述,它们被保存在一组编译好的terminfo文件中,这些文件通常可以在 /usr/lib/terminfolusr/share/terminfo 目录中找到。

在这里插入图片描述在这里插入图片描述
如图,为linux终端对应的terminfo文件。

通过 infocmp 程序输出已编译terminfo数据项的可读版本。

在这里插入图片描述每个terminfo定义由3种数据项组成。每个数据项被称为 capname,它们分别用于定义终端的一种功能标志。

布尔功能标志 指出终端是否支持某个特定的功能。
数值功能标志 定义长度。
字符串功能标志 用于访问终端功能的输出字符串和当用户按下特定按键时终端接收到的输入字符串。

其中%i表示增加参数值,\E表示发送Escape字符,%pn为将第n个参数入栈。

使用terminfo功能标志
#include <term.h>
int setupterm(char *term, int fd, int *errret);

返回值:
-1:数据库不存在。
0:数据库中没有匹配的数据项。
1:成功。

将当前终端类型设置为参数term指向的值,如果term是空指针,就使用环境变量TERM的值。参数fd为一个打开的文件描述符,它用于向终端写数据。如果参数errret不是一个空指针,则函数的返回值保存在该参数指向的整型变量中。

#include <term.h>
int tigetflag(char *capname);	//失败时返回-1
int tigetnum(char *capname);	//失败时返回-2
char *tigetstr(char *capname);	//失败时返回(char *)-1
#include <term.h>
char *tparm(char *cap, long p1, long p2, ..., long p9);

替换功能标志中的参数,最多九个,并返回一个可用的escape转义序列。

#include <term.h>
int putp(char *const str);
int tputs(char *const str, int affcnt, int (*putfunc)(int));

光标移动到第5行第30列,可以使用如下代码:

char *cursor;
char *esc_sequence;
cursor = tigetstr("cup");
esc_sequence = tparm(cursor, 5, 30);
putp(esc_sequence);

tputs函数是为不能通过标准输出stdout访问终端的情况准备的,它可以指定一个用于输出字符的函数。返回值为putfunc的返回结果。参数affcnt的作用是表明受这一变化影响的行数,一般被设置为1。putp(string)等同于tputs(string,1,putchar)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值