linux使用terminfo数据库来描述终端能力以及调用对应功能的方法
POSIX定义了完成终端I/O的标准方法:TERMIOS函数族
#include <termios.h>
#include <unistd.h>
struct termios{
tcflag_t c_iflag; /* input modes */
tcflag_t c_oflag; /* output modes */
tcflag_t c_cflag; /* control modes */
tcflag_t c_lflag; /* local modes */
cc_t c_cc [NCCS]; /* control chars */
}
1.模式
Cbreak模式
除了”Del”和”Ctrl”键外,接受其他所有字符输入,数都可以禁止行缓冲(line buffering)。控制字符将被终端驱动程序解释成其它字符。
Raw模式
可以禁止行缓冲(line buffering),处理挂起(CTRLZ)、中断或退出(CTRLC)等控制字符时,将直接传送给程序去处理而不产生终端信号
详情查看curses库中的cbreak()和 raw()函数。
另外可以用命令直接操作
stty -a 这个命令用来查看当前终端的设置情况
stty sane 如果不小心设错了终端模式,可用这个命令恢复,另一种恢复办法是在设置之前保存当前stty设置,在需要时再读出
stty -g > save_stty 将当前设置保存到文件save_atty中
stty $(cat save_stty) 读出save_atty文件,恢复原终端设置
2.获取和设置终端属性
int
tcgetattr
(int fd, struct termios *termios_p);
tcgetattr
(int fd, struct termios *termios_p);
int
tcsetattr
(int fd, int optional_actions, struct termios *termios_p);
tcsetattr
(int fd, int optional_actions, struct termios *termios_p);
其中optional_actions决定什么时候起作用,可取如下值
TCSANOW:不等数据传输完毕就立即改变属性。
TCSADRAIN:等待所有数据传输结束才改变属性。
TCSAFLUSH:清空输入输出缓冲区才改变属性。
注意
:当进行多重修改时,应当在这个函数之后再次调用 tcgetattr() 来检测是否所有修改都成功实现。
3.波特率函数
获取波特率
speed_t
cfgetospeed
(struct termios *termios_p);
cfgetospeed
(struct termios *termios_p);
speed_t
cfgetispeed
(struct termios *termios_p);
cfgetispeed
(struct termios *termios_p);
设置波特率
int
cfsetospeed
(struct termios *termios_p, speed_t speed);
cfsetospeed
(struct termios *termios_p, speed_t speed);
int
cfsetispeed
(struct termios *termios_p, speed_t speed);
cfsetispeed
(struct termios *termios_p, speed_t speed);
4.线路控制函数
int
tcdrain
(int fd); //等待所有写入fd中的数据输出
tcdrain
(int fd); //等待所有写入fd中的数据输出
int
tcflush
(int fd, int queue_selector); //丢弃要写入fd,但尚未传输的数据,或者收到但是尚未读取的数据。
tcflush
(int fd, int queue_selector); //丢弃要写入fd,但尚未传输的数据,或者收到但是尚未读取的数据。
取决于queue_selector 的值:
TCIFLUSH刷新收到的数据但是不读TCOFLUSH刷新写入的数据但是不传送TCIOFLUSH同时刷新收到的数据但是不读,并且刷新写入的数据但是不传送
int
tcflow
(int fd, int action); //挂起 fd 上的数据传输或接收。
tcflow
(int fd, int action); //挂起 fd 上的数据传输或接收。
取决于 action 的值:
TCOOFF挂起输出TCOON重新开始被挂起的输出TCIOFF发送一个 STOP 字符,停止终端设备向系统传送数据TCION发送一个 START 字符,使终端设备向系统传输数据
打开一个终端设备时的默认设置是输入和输出都没有挂起。
int
tcsendbreak
(int fd, int duration); //传送连续的 0 值比特流,持续一段时间,如果终端使用异步串行数据传输的话。
tcsendbreak
(int fd, int duration); //传送连续的 0 值比特流,持续一段时间,如果终端使用异步串行数据传输的话。
如果 duration 是 0,它至少传输 0.25 秒,不会超过 0.5 秒。如果 duration 非零,它发送的时间长度由实现定义。
如果终端并非使用异步串行数据传输,tcsendbreak() 什么都不做。
5.进程组控制函数
pid_t
tcgetpgrp
(int fd); //获取前台进程组的进程组ID
tcgetpgrp
(int fd); //获取前台进程组的进程组ID
int
tcsetpgrp
(int fd, pid_t pgrpid); //设置前台进程组的进程组ID
tcsetpgrp
(int fd, pid_t pgrpid); //设置前台进程组的进程组ID
pid_t
tcgetsid
(int fd); //获取会话首进程的进程组ID
tcgetsid
(int fd); //获取会话首进程的进程组ID
6.cfmakeraw
设置终端的 Raw 模式 ,设置终端属性:
termios_p->c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP| INLCR | IGNCR | ICRNL | IXON);termios_p->c_oflag &= ~OPOST;termios_p->c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);termios_p->c_cflag &= ~(CSIZE | PARENB);termios_p->c_cflag |= CS8;
7.其他
#include <stdio.h>
char *
ctermid
(char *s); //决定控制终端名称
ctermid
(char *s); //决定控制终端名称
#include <unistd.h>
int
isatty
(int desc); //判断描述符是否为终端
isatty
(int desc); //判断描述符是否为终端
char *
ttyname
(int desc); //返回终端名称
ttyname
(int desc); //返回终端名称
int
getopt
(int argc,char * const argv[ ],const char * optstring); //分析命令行参数
getopt
(int argc,char * const argv[ ],const char * optstring); //分析命令行参数
其中argc和argv是由main()传递的参数个数和内容,optstring 则代表欲处理的选项字符串。
版权声明:本文为williamwang2013原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。