乡下人产国偷v产偷v自拍,国产午夜片在线观看,婷婷成人亚洲综合国产麻豆,久久综合给合久久狠狠狠9

  • <output id="e9wm2"></output>
    <s id="e9wm2"><nobr id="e9wm2"><ins id="e9wm2"></ins></nobr></s>

    • 分享

      fork()函數(shù)的用法[轉(zhuǎn)]

       名館58 2012-10-25
      fork() 基礎(chǔ)
      "Fork",除了它是一個(gè)當(dāng)你不停地敲入后看起來非常奇怪的單詞以外,通常是指 Unix 產(chǎn)生新進(jìn)程的方式。由于系統(tǒng)調(diào)用的用法將會(huì)在其他 IPC 的文檔中出現(xiàn),本文只是一個(gè)快速的,不太精確的 fork() 初級(jí)讀本。如果你已經(jīng)通曉 fork() ,最好跳過此節(jié)。 
      "Seek ye the Gorge of Eternal Peril"
      fork() 可被想象為力量的象征,力量有時(shí)可以被想象為毀滅的象征。因此,當(dāng)你的系統(tǒng)由于 fork() 而雜亂無章時(shí),一定要小心。這并不是說永遠(yuǎn)也別碰 fork(), 你只需要保持謹(jǐn)慎。它是象劍刃之類的一種東西,如果你很小心,就不會(huì)被開膛破肚。 

      如果你還在看的話,我想應(yīng)該拿出點(diǎn)實(shí)際東西出來了。正如我所說, fork() 是 Unix 啟動(dòng)新進(jìn)程的方式。最基本的,它是這樣工作的:父進(jìn)程(已經(jīng)存在的那一個(gè)) fork() 一個(gè)子進(jìn)程(新的一個(gè))。子進(jìn)程得到父進(jìn)程數(shù)據(jù)的一個(gè) 拷貝.瞧!以前只有一個(gè)進(jìn)程而現(xiàn)在有了兩個(gè)。 

      當(dāng)然,在 fork() 進(jìn)程時(shí) 你必須得應(yīng)付各種各樣的情況,否則,你的系統(tǒng)管理員會(huì)對(duì)你怒目而視,因?yàn)槟闾顫M了系統(tǒng)的進(jìn)程表 ,而他們不得不按下機(jī)器的重啟鍵 。 

      首先,你必須知道在 Unix 下的一些進(jìn)程的運(yùn)作方式。當(dāng)一個(gè)進(jìn)程死亡時(shí),它并不是完全的消失了。進(jìn)程終止,它不再運(yùn)行,但是還有一些殘留的小東西等待父進(jìn)程收回。這些殘留的東西包括子進(jìn)程的返回值和其他的一些東西。當(dāng)父進(jìn)程 fork() 一個(gè)子進(jìn)程后,它必須用 wait() (或者 waitpid())等待子進(jìn)程退出。正是這個(gè) wait() 動(dòng)作來讓子進(jìn)程的殘留物消失。 

      自然的,在上述規(guī)則之外有個(gè)例外:父進(jìn)程可以忽略 SIGCLD 軟中斷而不必要 wait()。可以這樣做到(在支持它的系統(tǒng)上): 

      main()
      {
      signal(SIGCLD, SIG_IGN); /* now I don't have to wait()! */
      .
      .
      fork();fork();fork(); /* Rabbits, rabbits, rabbits! */

      現(xiàn)在,子進(jìn)程死亡時(shí)父進(jìn)程沒有 wait(),通常用 ps 可以看到它被顯示為“<defunct>”。它將永遠(yuǎn)保持這樣只到父進(jìn)程 wait(),或者按以下方法處理。 

      這里是你必須知道的另一個(gè)規(guī)則:當(dāng)父進(jìn)程在它 wait() 子進(jìn)程之前死亡了(假定它沒有忽略 SIGCLD),子進(jìn)程將把 init (PID 1)進(jìn)程作為它的父進(jìn)程。如果子進(jìn)程工作得很好并能夠控制,這并不是問題。但如果子進(jìn)程已經(jīng)是 defunct,我們就有了一點(diǎn)小麻煩??矗鹊母高M(jìn)程不可能再 wait(),因?yàn)樗呀?jīng)消亡了。這樣,init 怎么知道 wait() 這些 zombie 進(jìn)程。 

      答案:不可預(yù)料的。在一些系統(tǒng)上,init 周期性的破壞掉它所有的 defunct 進(jìn)程。在另外一些系統(tǒng)中,它干脆拒絕成為任何 defunct 進(jìn)程的父進(jìn)程,而是馬上毀滅它們。如果你使用上述系統(tǒng)的一種,可以寫一個(gè)簡單的循環(huán),用 屬于 init 的 defunct 進(jìn)程填滿進(jìn)程表。這大概不會(huì)令你的系統(tǒng)管理員很高興吧? 

      你的任務(wù):確定你的父進(jìn)程不要忽略 SIGCLD,也不要 wait() 它 fork() 的所有進(jìn)程。不過,你也每必要 總是這樣做(比如,你要起一個(gè) daemon 或是別的什么東西),但是你必須小心編程,如果你是一個(gè) fork() 的新手。另外,也不要在心理上有任何束縛。 

      總結(jié):子進(jìn)程成為 defunct 只到父進(jìn)程 wait(),除非父進(jìn)程忽略了 SIGCLD 。更進(jìn)一步,父進(jìn)程沒有 wait() 就消亡(仍假設(shè)父進(jìn)程沒有忽略 SIGCLD )的子進(jìn)程(活動(dòng)的或者 defunct)成為 init 的子進(jìn)程,init 用重手法處理它們。 

      “我已經(jīng)有了心理準(zhǔn)備,把按鈕給我”
      好的!這里是怎樣使用 fork() 的例子: 
      #include <stdio.h>
      #include <stdlib.h>
      #include <errno.h>
      #include <unistd.h>
      #include <sys/types.h>
      #include <sys/wait.h>

      main()
      {
      pid_t pid;
      int rv;

      switch(pid=fork()) {
      case -1:
      perror("fork"); /* something went wrong */
      exit(1); /* parent exits */

      case 0:
      printf(" CHILD: This is the child process!\n");
      printf(" CHILD: My PID is %d\n", getpid());
      printf(" CHILD: My parent's PID is %d\n", getppid());
      printf(" CHILD: Enter my exit status (make it small): ");
      scanf(" %d", &rv);
      printf(" CHILD: I'm outta here!\n");
      exit(rv);

      default:
      printf("PARENT: This is the parent process!\n");
      printf("PARENT: My PID is %d\n", getpid());
      printf("PARENT: My child's PID is %d\n", pid);
      printf("PARENT: I'm now waiting for my child to exit()...\n");
      wait(&rv);
      printf("PARENT: My child's exit status is: %d\n", WEXITSTATUS(rv));
      printf("PARENT: I'm outta here!\n");
      }
      }


      這個(gè)例子中有大量的地方需要講解,我們從頭開始。 
      pid_t 是通用的進(jìn)程類型。在 Unix 中,它是一個(gè) short。因此,我調(diào)用 fork() 并把返回值存入 pid 變量。 fork() 很容易,它的返回值只可能是三種情況: 


      0: 
      如果返回 0,你正在子進(jìn)程中。你可以通過調(diào)用 getppid() 得到父進(jìn)程的 PID 。當(dāng)然,你也可以通過調(diào)用 getpid 得到自己的 PID 。 

      -1: 
      如果返回 -1,有些東西出了錯(cuò),將不會(huì)產(chǎn)生子進(jìn)程。用 perror() 看看發(fā)生了什么事情。你可能已經(jīng)填滿了進(jìn)程表——如果你一轉(zhuǎn)身,發(fā)現(xiàn)系統(tǒng)管理員拿著消防斧正沖你走過來。 

      其他: 
      fork() 返回的其他值意味著你正在父進(jìn)程中,返回值是子進(jìn)程的 PID 。這是得到子進(jìn)程 PID 的唯一方法,因?yàn)闆]有諸如 getcpid() 之類的系統(tǒng)調(diào)用(顯而易見是因?yàn)楦高M(jìn)程與子進(jìn)程之間的一對(duì)多關(guān)系)。 
      當(dāng)子進(jìn)程最終調(diào)用 exit() 時(shí),返回值將被傳遞到正在 wait() 的父進(jìn)程。正如你從 wait() 調(diào)用所看到的那樣,當(dāng)我們打印返回值時(shí)會(huì)有些古怪。WEXITSTATUS() 到底是什么東西?它是一個(gè)宏,從 wait() 返回值中提取實(shí)際的返回值。對(duì),在這個(gè) int 中隱藏了太多的信息,你需要自己來挖掘。 

      現(xiàn)在你發(fā)問了,“wait() 怎么知道在哪個(gè)進(jìn)程上等待?我的意思是,由于父進(jìn)程可以有多個(gè)子進(jìn)程, wait() 實(shí)際等待地是哪一個(gè)?”我的朋友,答案非常簡單,它等待最先退出的那一個(gè)。你可以通過以子進(jìn)程的 PID 為參數(shù)調(diào)用 waitpid() 指明是哪一個(gè)子進(jìn)程。 

      上例中另一個(gè)需要注意的有趣的地方是父進(jìn)程和子進(jìn)程都使用 rv 變量。難道這意味著它被進(jìn)程共享了嗎?不!如果是這樣,我就不會(huì)寫這篇 IPC 的文章了。每個(gè)進(jìn)程對(duì)所有變量都有自己的一個(gè)拷貝。還復(fù)制了其他的很多東西,你必須閱讀 man 看看究竟是什么。 

      上述程序中最后要注意的一個(gè)問題:我使用了一個(gè) switch 語句來處理 fork(),這并不是非常典型,大多數(shù)情況下,你將會(huì)看到 if 語句;有時(shí)短得象這樣:ere; sometimes it's as short as: 

      if (!fork()) {
      printf("I'm the child!\n");
      exit(0);
      } else {
      printf("I'm the parent!\n");
      wait(NULL);
      }

      Oh yeah——上述程序也示范了如果你不關(guān)心返回值的話,怎樣使用 wait():你只須用 NULL 參數(shù)調(diào)用它。 
      結(jié)論
      現(xiàn)在你知道了 fork() 的所有的有力的功能!它不光在計(jì)算機(jī)相關(guān)領(lǐng)域非常有用,而且會(huì)令你的朋友在 party 上大開眼界。另外,它會(huì)幫助你在異性面前更有魅力,男的除外。

        本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點(diǎn)擊一鍵舉報(bào)。
        轉(zhuǎn)藏 分享 獻(xiàn)花(0

        0條評(píng)論

        發(fā)表

        請遵守用戶 評(píng)論公約

        類似文章 更多