Linux下的進程本身都是以init為祖先進程的一個樹狀進程族譜,Init進程就是這個樹的根。但是為方便管理有其他層級關系進程們,又在簡單的父子關系之外增加了進程組和會話的關系,從而方便進程的管理。當一個用戶登錄到系統時登錄程序就會將登錄的shell設置成一個會話首領和組長進程。簡單來說是這樣的一種關系 會話 > 包括進程組 > 包括進程 。而增加這樣的額外關系僅僅是為了方便管理控制所有由關系的進程(作業)。在Linux中一個進程除了是屬於他父進程的子進程外他還是一個進程組的成員,而同一進程組有這樣一個特點-----信號會被傳遞到同一進程組的所有進程。
一般情況下一個進程創建的一個子進程這個子進程就和父進程同屬一個進程組,那么如果都是這樣的情況那Linux中應該就只有一個進程組。所以這種情況其實是一種特殊情況。這種情況會導致不同用戶的進程之間可以發送信號。所以Linux允許進程修改自己或子進程(執行exec前)的進程組和會話組,從而將進程進行又一層的分組管理。進程可以通過調用setpgid來修改自己的進程組
int setpgid(pid_t pid,pid_t pgid);
這個調用必須滿足
- 調用進程不能是當前進程組的首領進程。
- 調用進程不能是會話首領進程。
- pid只能是當前調用進程的pid(傳入0),或者當前調用進程的子進程(未執行exec調用前),而且因為子進程和父進程的運行順序不確定通常情況下要在子進程和父進程中同時調用此接口,確保子進程運行之初就在正確的進程組。
一個進程還可以將自己設置為一個新的會話的新進程組成員通過調用setsid()
pid_t setsid(void);
調用的進程不能是一個進程組的或會話的首領進程,成功時返回新創建的會話的會話ID。
總之會話和進程組常常用於作業控制,比如你的代碼你希望他單獨成為為一個組可以統一開始或結束,而不受父進程shell的的控制或者影響。反過來會話和進程組的概念也是為了方便shell管理用戶的進程的,因為當進程組首領進程結束時進程組還是存在的,其他進程還是在運行的,當時當會話首領進程結束時,會話內的所有進程都會結束(ubantu14.04下測試)。
測試代碼
#include <sys/types.h> #include <unistd.h> #include <stdio.h> #include <error.h> int main(char argc,char* argv) { pid_t newSid; newsid=setsid(); printf("The new sid is %d\n",newsid); while(1) { sleep(1); printf("I ma Running\n"); } return 0; }