進程基本屬性
1.進程ID(PID)
函數定義:#include <sys/types.h>
#include <unistd.h>
pid_t getpid(void);
函數說明:
每一個進程都有一個非負整型表示的唯一進程ID(PID).好比方我們的身份證一樣,每一個人的身份證號是唯一的.由於進程ID標示符總是唯一的,常將其用來做其它標示符的一部分以保證其唯一性。進程ID(PID)是無法在用戶層改動的.
在Linux系統中,PID為0 的進程一般是調度進程。經常被稱為交換進程,也是第一個系統進程.第一個用戶進程是init進程。其PID為1.
在應用編程中。調用getpid()函數能夠獲得當前進程的PID,此函數沒有參數,假設運行成功返回當前進程的PID。失敗返回-1。出錯原因存儲於errno.
樣例1:打印自己的進程ID(PID).
#include <unistd.h> #include <stdio.h> int main() { pid_t pid; //pid_t 事實上是int pid = getpid(); printf("the current program's pid is %d\n",pid); while(1); return 0; }
執行后使用“ps u”命令查看對比一下.
2.父進程ID(PPID)
函數定義:#include <sys/types.h>
#include <unistd.h>
pid_t getppid(void);
函數說明:
不論什么進程(除init進程)都是由還有一個進程創建。該進程稱為被創建進程的父進程。被創建的進程稱為子進程。父進程ID無法在用戶層改動.父進程的進程ID即為子進程的父進程ID(PPID).
用戶能夠通過調用getppid()函數來獲得當前進程的父進程ID(PPID).此函數沒有參數,假設運行成功返回當前進程的父進程ID(PPID)。失敗返回-1,出錯原因存儲於errno.
樣例1:打印自己的父進程PPID.
#include <unistd.h> #include <stdio.h> int main() { pid_t ppid; //pid_t 事實上是int ppid = getppid(); printf("the current program's ppid is %d\n",ppid); while(1); return 0; }
執行后使用“ps u”命令查看對比一下.
3.進程組ID(process group ID PGID)
函數定義:#include <unistd.h>
int setpgid(pid_t pid, pid_t pgid);
pid_t getpgid(pid_t pid);
pid_t getpgrp(void); /* POSIX.1 version */
pid_t getpgrp(pid_t pid); /* BSD version */
int setpgrp(void); /* System V version */
int setpgrp(pid_t pid, pid_t pgid); /* BSD version */
函數說明:
在Linux系統中。每一個用戶都實用戶ID(UID)和用戶組ID(GUID).相同,進程也擁有自己的進程ID(PID)和進程組ID(PGID). 進程組是一個或多個進程的集合;他們與同一作業相關聯.每一個進程組都有唯一的進程組ID(PGID),進程組ID(PGID)能夠在用戶層改動.比方。將某個進程加入到還有一個進程組,就是使用setpgid()函數改動其進程組ID.
用戶能夠通過調用getpgid()函數來獲得當前進程的進程組ID(PGID).若此參數為0表示獲取當前進程的進程組ID,假設運行成功返回當前進程的進程組ID(PGID)。失敗返回-1。出錯原因存儲於errno. 建議使用POSIX.1規定中的無參數getprgp()函數替代getpgid(pid)函數.
進程組ID(PGID)也能夠通過函數getpgrp()獲得.通過fork()函數產生的子進程會繼承它的父進程的進程組ID(PGID).
每一個進程組都能夠有一個組長進程,組長進程的進程組ID等於其進程ID.但組長進程能夠先退出。即僅僅要在某個進程組中有一個進程存在,則該進程組就存在,與其組長進程是否存在無關.進程組的最后進程能夠退出或轉移到其它組.
能夠將某個進程增加到某個進程組中,調用系統函數setpgid().其第一個參數為欲改動進程組ID(PGID)的進程ID(PID),第二參數為新的進程組ID(PGID),假設這兩個參數相等,則由pid指定的進程變為該進程組組長。假設pid為0,則使用調用者的進程ID(即改動當前進程的進程組ID(PGID為指定的pgid));假設pgid是0,則由pid指定的進程ID(PID)。用做進程組ID(PGID)(即:pid所指進程作為進程組的組長進程).
一個進程僅僅能為自己或子進程設置進程組ID(PGID),假設在它的子進程中調用了exec()等系列函數,就不再能改變該子進程的進程組ID(PGID).
#include <unistd.h> #include <stdio.h> int main() { int i; printf("\t pid \tppid \t pgid\n"); printf("parent:\t%d\t%d\t%d\n",getpid(),getppid(),getpgid(0)); for(i=0; i<2; i++) { if(fork()==0) { printf("child:\t%d\t%d\t%d\n",getpid(),getppid(),getpgid(0)); } } sleep(500); return 0; }
輸出:
4.會話(session)
函數定義:#include <unistd.h>
pid_t getsid(pid_t pid);
pid_t setsid(void);
函數說明:
會話是一個或多個進程組的集合.系統調用函數getsid()用來獲取某個進程的會話ID(SID).
假設pid是0。返回調用進程的會話SID,一般說來。改制等於進程組ID(PGID).假設pid並不屬於調用者所在的會話。則調用者就無法獲取SID.
某個進程的會話ID也是能夠改動的。調用函數setsid()用來創建一個新的會話.
假設調用進程已經是一個進程組的組長,則此函數返回錯誤.假設不是,則返回一個新的會話.
(1)該進程變成新會話首進程。會話首進程是創建該會話的進程。此時,該進程是新會話唯一的進程.
(2)該進程成為一個新的進程組的組長進程.新的進程組ID(PGID)是該調用進程的PID.
(3)該進程沒有控制終端.假設在調用setsid()之前該進程就有一個控制終端,那么這樣的聯系也會中斷.

圖1 進程組合會話的進程安排
5.控制終端(controlling terminal)
函數定義:#include <unistd.h>
pid_t tcgetpgrp(int fd);
int tcsetpgrp(int fd, pid_t pgrp);
函數說明:
會話和進程組的關系:
(1)一個會話能夠有一個控制終端,建立於控制終端相連接的會話首進程被稱為控制進程.
(2)一個會話中的幾個進程組可被分為一個前台進程組和幾個后台進程組,假設一個會話有一個控制終端,則他有一個前台進程組.
(3)不管何時鍵入終端的中斷鍵,都會將中斷信ID發送給前台進程組的全部會話。不管何時鍵入終端的退出鍵,都會將退出信ID發送給前台進程組的全部會話.
假設終端監測到調制解調器(或網絡)已經斷開連接,則將掛斷信ID發送給控制進程(會話首進程).
調用函數tcgetgrpt()獲取與打開的終端相關聯的前台進程組的進程組ID.
調用函數tcsetgrpt()設置某個進程組是前台進程還是后台進程組.
假設進程有一個控制終端,則將前台進程組ID設置為pgrp,pgrp的值應該在同一會話中的一個進程組的ID。fd為控制終端的文件描寫敘述符.
假設調用tcsetpgrp()函數的是會話中的后台進程組的進程,則該進程不會堵塞,或者忽略SIGTTOU信號.信號SIGTTOU將會發送給該進程組的全部進程.
當fd是指向進程的控制終端,函數tcgetpgrp()返回終端的前台進程組的進程組ID,該ID值是一個大於1且沒有使用的值.假設fd指向的不是進程的終端,則函數返回-1,並設置errno指示出錯.

圖2 顯示控制終端的進程組和會話
筆者:個人能力有限,僅僅是學習參考...讀者若發現文中錯誤,敬請提出.
--
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------勿在浮沙築高台。靜下心來,慢慢地沉淀---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------