前一章文章我們簡單的說了一下父子進程以及fork函數,那么fork函數創建的新進程與原進程有什么聯系呢?如果其中一方結束了會怎么樣?他們真的形同父子嗎?他們的數據是否共享?以及一些其他的進程問題,這篇文章我們會講到。
一、父子進程
通過fork函數創建的新進程是原進程的子進程,而調用fork函數的進程是fork函數創建出來的新進程的父進程。也就是說,通過fork函數創建的新進程與原進程是父子關系,fork就相當於一個憑證,有fork,就有父子關系。
我們可以通過兩個函數來做實驗:
getpid() 用於獲取調用getpid這個函數的進程的pid;
getppid() 用於獲取調用getppid這個函數的進程的父進程的pid。

以上這段代碼,我在父進程執行的代碼段,加一個sleep(1),這是因為,整個程序運行的時間太短,當子進程運行getppid時,父進程可能已經結束從而導致一些意料之外的結果,好在有sleep()函數幫我們完成了測試:

可以看到,父進程在子進程結束之后再結束,使得子進程獲取了其父進程的pid,哦耶。
既然剛剛說到,父進程結束了,而子進程並未結束,會有意料之外的事,這時會發生什么呢?
來看:

此時我讓子進程進入死循環,並且放入后台運行,從而使得我們可以一直獲取他們的pid,讓父進程直接結束。
得到如下結果:

可以看到,新進程的父進程pid變成了1,那pid為1的進程又是何方神聖呢?
我們通過ps -A命令來查看:

現在我們知道了,當父進程結束了,兒子進程未結束時,子進程就變成了所謂的孤兒進程。該就交由init進程管理,init進程是一個守護進程,因為init這個進程管理了很多孤兒進程,所以也稱之為進程的孤兒院。
二、數據共享
我們現在通過一段代碼研究一下父子進程的是否存在數據共享。

我們現在簡單把數據分成三種:堆區數據、棧區數據、全局數據。所以我現在有三個變量,同時,我讓子進程改變這三個變量的值。讓父進程沉睡兩秒鍾以確保子進程運行結束。
結果如下:

可以看到,其值發生了改變,這也說明,附子進程的堆區數據、棧區數據、全局數據是不共享的。
那子進程能和父進程共享文件嗎?我們看看以下代碼:

我先open一個我創建好的在同一目錄下的a.txt文件,a.txt文件中我寫了“Hello World!”
讓父子進程一起一個字節一個字節的讀文件里字符,每讀一次sleep一秒鍾。

結果如下:

這是什么呢,這就是說,並不是一個進程操作一個文件時,另一個進程就不能操作,而且,父子進程可以同時操作同一個文件。
也就是,在父子進程中,文件描述符以及文件偏移量,都是共享的!
為什么文件就能共享了呢,在linux源碼里,每個進程都有一個PCB(進程控制塊)結構體,每個PCB里,存了一個結構體指針指向一個我們理解為文件描述符的結構體struct file,而這個結構體里,才存了文件的id,從什么地方開始寫,模式等等。值得注意的事,這個結構體里有一個指針才是指向真正的文件的。

