歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Unix知識 >> Unix基礎知識

終端tty、虛擬控制台及FrameBuffer的切換過程

一、區分/dev/tty、/dev/console、/dev/pts、/dev/ttyn /dev/ttySn

通常我們在linux下看到的控制台(console)是由幾個設備完成的。分別是/dev/ttyN.通常使用熱鍵 alt+Fn來在這些虛擬終端之間進行切換。所有的這些tty設備都是由linux/drivers/char/console.c和vt.c對應。

控制終端 /dev/tty指的是當前所處的終端,輸出到此的內容只會顯示在當前工作的終端顯示器上,如果當前進程有控制終端(Controlling Terminal)的話,那麼/dev/tty就是當前進程的控制終端的設備特殊文件。可以使用命令”ps –ax”來查看進程與哪個控制終端相連。對於你登錄的shell,/dev/tty就是你使用的終端,設備號是(5,0)。使用命令”tty”可以查看它具體對應哪個實際終端設備。/dev/tty有些類似於到實際所使用終端設備的一個聯接。這個終端文件可以由各個用戶共享控制台終端 /dev/ttyn  n(0到6)  tty1,tty2就是不同的虛擬終端(virtual console)./dev/console 就是tty0 ,tty0則是當前所使用虛擬終端即激活的虛擬終端的一個別名,系統所產生的信息會發送到該終端上,實際上機器只有一個屏幕,也就是我們看到的這個屏幕,可以理解為console指向激活的那個tty,准確地說是激活的那個tty才將輸出顯示到console。歷史上,console指主機本身的屏幕鍵盤,而tty指用電纜鏈接的其它位置的控制台(僅包含屏幕和鍵盤)。tty0是系統自動打開的,但不用於用戶登錄

偽終端 /dev/pts是遠程登陸(telnet,ssh等)後創建的控制台設備文件所在的目錄。由於可能有好幾千個用戶登陸,所以/dev/pts其實是動態生成的,不象其他設備文件是構建系統時就已經產生的硬盤節點(如果未使用devfs) 。第一個用戶登陸,console的設備文件為/dev/pts/0,第二個為/dev/pts/1,以此類推。這裡的0、1、2、3不是具體的標准輸入或輸出,而是整個控制台。你可嘗試 echo

"aaaaaa" > /dev/pts0、1、2……。

串行端口終端(/dev/ttySn)

串行端口終端(Serial Port Terminal)是使用計算機串行端口連接的終端設備。計算機把每個串行端口都看作是一個字符設備。有段時間這些串行端口設備通常被稱為終端設備,因為 那時它的最大用途就是用來連接終端。這些串行端口所對應的設備名稱是/dev/tts/0(或/dev/ttyS0)、/dev/tts/1(或/dev

/ttyS1)等,設備號分別是(4,0)、(4,1)等,分別對應於DOS系統下的COM1、COM2等。若要向一個端口發送數據,可以在命令行上把標 准輸出重定向到這些

特殊文件名上即可。例如,在命令行提示符下鍵入:echo test > /dev/ttyS1會把單詞”test”發送到連接在ttyS1(COM2)端口的設備上。

二、用ioct1函數操縱虛終端設備文件

虛終端,也叫虛屏,它的英文名字為virtual terminal,縮寫為VT或vt。在Unix系統用戶中,虛終端有著廣泛的應用。它解決了主控台單一交互界面的限制,使用戶可在保護當前界面的情況下啟用另一界面去做另一工作。我們可利用Unix系統提供的系統調用來編制虛終端程序,並可把它加入到我們的應用程序中去。本人就在此虛終端程序的基礎上編寫了圖形軟件,它能夠保存和恢復先前的界面。可利用ioct1函數操縱虛終端設備文件,實現與Unix系統內核的交互,得到我們所需要的服務。使用ioct1的具體形式如下: int ioct1(int filedes,int request,…/*參數*/) 其中filedes為打開的虛終端設備文件描述符,request為請求的服務,隨後的參數可為各種數據類型,視具體情況而定。與虛終端有關的用於ioct1調用中

request值主要有以下幾個:

