linux下訊號編程簡介——不可靠的訊號

來源:互聯網
上載者:User

linux下訊號編程簡介——不可靠的訊號
( 作者:mikespook | 發布日期:2002-12-8 | 瀏覽次數:135 )

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

  訊號是什嗎?其實這是一個很有意思的東西。比如說汽車行駛在路上相互鳴笛這就是訊號;同樣遇到紅燈必須停下來這也是

訊號。對應到作業系統中,假設進程就是汽車,那麼進程之間可以發送訊號;同樣如果假設作業系統是公路系統,那麼作業系統

也可以向進程發送訊號。
    在linux中訊號分為不可靠(或叫不安全)的訊號與可靠的訊號。後面我會解釋為什麼這麼說。
    首先,簡單介紹一下linux系統中的通用訊號:
    SIGHUP   終端線以掛起。這是指當丟失載波訊號時數據機線的掛起操作。然而,當它用logout函數關閉時,也將適用於

任一終端裝置。
    SIGINT   終端線已經收到中斷字元。
    SIGQUIT  終端線已經收到退出字元。
    SIGUSR1  使用者定義訊號1。
    SIGUSR2  使用者定義訊號2。
    SIGTERM  正被終止的進程。
    SIGCHLD  一個子進程已經終止。
    SIGPIPE  半關閉管道發生寫操作。
    SIGALRM  Alarm函數記時器到時。
    再來看看要用的函數signal()。signal()函數的定義在標頭檔 signal.h 中,它的函數原形是 sig_t signal(int sig,

sig_t func); 第一個參數是想要註冊的訊號,第二個參數是指向訊號處理函數的指標,或預設操作。系統提供了兩種預設操作:

SIG_DEL 和 SIG_IGN,分別是預設訊號操作和忽略訊號。

    好了說了一大堆枯燥無味的東西,有些暈了。單刀直入,看一個程式把。還記得上次那個多進程的程式嗎?我對其進行了一

些修改。使得當子進程運行結束後不必等父進程順序運行到 wait() 函數,而是直接轉入訊號處理函數。唉,複雜說不清楚。自

己看吧!

/*--------------------------signal_fork.c------------------------------*/
/* mikespook */
/* exercise function signal() */
/* 2002.7.18 */

#include
#include
#include
#include
#define FAC_N 65535

/* 子進程調用的函數,這裡我為了類比一個很大的後台操作用了一個迴圈。 */
void big_loop(int n);
/* 父進程調用的函數,其實不放到函數裡也可以,不過為了程式的結構更好看還是放到函數裡的好 */
void input_information();
/* 訊號處理函數,當父進程收到SIGCHLD訊號的時候就會轉入該函數進行操作 */
void handler();

int main()
{
  /* 進程號 */
  pid_t pid;
  /* 想用訊號?那先對訊號處理函數進行註冊,對應起來 */
  signal(SIGCHLD, handler);
  /* 程式在這裡“分叉”,新的進程建立了 */
  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());
      /* 子進程執行完了,發送訊號 SIGCHLD。由於前面對這個訊號進行了註冊,這時就會轉入訊號處理操作。 */
      break;
    /* 哈哈,返回的即不是錯誤,又不是子進程,那就是父進程嘍。*/
    default:
      /* 這裡讓使用者輸入了4個數 */
      input_information();
      /* 取得子進程的PID。*/
      printf("PID:%d/n", getpid());
      break;
  }
  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]);
}

/* 訊號處理函數,當子進程結束的時候會向父進程發送 SIGCHLD 訊號,這時程式會轉入這個函數裡進行處理 */
void handler()
{
  /* 父進程確認,子進程退出 */
  wait();
}
/*--------------------------signal_fork.c------------------------------*/

    看到了吧,訊號的使用還是很簡單的。但是這是不可靠的訊號使用方法。為什嗎?道理很簡單,當你程式啟動並執行時候收到一

個需要處理的訊號,你的程式就會轉入訊號處理函數,對訊號進行處理,處理完後再繼續執行後續程式。在這個過程中如果正好

是執行 malloc() 這樣的函數時收到了訊號,那麼當訊號處理完畢後因為 malloc() 不是一個可重新進入的函數,程式不會繼續執行

malloc() ,這樣空間也許不會分配,而造成錯誤。所以我們還需要可靠的訊號處理方式,也就是說當執行某些不可被中斷的操作

的時候屏蔽掉訊號處理。直到這些關鍵操作完成,再對訊號進行處理。以後我會給大家詳細的解釋可靠訊號的操作。

引用:http://blog.csdn.net/zhoujunyi/archive/2007/04/13/1563180.aspx

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.