標籤:
linux的終端,網路虛擬終端,偽終端轉自:http://www.xuebuyuan.com/877887.html Linux上許多網路服務應用,如l2tp、pptp、telnet,都用到了偽終端。有朋友在問這方面的概念,把偶知道的寫下來,以供討論。
一、終端
要理解偽終端(Pseudo Terminal),先來看看什麼是“終端”(Terminal)。
終端是一種字元型裝置,它有多種類型,通常使用tty來簡稱各種類型的終端裝置。
1、序列埠終端(/dev/ttySx)
序列埠終端(Serial Port Terminal)是使用電腦序列埠串連的終端裝置。電腦把每個序列埠都看作是一個字元裝置。
這些序列埠所對應的裝置名稱是/dev/ttyS0、/dev/ttyS1等,分別對應於DOS系統下的COM1、COM2等。
- [[email protected] ~]# ls -l /dev/ttyS*
- crw-rw---- 1 root uucp 4, 64 Jan 8 13:39 /dev/ttyS0
- crw-rw---- 1 root uucp 4, 65 Jan 8 13:39 /dev/ttyS1
- crw-rw---- 1 root uucp 4, 66 Jan 8 13:39 /dev/ttyS2
- crw-rw---- 1 root uucp 4, 67 Jan 8 13:39 /dev/ttyS3
複製代碼
2、控制台終端(/dev/ttyn, /dev/console)
在Linux系統中,電腦顯示器通常被稱為控制台終端(Console)。它模擬了類型為Linux的一種終端(TERM=Linux),
與之相關聯的裝置檔案為:tty0、tty1、tty2……。當使用者從控制台上登入時,使用的是tty1。使用Alt+[F1—F6]按鍵組合時,我們就可以切換
到tty2、tty3……上面去。tty1 –tty6等稱為虛擬終端,而tty0則是當前所使用虛擬終端的一個別名,系統所產生的資訊會發送到該終端上。
因此不管當前正在使用哪個虛擬終端,系統資訊都會發送到控制台終端上。使用者可以登入到不同的虛擬終端上去,因而可以讓系統同時有幾
個不同的會話期存在。只有系統或超級使用者root可以向/dev/tty0進行寫操作。
作為一個測試例子,在控制台終端下,運行命令:
- #echo "write to ttyS0" > /dev/ttyS0
複製代碼
在序列埠終端中可以看到輸出:
- # write to ttyS0
複製代碼
3、控制終端(/dev/tty)
控制終端並不面對裝置,而是面對進程,關於這個概念,《Unix環境進階編程》第9章有詳細論述。
二、從終端登入簡述
Linux系統引導的時候,會運行init進程,它會執行/etc/inittab(這跟具體的init類型有關,我使用了busybox的init,但其本質是一樣的):
- [[email protected] ~]# cat /etc/inittab
- ::sysinit:/etc/init.d/rcS
- ::respawn:/sbin/getty 9600 ttyS0
複製代碼
它會調用getty在指定傳輸速率上開啟ttyS0,即,序列埠終端。開啟成功後,stdout,stdin,stderr都被設定到該備上,然後getty輸出:"login:"之類的提示符,等待使用者輸入。
當使用者鍵入使用者名稱後,getty就執行login程式,類似於:execle("login")。login可以調用getpass()以顯示Password:並讀入使用者口令。並且調用getpwnam進行口令驗證。如果成功,調用類似execle("shell")。這樣,登入使用者就擁有了一個shell了。
三、偽終端
上述登入過程,對於網路使用者來說,卻不能完全實用。很顯然,網路使用者並不需要一個串口,也不需要一個顯示器,他需要的是在他的本地顯示裝置上,運行Linux的shell。這種網路使用者被稱為網路虛擬終端。以telnetd為例,它至少應該是這樣子的:
圖一:telnet登入假想圖
這裡,這個“某個終裝置”,自然不可能是一個實際的物理終端裝置,因為壓根沒有這樣的裝置。這樣,偽終端的概念就被引入進來了。偽終端裝置是一種特殊的終端驅動裝置, 它並不驅動某個物理裝置,而是用來將終端的輸出定向到應用程式中進行處理。偽終端裝置之所以存在是為了提供在程式控制下的一種類比串列終端行為的方法。
偽終端與前面說的終端在表現形式上,最大的不同,就是它總是成對出現,而不是單一的一個。它分為“偽終端主裝置(/dev/ptyMN)”和“偽終端從裝置”。(/dev/ttyMN)。其中,M與N的命名方式如下:
- M: p q r s t u v w x y z a b c d e 共16 個
- N: 0 1 2 3 4 5 6 7 8 9 a b c d e f 共16 個
複製代碼
這樣,預設支援最大是256個。
任何寫入到偽終端主裝置的輸入,都會作為偽終端從裝置的輸入,反之亦然。類似於管道,如:
一個典型的偽終端進程結構如:
這張圖的關鍵在於:如果把偽終端從裝置想像為傳統的終端裝置,把主裝置看成進程讀寫資料的一個“介面”,那麼它的工作原理,就跟傳統終端一樣了。
上述只是一個本地進程,把網路引入進來,對應到telnetd上面來,應該是下面這個樣子:
同樣的登入方式,就變成了這樣:
1、如果某人在網上使用telnet程式串連到本機伺服器,則telnetd程式就可能會開始串連到裝置ptyp2(m2)上(一個偽終端主裝置上)。
2、telnetd產生一個子進程,進行getty程式,其開啟一個對應的從裝置對應的ttyp2(s2),並設定stdin\stdout\stderr;
3、telnetd通過核心tcp/ip協議棧從遠端擷取了一個字元時,該字元就會通過m2、s2傳遞給getty程式,而getty程式就會通過s2、m2和telnetd程式往網路上返回”login:”字串資訊;
4、這樣,登入程式與telnetd程式就通過“偽終端”進行通訊;
四、偽終端的數量
對於Linux下的應用而言,知道偽終端的數量是一個關鍵的東東,或者它直接決定了最大支援使用者數,例如PPTP VPN的應用。(沒有多餘的可以供開啟的
偽終端裝置了)。
對於2.6.X而言,在
- Device Drivers --->
- Character devices --->
- [*] Legacy (BSD) PTY support
- (256) Maximum number of legacy PTY in use
複製代碼
可以設定。應該將它調整到足夠地大,以供支援應用。同時,/dev目錄下,應該有相應的裝置檔案:
- #ls -l /dev/ptyp*
- crw-r--r-- 1 root root 2, 0 Dec 18 05:36 /dev/ptyp0
- crw-r--r-- 1 root root 2, 1 Dec 18 05:36 /dev/ptyp1
- crw-r--r-- 1 root root 2, 2 Dec 18 05:36 /dev/ptyp2
- crw-r--r-- 1 root root 2, 3 Dec 18 05:36 /dev/ptyp3
複製代碼
- #ls -l /dev/ttyp*
- crw------- 1 root root 3, 0 Dec 18 05:36 /dev/ttyp0
- crw------- 1 root root 3, 1 Dec 18 05:36 /dev/ttyp1
- crw-r--r-- 1 root root 3, 2 Dec 18 05:36 /dev/ttyp2
- crw------- 1 root root 3, 3 Dec 18 05:36 /dev/ttyp3
複製代碼
這樣命令方式,並且要指定數量的方式實在是讓人鬱悶。因為它有一個數量上限的問題,最大256。
為瞭解決這個問題,Linux引入了一種新的命名方式:UNIX98_PTYS。關於這個東東,核心是這樣解釋的:
- Linux has traditionally used the BSD-like names /dev/ptyxx for
- masters and /dev/ttyxx for slaves of pseudo terminals. This scheme
- has a number of problems. The GNU C library glibc 2.1 and later,
- however, supports the Unix98 naming standard: in order to acquire a
- pseudo terminal, a process opens /dev/ptmx; the number of the pseudo
- terminal is then made available to the process and the pseudo
- terminal slave can be accessed as /dev/pts/<number>. What was
- traditionally /dev/ttyp2 will then be /dev/pts/2, for example.
- All modern Linux systems use the Unix98 ptys. Say Y unless
- you‘re on an embedded system and want to conserve memory.
複製代碼
這樣,可以通過訪問/dev/ptmx裝置檔案的形式,來訪問偽終端裝置了,例如我的PPTP伺服器,當有五個使用者撥入後:
- # ls -l /dev/pts/
- crw------- 1 root root 136, 0 Jan 8 12:18 0
- crw------- 1 root root 136, 1 Jan 8 08:08 1
- crw------- 1 root root 136, 2 Jan 8 14:10 2
- crw------- 1 root root 136, 3 Jan 8 14:27 3
- crw------- 1 root root 136, 4 Jan 8 08:29 4
複製代碼
linux的終端,網路虛擬終端,偽終端