終端登入:
當系統自舉時,核心建立id為1
的程序,也就是
init
程序,init
程序系統進入多使用者狀態。
init程序讀取
/etc/inittab
,對每乙個允許登入的終端裝置,
init
呼叫一次
fork
,它所生成的子程序執行(
exec
)getty
程式。
getty為終端裝置呼叫
open
函式,如果沒有請求則阻塞,如果有請求,則檔案描述符
0,1,2
就設定到該裝置,然後
getty
輸出」login「
等的資訊並等帶使用者輸入使用者名稱。
當使用者鍵入使用者名稱後,getty
的工作就完成了。
然後以類似於這樣的方式呼叫login程式
execle(
「/bin/login」
,「login」
,「-p」
,username
,(char*
)0,envp);
init以空環境(即無
envp
引數)呼叫乙個
getty
,gettty
以終端名和
gettytab
中說明的環境字串。
-p標識通知
login
保留傳遞給它的環境,也可將其他環境字串加到該環境中,但是不要替換它。
程序組乙個或多個程序的集合,程序組屬於乙個會話。fork
並不改變程序組id
程序組組長
pid與
pgid
相等的程序。組長可以改變子程序的程序組
id,使其轉移到另乙個程序組
例如乙個shell
程序,當使用管道線時,如
echo 「hello」 |cat
,bash
以第乙個命令的程序id
為該管道線內所有程序設定程序組id
。此時echo
和cat
的程序組
id都設定成
ehco
的程序id
前台程序組
該程序組中的程序能夠向終端裝置進行讀寫
登入shell
通過呼叫
tcsetpgrp
()函式設定前台程序組,該函式將終端裝置的
fd與指定程序組相關聯。成為前台程序組的程序其
pgid=tpgid
,常常可以通過比較他們來判斷前台程序組
後台程序組
乙個會話中,除前台程序組,會話首程序以外的所有程序組。該程序組中的終端裝置寫,但是當試圖讀終端裝置時將會收到sigttin
訊號,並停止。登入
shell
可以根據設定在終端上發出一條訊息通知使用者有程序需要讀終端。
前台程序組只有乙個,而後台程序組同時可存在多個。
孤兒程序組
posix定義為:該組中的每個成員要麼是該組的乙個成員,要麼不是該組所屬會話的成員
簡單來說:有bash
產生的新程序組中,至少有乙個程序的
ppid
指向該bash
,否則該程序組成為孤兒程序組,無法將程序狀態改變通知
bash
posix要求系統向孤兒程序中處於停止狀態的每乙個程序傳送結束通話訊號(
sighup
),接著又向其傳送繼續訊號(
sigcont
)對結束通話訊號的預設動作是終止該程序(注意終止程序和停止程序是有區別的,停止指暫停,終止指退出)
為什麼有孤兒程序組
有孤兒程序,對應的也有孤兒程序組的概念。為何引入這個概念以及這個概念的引入需要os
的實現者作些什麼呢?先看兩個前提,首先,
posix
用乙個session
的概念來描述一次使用者的登入以及該使用者在此次登入後的操作,然後用作業的概念描述不同操作的內容,最後才用程序的概念描述不同操作中某乙個具體的工作;其次,
unix
最初將所有的程序組織成了樹的形式,這樣就便於追蹤每個程序也便於管理,有了上述兩個前提事情就很明白了,一切都是為了便於管理,一切都是為了登入使用者的安全,即此次登入使用者的作業是不能被下個登入使用者所控制的,即使它們的使用者名稱一致也是不行的,因此所謂的孤兒程序組簡單點說就是脫離了創造它的session
控制的,離開其
session
眼線的程序組,
unix
中怎樣控制程序,怎樣證明是否在自己的眼線內,那就是樹形結構了,只要處於以自己為根的子樹的程序就是自己眼線內的程序,這個程序就是受到保護的,有權操作的,而在別的樹枝上的程序原則上是觸動不得的,
unix
中建立程序使用
fork
,自然地這麼一「叉子」就形成了自己的乙個樹枝,當然在自己眼線了,一般對於登入使用者而言乙個會話起始於一次
login
之後的shell
,只要該使用者不
logout
,在該終端的
shell
上執行的所有的非守護程序都是該
shell
的後代程序,因此它們組成乙個會話,全部在
shell
的眼線中,乙個會話終止於會話首長的
death
。現在考慮一下終端上的
shell
退出後的情景,按照規定,該終端上所有的程序都過繼給了別的程序,大多數情況是
init
程序,然後緊接著另外乙個使用者登入了這個終端或者知道前乙個登入使用者金鑰的另乙個有不好念頭的人登入了該終端,當然為其啟動的
shell
建立了乙個新的
session
,由於之前登入的使用者已退出,現在登入的使用者由於之前使用者的程序組都成了孤兒程序組,所以它再有惡意也不能控制它們了,那些孤兒程序組中的成員要麼繼續安全的執行,要麼被
shell
退出時發出的
sighup
訊號殺死。
需要注意的
一般乙個登入shell
就是乙個會話首程序,會話首程序獲得乙個控制終端給前台程序組用,會話首程序也只能通過控制終端來控制別的程序,所謂的控制就是傳送訊號(如
ctl+c等)
一些函式
獲得程序組id
#include
pid_t getpgrp(void); 返回值:呼叫程序的程序組id
#include
int setpgid(pid_t pid,pid_t pgid); 返回值:成功返回
0,出錯返回-1
setpgid函式將
pid程序的程序組
id設定為
pgid,
(1)如果兩個引數相等,則由pid
指定的程序變成程序組組長。
(2)如果pid為0,
則使用呼叫者的程序id
(3)如果pgid為0,
則由pid
指定的程序
id用作程序組id
#include
pid_t setsid(void); 返回值:成功返回程序組
id,若出錯返回-1
如果呼叫此函式的程序不是乙個程序組的組長,則此函式就會建立乙個新會話,結果會發生下面三件事:
(1)該程序變為會話首程序。此時,該程序是新會話中的唯一程序
(2)該程序成為乙個新程序組的組長程序。新程序的組id
是呼叫程序的程序id。
(3)該程序沒有控制終端。如果在呼叫setsid
之前該程序有乙個控制終端,那麼也會被中斷
如果呼叫程序呼叫程序是乙個程序組的組長,則此函式返回出錯。為了保證不會出錯,通常先呼叫fork
,然後使其父程序終止,而子程序則繼續。因為子程序繼承了父程序的程序組
id,而其程序
id則是重新分配的,兩個不肯能相等,所以這就保證子程序不會是乙個程序組的組長。
#include
pid_t tcgetpgrp(int filedes);返回值:成功則返回前台程序組
id,出錯返回-1
int tcsetpgrp(
int fileds
,pid_t pgrpid);
返回值:成功返回
0,出錯返回-1
tcgetpgrp返回前台程序組的程序組
id,該前台程序組與在
fileds
上開啟的終端相關聯
tcsetpgrp將前台程序組
id設定為
pgrpid
,pgrpid
應是在同一會話中的乙個程序組的id。
fileds
必須引用該會話的控制終端。
#include
pid_t tcgetsid(int filedes); 返回值:成功返回會話首程序的程序組
id,出錯返回
-1.
需要管理控制終端的應用程式可以呼叫tcgetsid
函式識別出控制終端的會話首程序的會話id
觀察程序組id
與程序id
需要用到的命令
ps -o pid,
ppid
,pgrp
,session
,tpgid
,comm
其中pgrp
表示程序組id,
tpgid
表示前台程序組id,
comm
表示啟動該程序的命令。
孤兒程序 孤兒程序組 守護程序
1.孤兒程序的定義 定義1 該程序組的每個成員的父程序要麼是該組的成員,要麼在其它會話中。定義2 乙個程序不是孤兒程序組的條件是 該組有乙個程序,其父程序在屬於同一會話的另乙個組中。只要能夠滿足上面其中的任乙個定義,則此程序組就是孤兒程序組。可能讀起來比較拗口,看圖 1 中的例子可能會清楚點。圖 1...
孤兒程序組
孤兒程序組定義為 該組中每個成員的父程序要麼是該組的乙個成員,要麼不是該組所屬會話的成員。如果某個程序終止,使得某個程序組成為孤兒程序組的話,系統會向孤兒程序組裡面每個處於停止狀態程序傳送乙個sighup訊號,然後傳送sigcont訊號。include include include include...
孤兒程序組
孤兒程序組 該程序組中每乙個程序的父程序都屬於另乙個session.怎樣建立孤兒程序組?fork 後,子程序繼承父程序的gid,然後父程序退出,那麼子程序變成了孤兒程序,其所在的程序組也變成了孤兒程序組。特性1 父程序終止後,程序組成為了孤兒程序組。那麼新的孤兒程序組中處於停止 stopped 狀態...