一、進程組,作業,會話的概念
1、進程組:是一個或多個進程的集合。通常,與同一作業相關聯,可以接收來自同一終端的各種訊號。每個進程都有一個唯一的進程組ID。每個進程組都可以有一個組長進程。組長進程的識別是,其進程組ID等於其進程ID。組長進程可以建立一個進程組,建立該組中的進程,然後終止。只要在某個進程組中有一個進程存在,則該進程組就存在,這與組長進程是否終止無關。
2、作業:Shell分前後台來控制的不是進程而是作業(job)或是進程組。一個前台作業可以由多個行程組成,一個後台也可以由多個行程組成,shell可以執行一個前台作業和任意多個後台作業,稱為作業控制。
作業與進程組的差異:如果作業中的某個進程又建立了子進程,子進程不屬於作業。
一旦作業運行結束,Shell就把自己提到前台,如果原來的前台進程還存在(如果這個子進程還沒終止),它自動變成後台進程組。
3、會話:是一個或多個進程組的集合。一個會話可以有一個控制終端。建立與控制終端連線的會話首進程稱為控制進程。一個會話中的幾個進程組可被分成一個前台進程組以及一個或多個後台程序組。所以在一個會話中,應該包含控制進程(會話首進程),一個前台進程組和任意後台進程組。
****************(進程組就相當於一個班級,組長進程就像當於班長。會話就相當於一個年級。一個年級有一個教務處。(控制終端))。
二、終端
1、終端的概念:使用者透過終端登入系統後得到一個Shell進程,這個終端稱為Shell進程的控制終端,
每個進程都可以透過一個特殊的設備檔案/dev/tty存取它的控制終端。事實上每個終端設備
都對應一個不同的設備檔案,/dev/tty提供了一個通用的介面,一個進程要存取它的控制終端既可以透過/dev/tty也可以透過該終端設備所對應的設備文件來存取。 ttyname函數可以由檔案描述子查出對應的檔案名稱,該檔案描述子必須指向一個終端裝置而不能是任意檔案。
****************查看一下各種不同的終端機所對應的設備檔案名稱。
1 #include<stdio.h> 2 #include<unistd.h> 3 int main() 4 { 5 printf("fd: %d -> %s\n",0,ttyname(0)); 6 printf("fd: %d -> %s\n",1,ttyname(1)); 7 printf("fd: %d -> %s\n",2,ttyname(2)); 8 }
2、終端登入過程:
一台PC通常只有一套鍵盤和顯示器,也就是只有一套終端設備,但是可以透過Ctrl-Alt-F1~Ctrl-Alt- F6切換到6個字元終端,相當於有6套虛擬的終端設備,它們共用同一套實體終端設備,對應的設備檔案分別是/dev/tty1~/dev/tty6,所以稱為虛擬終端(Virtual Terminal)。裝置檔案/dev/tty0表示目前虛擬終端,例如切換到Ctrl-Alt-F1的字元終端機時/dev/tty0就表示/dev/tty1,切換到Ctrl-Alt- F2的字元終端時/dev/tty0就表示/dev/tty2,就像/dev/tty一樣也是一個通用的介面,但它不能表示圖形終端機視窗所對應的終端。
a、系統啟動時,init程序根據設定檔/etc/inittab決定需要開啟哪些終端。
b、getty根據命令列參數打開終端設備作為它的控制終端,把文件描述符0、1、2都指向控制
終端,然後提示用戶輸入帳號。使用者輸入帳號之後,getty的任務就完成了,它再執行login程式:
execle("/bin/login", "login", "-p", username, NULL, envp);
c、login程式提示使用者輸入密碼(輸入密碼期間關閉終端的回顯),然後驗證帳號密碼的正確性。 如果密碼不正確,login程序終止,init會重新fork/exec一個getty程序。如果密碼正確,login程式設定一些環境變數,設定目前工作目錄為該使用者的主目錄,然後執行Shell:
execl("/bin/bash", "-bash", NULL);
三、守護程式
1. 守護程式也稱為精靈進程(Daemon),是運行在後台的一種特殊進程。它獨立於控制終端並且週期性地執行某種任務或等待處理某些發生的事件。
2、用ps axj | grep -E 'd$'查看守護程序
參數a表示不僅列當前用戶的進程,也列出所有其他用戶的進程,參數x表示不僅列有控制終端的進程,也列出所有無控制終端的程序,參數j表示列出與作業控制相關的資訊。
3、創建守護程序
調用函數setsid函數創建一個新的Session,並成為Session Leader(會話首程序),調用成功返回新創建的Session id,出錯返回-1;
a、調用umask將文件模式建立屏蔽字設定為0.
b、呼叫fork,父進程退出(exit)。原因:
1)如果該守護程式是作為一條簡單的shell指令啟動的,那麼父程式終止使得shell認為該指令已經執行完畢。
2)保證子進程不是一個進程組的組長進程。
c、呼叫setsid建立一個新會話。 setsid會導致:
1)呼叫進程成為新會話的首進程。
2)呼叫進程成為一個進程組的組長進程 。
3)呼叫進程沒有控制終端。 (再次fork一次,保證daemon進程,之後不會開啟tty裝置)
d、將目前工作目錄變更為根目錄。
e、關閉不在需要的文件描述符。
f、其他:忽略SIGCHLD訊號。
#include<stdio.h> 2 #include<stdlib.h> 3 #include<unistd.h> 4 void mydeamon(void) 5 { 6 pid_t id=fork(); 7 umask(0);//将文件模式创建屏蔽字设置为0. 8 if(id>0) 9 { 10 exit(0);//调用fork,父进程退出(exit) 11 } 12 setsid();//调用setsid创建一个新会话 13 chdir("/");//将当前工作目录更改为根目录。 14 close(0);//关闭不在需要的文件描述符。 15 close(1); 16 close(2); 17 } 18 int main() 19 { 20 mydeamon(); 21 while(1); 22 return 0; 23 }
用ps axj |grep "檔案名稱"查看剛剛建立的守護程式
以上就是Linux--終端、作業控制、與守護程式的內容,更多相關內容請關注PHP中文網(www .php.cn)!