linux下多進程編程簡介

來源:互聯網
上載者:User
兩年前的文章,拿過來充充門面。————————————————————————linux下多進程編程簡介

( 作者:mikespook | 發布日期:2002-12-8 | 瀏覽次數:272 )

關鍵字:Linux,多進程,fork(),wait()
前言:
    本文章只是為了給廣大和我一樣的菜鳥一個指引。如果你是高手,或對編程毫沒有興趣。建議請不要在此浪費時間。

  多進程是一個非常有用的東西。記得我上次介紹的那個TCP connect掃描器麼,是不是很慢?如果你使用多進程分段掃描連接埠,你會發現速度大大提升。下面我們就來看看怎麼在Linux下進行多進程編程。
    首先,簡單介紹一下我們要用的函數:fork()、wait()。
    fork()函數是一個很有意思的函數。他可以建立一個新進程,把當前的進程分為父進程和子進程。原來進程的所有頁面在調用fork()函數時被分為相同的兩份,所以父進程和子進程都使用相同的映像。該函數與普通函數的不同之處是函數如果調用成功會返回兩次,在父進程中返回子進程的PID;在子進程中返回0。成功後,父進程和子進程都在fork()函數後繼續執行。如果函數調用不成功,則返回一次,傳回值為 -1。
    由於在進程運行時,如果子進程先退出,它不會從進程列表裡清除。而要發一個SIGCHLD(或SIGCLD)訊號給父進程,父進程確認後子進程才會退出。在等待父進程確認期間,子進程處於“zombie”狀態。所以我們就需要使用wait()函數。如果調用wait()函數時已經有一個處於“zombie”狀態的子進程,那麼函數立即返回的同時該子進程從記憶體中清除出去;否則,主進程會被掛起,直到其中一個進程退出。直接調用wait()函數有個很明顯的缺點就是父進程會被掛起而無法進行其他任務。解決辦法就是攔截處理訊號SIGCHLD(或SIGCLD),這我會在以後講訊號處理的文章中給大家簡單的說說。

老規矩,通過原始碼來學習多進程編程。

/*--------------------------fork.c------------------------------*/
/* mikespook */
/* exercise function fork() and wait()*/
/* 2002.5.28 */

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#define FAC_N 65535

/* 子進程調用的函數,這裡我為了類比一個很大的後台操作用了一個迴圈。 */
void big_loop(int n);
/* 父進程調用的函數,其實不放到函數裡也可以,不過為了程式的結構更好看還是放到函數裡的好 */
void input_information();

int main()
{
  /* 進程號 */
  pid_t pid;
  /* 程式在這裡“分叉”,新的進程建立了 */
  pid = fork();
  /* 通過fork()的傳回值來判斷是父進程還是子進程 */
  switch(pid){
    /* 返回 -1,很不幸,建立進程失敗了。可能是沒有足夠的記憶體空間,也可能已經開起了太多的進程。 */
    case -1:
      perror("fork/n");
      break;
    /* 返回 0,現在是在子進程裡運行,那就調用子進程的操作函數。 */
    case 0:
      /* 一個運行65535次的迴圈,如果你的機子太快,不能看清楚兩個進程同時啟動並執行效果,那就再加大迴圈次數。或用sleep()函數 */
      big_loop(FAC_N);
      /* 取得子進程的PID,你可以看清楚子進程和父進程的PID是不同的(子進程的PID比父進程的要大,因為是在父進程運行後才建立的)。*/
      printf("PID:%d/n", getpid());
      break;
    /* 哈哈,返回的即不是錯誤,又不是子進程,那就是父進程嘍。*/
    default:
      /* 這裡讓使用者輸入了4個數 */
      input_information();
      /* 取得子進程的PID。*/
      printf("PID:%d/n", getpid());
      break;
  }
  /* 等著吧,子進程不退出,你父進程也不能退出的。 */   
  wait();
  exit(0);  
}

/*big_loop: 簡單,一看就明白,不解釋了。*/
void big_loop(int n)
{
  int i;
  for(i = 0; i < n; i++){
    switch(i % 4){
      case 0:
        putchar('-');
        break;
      case 1:
        putchar('/');
        break;
      case 2:
        putchar('|');
        break;
      case 3:
        putchar('//');
        break;
    }
    putchar('/b');
  }
}

/*input_information: 簡單,一看就明白,也不解釋了。*/
void input_information()
{
  int n_table[4], i;

  for(i = 0; i < 4; i++){
    printf("Number %d:/t", i);
    scanf("%d", &n_table[i]);
  }

   printf("Number1/tNumber2/tNumber3/tNumber4/n");
   printf("%d/t%d/t%d/t%d/n", n_table[0], n_table[1], n_table[2], n_table[3]);
}
/*--------------------------fork.c------------------------------*/

  同樣,我再給大家補充幾點,以供參考。
  多進程的好處是同時並行的運行多個任務。由於各自使用獨立的記憶體空間,所以不容易由於衝突而出錯。但是這樣就給進程間的通訊帶來了一定的麻煩。當然有很多辦法,比如管道,訊息等等可以解決這個問題。多進程還有一個問題就是記憶體空間的浪費。一個進程就是一個完整的記憶體映像,有一些資料重複放置,這樣對記憶體空間浪費是很嚴重的(我想這也就是多線程比多進程要優越的原因,可惜我還沒有完全搞明白linux下的多線程,要不然也和大家討論討論。過段時間吧!)。還有,我要提示的是上面這個例子我在最後用了wait()函數,這樣父進程運行完後回等著子進程退出才退出。你可以試試把wait();這個語句去掉,看看什麼效果?父進程運行完退出了,我們回到了[mikespook @ lazycat]$的提示符下,而子進程繼續在運行。有時我們可以利用這個把一個進程放到後台去運行(比如木馬……當然啦,我不是建議你做木馬!)。
  好啦,Linux下的多進程編程就怎麼點內容,是不是很簡單呢?其實,讓兩個進程獨立運行很容易,關鍵的痛點是父進程和子進程共用資料,進行通訊。我會在以後的文章中慢慢和大家討論的(其實關鍵是有一些東西還沒有悟透,不敢拿出來丟人^%^)。

給大家個好站:http://www.opengroup.org/onlinepubs/007908799/  線上的man手冊,有什麼不明白的地方可以到這裡查詢。可惜,是E文的。
由於我是菜鳥,或許有什麼不對的地方。也可能一些細節我沒有考慮到。如果你知道的話希望不惜指教。小弟感激不盡!!

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.