在終端和運行的程序之間有一個終端行規程(見http://www.CUOXin.com/nufangrensheng/p/3575752.html中的圖18-2),通過它我們能夠在終端上設置特殊字符(退格、行刪除、中斷等)。但是,當一個登陸請求到達網絡連接時,終端行規程并不是自動被加載到網絡連接和登陸程序shell之間的。
概述偽終端這個術語暗示對于一個應用程序而言,它看上去像一個終端,但事實上偽終端并不是一個真正的終端。下圖顯示了使用偽終端時相關進程的典型結構。其中關鍵點如下:
????通常一個進程打開偽終端設備,然后調用fork。子進程建立了一個新會話,打開一個相應的偽終端從設備,將其描述符復制到標準輸入、標準輸出和標準出錯,然后調用exec。偽終端從設備成為子進程的控制終端。
我們通常用pty表示偽終端,而用tty表示終端。
偽終端的典型用途偽終端可用于構造網絡登錄服務器。典型的例子是telnetd和rlogind服務器。一旦登陸shell運行在遠端主機上,即可得到如下圖所示的結構。Telnetd服務器使用類似的結構。
在rlogind服務器和登錄shell之間有兩個exec調用,這是因為login程序通常是在兩個exec之間檢驗用戶是否合法。
本圖的另一個關鍵點是驅動PTY主設備的進程通常同時在讀寫另一個I/O流。圖中另一個I/O流是TCP/ip框。這表示該進程必然使用了如select或poll那樣的I/O多路轉接,或被分成兩個進程或線程。
script(1)程序是隨大多數UNIX系統提供的,它將終端會話的所有輸入和輸出信息復制到一個文件中。它將自己置于終端和登錄shell的一個新調用之間,從而完成此工作。下圖詳細描述了script程序中有關的交互。這里要特別指出,script程序通常是從登錄shell啟動的,該shell然后等待script程序的結束。
Script程序運行時,位于PTY從設備之上的終端行規程的所有輸出都被復制到script文件中(通常叫做typescript)。因為擊鍵通常由該行規程模塊回顯,所以該script文件也包括了輸入的內容。但是,因為鍵入的口令(密碼)不被回顯,所以該文件不會包含口令。
偽終端可以用來在非交互模式中驅動交互程序的運行。許多程序需要一個終端才能運行,passwd(1)命令就是一個例子,它要求用戶在系統提示后輸入命令。
為了支持處理操作模式而修改所有交互式程序,是非常麻煩的。相比之下,一個更好的解決方法是通過一個腳本來驅動交互式程序。Expect程序提供了這樣的方法,它使用偽終端來運行其他程序。
程序清單15-10(http://www.CUOXin.com/nufangrensheng/p/3561379.html)所示的協同進程例子中,我們不能調用使用標準I/O庫進行輸入、輸出的協同進程,這是因為當通過管道與協同進程進行通信時,標準I/O庫會將標準輸入和輸出的內容放到緩沖區中,從而引起死鎖。如果協同進程是一個已經編譯的程序而我們又沒有源程序,則無法在源程序中加入fflush語句來解決這個問題。圖15-8(http://www.CUOXin.com/nufangrensheng/p/3561379.html)顯示了一個進程驅動協同進程的情況。我們須要做的是將一個偽終端放到兩個進程之間(如下圖所示),這誘使協同進程認為它是由終端而非另一個進程驅動的。
現在協同進程的標準輸入和標準輸出就像終端設備一樣,所以標準I/O庫會將這兩個流設置為行緩沖。
使用任何一個標準shell,可以將一個需要長時間運行的程序放到后臺去運行。但是如果將該程序的標準輸出重定向到一個文件,并且它產生的輸出又不多,那么我們就不能方便地監控程序的進展,這是因為標準I/O庫會將標準輸出全部放在緩沖區中。我們看到的將只是標準I/O庫函數寫到輸出文件中的成塊輸出,有時甚至是大到8192字節的一塊。
如果有源程序,則可以加入fflush調用。另一種方法是,可以在pty程序下運行該程序,讓標準I/O庫認為標準輸出是終端。下圖說明了這個結構,我們將這個緩慢輸出的程序稱為slowout。從登錄shell到pty進程的fork/exec箭頭用 虛線表示,以強調pty進程是作為后臺任務運行的。
新聞熱點
疑難解答