目錄
fork
介紹
fork的返回值問題
介紹
fork()時,系統要做什么?
數據是否要獨立?
如果共享的話,就會出現問題!
寫時拷貝?
引入
介紹
舉例(fork返回值)
fork返回的值是什么?
創建失敗的原因
子進程執行位置從哪里開始
引入
進程切換
子進程執行的位置
子進程的用途
fork
介紹
- fork()函數是一個系統調用,用于創建一個新的進程
- 它會復制當前進程的內容,并在新進程中運行,當前進程是新進程的父進程,從而使父進程和子進程可以并行執行
- 各自有自己的獨立地址空間,但它們可以共享一些資源,如文件描述符
- 頭文件:<unistd.h>
fork的返回值問題
介紹
?
- 當我們運行起來這個程序時,我們會發現,我們已經成功創建出了子進程(因為有兩個pid被打印出來,并且其中一個是另一個的父親)
- 但是,我們仔細觀察觀察,似乎ret這個變量似乎有不同的值
- 因為我們看到它可以同時執行if 和 else的內容,也就是說,在兩個進程中,實際上ret的值是不同的
- 這是為什么呢?
?
fork()時,系統要做什么?
- 首先明確: 進程 = 內核數據結構(os來分配) + 進程代碼和數據(一般從磁盤中來)
- 執行fork,也就是創建了一個新的進程,只不過這個新進程有點特殊,數據幾乎全部都繼承自創建自己的父進程
- 控制權轉移到內核中后(os會為子進程分配空間,提供初始值)
- 從fork()函數的返回值開始,就開始并行執行兩個進程啦
數據是否要獨立?
- 因為進程具有獨立性,所以子進程也得有自己的代碼和數據
- 但是我們沒有加載內存的過程,它也就沒有自己的代碼和數據,就可以和父進程共享使用
- 代碼共享沒有什么問題,因為不可更改,都是只讀
- 但是!!數據可不能共享,它是可寫的!
如果共享的話,就會出現問題!
- 一般創建子進程就是為了和父進程執行不同的操作
- 如果其中一個變量一修改,另一個進程也會受到影響的話,未免也太挫了,也不滿足獨立性
- 所以!數據必須分離!!
寫時拷貝?
引入
雖然數據要分離,但是子進程用不到的那些數據還有必要再拷貝一份嗎?
- 顯然是沒有的
- 這樣的情況下,共享也是沒有問題的
- (這樣的例子可以在c語言中看到,比如兩個指針指向同一個常量字符串,編譯器也不會傻到開辟兩份空間存儲內容一樣的字符串)
- 因此,只有將來會被父/子進程寫入的數據,才值得被拷貝
介紹
- 但是,其實os也無法知道哪些數據會被寫入,提前拷貝了也不會立馬使用(相當于占著茅坑不拉屎)
- 所以,os選擇了寫時拷貝技術來將數據分離
舉例(fork返回值)
- 所以前面的fork返回值問題,實際上返回值接收的這一過程就是寫入
- 所以發生了寫時拷貝
- 父子進程這一變量存在兩份,但虛擬地址并沒有改變,也就導致了我們看到的結果
- 但是可以通過不同的頁表映射,從而找到實際的物理地址
fork返回的值是什么?
雖然我們已經知道了兩個進程中的ret不一樣,但為什么會不一樣呢?
- 是因為fork()在不同進程中返回了不同的值
- fork()在父進程中返回子進程的進程pid(該值一般大于0),而在子進程中返回0
- fork的返回值由os控制
- 它將子進程的pid返回給父進程,以便父進程可以管理子進程,然后繼續下面的代碼
- 子進程返回0,用于區分子進程
- 如果父進程收到-1,則代表進程創建失敗
創建失敗的原因
- 創建內存是需要使用內存資源的
- 如果當前系統有太多進程,內存資源不足時,os就可能不讓你繼續創建了
- 而且作為一個用戶,可擁有的進程數是一定的
子進程執行位置從哪里開始
引入
我們其實還會發現,在fork之前的語句,子進程并沒有執行:
我們會發現,在fork之前的那句打印只出現了一次,說明子進程是沒有執行那個語句的
可以說明 -- 子進程并不是從頭開始執行程序的
那子進程從哪里開始執行呢?
進程切換
- cpu使用進程切換的策略執行語句
- 并且要保證每個進程下次來的時候,必須從之前的位置繼續運行(而不是重新來過,不然前面就白執行了)
- 所以cpu必須要有對應的寄存器數據(EIP? ,??程序計數器(pc指針)),來記錄當前運行進程的執行位置
- cpu執行指令靠的就是EIP中的地址 (地址+指令長度=下一條指令地址)
- 每個進程走的時候,帶走這份數據,下次來的時候再給寄存器,就可以實現想要的效果啦
- (寄存器數據也就是進程的上下文數據)
子進程執行的位置
- 而子進程成功創建的時候,恰好為fork該執行return指令的時候
- 因為當執行到return時,就說明它的主要功能已經實現,也就是子進程已經創建出來了
- 它里面的pc也就繼承自父進程的進度(return的那里),他就認為自己的EIP起始值就是return指令的地址
- 所以子進程就從return開始執行
- 也可以通過這個理論,修改子進程的pc值
子進程的用途
就 -- 要么子承父業,要么自己獨自發展
?