當(dāng)你打開終端并輸入命令時會發(fā)生什么?(下)
哈嘍大家好,我是咸魚
我們先來大致回顧一下文章《當(dāng)你打開終端并輸入命令時會發(fā)生什么?(上)》的內(nèi)容
終端設(shè)備是由電傳打字機(jī)演變過來的,電傳打字機(jī)通過物理線與大型計(jì)算機(jī)連接在一塊來實(shí)現(xiàn)輸入輸出
如上圖,分別是二戰(zhàn)時期的電傳打字機(jī)和西門子 “Fernscheiber 100” 電傳打字機(jī)
隨著技術(shù)的不斷發(fā)展(尤其是顯示技術(shù)),帶顯示屏的終端設(shè)備隨之誕生
而現(xiàn)在隨著個人電腦的普及,出現(xiàn)了基于屏幕顯示的圖形用戶界面(GUI),演變成了現(xiàn)在的計(jì)算機(jī)終端
現(xiàn)在的終端大多都是計(jì)算機(jī)上的一個應(yīng)用程序,它們通常被稱為終端模擬器,充當(dāng)用戶與操作系統(tǒng)交互的界面(比如說 Linux 中的 Xterm、Xshell,Windows 中的控制臺),而不必使用專門的終端。輸出系統(tǒng)是屏幕,輸入系統(tǒng)是鍵盤
以 Linux 為例,當(dāng)我們打開終端時,通常會啟動一個 shell 進(jìn)程,用于與用戶交互。用戶在終端中輸入的命令將傳遞給 shell 進(jìn)程,然后由 shell 解釋和執(zhí)行這些命令
這個過程包括將用戶輸入的命令解析為操作系統(tǒng)可以理解的指令,執(zhí)行這些指令,并將執(zhí)行結(jié)果返回給終端顯示給用戶
輸入命令
當(dāng)我們在終端中輸入命令時,鍵盤輸入的字符會被轉(zhuǎn)換成相應(yīng)的字符編碼(比如說 backspace
鍵被轉(zhuǎn)譯成 ASCII 字符 0x08
)
這些字符通過終端寫入到 PTY leader,接著 TTY driver 從 PTY leader 中讀取字符并存儲到 line discipline 中(line discipline 為 PTY 兩端之間的中間緩沖區(qū))
不但如此,line discipline 還負(fù)責(zé)解釋來自 PTY leader 的字符然后根據(jù)自己的規(guī)則去處理它們(比如進(jìn)行回退、刪除字符等,或者處理特殊字符)
舉個例子,line discipline 收到 backspace
時,它會根據(jù)自己的規(guī)則解釋成 ERASE 字符,然后進(jìn)行編輯,方法是刪除最后一個字符
接著將刪除操作返回給 PTY leader,這樣終端就可以從 PTY leader 那里讀取到更改并將其反映在終端顯示中
需要注意的是,上面這段過程里字符還沒有被寫入到 PTY follower 中,只是處在【編輯】部分
當(dāng)我們在鍵盤敲下 CTRL+C
時,line discipline 會解釋成 INTR
(INTERRUPT 的縮寫),這時候就會向 PTY follower 發(fā)送一個 SIGINT 信號去中斷在前臺運(yùn)行的任何進(jìn)程
如果不是特殊字符(比如輸入 ls
),line discipline 會將字符返回給 PTY leader,終端程序讀取并顯示在屏幕上,這就是為什么你在鍵盤敲一個字符,顯示器就會顯示一個字符(echo 功能)
現(xiàn)在 shell 進(jìn)程也會緩沖用戶的輸入,以實(shí)現(xiàn)一些高級的功能:比如命令歷史記錄或 tab 鍵自動補(bǔ)全
執(zhí)行并解析命令
當(dāng)我們輸入完命令之后,就要按下回車鍵(Enter)來執(zhí)行命令了
一旦按下回車鍵,line discipline 解釋為換行字符(newline),通常表示為 NL
。
然后一并將用戶的命令轉(zhuǎn)發(fā)到 PTY follower ,而 shell 進(jìn)程跟 follower 相連,shell 拿到命令之后就會去解析并執(zhí)行
當(dāng) shell 進(jìn)程接收到用戶的輸入和換行符時,它會開始解析并執(zhí)行命令。這個過程包括命令解析、查找可執(zhí)行文件或內(nèi)置命令,以及執(zhí)行相應(yīng)的操作
首先對命令解析成一個一個 token 并進(jìn)行語法/語義分析,以 ls
命令為例:
-
ls > foo.txt
:正確 -
ls >
:語法不正確,>
后面缺少內(nèi)容 -
ls | foo.txt
:語義不正確,管道的兩端都需要是可運(yùn)行的進(jìn)程
然后接著解析那些不是 shell 關(guān)鍵字或者路徑的 token,shell 需要知道這些 token 的含義,所以 shell 會去根據(jù)下面幾個部分去遞歸查找 token 引用的內(nèi)容:
-
aliases:命令別名,通常用于縮寫復(fù)雜的命令(例如
alias ll="ls -lh"
) - function:函數(shù)
- environment variables:環(huán)境變量
-
builtins:shell 內(nèi)嵌命令(例如
cd
pwd
exit
kill
) -
PATH executables:shell 可以找到(通過
$PATH
變量)并運(yùn)行的外部命令
我們可以通過 type
命令知道對應(yīng)的類型
[root@minion1 ~]# type ll
ll 是 'ls -l --color=auto' 的別名
[root@minion1 ~]# type cd
cd 是 shell 內(nèi)嵌
[root@minion1 ~]# type python
python 是 /usr/bin/python
與 shell 內(nèi)嵌命令不同的是,可執(zhí)行命令是單獨(dú)的程序或腳本文件,具有執(zhí)行權(quán)限,可以作為單獨(dú)的進(jìn)程執(zhí)行
當(dāng)用戶在 shell 中輸入一個命令時,shell 會查找可執(zhí)行文件的位置,并在找到后創(chuàng)建一個新的子進(jìn)程來運(yùn)行該可執(zhí)行文件,并將相應(yīng)的命令參數(shù)傳遞給這個新的子進(jìn)程
我們可以通過 pstree
命令來查看進(jìn)程之間的關(guān)系文章來源:http://www.zghlxwxcb.cn/news/detail-760516.html
返回輸出
當(dāng) shell 執(zhí)行完命令之后,把生成的輸出寫入到 PTY follower ,接著傳到 line discipline 中,line discipline 不會處理這些輸出,而是轉(zhuǎn)發(fā)給 PTY leader,然后終端就會讀取并顯示到屏幕上
參考文章:https://www.warp.dev/blog/what-happens-when-you-open-a-terminal-and-enter-ls文章來源地址http://www.zghlxwxcb.cn/news/detail-760516.html
到了這里,關(guān)于當(dāng)你打開終端并輸入命令時會發(fā)生什么?(下)的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!