1. 程式人生 > >函式可以有兩個返回值?初探神奇的fork()函式

函式可以有兩個返回值?初探神奇的fork()函式

一個函式的返回值可有兩個

這裡寫圖片描述

一個很簡單的選擇分支結構,學過基本語法的都知道,如果走if,就不會走else if. 當然,那是沒有碰到fork()函式的時候.

為什麼呢? 我們編譯執行一下程式碼來觀察結果.

這裡寫圖片描述

發現兩個printf都被執行了?難道if else 結構失效了? 其實不然

當程式執行起來就變成了程序

我們寫的程式碼當沒被執行的時候,只是躺在磁碟中冰冷冷的文字,當它被載入記憶體後,它變成程序後,生命週期才開始. 可執行程式載入記憶體的過程叫做”記憶體對映

Linux通過將一個虛擬記憶體區域與一個磁碟上的物件關聯起來,以初始化這個虛擬記憶體區域的內容,這個過程成為記憶體對映.
–<<深入理解計算機系統>>

但這和一個函式有兩個返回值有什麼關係嗎?

其實,並不是一個函式有兩個返回值,而是呼叫fork函式後,在記憶體中一個程序被複製成兩個程序, 分別被cpu執行. 那麼執行出來肯定就會有兩個結果.

簡單點說就是一份文字,被分別兩個人去解讀,那麼肯定就會有兩個結果.

讓父子程序各司其職

fork()函式是建立一個新程序, 它的返回值分別是

  • 子程序返回 0
  • 父程序返回子程序的程序號 (PID)

那麼,我們就可以通過fork()函式的返回值識別父子程序,讓其通過if else分流,幹不同的事情

在程式碼中也有用到 getpid()和getppid(),其中

  • getpid()函式是返回該程序
    的的ID號 ID號的型別是 pid_t
  • getppid() 函式是返回該程序的父程序的ID號

遇到分歧如何處理

使用fork()函式,我們可以實現父子程序的各司其職,通常情況下井水不犯河水,

但是如果父子程序的任務重疊了,都想去改一數的值,那麼情況是什麼樣的呢?

這裡寫圖片描述

是兒子讓老子 或者 老子讓兒子呢?

這裡寫圖片描述

顯而易見,當出現數據改動時,父子程序還是是各自執行各自的.

其中在fork之後發生資料改動的情況,叫做”寫時拷貝

在解釋什麼是寫時拷貝 之前,我們有必要說說當函式呼叫fork()時會發生什麼

怎麼建立一個新程序

當一個程式進入記憶體後,作業系統去管理,排程它,那麼肯定首先要獲得這個程序的資訊(PCB

Process Control Block)

就好像學校在管理學生時,需要知道學生的姓名,年齡等資訊

在Linux中,程序的資訊被描述為一個叫task_struct 的結構體,作業系統通過對這個結構體的操控,間接操控程序.

呼叫程式fork()函式後,就把原來程序的 task_struct 直接又複製了一份,改一下里面的PID,就變成了一個新程序, 六耳獼猴.

因為程序是執行在虛擬記憶體中的,而且每個程序都有自己的虛擬記憶體空間

最後要對映到實體記憶體中,

實體記憶體是有限的,你不能複製一個程序,又對映到新的實體記憶體中去.國土寶貴,不會讓你這麼幹.

解決的方法就是 寫時拷貝:

你隨便複製原有程序,隨便開闢虛擬記憶體空間,

但是你只要是從我這複製的資訊, 那麼就必須對映到同一片實體記憶體上去,

並且咱兩對這片物理空間都不能修改(標記為只讀)

你想修改就重找一實體地址去儲存你的值.

這裡寫圖片描述