linux中进程pts 1和pts 3,termial创建时ptmx与pts的关系
我們打開一個terminal,那么將會在devpts文件系統/dev/pts下創建一個對應的pts字符文件,
該pts字符文件節點直接由/dev/ptmx節點的驅動函數ptmx_open()
調用devpts_pty_new(tty->link)
[tty對應ptmx,tty->link對應/dev/pts/xxx,那么tty->link->link又對應回ptmx
同樣ptm_driver->other等于pts_driver,pts_driver->other等于ptm_driver]主動創建,
而非通過netlink的udev或者hotplug配合創建[luther.gliethttp]
1.首先我們打開3個新的terminal終端
使用who am i查詢當前終端對應的pts號
luther@gliethttp:~$ who am i
luther?? pts/3??????? 2009-07-03 09:05 (:0.0)
luther@gliethttp:~$ who am i
luther?? pts/4??????? 2009-07-03 09:08 (:0.0)
luther@gliethttp:~$ who am i
luther?? pts/5??????? 2009-07-03 09:08 (:0.0)
他們分別對應pts 3,4和5.
2.在pts/4終端中執行如下命令
luther@gliethttp:~$ cat /dev/pts/3
llllllllls
3.在pts/3終端中輸入平常的命令ls
你會發現輸入的數據并不能被完全顯示,而2步驟中運行的cat? /dev/pts/3
命令確出現了不完整命令,這是怎么回事呢,接下來我們講一講該現象背后的故事[luther.gliethttp].
luther@gliethttp:~$ l
4.講講現象背后的故事
當ubuntu系統創建一個新的terminal時(比如上面的pts/3) 4.1 首先執行ptm = open('/dev/ptmx',...)操作 4.2 接下來fork(),然后child將打開'/dev/pts/3',dup2到0,1和2句柄上,隨后執行execl啟動一個shell. pts = open('/dev/pts/3',...); dup2(pts, 0); // 對應lib庫中stdin dup2(pts, 1); // 對應lib庫中stdout dup2(pts, 2); // 對應lib庫中stderr close(pts); execl("/system/bin/sh", "/system/bin/sh", NULL); // 這樣sh輸入數據將全部來自pts, // sh的輸出數據也都全部輸送到pts,也就直接送到了打開ptmx的新terminal中. 4.3 新terminal將啟動GUI,捕獲按鍵數據,然后寫入ptm,這樣pts將收到數據,進而sh將從stdin中獲得數據, 于是sh將作進一步運算,將結果送給stdout或stderr,進而送給pts,于是ptm獲得數據,然后terminal的GUI 將數據顯示出來.
具體流程圖如下[luther.gliethttp]:
terminal捕獲到key按鍵值 ptm pts/3 stdin shell讀到數據
shell數據結果 stdout pts/3 ptm terminal顯示
4.4 好了,正常的啟動流程圖已經有了,來看看,我們試驗時數據出現顯示異常的現象背后到底是怎么發生的.
與上面正常流程不同的時,我們在另外一個地方執行了cat.
這種情況下的流程圖為[luther.gliethttp]:
terminal ptm pts/3 shell
|
運行在pts/4上的 cat /dev/pts/3
很明顯terminal發送數據到pts/3之后,
因為有2個獨立的進程都在等待pts/3的數據,所以他們之間就發生了對pts/3數據搶奪現象,
因為linux內核調度器根據當時情況隨時都會將他們中的一個調出或者調入,因此數據
就出現了一部分被送到了pts/4的cat命令,另一部分被送到了shell,
因為shell具有回顯能力,shell將它接收到的所有字符串一一回顯給terminal,所以terminal顯示
到的數據就是shell與cat命令爭搶數據時,shell自己搶到的數據,
而pts/4上顯示的數據就是cat命令搶到的數據[luther.gliethttp]
比如我們仍然在pts/4上執行cat命令,然后我們在pts/5上執行echo命令
luther@gliethttp:~$ who am i
luther?? pts/5??????? 2009-07-03 09:08 (:0.0)
luther@gliethttp:~$ echo 'luther.gliethttp' >/dev/pts/3
這時pts/3對應的terminal將完全顯示'luther.gliethttp'字符串,因為沒有人和ptm爭搶數據[luther.gliethttp].
4.5 在pts/3自己所在terminal中執行cat回是什么現象呢,我么繼續看看
luther@gliethttp:~$ cat /dev/pts/3
ls
ls
pwd
pwd
可以看到,輸入ls回車之后,顯示了2個ls,其中1個ls數據是cat命令自己回顯出來的,
另外一個ls就來自/dev/pts/3文件,那這是怎么回事呢,原因是這樣的,
cat和terminal都能獲得鍵盤數據,cat將鍵盤數據直接回顯到terminal上,
而terminal捕獲的數據將通過ptm發送到pts/3,而cat自己又在等待pts/3的數據,所以
cat將從pts/3上再次讀取到ptm發送過來的數據,再一次顯示到terminal上,
那同樣是cat pts/3,為什么就不一樣呢,通過strace發現,如果在
terminal中直接調用庫函數execve()執行另外一個shell命令,那么sh自身將停止對stdin進行數據讀取,
只是等待shell命令退出,數據讀取操作權完全交給被執行的shell命令(cat),
所以cat這時0,1,2都是對應pts/3,因為cat /dev/pts/3命令需要打開文件,
所以fd = open('/dev/pts/3',...)之后,fd數值將等于3,這樣cat /dev/pts/3他的
0,1,2和3這4個句柄都對應pts/3節點[0為stdin,1為stdout,2為stderr]
所以讀取pts/3的進程只有了一個,沒有人和他爭數據了,當然cat能夠完全獲得數據了,呵呵[luther.gliethttp]
總結
以上是生活随笔為你收集整理的linux中进程pts 1和pts 3,termial创建时ptmx与pts的关系的全部內容,希望文章能夠幫你解決所遇到的問題。
 
                            
                        - 上一篇: win7 能下node什么版本_微软从未
- 下一篇: d3js mysql_D3js技术文档
