<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          一次fork引發(fā)的慘案!

          共 2975字,需瀏覽 6分鐘

           ·

          2021-11-24 05:13

          “你還有什么要說的嗎?沒有的話我就要動手了”,kill程序最后問道。

          這一次,我沒有再回答。

          只見kill老哥手起刀落,我短暫的一生就這樣結束了···

          a3785b02fe30dc3acc409c8c0937df44.webp

          我是一個網(wǎng)絡程序,一直以來都運行在Windows系統(tǒng)上,日子過得很舒服。可前段時間,程序員告訴我要把我移植到Linux系統(tǒng)下運行,需要對我大動手術,我平靜的生活就這樣被打破了。

          來到這個叫Linux的地方運行,一切對我都很陌生,沒有了熟悉的C盤、D盤和E盤,取而代之的是各種各樣的目錄。

          /bin
          /boot
          /etc
          /dev
          /mnt
          /opt
          /proc
          /home
          /usr
          /usr64
          /var
          /sys
          ...

          這里很有意思,一切都是文件,硬件設備是文件、管道是文件、網(wǎng)絡套接字也是文件,搞得我很不適應。

          這些都還好,我都還能接受,但直到今天···

          奇怪的fork

          今天早上,我收到了一個網(wǎng)絡請求,需要完成一個功能,這個工作比較耗時,我準備創(chuàng)建一個子進程,讓我的小弟去完成。

          這是我第一次在Linux系統(tǒng)上創(chuàng)建進程,有點摸不著北,看了半天,只看到程序員在我的代碼里寫了一個fork函數(shù):

          pid_t?pid=fork();
          if?(?pid?>?0?)?{
          ????···
          }?else?if(?pid?==?0?)?{
          ????···
          }?else?{
          ????···
          }

          我晃晃悠悠的來到fork函數(shù)的門前,四處觀察。

          “您是要創(chuàng)建進程嗎?”,fork函數(shù)好像看出了我的來意。

          “是的,我是第一次在這里創(chuàng)建進程,以前我在Windows那片兒的時候,都是調用CreateProcess,但這里好像沒有叫這個名字的函數(shù)···”

          fork函數(shù)聽后笑了起來,說道:“別找了,我就是負責創(chuàng)建進程的函數(shù)”

          “你?fork不是叉子的意思嗎,好端端的干嘛取這么個名字?”,我一邊說,一邊朝fork函數(shù)走去。

          676e3162198e6d7c7020adc162642929.webp

          fork沒有理會我的問題,只是說道:“您這邊稍坐一下,我要跟內核通信一下,讓內核創(chuàng)建一個子進程”

          這下我倒是明白他的意思,像創(chuàng)建進程這種操作,都是由操作系統(tǒng)內核中的系統(tǒng)調用來完成的,而像fork這些我們可以直接調用的函數(shù)只是應用層的接口而已,這跟以前在Windows上是一樣的。

          不過我突然反應過來,著急問道:“唉,我還沒告訴你要創(chuàng)建的進程參數(shù)呢,你怎么知道要啟動哪個程序?”

          fork撲哧一下笑出了聲,不過并沒有回答我的問題。

          人生地不熟的,我也沒好再多問,只好耐心等待,等待期間我竟然睡著了。

          68b68886539612b250ba7ebd3f943929.webp

          “醒醒”,不知過了多久,fork函數(shù)叫醒了我:“創(chuàng)建完成了,請拿好,這是進程號pid”,說完給了我一個數(shù)字。

          我攤開一看,居然寫了一個大大的0!

          “怎么搞的,創(chuàng)建失敗了?”,我問到。

          “沒有啊,您就是剛剛創(chuàng)建的子進程”

          “啥?你是不是搞錯了,我就是專程來創(chuàng)建子進程的,我自己怎么會是子進程?”

          fork函數(shù)又笑了,“我沒有搞錯,您其實已經(jīng)不是原來的你了,而是一個復制品,是內核剛剛復制出來的”

          “復制品?什么意思?”,我越聽越懵!

          “每個進程在內核中都是一個task_struct結構,剛才您睡著期間,內核在創(chuàng)建進程的時候,把內核中原來的你的task_struct復制了一份,還創(chuàng)建了一個全新的進程地址空間和堆棧,現(xiàn)在的你和原來的你除了極少數(shù)地方不一樣,基本上差不多”

          8ab249ba50a4161072298557b7c2478a.webp

          “那原來的我呢?去哪里了”

          “他已經(jīng)變成你的父進程了,我是一個特殊的函數(shù),一次調用會返回兩次,在父進程和子進程中都會返回。在原來的進程中,我把你的進程號給了他,而我返回給你0,就表示你現(xiàn)在就是子進程”

          原來是這樣,我大受震撼,這簡直顛覆我的認知,居然還有如此奇特的函數(shù),調用一次,就變成了兩個進程,思考之間,我忽然有些明白這個函數(shù)為什么要叫fork的原因了。

          寫時拷貝

          “您是剛來咱們這里吧,可能還不太熟悉,慢慢就習慣了”

          “你們這效率也太高了吧,整個進程地址空間那么大,居然這么快就復制了一份!”

          fork函數(shù)又笑了!難道我又說錯話了?

          “進程的內存地址空間可沒有復制,你現(xiàn)在和父進程是共享的內存空間的”

          “啥?共享?你剛才不是說創(chuàng)建了新的進程空間和堆棧嗎?”

          “您看到的內存地址空間是虛擬的,您的內存頁面和父進程的內存頁面實際上是映射的同一個物理內存頁,所以實際上是共享的喲”

          c6092b8b5ad3caaa17ba3dd2ddd2102c.webp

          “原來是這樣,可是弄成共享了,兩個進程一起用,豈不是要出亂子?”

          “放心,內核把這些頁面都設置成了只讀,如果你們只是讀的話,不會有問題,但只要有一方嘗試寫入,就會觸發(fā)異常,內核發(fā)現(xiàn)異常后再去分配一個新的頁面讓你們分開使用。哦對了,這個叫寫時拷貝(COW) 機制”

          b0156b38e318d0b12d5b100fbdc7ad19.webp

          “有點意思,你們倒是挺聰明的”

          “沒辦法,盡量壓縮成本,提高創(chuàng)建進程的效率嘛,因為進程中的很多內存頁面都只會去讀,如果全部無腦拷貝一份,那不是太浪費資源和時間了嗎”,fork函數(shù)說到。

          “有道理,有道理”,我點了點頭,告別了fork函數(shù),準備回去繼續(xù)工作。

          消失的線程們

          本以為這奇怪的進程創(chuàng)建方式已經(jīng)讓我大開眼界了,沒想到可怕的事情才剛剛開始。

          告別fork函數(shù)沒多久,我就卡在了一個地方?jīng)]法執(zhí)行下去,原來,前面有一把鎖被別的線程占用了,而我現(xiàn)在也需要占用它。

          這倒也不足為奇,以往工作的時候,也經(jīng)常碰到鎖被別的線程鎖定的情況,但這一次,我等了很久也一直不見有線程來釋放。

          “喂,醒醒”

          不知過了多久,我竟然又睡著了。

          睜開眼睛,另一個程序站出現(xiàn)在了我的面前。

          “你是?”

          “你好,我是kill

          “kill?那個專門殺進程的kill程序?你來找我干嘛”,我驚的一下睡意全無。

          20a280fe10b7cdfa87a3d8ddbed420ac.webp

          kill程序從背后拿出了兩個數(shù)字:9,1409

          “你看,這是我收到的參數(shù),1409是你的進程號PID,9表示要強制殺死你”

          “啊?為什么?”,那一刻,我徹底慌了。

          “可能是你卡死在這里太久了吧,人類才啟動我來結束你的運行”,kill程序說到。

          “是啊,不知道是哪個該死的線程占用了這把鎖一直不釋放,我才卡在這里”,我委屈的說到。

          “哪里有別的線程,我看了一下,你這進程就只有一個線程啊!”

          “你看錯了吧?”,說完,我認真檢查了起來,居然還真只有一個線程了!我白等了這么久!

          “奇怪了,我明明是一個多線程的程序啊!”,我眉頭緊鎖。

          “你仔細想想,剛才有沒有發(fā)生什么事情?”,kill程序問到。

          “我就執(zhí)行了一下fork,生成了一個子進程,哦對了,我就是那個子進程”

          “難怪!”,kill程序恍然大悟。

          “難怪什么?

          “fork那家伙創(chuàng)建子進程的時候,只會復制當前的線程,其他線程不會被復制!”,Kill程序說完嘆了口氣,仿佛已經(jīng)見怪不怪了。

          “what?怎么會這樣?其他線程沒復制,那豈不是要出亂子?”

          kill程序不緊不慢地說道:“這都是歷史遺留問題了,早期都是單線程的程序,一個task_struct就是一個進程,fork這樣做是沒有問題的,后來出現(xiàn)了多線程技術,一個task_struct實際上是一個線程了,多個task_struct通過共享地址空間,成為一個線程組,也就是進程,但fork仍然只復制當前的線程,就有了這個問題”

          “我去,這坑爹的fork!”

          “你不是第一個被坑的了!等著程序員把你重新改造下吧”

          “唉···”,我長長的嘆了口氣。

          “你還有什么要說的嗎?沒有的話我就要動手了”,kill程序最后問道。

          這一次,我沒有再回答。

          只見kill老哥手起刀落,一切都消失了···

          【完】

          趣話計算機底層技術,喜歡的話,記得三連哦~


          瀏覽 45
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  免费av毛片网站 免费av中文字幕 | 国产69天堂 | 深夜精品福利 | 青春草亚洲视频在线观看 | 欧美真干|