ermios 結構是在POSIX規範中定義的標準接口,它相似於系統V中的termio接口,經過設置termios類型的數據結構中的值和使用一小ios
組函數調用,你就能夠對終端接口進行控制。shell
能夠被調整來影響終端的值按照不一樣的模式被分爲以下幾組:數組
1.輸入模式數據結構
2.輸出模式函數
3.控制模式spa
4.本地模式命令行
5.特殊控制模式code
最小的termios結構的典型定義以下:blog
struct termios { tcflag_t c_iflag; tcflag_t c_oflag; tcflag_t c_cflag; tcflag_t c_lflag; cc_t c_cc[NCCS]; };
結構成員的名稱與上面列出的5種參數類型相對應。接口
你能夠調用函數tcgetattr來初始化一個終端對應的termios結構,該函數的原型以下:
#include<termios.h> int tcgetattr(int fd, struct termios *termios_p);
這個函數調用把當前終端接口變量的值寫入termios_p參數指向的結構。若是這些值其後被修改了,你能夠經過調用函數tcsetattr來從新配置終端接口。
#include<termios.h> int tcsetattr(int fd , int actions , const struct termios *termios_h);
參數actions控制修改方式,共有三種修改方式,以下所示。
1.TCSANOW:馬上對值進行修改
2.TCSADRAIN:等當前的輸出完成後再對值進行修改。
3.TCSAFLUSH:等當前的輸出完成以後,再對值進行修改,但丟棄還未從read調用返回的當前的可用的任何輸入。
接下來咱們將分別對五種模式進行介紹。
輸入模式控制輸入數據在傳遞給程序以前的處理方式。你經過設置termios結構中的c_iflag成員的標誌對它們進行控制。全部的標誌都被定義爲
宏,並可經過按位或的方式結合起來。
可用於c_iflag成員的宏以下所示:
BRKINT:當在輸入行中檢測到一個終止狀態時,產生一箇中斷。
TGNBRK:忽略輸入行中的終止狀態。
TCRNL:將接受到的回車符轉換爲新行符。
TGNCR:忽略接受到的新行符。
INLCR:將接受到的新行符轉換爲回車符。
IGNPAR:忽略奇偶校檢錯誤的字符。
INPCK:對接收到的字符執行奇偶校檢。
PARMRK:對奇偶校檢錯誤做出標記。
ISTRIP:將全部接收的字符裁減爲7比特。
IXOFF:對輸入啓用軟件流控。
IXON:對輸出啓用軟件流控。
若是BRKINT和TGNBRK標誌都未被設置,則輸入行中的終止狀態就被讀取爲NULL(0X00)字符。
輸出模式控制輸出字符的處理方式,即由程序發出的字符在傳遞到串行口或屏幕以前如何處理.經過設置c_oflag成員的標識對輸出模式進行控制.
OPSOT:打開輸出處理功能
ONLCR:將輸出中的換行符轉換爲回車符
OCRNL:將回車符轉換爲換行符
ONOCR:第0行不輸出回車符
ONLRET:不輸出回車符
NLDLY:換行符延時選擇
CRDLY:回車符延時
TABDLY:製表符延時
...
輸出模式用得也很少
控制模式控制終端的硬件特性,經過c_cflag成員標識配置.
CLOCAL:忽略全部調制解調器的狀態行
CREAD:啓用字符接收器
CS5/6/7/8:發送或接收字符時使用5/6/7/8比特
CSTOPB:每一個字符使用兩中止位
HUPCL:關閉時掛斷調制解調器
PARENB:啓用奇偶校驗碼的生成和檢測功能
PARODD:只使用奇檢驗而不用偶校驗
通常也不用這種方式,一般直接修改終端配置文件來修改硬件特性要容易一些
五.本地模式
經過c_lflag成員控制終端的某些特性
ECHO:啓用輸入字符的本地回顯功能
ECHONL:回顯換行符
ICANON:啓用標準輸入處理
ISIG:啓用信號
...
最經常使用的是ECHO和ICANON標誌,前者抑制鍵入字符的回顯(抑制??),後者如說明
標準模式和非標準模式下,c_cc數組的下標有不一樣的值:
標準模式:
VEOF:EOF字符
VEOL:EOL字符
VERASE:ERASE字符
VINTR:INTR字符
VKILL:KILL字符
VQUIT:QUIT字符
VSTART:START字符VSTOP:STOP字符
非標準模式:
VINTR:INTR字符
VMIN:MIN值
VQUIT:QUIT字符
VSUSP:SUSP字符
VTIME:TIME值
VSTART:START字符
VSTOP:STOP字符
INTR:該字符使終端驅動程序向與終端相連的進程以送SIGINT信號
QUIT:該字符使終端驅動程序向與終端相連的進程發送SIGQUIT信號
EOF;該字符使終端驅動程序將輸入行中的所有字符傳遞給正在讀取輸入的應用程序.若是輸入行爲空,read調用將返回0,就好像在文件尾調用read同樣
...
這兩個值只用於非標準模式,二者結合共同控制對輸入的讀取方式,還能控制在一個程序試圖與一個終端關聯的文件描述符時將發生的狀況
MIN = 0, TIME = 0時:read當即返回,若是有待處理的字符,它們就會被返回,若是沒有,read調用返回0,且不讀取任何字符
MIN = 0, TIME > 0時:有字符處理或通過TIME個0.1秒後返回
MIN > 0, TIME = 0時:read一直等待,直到有MIN個字符能夠讀取,返回值是字符的數量.到達文件尾時返回0
MIN > 0, TIME > 0時:read調用時,它會等待接收一個字符.在接收到第一個字符及其後續的每一個字符後,啓用一個字符間隔定時器.當有MIN個字符可讀或兩字符間的時間間隔超進TIME個0.1秒時,read返回
經過設置MIN和TIME值,咱們能夠逐個字符地對輸入進行處理
stty -a:這個命令用來查看當前終端的設置狀況
stty sane:若是不當心設錯了終端模式,可用這個命令恢復,另外一種恢復辦法是在設置以前保存當前stty設置,在須要時再讀出
stty -g > save_stty:將當前設置保存到文件save_atty中
stty $(cat save_stty):讀出save_atty文件,恢復原終端設置
第三種恢復的辦法是從新打下一個終端模擬器.查看死掉的終端進程,kill掉它
4.在命令行模式下設置終端模式
好比想讓shell腳本讀取單個字符,就須要關閉標準模式,同時將MIN設爲1,TIME設爲0:
stty -icanon min1 time 0
另外一個例子是關閉輸入密碼時的回顯功能:
atty -echo
使用完這個命令後要執行atty echo,將回顯功能再次恢復
termios結構中沒有關於終端速度的成員和標識,但咱們能夠經過一組函數來實現.注意輸入和輸出是分開的,應使用不一樣的函數
#include <termios.h> speed_t cfgetispeed(const struct termios *); speed_t cfgetospeed(const struct termios *); int cfsetispeed(struct termios *, speed_t speed); int cfseospeed(struct termios *, speed_t speed);
這些函數只做用於termios結構,所以須要先調用tcgetattr()得到termios結構,再調用以上函數之一設置終端速度,最後調用tcsetattr()使設置生效
上面的speed參數可設的值,其中比較重要的幾個:
B0:掛起終端
B1200:1200波特
B2400:2400波特
B9600:9600波特
B19200:19200波特
B38400:38400波特
這些函數直接做用於文件描述符,不須要讀寫termios結構:
#include <termios.h> int tcdrain(int fd);讓調用程序一直等待,直到全部排隊的輸出都發送完畢 int tcflow(int, int flowtype);暫停或從新開始輸出 int tcflush(int fd, int in_out_selector);清空輸入,輸出或二者都清空