每個(gè)進(jìn)程除了一定有PID還會(huì)有PPID,也就是父進(jìn)程ID,通過(guò)PPID可以找到父進(jìn)程的信息。
為什么進(jìn)程都會(huì)有父進(jìn)程ID呢?因?yàn)檫M(jìn)程都是由父進(jìn)程衍生出來(lái)的,后面會(huì)詳細(xì)介紹幾種衍生的方法。那么跟人類起源問(wèn)題一樣,父進(jìn)程的父進(jìn)程的父進(jìn)程又是什么呢?實(shí)際上有一個(gè)PID為1的進(jìn)程是由內(nèi)核創(chuàng)建的init進(jìn)程,其他子進(jìn)程都是由它衍生出來(lái),所以前面的描述并不準(zhǔn)確,進(jìn)程號(hào)為1的進(jìn)程并沒有PPID。
因?yàn)樗羞M(jìn)程都來(lái)自于一個(gè)進(jìn)程,所以Linux的進(jìn)程模型也叫做進(jìn)程樹。
要想獲得進(jìn)程的PPID,可以通過(guò)以下Getppid()
這個(gè)函數(shù)來(lái)獲得,print_ppid.go程序的代碼如下。
package main
import (
"fmt"
"os"
)
func main() {
fmt.Println(os.Getppid())
}
root@87096bf68cb2:/go/src# go run print_ppid.go
2892
root@87096bf68cb2:/go/src# go run print_ppid.go
2902
有趣的事情發(fā)生了,有沒有發(fā)現(xiàn)每次運(yùn)行的父進(jìn)程ID都不一樣,這不符合我們的預(yù)期啊,原來(lái)我們通過(guò)go run
每次都會(huì)啟動(dòng)一個(gè)新的Go虛擬機(jī)來(lái)執(zhí)行進(jìn)程。
如果我們先生成二進(jìn)制文件再執(zhí)行結(jié)果會(huì)怎樣呢?
root@87096bf68cb2:/go/src# ./print_ppid
1
root@87096bf68cb2:/go/src# ./print_ppid
1
root@87096bf68cb2:/go/src# ps aux |grep "1" |grep -v "ps" |grep -v "grep"
root 1 0.0 0.3 20228 3184 ? Ss 07:25 0:00 /bin/bash
這次我們發(fā)現(xiàn)父進(jìn)程ID都是一樣的了,而且通過(guò)ps
命令可以看到父進(jìn)程就是bash
,說(shuō)明通過(guò)終端執(zhí)行命令其實(shí)是從bash
這個(gè)進(jìn)程衍生出各種子進(jìn)程。
為了執(zhí)行這個(gè)程序要查找包依賴、編譯、打包、鏈接(和go build
做一樣的東西)然后執(zhí)行,這是全新的進(jìn)程。
拿到PID和PPID后有什么用呢?馬上揭曉。