Linux值程序 程序組 會話的關係

2021-09-02 23:36:59 字數 3984 閱讀 4149

程序是作業系統的乙個核心概念。每個程序都有自己唯一的標識:程序id,也有自己的生命週期。乙個典型的程序的生命週期如圖4-1所示。

程序都有父程序,父程序也有父程序,這就形成了乙個以init程序為根的家族樹。除此以外,程序還有其他層次關係:程序、程序組和會話。

這樣說來,乙個程序會有如下id:

·pid:程序的唯一標識。對於多執行緒的程序而言,所有執行緒呼叫getpid函式會返回相同的值。

·pgid:程序組id。每個程序都會有程序組id,表示該程序所屬的程序組。預設情況下新建立的程序會繼承父程序的程序組id。

·sid:會話id。每個程序也都有會話id。預設情況下,新建立的程序會繼承父程序的會話id。

可以呼叫如下指令來檢視所有程序的層次關係:

ps 

-ejh

ps axjf程序,可以呼叫以下函式獲取程序組id跟會話id.

pid_t

getpgrp

(void

);pid_tgetsid

(pid_t

pid);

前面提到過,新程序預設繼承父程序的程序組id和會話id,如果都是預設情況的話,那麼追根溯源可知,所有的程序應該有共同的程序組id和會話id。但是呼叫ps axjf可以看到,實際情況並非如此,系統中存在很多不同的會話,每個會話下也有不同的程序組。

為何會如此呢?

就像家族企業一樣,如果從創業之初,所有家族成員都墨守成規,循規蹈矩,預設情況下,就只會有乙個公司、乙個部門。但是也有些「叛逆」的子弟,願意為家族公司開疆拓土,願意成立新的部門。這些新的部門就是新建立的程序組。如果有子弟「離經叛道」,甚至不願意呆在家族公司裡,他別開天地,另創了乙個公司,那這個新公司就是新建立的會話組。由此可見,系統必須要有改變和設定程序組id和會話id的函式介面,否則,系統中只會存在乙個會話、乙個程序組。

程序組和會話是為了支援shell作業控制而引入的概念。

當有新的使用者登入linux時,登入程序會為這個使用者建立乙個會話。使用者的登入shell就是會話的首程序。會話的首程序id會作為整個會話的id。會話是乙個或多個程序組的集合,囊括了登入使用者的所有活動。

在登入shell時,使用者可能會使用管道,讓多個程序互相配合完成一項工作,這一組程序屬於同乙個程序組。

當使用者通過ssh客戶端工具(putty、xshell等)連入linux時,與上述登入的情景是類似的。

4.2.1 程序組

修改程序組id的介面如下

int

setpgid

(pid_t

pid,

pid_t

pgid

);這個函式的含義是,找到程序id為pid的程序,將其程序組id修改為pgid,如果pid的值為0,則表示要修改呼叫程序的程序組id。該介面一般用來建立乙個新的程序組。

下面三個介面含義一致,都是創立新的程序組,並且指定的程序會成為程序組的首程序。如果引數pid和pgid的值不匹配,那麼setpgid函式會將乙個程序從原來所屬的程序組遷移到pgid對應的程序組。

setpgid(0,0)

setpgid(getpid

(),0

)setpgid

(getpid

(),getpid

())setpgid函式有很多限制:

·pid引數必須指定為呼叫setpgid函式的程序或其子程序,不能隨意修改不相關程序的程序組id,如果違反這條規則,則返回-1,並置errno為esrch。

·pid引數可以指定呼叫程序的子程序,但是子程序如果已經執行了exec函式,則不能修改子程序的程序組id。如果違反這條規則,則返回-1,並置errno為eaccess。

·在程序組間移動,呼叫程序,pid指定的程序及目標程序組必須在同乙個會話之內。這個比較好理解,不加入公司(會話),就無法加入公司下屬的部門(程序組),否則就是部門要造反的節奏。如果違反這條規則,則返回-1,並置errno為eperm。

·pid指定的程序,不能是會話首程序。如果違反這條規則,則返回-1,並置errno為eperm。

有了建立程序組的介面,新建立的程序組就不必繼承父程序的程序組id了。最常見的建立程序組的場景就是在shell中執行管道命令,**如下:cmd1 | cmd2 | cmd3

下面用乙個最簡單的命令來說明,其程序之間的關係如圖4-2所示。