VT_OPENQRY 查找一個可利用的虛終端。用於ioct1系統調用的參數是一個指向長整數的指針。該長整數的值將被置為第一個可利用的無進程在其上打開的虛終端的序號。如果沒有可利用的虛終端,則該長整數的值被置為-1。VT_GETMODE 獲取活動虛終端當前所在的狀態。用於ioct1系統調用的參數是一個指向 vt_mode結構的指針。結構vt-mode定義如下:

struct vt-mode {

char mode;/* VT mode */

char waitv;/* if set,hang on writes when not active */

short relsig;/*signal to use for release request */

short acqsig; /*signal to use for display acquired */

short frsig; /*not use set to 0 */

}

在結構vt_mode中,mode字段的值可為VT_AUTO和VT_PROCESS,它們的宏定義如下:

#define VT_AUTO 0x00 /*自動切換*/

#define VT_PROCESS 0x01 /*進程控制切換*/

VT_SETMODE 設置虛終端模式(自動或進程控制)。用於ioctl系統調用的參數是一個″vt_mode″結構的指針(結構定義見VT_GETMODE)。

VT_GETSTATE 獲取全部虛終端的狀態信息。用於ioctl的系統調用的參數是一個指向vt_stat結構的指針,該結構定義如下:

struct vt_stat {

ushort v_active;/*活動的vt*/

ushort v_signal;/*要發送的信號(用於VT_SENDSIG)*/

ushort v_state; /*vt位掩碼(VT_SENDSIG和VT_GETSTATE)*/

}

該調用在v_active字段返回活動虛終端號,在v_state字段中可獲得全部虛終端狀態的位掩碼(v_state的位x是虛終端x的狀態,該位為1說明對應的虛終端是打開狀態,否則為可利用狀態)。VT_SENDSIG 指定要發送給虛終端(在v_state中)的位屏蔽的信號(在v_signa1中)。用於ioct1的系統調用的參數是一個指向vt_stat結構的指針(結構定義見前面VT_GETSTATE)。 VT_RELDISP 用於告訴虛終端管理器進程是否已經釋放了顯示。一個零值指示拒絕釋放顯示。 VT_ACTIVATE 使在參數中指定的虛終端號為活動虛終端。″VT″管理器將產生一個切換,如同在鍵盤上按組合熱鍵一樣。如果指定的虛終端不處於打開狀態或者不存在,調用將失敗,並置errno的值為ENXI0。 VT_WAITACTIVE 等待虛終端被激活,不需要參數。

有了上面的介紹,現在我們就可以實現虛終端了:

1查找是否有可利用的虛終端,如沒有,則結束。

2打開可利用虛終端設備文件,以便進行。

3利用ioct1的TCSETSW功能設置虛終端參數,其作用同Unix的stty命令一樣。

4利用ioct1的VT_ACTIVATE功能激活虛終端,並利用VT_WAITACTIVE功能等待其可用。

5用putenv函數設置環境變量。

至此,一個虛終端程序就實現了(當然,是利用Unix系統提供的功能,但它與Unix提供的newvt命令的實現並無區別)。在這個虛終端裡,我們可方便地實現我們自己想要的功能,而不必擔心會破壞原來的環境。

三 、虛擬控制台的切換過程

1. 1) 虛擬終端的切換在控制台軟中斷中運行,當按"ALT F1" 時,鍵盤中斷設置變量want_console 為0,然後激發控制台軟中斷(console_softint),如果請求的控制台存在並且不等於當前控制台,這時調用change_console(want_console)切換控制台。

2) 當前控制台就是直接操作物理屏幕的控制台,用fg_console變量指示。控制台的切換就是物理屏幕在虛擬控制台之間的切換,與CPU在進程之間的切換有些類似,當前物理顯示屏的內容被保存在當前控制台的局部屏幕緩沖區之中,新控制台成為當前控制台,新當前控制台的局部屏幕被恢復到物理屏幕。當輸出到背景控制台時, 文本被緩沖在該控制台的局部屏幕緩沖區中。

