1. 程式人生 > >Linux程序分析(二) 父子程序與程序組

Linux程序分析(二) 父子程序與程序組

ps命令一般用來顯示終端資訊和程序資訊,執行命令ps -eo pid,comm,cmd可以輸出所有程序的資訊,e代表所有程序,後面三個引數是需要輸出的資訊。

第一列PID是一個整數,每一個程序都有一個唯一的PID來代表自己的身份,程序也可以根據PID來識別其他的程序。第二列COMMAND是這個程序的簡稱。第三列CMD是程序所對應的程式以及執行時所帶的引數。

PID為1的程序是systemd,執行/sbin/init後出現。如果執行ps aux命令,可以看到第一個程序就是init

計算機啟動時,只有一個根程序init,可以通過命令pstree檢視。Linux建立新程序用的是fork機制,所有程序都是從init

程序fork而來,也就是說Linux程序是個樹形結構。目前Systemd取代了initd,成為系統的第一個程序(PID=1),其他程序都是它的子程序。根據 Linux 慣例,字母d是守護程序(daemon)的縮寫。 Systemd 這個名字的含義,就是它要守護整個系統。

fork複製老程序產生了新程序,它在記憶體中開闢一段空間供子程序使用,並將老的程序空間中的內容複製到新的空間中,此後兩個程序同時執行。老程序被稱為父程序,新程序為子程序,Linux提供了ppid表示某程序的父程序ID。fork函式返回型別為pid_t,實質為unsigned int,而且有兩次返回,一次返回子程序ID給父程序,一次返回0給子程序。

父子程序的相同之處:使用者ID,宿主工作目錄,工作目錄,程式碼段、棧堆、環境變數等等。
父子程序的不同之處:程序PID,PPID,fork返回值,程序執行時間,定時器。
父子程序間遵循**讀時共享寫時複製**的原則,這是為了節省記憶體。
父子程序共享:檔案描述符,mmap的對映區。

通常在呼叫fork函式之後,程式會設計一個if結構。當PID等於0時,說明該程序為子程序,那麼讓它執行某些指令,比如說使用exec庫函式讀取另一個程式檔案,並在當前的程序空間執行 (這實際上是fork的一大目的: 為某一程式建立程序);而當PID為一個正整數時,說明為父程序,則執行另外一些指令。由此,就可以在子程序建立之後,讓它執行與父程序不同的功能。fork之後先執行父程序還是子程序是不確定的,取決於核心的排程演算法。

程序組

每個程序都屬於一個程序組,程序組包含多個程序,其中一個是領導程序,領導程序的PID就是程序組的PID。
執行命令ps -o pid,pgid,ppid,comm | cat

 PID  PGID  PPID COMMAND
17763 17763 17751 bash
18534 18534 17763 ps
18535 18534 17763 cat

PID為程序自身的ID,PGID為程序所在的程序組的ID,PPID為程序的父程序ID。從上面的結果,我們可以推測出如下關係:

ps和cat都是bash的子程序。程序組的領導程序的PID成為程序組ID。領導程序可以先終結。此時程序組依然存在,並持有相同的PGID,直到程序組中最後一個程序終結。

pid,ppid,pgid資訊都儲存在Linux核心區的task_struct結構體中,核心可以通過檢視自己空間中的各個程序的附加資訊就能知道程序的概況,而不用進入到程序自身的空間。

getpgrp函式可獲取當前程序的程序組ID。getpgid函式可獲取指定程序的程序組ID。setpgid函式可改變程序預設的程序組,可加入另一個程序組或建立程序組。