函式可以有兩個返回值?初探神奇的fork()函式
一個函式的返回值可有兩個
一個很簡單的選擇分支結構,學過基本語法的都知道,如果走if,就不會走else if. 當然,那是沒有碰到fork()函式的時候.
為什麼呢? 我們編譯執行一下程式碼來觀察結果.
發現兩個printf都被執行了?難道if else 結構失效了? 其實不然
當程式執行起來就變成了程序
我們寫的程式碼當沒被執行的時候,只是躺在磁碟中冰冷冷的文字,當它被載入記憶體後,它變成程序後,生命週期才開始. 可執行程式載入記憶體的過程叫做”記憶體對映”
Linux通過將一個虛擬記憶體區域與一個磁碟上的物件關聯起來,以初始化這個虛擬記憶體區域的內容,這個過程成為記憶體對映.
–<<深入理解計算機系統>>
但這和一個函式有兩個返回值有什麼關係嗎?
其實,並不是一個函式有兩個返回值,而是呼叫fork函式後,在記憶體中一個程序被複製成兩個程序, 分別被cpu執行. 那麼執行出來肯定就會有兩個結果.
簡單點說就是一份文字,被分別兩個人去解讀,那麼肯定就會有兩個結果.
讓父子程序各司其職
fork()函式是建立一個新程序, 它的返回值分別是
- 子程序返回 0
- 父程序返回子程序的程序號 (PID)
那麼,我們就可以通過fork()函式的返回值識別父子程序,讓其通過if else分流,幹不同的事情
在程式碼中也有用到 getpid()和getppid(),其中
- getpid()函式是返回該程序
- getppid() 函式是返回該程序的父程序的ID號
遇到分歧如何處理
使用fork()函式,我們可以實現父子程序的各司其職,通常情況下井水不犯河水,
但是如果父子程序的任務重疊了,都想去改一數的值,那麼情況是什麼樣的呢?
是兒子讓老子 或者 老子讓兒子呢?
顯而易見,當出現數據改動時,父子程序還是是各自執行各自的.
其中在fork之後發生資料改動的情況,叫做”寫時拷貝”
在解釋什麼是寫時拷貝 之前,我們有必要說說當函式呼叫fork()時會發生什麼
怎麼建立一個新程序
當一個程式進入記憶體後,作業系統去管理,排程它,那麼肯定首先要獲得這個程序的資訊(PCB
就好像學校在管理學生時,需要知道學生的姓名,年齡等資訊
在Linux中,程序的資訊被描述為一個叫task_struct 的結構體,作業系統通過對這個結構體的操控,間接操控程序.
呼叫程式fork()函式後,就把原來程序的 task_struct 直接又複製了一份,改一下里面的PID,就變成了一個新程序, 六耳獼猴.
因為程序是執行在虛擬記憶體中的,而且每個程序都有自己的虛擬記憶體空間
最後要對映到實體記憶體中,
而實體記憶體是有限的,你不能複製一個程序,又對映到新的實體記憶體中去.國土寶貴,不會讓你這麼幹.
解決的方法就是 寫時拷貝:
你隨便複製原有程序,隨便開闢虛擬記憶體空間,
但是你只要是從我這複製的資訊, 那麼就必須對映到同一片實體記憶體上去,
並且咱兩對這片物理空間都不能修改(標記為只讀)
你想修改就重找一實體地址去儲存你的值.