日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > linux >内容正文

linux

Linux中fork函数详解(附图解与代码实现)

發布時間:2023/12/14 linux 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Linux中fork函数详解(附图解与代码实现) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

我們先來看個代碼,判斷一下這個代碼的輸出結果會是什么樣的,先不要去看運行結果,判斷好后再去看看是否和你的預期結果一致。

#include<stdio.h> #include<unistd.h> #include<stdlib.h> #include<string.h>int main(void) {pid_t pid;pid = fork();printf("xxxxxxxxxx\n");while (1) {sleep(1);}return 0; }

———————————————————————————————————————————

運行結果:

xxxxxxxxxx

xxxxxxxxxx

是不是和你預想的結果不太一樣呢?為什么會是輸出兩遍呢?這是什么原理呢?

抱著這樣的問題,讓我們來研究一下fork函數的奧秘吧。

fork函數

功能:創建一個與原來進程幾乎完全相同的進程

這也就代表著,父進程可通過調用該函數創建一個子進程,兩個進程可以做完全相同的事

返回值:pid_t類型的變量,也就是進程id類型的變量

這里有個非常讓人驚訝的地方,fork函數的返回值是2個!!!

想想自己學了那么久的編程,好像沒有返回值是兩個的函數啊。別慌,接著往下看

我們來對父進程通過fork函數創建子進程的過程做個具體的說明,上圖!

? ? ? 在上述這個圖中,當調用fork函數時,操作系統會從用戶態切換回內核態來進行進程的創建,會調用fork函數中的_CREATE函數和_CLONE函數。

? ? ? 首先調用_CREATE函數,子進程進行虛擬地址申請,在子進程的內核空間中進行不完全拷貝,為什么是不完全拷貝呢?就像父親和兒子的關系一樣,你可以和你爸爸的民族,籍貫所在地一樣,但你不能和你爸的年齡,身份證號都一樣吧。PCB作為每個進程的唯一標識符,就像每個人的身份證一樣,是不可能完全一樣的,所以這個地方時不完全拷貝,如pid就需要自己生成。這個地方的子進程是新生態。

? ? ? 之后調用_CLONE函數,向父進程拷貝必要資源,子進程的用戶空間進行完全拷貝,子進程繼承所有父進程資源,如臨時數據堆棧拷貝,代碼完全拷貝。

?這個時候就有善于思考的同學會發現,并提出以下問題:

誒誒誒,你這父進程創建一個子進程,你這子進程把你的代碼完全拷貝走了。

  • 那子進程不是把fork函數也拷貝走了嗎?
  • 那子進程不也可以通過fork函數創建孫線程了嗎?
  • 那你這不是子又生孫,孫又生子嗎?
  • 那你這不無限創造進程了嗎?
  • 那為什么上面的代碼的運行結果只有兩個輸出?

考慮的非常好啊,這也是我們下面要講的問題

講解完父進程如何通過fork函數創建子進程,接下來我們就要講解父子進程如何執行fork函數

上圖!

?其實大體來說,我們可以將fork函數分為三步

  • 調用_CREATE函數,也就是進程創建部分
  • 調用_CLONE函數,也就是資源拷貝部分
  • 進程創建成功,return 0;? ? ?失敗,return -1:
  • ? ? ? ? 前2步也就是父進程通過fork函數創建子進程的步驟,在執行完_CLONE函數后,fork函數會有第一次返回,子進程的pid會返回給父進程。

    ? ? ? ? 要注意的是,在第3步中,fork函數不是由父進程來執行,而是由子進程來執行,當父進程執行完_CLONE函數后,子進程會執行fork函數的剩余部分,執行最后這個語句,fork函數就會有第二次返回,如果成功就返回0,失敗就返回-1。

    ? ? ? ? 我們就可以總結得出,父子進程都執行fork函數,但執行不同的代碼段,獲取不同的返回值。所以fork函數的返回值情況如下:

    ? ? ? ? 父進程調用fork,返回子線程pid(>0)

    ? ? ? ? 子進程調用fork,子進程返回0,調用失敗的話就返回-1

    ? ? ? ? 這也就說明了fork函數的返回值是2個

    可以通過下面的代碼來驗證該過程

    #include<stdio.h> #include<unistd.h> #include<stdlib.h> #include<string.h>int main(void) {//Parent Startpid_t pid;pid = fork();if (pid > 0){printf("parent running\n");while (1){sleep(1);}}else if (pid == 0){//Child Startprintf("Child Running\n");while (1){sleep(1);}//Child End}else{perror("fork call failed\n");}while (1){sleep(1);}return 0; } //Parent End

    運行結果:

    parent running

    Child Running

    另外和大家說一個小知識點

    整個Linux操作系統都是由父子進程結構構成

    每個進程都有創建者,也就是父進程,但是有一個進程例外,也就是init進程

    init進程(0 or 1),init進程是系統啟動初始化后的第一個進程

    今天的學習記錄到此結束啦,咱們下篇文章見,ByeBye!

    總結

    以上是生活随笔為你收集整理的Linux中fork函数详解(附图解与代码实现)的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。