終端控制--termios結構

LINUX程序設計第三版 5.4節

一.termios是在POSIX規範中定義的標準接口,通過設置termios類型的數據結構中的值和使用一組函數調用,我們可以對終端接口進行控制

可用來調整終端行爲的操作模式:

輸入模式

輸出模式

控制模式

本地模式

特殊控制字符

最小的termios結構典型定義:

#include <termios.h>

struct termios{

    tcflag_t c_iflag;

    tcflag_t c_oflag;

    tcflag_t c_cflag;

    tcflag_t c_lflag;

    cc_t c_cc[NCCS];  

};

結構成員的名稱與上面5種操作模式對應.

兩個操作函數:

#include <termios.h>

int tcgetattr(int fd, struct termios,*termios_p);

將當前的終端接口變量值寫入termios結構中

int tcsetattr(int fd, int actions, const struct termios *termios_p);

使用termios中的值修改終端的行爲,其中actions參數的三種,表示三種修改方式:

TCSANOW-立即修改

TCSADRAIN-完成當前輸出後修改

TCSAFLUSH-完成當前輸出後修改,但丟棄還未從read調用返回的當前可用的輸入

程序運行前要保存終端設置,運行結束後要恢復它們

二.輸入模式

輸入模式控制輸入數據(終端驅動程序從串行口或鍵盤接收到的數據)在被傳送給程序之前的處理方式,通過設置tc_iflag成員標識實現.所有的標識都被定義爲宏,可用按位或方式結合,其他輸入模式也採用這種方法

BRKINT:在輸入中檢測到一個終止條件時,產生一箇中斷

IGNBRK:忽略輸入中的終止條件

ICRNL:將接收到的回車符轉換爲換行符

IGNCR:忽略接收到的換行符

INLCR:將接收到的換行符轉換爲回車符

...

一般用戶不必頻繁修改輸入模式,因爲默認的值通常就是最合適的

三.輸出模式

輸出模式控制輸出字符的處理方式,即由程序發出的字符在傳遞到串行口或屏幕之前如何處理.通過設置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字符

1.字符

INTR:該字符使終端驅動程序向與終端相連的進程以送SIGINT信號

QUIT:該字符使終端驅動程序向與終端相連的進程發送SIGQUIT信號

EOF;該字符使終端驅動程序將輸入行中的全部字符傳遞給正在讀取輸入的應用程序.如果輸入行爲空,read調用將返回0,就好像在文件尾調用read一樣

...

2.TIME和MIN值

這兩個值只用於非標準模式,兩者結合共同控制對輸入的讀取方式,還能控制在一個程序試圖與一個終端關聯的文件描述符時將發生的情況

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值,我們可以逐個字符地對輸入進行處理

3.通過shell訪問終端模式

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,將回顯功能再次恢復

5.終端速度

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波特

6.其他函數

這些函數直接作用於文件描述符,不需要讀寫termios結構:

#include <termios.h>

int tcdrain(int fd);讓調用程序一直等待,直到所有排隊的輸出都發送完畢

int tcflow(int, int flowtype);暫停或重新開始輸出

int tcflush(int fd, int in_out_selector);清空輸入,輸出或兩者都清華空


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章