3) 當應用程序在某個虛擬控制台中使顯示設備處於圖形狀態時,內核無法正常切換到另一文本控制台,這時可以用KDSETMODE ioctl將控制台設置為KD_GRAPHICS狀態,這樣可防止控制台輸出和切換操作。為了在圖形狀態下也能切換控制台,可以采用進程屏幕切換機制(VT_PROCESS)。當某個控制台被某個進程設置為VT_PROCESS模式時,當離開該控制台時, 內核向該進程生成"釋放"信號(relsig),當進入該控制台時,內核向該進程發送"獲得"信號(acqsig)。該信息由vt_mode結構描述,用VT_SETMODE ioctl設置。

4) 對於X窗口來說,X服務器啟動時切換到第一個未分配的控制台來使用顯示器,當離開該控制台時,內核在X服務器中產生信號,X服務器將顯示器恢復為文本狀態,然後向內核發出"顯示器已釋放"(VT_RELDISP)設備控制消息,內核再接著將顯示器切換到新的控制台。反之,當從文本控制台進入X窗口的圖形控制台時,內核保存當前文本控制台的屏幕現場後向X服務器發出信號,X服務器再將屏幕恢復到圖形狀態。

四、基本的讀寫FrameBuffer的步驟:

1 打開framebuffer設備;

2 通過ioctl取得fixed screen information;

3 通過ioctl取得variable screen information;

4 通過mmap映射設備內存到進程空間;

5 寫framebuffer;

6 關閉framebuffer設備;

/dev/tty的妙用標准的輸入輸出往往不能夠輸入到/dev/tty文件中。而是需要通過重定向功能,把一些命令的輸出重定向到這個文件中。另外需要說明的是,普通終端的話往往是每個用戶之間相互獨立的。也就是說,每個用戶的輸出彼此之間是互不干涉的。但是/det/tty這個文件由其特殊性。這個終端文件可以由各個用戶共享。

1. 利用這個文件來屏蔽不需要的結果信息。

系統工程師可以輕松的通過/dev/tty文件來過濾這些無用的提示信息。如只需要把腳本程序的運行結果通過重定向服務重定向到/dev/tty文件中。在這個重定向的過程中,Unix系統的shell會采取一定的內部處理機制,會忽略掉echo等命令。也就是說,只要把命令的標准輸出重定向到這個文件中,則利用echo命令設置的一些提示信息都會被忽略掉。此時在這個文件中,存儲的只有一些必要的運行信息,如錯誤或者警告信息等等。

2. 當作其他命令的參數。

系統工程師即希望把命令的結果輸出到終端中,同時保存到一個文件中,就需要利用tee命令,如who | tee userinfo.txt。(注意,如果利用了tee命令的話,在可以不再使用重定向符號)。到這裡為止沒有涉及到/dev/tty這個文件。who | tee userinfo.txt這個命令的顯示結果,只會顯示當前登錄的用戶明細,而不會顯示當前有多少個用戶登錄到系統中。如果其他腳本程序需要用到當前登錄用戶的總數而不需要明細,那麼該如何處理呢?此時就需要利用/dev/tty文件作為參數了。如可以使用who | tee /dev/tty |wc –l 命令。這個命令可以把當前用戶的明細以及總共的用戶數量顯示出來。以上這個命令其實我們可以分為四個步驟。第一步系統先執行who命令;第二步tee命令把who命令執行對結果保存到/dev/tty文件中;第三步wc命令會統計/dev/tty文件中的行數。由於一個終端對相當於一個文件,故利用wc命令可以統計出當前系統登錄用戶的數量。第四步再把這個統計的結果顯示在終端上。所以說,把/dev/tty文件當作其他命令的一個參數,一個一起組合以實現一些比較復雜的功能。

需要注意的是命令 >/dev/tty與命令> file連個命令其最終的結果有可能相同,也有可能不同。前者在把命令的顯示結果保存到/dev/tty文件中的時候,會過濾掉echo等命令設置的信息。而後者這個命令這會把顯示的結果一五一十的照搬到file文件中去。也就是說,如果在命令或者腳本程序中沒有echo等類似的命令設置信息的話在,則這兩個命令重定向文件後所保存文件的內容是一致的。但是如果在命令或者腳本程序中有類似的提示命令的話,則兩個文件的顯示結果則會不同。為此系統工程師就需要根據自己的實際需要,來選擇合適的重定向文件,看看有否必要采用/dev/tty文件

Copyright © Linux教程網 All Rights Reserved