APUE 2 - 進程組(process group) 會話(session) job

 

進程組(process group)html

進程組顧名思義是指一個或多個進程的集合。他們一般與同一個job(能夠從同一個終端接收信號)相關聯。每一個進程組擁有一個惟一的Process Group Id。可使用getpgrp或getpgid獲取進程的Process Group Id:shell

 1 #include <unistd.h>
 2 
 3 /*
 4 返回調用進程的進程組Id
 5 */
 6 pid_t getpgrp(void);
 7 
 8 /*
 9 若pid爲0,做用與getpgrp相同
10 */
11 pid_t getpgid(pid_t pid);

每一個進程組能夠有一個進程組leader,leader的進程Id與其進程組id相同。不管進程組leader是否終止,只要進程組中存在未終止的進程這個進程組就不會消失。進程組leader終止後進程組中便不存在進程組leader,它不會自動推選新的進程組leader。參見 : Must a process group have a running leader process? 網絡

能夠經過setpgid函數設置進程組Id:session

1 #include <unistd.h>
2 
3 /*
4 設置pid所在進程組Id爲pgid
5 */
6 int setpgid(pid_t pid, pid_t pgid);

調用進程只能設置他本身和他的子進程的Process Group Id,而且若是他的子進程調用了exec類函數,那麼調用進程也沒法更改它的這個子進程的Process Group Id。在 job-control shells中,這個方法經常使用於fork調用後父進程來設置子進程的Process Group Id,或者子進程設置它本身的Process Group Id。固然,fork調用後子進程是會繼承父進程的Process Group Id的,fork後setpgid目的是爲了確保子進程的Process Group Id而避免由於併發竟態致使的意外(這個地方不太懂,沒構建出做者設想的竟態環境)。併發

 

 

會話(session)函數

會話(session)指一個或多個進程組的集合。spa

上圖所示的session結構可使用shell中的pipeline來表示:unix

proc1 | proc2 &
proc3 | proc4 | proc5

在上面示例中,login shell所在的進程組和proc一、proc2所在的進程組爲後臺進程組, proc3,proc4,proc5所在的進程組爲前臺進程組。一個會話中只能有一個前臺進程組,能夠有一個或多個後臺進程組。關於前臺進程組與後臺進程組咱們在後面介紹。code

進程能夠經過setsid來建立新的session。htm

1 #include <unistd.h>
2 
3 /*
4 成功,返回進程組ID,不然返回 -1
5 */
6 pid_t setsid(void);

setsid函數成功時返回的是調用進程的Process Group Id,也是調用進程的Process Id, 由於session leader 永遠是它所在的進程組leader。其實UNIX中是沒有相似 Process Id 或 Process Group Id 的 "Session Id" 這個東西的,有的僅僅是"Session leader"。 咱們能夠認爲 session leader 的 Process Group Id 或 Process Id爲其所在 session 的 Session Id。

setsid在調用時有3件事會發生:
  • 調用進程成爲新session的session leader(A session leader is the process that creates a session)。此時此進程是新session中的惟一進程。
  • 調用進程成爲新進程組的leader。新進程組的Process Group ID 等於 調用進程的 Process ID。
  • 調用進程不會再有控制終端。若是調用進程在調用setsid前擁有控制終端的話,那麼調用setsid後他將斷開與其控制終端的聯繫。
進程組leader不能夠調用setrsid,若是調用者是進程組leader,那麼setsid會返回一個error(大概由於一個進程不能夠是兩個進程組的leader?)。爲了保證setsid的調用者不是進程組Id,許多實現經過調用fork,而後終止父進程,使子進程繼續執行。咱們能夠保證此時子進程不會是任何進程組的leader。由於子進程繼承父進程的進程組,而子進程的Process Id 是新產生的,所以子進程的Process Id 不可能與其繼承的Process Group Id 相同。
能夠經過getsid函數獲取session leader 的 Process Group Id:
1 #include <unistd.h>
2 
3 /*
4 獲取pid所在session的session leader
5 的Process Group ID
6 */
7 pid_t getsid(pid_t pid);

 

 