ps程序和grep程序都是bash建立的子程序,兩者通過管道協同完成一項工作,它們隸屬於同乙個程序組,其中ps程序是程序組的組長。

程序組的概念並不難理解,可以將人與人之間的關係做模擬。一起工作的同事,自然比毫不相干的路人更加親近。shell中協同工作的程序屬於同乙個程序組,就如同協同工作的人屬於同乙個部門一樣。

引入了程序組的概念,可以更方便地管理這一組程序了。比如這項工作放棄了,不必向每個程序一一傳送訊號,可以直接將訊號傳送給程序組,程序組內的所有程序都會收到該訊號。

前文曾提到過,子程序一旦執行exec,父程序就無法呼叫setpgid函式來設定子程序的程序組id了,這條規則會影響shell的作業控制。出於保險的考慮,一般父程序在呼叫fork建立子程序後,會呼叫setpgid函式設定子程序的程序組id,同時子程序也要呼叫setpgid函式來設定自身的程序組id。這兩次呼叫有一次是多餘的,但是這樣做能夠保證無論是父程序先執行,還是子程序先執行,子程序一定已經進入了指定的程序組中。由於fork之後,父子程序的執行順序是不確定的,因此如果不這樣做,就會造成在一定的時間視窗內,無法確定子程序是否進入了相應的程序組。

使用者在shell中可以同時執行多個命令。對於耗時很久的命令(如編譯大型工程),使用者不必傻傻等待命令執行完畢才執行下乙個命令。使用者在執行命令時,可以在命令的結尾新增「&」符號,表示將命令放入後台執行。這樣該命令對應的程序組即為後台程序組。在任意時刻,可能同時存在多個後台程序組,但是不管什麼時候都只能有乙個前台程序組。只有在前台程序組中程序才能在控制終端讀取輸入。當使用者在終端輸入訊號生成終端字元(如ctrl+c、ctrl+z、ctr+\等)時,對應的訊號只會傳送給前台程序組。

shell中可以存在多個程序組,無論是前台程序組還是後台程序組,它們或多或少存在一定的聯絡,為了更好地控制這些程序組(或者稱為作業),系統引入了會話的概念。會話的意義在於將很多的工作囊括在乙個終端,選取其中乙個作為前台來直接接收終端的輸入及訊號,其他的工作則放在後台執行。

會話會話是乙個或多個程序組的集合,以使用者登入系統為例,可能存在如圖4-3所示的情況。

系統提供setsid函式來建立會話,其介面定義如下:

#include

pid_tsetsid

(void

);如果這個函式的呼叫程序不是程序組組長,那麼呼叫該函式會發生以下事情:

1)建立乙個新會話,會話id等於程序id,呼叫程序成為會話的首程序。

2)建立乙個程序組,程序組id等於程序id,呼叫程序成為程序組的組長。

3)該程序沒有控制終端,如果呼叫setsid前,該程序有控制終端,這種聯絡就會斷掉。

呼叫setsid函式的程序不能是程序組的組長,否則呼叫會失敗,返回-1,並置errno為eperm。

這個限制是比較合理的。如果允許程序組組長遷移到新的會話,而程序組的其他成員仍然在老的會話中,那麼,就會出現同乙個程序組的程序分屬不同的會話之中的情況,這就破壞了程序組和會話的嚴格的層次關係了。

Linux 程序組 會話 守護程序

程序組 乙個或多個程序的集合 程序組id 正整數 兩個函式 getpgid 0 getpgrp eg 顯示子程序與父程序的程序組id 1 include 2 include 3 include 45 int main else if pid 0 1718 sleep 3 19 printf the ...

程序 程序組 會話

1.程序組 每個程序屬於乙個程序組,程序組是乙個或多個程序的集合,每個程序有乙個唯一的程序組id。獲取程序組的兩個函式 include pid t getpgrp void pid t getpgrp pid t pid 程序組可以有乙個組長程序,組長程序的標識是,其程序組id等於其程序id。程序組...

linux的會話 程序 程序組等概念

1.一些縮寫 pid 程序id 由核心根據延遲重用演算法生成 ppid 父程序id 只能由核心修改 pgid 程序組id 子程序 父程序都能修改 sid 會話id 程序自身可以修改,但有限制,詳見下文 tpgid 控制終端程序組id 由控制終端修改,用於指示當前前台程序組 2.關於程序 程序組 會話...