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

歡迎訪問 生活随笔!

生活随笔

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

linux

linux fork函数的精辟解说

發布時間:2023/12/15 linux 40 豆豆
生活随笔 收集整理的這篇文章主要介紹了 linux fork函数的精辟解说 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

此文原文來源于一個blog,文章的名稱為:linux fork函數的精辟解說原文地址:http://blog.chinaunix.net/space.php?uid=12461657&do=blog&id=3062996感覺這篇文章不錯,在此分享下來,在原文的基礎上增加了自己的一些理解和說明。

  開始演示:[plain]view plaincopyprint?

  [root@test code]# cat fork.c #include <stdio.h> #include <unistd.h> #include <sys/types.h>

  main()

  { pid_t pid;pid=fork();if (pid < 0)

  printf("Error in fork!");else if (pid == 0)

  printf("I am the child process. The process id is %d\n",getpid());else printf("I am the parent process. The process id is %d\n",getpid());} [root@test code]# gcc fork.c -o fork [root@test code]# ./fork I am the child process. The process id is 6260 I am the parent process. The process id is 6259先說什么是進程一個進程,就是一個可執行程序的一次執行過程中的一個狀態。

  打個比方

  我們把一個大學數學老師比作一個可執行程序,老師就是一個人,相當于一份源碼,這個數學老師每個學期可能要教多個班,假設他教1班和2班,時間是一個學期,那么他從開學到期末教這兩個班這個過程就是兩個進程,兩個進程的周期都是一個學期。

  在稍微理解了進程的概念之后,我們說在正在運行的計算機中,不管是Linux或者是Windows系統都運行有很多進程,雖然我們的系統中進程比較多,但是對于單核的CPU而言,每一時刻只能有一個進程占用CPU,其他的進程就可能處在等待執行、就緒、結束等狀態(狀態名稱可能隨不同操作系統而相異)。

  那么要使我們的操作系統能夠正常執行,操作系統對這些進程的管理,典型的情況,是通過內存中的進程表完成的(這里的進程表不是源碼的意思)。進程表中的每一個表項,記錄的是當前操作系統中一個進程的情況,比如執行到哪里,下一步要執行什么命令等。

  一個稱為“程序計數器(program counter, pc)”的寄存器,指出當前占用CPU的進程要執行的下一條指令的位置。當分給某個進程的CPU時間已經用完,操作系統將該進程相關的寄存器的值,保存到該進程在進程表中對應的表項里面;然后把將要接替掉當前進程的那個進程的上下文從內存的進程表中讀入,并更新相應的寄存器。這個過程稱為“上下文交換(process context switch)”,實際的上下文交換需要涉及到更多的數據,那和fork無關,不再多說,主要要記住程序寄存器pc指出程序當前已經執行到哪里,是進程上下文的重要內容,換出 CPU的進程要保存這個寄存器的值,換入CPU的進程,也要根據進程表中保存的本進程執行上下文信息,更新這個寄存器)。

  好了,有這些概念打底,可以說fork了。當你的程序執行到下面的語句:pid=fork();操作系統會進行如下的大概過程:創建一個新的子進程,而這個子進程是父進程的副本,接下來這兩個進行就由操作系統調度,直到程序執行結束。

  那么這個過程,我們可以對其進行更加詳細的分析。在執行fork以后,操作系統復制一份當前執行的進程的數據,包括進程的數據空間、堆和棧等,并且在進程表中相應為它建立一個新的表項。上下文也是原進程(父進程)的拷貝。但是父、子進程共享正文段,也就是CPU執行的機器指令部分,這個可共享的,在存儲器中只需要一個副本,而且這個副本通常是只讀的。

  那在什么時候父子進程中就分道揚鑣呢?

  從上面的實驗結果我們看出那兩條打印出來的語句不是在同一個進程里面的,因為在同一個進程里面不可能存在,不通結果的getpid(),事實說明是兩個不同進程返回的結果,那么在執行pid=fork()以后,開始出現父、子進程,既然是兩個進程,那么接下來誰先被調度,也就是說執行pid=fork()以后,在單核CPU下,只會有一個進程被調度,假設是我們的父進程占用CPU時間,父進程繼續執行,操作系統對fork的實現,使這個調用在父進程中返回剛剛創建的子進程的pid(一個正整數),所以下面的if語句中pid<0, pid==0的兩個分支都不會執行。所以輸出I am the parent process……。

  子進程在之后的某個時候得到調度,它的上下文被換入。我們上面分析過,在子進行創建的時候也會復制父進程的上下文,所以子進程不會從頭開始執行,而是從pid=fork()開始執行,基于操作系統對fork的實現,使得子進程中fork調用返回0.所以在這個進程(中pid=0.這個進程繼續執行的過程中,if語句中 pid<0不滿足,但是pid==0是true.所以輸出I am the child process……。

  我們下面來看一個和我在上面分析的一個結論似乎存在矛盾的現象

  [plain]view plaincopyprint?

  [root@test code]# cat fork.c #include <stdio.h> #include <unistd.h> #include <sys/types.h>

  main()

  { pid_t pid;printf("fork!");pid=fork();if (pid < 0)

  printf("Error in fork!\n");else if (pid == 0)

  printf("I am the child process. The process id is %d\n",getpid());else printf("I am the parent process. The process id is %d\n",getpid());} [root@test code]# gcc fork.c -o fork [root@test code]# ./fork fork!I am the child process. The process id is 7378 fork!I am the parent process. The process id is 7377 [root@test code]#

  這里我添加了printf("fork!")這一行,執行了以后我們發現,“fork!”打印了兩次,我們上面不是說,fork以后的子進程的上下文不是和父進程一樣嗎,也就是說子進程不會從頭開始執行,應該從fork執行,那么fork!的出現不是有矛盾嗎?我們再來看看下面的現象

  [plain]view plaincopyprint?

  <span style="font-family:Courier New;">[root@test code]# cat fork.c #include <stdio.h> #include <unistd.h> #include <sys/types.h>

  main()

  { pid_t pid;printf("fork!\n");pid=fork();if (pid < 0)

  printf("Error in fork!\n");else if (pid == 0)

  printf("I am the child process. The process id is %d\n",getpid());else printf("I am the parent process. The process id is %d\n",getpid());} [root@test code]# gcc fork.c -o fork [root@test code]# ./fork fork!

  I am the child process. The process id is 7458 I am the parent process. The process id is 7457 [root@test code]#</span>

  這里我在printf("fork!")這一行的fork!后面添加了一個換行符,變成printf("fork!\n")執行以后發現只打印一個fork!這個到底是什么原因呢?

  主要的區別是因為有了一個\n 回車符號,說起真正的原因,這和printf的緩沖機制有關了,printf某些內容時,操作系統僅僅是把該內容放到了stdout的緩沖隊列里了,并沒有實際的寫到屏幕上,但是只要看到有\n 則會立即刷新stdout,因此就馬上能夠打印了。

  還沒有執行到fork()的時候,原進程運行了printf("fork!") 后,fork!僅僅被放到了緩沖里,執行了fork,這時候子進程復制一份父進程的數據,包括這個stdout緩沖,在子進程度stdout緩沖里面就也有了fork!。執行到后面這兩個緩沖都打印到屏幕上,所以出現兩次,并不是printf執行兩次。而運行 printf("fork!\n")后, fork!被立即打印到了屏幕上,之后fork到的子進程里的stdout緩沖里不會有fork!內容,因此你看到的結果會是fork!被printf了1次!!!

總結

以上是生活随笔為你收集整理的linux fork函数的精辟解说的全部內容,希望文章能夠幫你解決所遇到的問題。

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