進程間關係

說完了進程,我們來說一下進程間關係。

進程組


一個或者多個進程的集合,每一個進程除了有一個進程ID之外,它還屬於一個進程組。通常來說,進程組和作業相關聯,可以來接收同一個終端下的各種信號,每一個進程組也有對應的唯一進程組ID。
這裏寫圖片描述
這一列PGID就是進程組,我們可以看到上面那三個mydaemon的守護進程所在不同進程組。這裏下面的帶[]的都是內核進程,可以看到它們都在同一進程組。

組長進程:組長進程就是進程組id==進程id。
組長進程可以創建一個進程組,創建該進程組當中的進程,另外只要一個進程組當中有一個進程存在,進程組就存在。與組長進程的存在與否無關。所以一個進程組的週期就是從創建到最後一個進程終止。

會話


會話是一個或多個進程組的集合。
![enter description here][4]

一個會話有一個控制終端,簡歷與控制終端相連接的會話首進程叫做控制進程。一個會話當中分爲一個前臺進程組和多個後臺進程組。內核通常發信號給前臺進程組的所有進程。

會話的意義在於將多個工作囊括在一個終端,並且取其中的一個工作作爲前臺,來直接接受該終端的輸入輸出以及終端信號。其他的工作在後臺運行。

建立新會話,有一個函數setsid

![enter description here][3]

這個函數調用進程如果不是一個進程組組長進程,則這個函數會幹三件事:
1. 該進程變爲新會話的首進程,它成爲新會話的唯一的進程。
2. 該進程成爲一個新進程組的組長進程。新進程組ID是該調用進程的進程ID。
3. 該進程沒有控制終端,如果之前有,那麼被中斷。

看上面剛纔看過的那副圖,新標註的那一欄SID就是會話。
![enter description here][2]

控制終端


在前面的敘述中我們提到一個概念叫做控制終端,當會話的手進程打開第一個尚未與一個會話相關聯的終端設備是,系統將此作爲控制終端分配給此會話。

在UNIX系統中,用戶通過終端登錄系統後得到一個Shell進程,這個終端成爲Shell進程的控制終端(Controlling Terminal),控制終端是保存在PCB中的信息,而我們知道fork會複製PCB中的信息,因此由Shell進程啓動的其它進程的控制終端也是這個終端。默認情況下(沒有重定向),每個進程的標準輸入、標準輸出和標準錯誤輸出都指向控制終端,進程從標準輸入讀也就是讀用戶的鍵盤輸入,進程往標準輸出或標準錯誤輸出寫也就是輸出到顯示器上。在控制終端輸入一些特殊的控制鍵可以給前臺進程發信號,例如Ctrl-C表示SIGINT,Ctrl-\表示SIGQUIT。

每個進程都可以通過一個特殊的設備文件/dev/tty訪問它的控制終端。事實上每個終端設備都對應一個不同的設備文件,/dev/tty提供了一個通用的接口,一個進程要訪問它的控制終端既可以通過/dev/tty也可以通過該終端設備所對應的設備文件來訪問。ttyname函數可以由文件描述符查出對應的文件名,該文件描述符必須指向一個終端設備而不能是任意文件。在Linux上的命令tty 也可以查看到當前的終端。
比如我們在圖形界面下打開一個終端可能是/dev/pts/0, 第二個可能是/dev/pts/1 …(網絡終端)
而切換到字符界面下可能是/dev/tty1 …(虛擬終端)

![enter description here][5]

作業控制


事實上Shell分前後臺來進行控制的不是進程而是作業。一個前臺作業由多個進程組成,一個後臺作業也可以由多個進程組成,Shell可以運行一個前臺作業和多個後臺作業。

作業也有作業號:
![enter description here][6]

操作 含義 例子
& 在運行一個進程後面加上&,表示讓該進程在後臺進行運行。 ./a.out &
jobs 查看作業 jobs
bg 作業號 切換作業到後臺運行 bg 1
fg 作業號 切換作業到前臺運行 fg 2
Ctrl+Z 自動把進程切回後臺,切換Shell回前臺
Ctrl+C 作業終止,進程發信號給前臺進程

終端的登錄過程


最後我們來說一下終端的登錄過程。

![enter description here][7]
從gettty exec進程程序替換到login,然後再exec到bash,都是在一個initfork的子進程當中進行的。所以控制終端的進程是沒有發生變化的。文件描述符 0、1、2也依然指向控制終端,當進行從bashfork的時候,這個時候會複製PCB信息給子進程,所以其他進程的0、1、2也就一開始默認固定了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章