控制終端(controlling terminal)

 

session和進程組還有其餘幾個特性:
  • 一個session能夠擁有一個控制終端(固然也能夠沒有)。他一般是咱們登陸時的終端設備或僞終端。
  • 建立與控制終端的連接的session leader被稱爲控制進程 (Controlling Process)。
  • 一個會話中的進程組能夠劃分爲一個前臺進程組和一個或多個後臺進程組。
  • 若是一個會話擁有控制終端,那麼它有一個前臺進進程組,這個會話中的其餘進程組都是後臺進程組。
  • 不管什麼時候咱們按下終端的停止鍵(一般是 DELETE或Crtl-C),就會有一個停止信號發送給前臺進程組中的全部進程。
  • 不管什麼時候咱們按下終端的退出鍵(一般是Crtl-Backslash),就會有一個退出信號發送給前臺進程組中的全部進程。
  • 若是終端接口檢測到網絡斷開,那麼hang-up信號就會發送給控制進程,即the session leader。
下圖描述了這些特性:

通常咱們沒必要關心控制終端,它在咱們登陸時自動被建立。有事程序須要與控制終端通訊,不管是使用標準輸出仍是標準輸入重定向。程序保證與控制終端進行通訊的方法時讀寫 /dev/tty文件。這個特殊文件在內核中是控制終端的代名詞。若是程序沒有控制終端,那麼它打開/dev/tty文件將會失敗。
可使用tcgetpgrp函數獲取前臺進程組Id,使用tcsetpgrp設置前臺進程組:

 1 #include <unistd.h>
 2 
 3 /*
 4 經過打開終端的文件描述符獲取前臺進程組Id
 5 */
 6 pid_t tcgetpgrp(int fd);
 7 
 8 /*
 9 pgrpid 必須是相同session中的一個進程組Id
10 */
11 int tcsetpgrp(int fd, pid_t pgrpid);

關於session、process group、controlling terminal的更多信息 , 參見:The controlling-terminal and process-groups.

 

 

Job Control

 

job control 容許咱們在一個終端中啓動多個job,咱們能夠控制哪些job能夠接觸到終端,哪些在後臺運行。job control 要求3中形式的支持:
  1. shell須要支持job control
  2. 內核中的終端驅動必須支持job control
  3. 內核必須支持肯定的job-control信號
對咱們而言,當咱們在shell中使用job control時,咱們能夠在前臺或後臺啓動job。一個job僅僅是一些進程的集合,一般是一些使用pipeline鏈接的進程。
例:
# 在前臺啓動包含一個進程的job
vi main.c
# 兩個後臺jobs調用的全部進程都是後臺進程
pr *.c | lpr &
make all &

# 當咱們啓動一個後臺job時,shell會給這個job分配一個job id,
# 並打印這個job中的一個或多個進程IDs
$ make all > Make.out &
[1]    1475
$ pr *.c | lpr &
[2]    1490
終端驅動可識別3種特殊字符以產生髮送給前臺進程組的信號:
  • 停止字符(一般是DELETE或Crtl-C)產生SIGINT
  • 退出字符(一般是Crtl-Backslash)產生SIGQUIT
  • 暫停字符(一般是Crtl-Z)產生SIGSTP

如前所述,只有前臺job會接收到終端輸入,可是後臺job嘗試讀取終端並非錯誤的,終端驅動會檢測後臺進程的這種舉動並向後臺job發送一個特殊的信號:SIGTTIN。SIGTTIN一般會停止後臺job。

總結

    前面咱們討論了進程組、會話、前臺進程組、後臺進程組、控制終端、job control 這些unix系統息息相關的概念。經過這些知識咱們能夠了解到Unix系統中程序的工做模式及與用戶的交互方式。咱們甚至能夠推測從unix系統啓動到shell的正常運行及shell中啓動其餘進程的過程當中系統中發生的一些事情。這些對於unix系統底層開發應該是不可或缺的。
相關文章
相關標籤/搜索