[單刷APUE系列]第一章——Unix基礎知識[1]
[單刷APUE系列]第一章——Unix基礎知識[2]
[單刷APUE系列]第二章——Unix標準及實現
[單刷APUE系列]第三章——文件I/O
[單刷APUE系列]第四章——文件和目錄[1]
[單刷APUE系列]第四章——文件和目錄[2]
[單刷APUE系列]第五章——標準I/O庫
[單刷APUE系列]第六章——系統數據文件和信息
[單刷APUE系列]第七章——進程環境
[單刷APUE系列]第八章——進程控制[1]
[單刷APUE系列]第八章——進程控制[2]
[單刷APUE系列]第九章——進程關係
[單刷APUE系列]第十章——信號[1]ios
原著這裏前面實際上還有兩節,可是筆者感受並非特別重要,只是Unix各個實現的登陸,因此就直接從進程組開始講。
在使用man 2 intro
的時候,Unix系統手冊上已經寫了不少關於系統的概念,其中就有進程組概念shell
Each active process is a member of a process group that is identified by a non-negative integer called the process group ID. This is the process ID of the group leader. This grouping permits the signaling of related processes (see termios(4)) and the job control mechanisms of csh(1).
激活的進程都是進程組的醫院,進程組ID由進程組頂部進程的pid做爲標識,進程組主要用於相關進程之間的信號傳遞和做業控制。因爲進程組ID其實是一個pid,因此Unix系統給出瞭如下函數segmentfault
pid_t getpgrp(void); pid_t getpgid(pid_t pid);
getpgrp函數是返回當前進程的進程組ID,SUS標準還規定了getpgid用於返回指定pid的進程組ID,若是pid爲0,則返回當前進程的進程組ID。
進程組其實是一個虛概念,並非物理劃分的組,任何一個進程均可以認爲是一個進程組,進程自身就帶有一個屬性用於標識自身的進程組,當進程組ID和自身進程ID相等時,就是一個只有一個進程的進程組,固然,進程也能夠調用setpgid
函數加入一個進程組或者建立一個新進程組。session
int setpgid(pid_t pid, pid_t pgid);
setpgid函數將pid進程的進程組ID設置爲pgid,若是pid爲0,則使用調用者的進程ID,若是pgid爲0,則由pid指定的進程ID做爲進程組ID。ide
A session is a set of one or more process groups. A session is created by a successful call to setsid(2), which causes the caller to become the only member of the only process group in the new session.
會話是一系列進程組的集合,使用setsid函數來建立一個會話,而且當前的進程會變成新會話中的惟一進程組的惟一成員。既然前面提到了setsid函數,咱們就來看看手冊說明函數
pid_t setsid(void); The setsid function creates a new session. The calling process is the session leader of the new session, is the process group leader of a new process group and has no controlling terminal. The calling process is the only process in either the session or the process group. Upon successful completion, the setsid function returns the value of the process group ID of the new process group, which is the same as the process ID of the calling process.
和前面會話的講解基本差很少,就多了一點——沒有控制終端。在說明頁(man 2 intro)中,筆者並無找到有關會話ID的概念,可是確實存在會話惟一標示符,能夠類比前面的內容,大膽猜想一下,會話ID實際上就等於會話首進程的進程ID,實際上,在BSD系統歷史上,也確實引入了這個概念學習
pid_t getsid(pid_t pid); The session ID of the process identified by pid is returned by getsid(). If pid is zero, getsid() returns the session ID of the current process.
這個基本不用多說了。code
控制終端是什麼,手冊頁上是這麼描述的,A terminal that is associated with a session is known as the controlling terminal for that session and its members.
,除了控制終端之外,會話和進程組還有其餘特色進程
會話有控制終端,只要是能實現終端功能的設備都行ci
和控制終端創建連接的會話首進程是控制進程
會話中的進程組能夠分爲前臺進程組、後臺進程組
存在控制終端則一定存在前臺進程組
從上面能夠看到幾個新名詞,控制進程、前臺進程組和後臺進程組,控制進程這裏也直接拿手冊頁描述,A session leader with a controlling terminal is a controlling process.
,前臺後臺進程組可能常用Unix系統的人比較熟悉,前臺進程組在SSH斷線後就會自動終止,然後臺進程組則不會終止。
pid_t tcgetpgrp(int fildes); int tcsetpgrp(int fildes, pid_t pgid_id); pid_t tcgetsid(int fildes);
tcgetpgrp函數看函數名好像是得到進程組ID,可是其實是根據終端設備的文件描述符返回前臺進程組ID,tcsetpgrp則是當進程有一個控制終端的時候,將前臺進程組ID設置爲pgid_id,這個值應當是同一會話的一個進程組ID,filedes則是該會話的控制終端。實際上很是好理解,進程組ID的控制應當是歸屬會話的啓動進程的,也就是第一個進程,而更改前臺進程組ID則應當限定爲同一會話,將後臺進程組更改成前臺,這就是這兩個函數的做用。
最後一個tcgetsid函數則是得到會話ID,實際上前面也講過了,這個就是第一個進程組的第一個進程的進程ID。
shell環境下的做業控制各位應當是很熟悉了,做業控制就是在一個終端下進行的多任務處理,全部的做業實際上都是shell的子進程,這很容易理解。任何狀況下,終端都只有一個前臺任務,其餘都是後臺任務,對於後臺任務的處理,基本上都是使用&
讓其在後臺運行,或者說是更加廣泛的screen
命令,固然,這個不在討論範圍內,在前面的講解中,有一些關於終端產生信號的部分,其實有三個特殊字符用於產生信號
Ctrl+C => SIGINT
Ctrl+\ => SIGQUIT
Ctrl+Z => SIGTSTP
其中前兩個特殊字符已經講過,最後一個Ctrl+Z就是掛起信號。
在前面講過,shell執行程序是經過exec函數族來進行的,也就是說,全部的程序都是shell的子進程,通過前面的講解,應該知道進程至少有pid、ppid、pgid和sid四種屬性,對於經典的sh終端來講,因爲sh不支持做業控制,也就是說,只有一個前臺進程組存在,在實際使用中常用到管道,管道其實是一系列串行的任務集合,shell很是巧妙的逆序將其fork自身,而後反向執行,也就是說,因爲第一個任務的結果是第二個任務的輸入,因此實際上fork的過程是shell fork最後一個任務,逆序的向下派生的。筆者在這裏可能介紹的不夠全面,能夠看原著學習。
在前面介紹過一個進程若是沒有了父進程,則父進程變爲init進程,這種叫作孤兒進程,那麼也能夠類比到進程組,是否存在孤兒進程組。這節也是可看可不看。
實際上在寫這章的時候筆者是很頭疼的,由於基本沒什麼乾貨,都是些概念性的東西,不少都是man 2 intro
上面看看就完事了,特別是前面的終端登陸,實際上因爲原著已經很老了,不少實現基本都變了,因此很難寫出實踐和感想,筆者建議就只看看原著就好了。