Saturday, October 10, 2009

POSIX termios interface for canonical/non-canonical mode switching


前言
POSIX termios interface,提供一個介面讓我們可以做Termios Programming然而,Termios Programming是一個很大的主題,並且有許多的應用我們可以透過它來控制terminal在處理字元上的一些設定此外Serial Programming也是需要透過它來做一些設定,例如:設定Baud Rate或Parity Checking。甚至,它可以用來存取RS-232的serial port,並且做client-server終端控制的一些應用。而在這篇我想介紹的是利用termios來切換終端機接收字元的標準/非標準模式(canonical/non-canonical mode

Termios簡介
Termios是一個符合POSIX的介面有定義一些函式或巨集除了控制I/O; 它還可以控制硬體,例如決定使用多少位元來傳送跟接收字元; 並且,它也可以控制終端機的特性,例如決定終端機接收字元的模式(接下來本篇文章將以此來舉例); 最後,它也針對一些字元提供特殊的控制

標準/非標準模式(canonical/non-canonical mode)
不管在MS-DOS或是LINUX的終端機相信大家較常使用的是標準模式,而簡單的說,它就是允許使用者在按下Enter鍵前仍然可以修改輸入的字元(例如使用Backspace鍵來修改),所以按下Enter鍵,程式才會讀取字元。相對來說,非標準模式會讀取使用者輸入的任何字元,當然,我們可以利用termios來控制這些輸入,例如我們可以決定在非標準模式下,當使用者輸入多少個字元時即把這些字元傳送給終端機

如何利用termios來切換標準與非標準模式
底下就開始介紹如何使用termios來切換標準與非標準模式
1) 首先,要使用termios我們當然需要先把它include進來

#include <termios.h>

2) 接下來,宣告兩個termios結構(需要宣告兩個是因為,程式在做完任何只有程式本身所需的設定後,在程式結束前必須負責切換回終端機原本的設定,以免影響其它使用)

struct termios initial_settings, new_settings;

3) 取得目前終端機初始設定,並將設定存到initial_settings

tcgetattr(fileno(stdin),&initial_settings);

4) initial_settings複製給new_settings

new_settings = initial_settings;

5) 利用new_settings來做我們想要的設定,以我們的例子來講,我們需要切換成非標準模式

new_settings.c_lflag &= ~ICANON
6) 復原終端機原本的設定

tcsetattr(fileno(stdin),TCSANOW,&initial_settings);

如此,便可以切換成非標準模式,此外,在非標準模式下termios還有很多功能例如使用VTIMEVMIN來控制輸入舉個例子,每當使用者輸入兩個字元,終端機就自動接收這兩個字元,可以這麼寫

new_settings.c_cc[VMIN] = 2;
new_settings.c_cc[VTIME] = 0;

VMIN代表的是非canonical模式讀的最小字元數目。而VTIME代表讀取字元跟字元中間的延遲時間,設定成0代表不可慮VTIME。然而VMIN跟VTIME有許多不同組合,各代表著不同的意義,這就不是本篇文章討論範圍了

結論
termios允許我們去跟一些硬體做溝通,例如透過serial port跟其他設備溝通,目前又以嵌入式系統比較常需要使用,然而在PC上,由於各種傳輸規格日益增進,因此serial port的方法也慢慢被取代了

[Reference]
Beginning Linux Programming 4/e, Richard Stones and Neil Matthew


0 意見: