1、進程組,做業,會話的概念shell
一、進程組:是一個或多個進程的集合。一般,與同一做業相關聯,能夠接收來自同一終端的各類信號。每一個進程都有一個惟一的進程組ID。每一個進程組均可以有一個組長進程。組長進程的標識是,其進程組ID等於其進程ID。組長進程能夠建立一個進程組,建立該組中的進程,而後終止。只要在某個進程組中有一個進程存在,則該進程組就存在,這與組長進程是否終止無關。
bash
二、做業:Shell分先後臺來控制的不是進程而是做業(job)或者進程組。一個前臺做業能夠由多個進程組成,一個後臺也能夠由多個進程組成,shell能夠運行一個前臺做業和任意多個後臺做業,這稱爲做業控制。
ide
做業與進程組的區別:若是做業中的某個進程又建立了子進程,則子進程不屬於做業。 函數
一旦做業運行結束,Shell就把本身提到前臺,若是原來的前臺進程還存在(若是這個子進程還沒終止),它自動變爲後臺進程組。spa
三、會話:是一個或多個進程組的集合。一個會話能夠有一個控制終端。創建與控制終端鏈接的會話首進程被稱爲控制進程。一個會話中的幾個進程組可被分爲一個前臺進程組以及一個或多個後臺進程組。因此一個會話中,應該包括控制進程(會話首進程),一個前臺進程組和任意後臺進程組。命令行
****************(進程組就至關於一個班級,組長進程就像當於班長。會話就至關因而一個年級。一個年級有一個教務處。(控制終端))。
2、終端3d
一、終端的概念:用戶經過終端登陸系統後獲得一個Shell進程,這個終端稱爲Shell進程的控制終端,blog
每一個進程均可以經過一個特殊的設備文件/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 }
二、終端登陸過程:
一臺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、一、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);
3、守護進程
一、 守護進程也稱精靈進程(Daemon),是運行在後臺的一種特殊進程。它獨立於控制終端而且週期性地執行某種任務或等待處理某些發生的事件。
二、用ps axj | grep -E 'd$'查看守護進程
參數a表示不只列當前用戶的進程,也列出全部其餘用戶的進程,參數x表示不只列有控制終端的進程,也列出全部無控制終端的進程,參數j表示列出與做業控制相關的信息。
三、建立守護進程
調用函數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信號。
1 #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 "文件名"查看剛纔建立的守護進程