歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux綜合 >> 學習Linux >> 信號,信號韓劇

信號,信號韓劇

日期:2017/3/6 9:30:21   编辑:學習Linux

信號,信號韓劇


信號,信號韓劇


信號的基本概念: 每個信號都有一個編號和一個宏定義名稱 ,這些宏定義可以在 signal.h 中找到。 使用kill -l命令查看系統中定義的信號列表: 1-31是普通信號; 34-64是實時信號 所有的信號都由操作系統來發! 對信號的三種處理方式:忽略信號、直接執行進程對於該信號的默認動作、執行自定義動作;

產生信號的條件:

1.用戶在終端按下某些鍵時,終端驅動程序會發送信號給前台程序。 例如:Ctrl-c產生SIGINT信號,Ctrl-\產生SIGQUIT信號,Ctrl-z產生SIGTSTP信號 2.硬件異常產生信號。 這類信號由硬件檢測到並通知內核,然後內核向當前進程發送適當的信號。 例如:當前進程執行除以0的指令,CPU的運算單元會產生異常,內核將這個進程解釋為SIGFPE信號發送給當前進程。 當前進程訪問了非法內存地址,MMU會產生異常,內核將這個異常解釋為SIGSEGV信號發送給進程。 3.一個進程調用kill(2)函數可以發送信號給另一個進程。 可以用kill(1)命令發送信號給某個進程,kill(1)命令也是調用kill(2)函數實現的,如果不明確指定信號則發送SIGTERM信號,該信號的默認處理動作是終止進程。 信號 的產生: 1.通過終端按鍵產生信號 舉個栗子:寫一個死循環,前台運行這個程序,然後在終端鍵入Ctrl-c   當CPU正在執行這個進程的代碼 , 終端驅動程序發送了一 個 SIGINT 信號給該進程,記錄在該進程的 PCB中,則該進程的用戶空間代碼暫停執行 ,CPU從用戶態 切換到內核態處理硬件中斷。   從內核態回到用戶態之前, 會先處理 PCB中記錄的信號 ,發現有一個 SIGINT 信號待處理, 而這個信號的默認處理動作是終止進程,所以直接終止進程而不再返回它的用戶空間代碼執行。 2.調用系統函數向進程發信號
/*************************************************************************
 > File Name: test.c
 > Author:Lynn-Zhang
 > Mail: [email protected]
 > Created Time: Fri 15 Jul 2016 03:03:57 PM CST
 ************************************************************************/
 
#include<stdio.h>
int main()
{
    printf("get pid :%d circle ...\n",getpid());
    while(1);
    return 0;
}
寫一個上面的程序在後台執行死循環,並獲取該進程的id,然後用kill命令給它發送SIGSEGV信號,可以使進程終止。也可以使用kill -11 5796,11是信號SIGSEGV的編號。 kill命令是調用kill函數實現的。kill函數可以給一個指定的進程發送指定信號。

raise函數可 以給當前進程發送指定的信號 (自己給自己發信號 )

#include<signal.h>
int kill(pid_t pid,int signo);
int raise(int signo);
這兩個函數都是成功返回0,錯誤返回-1. 除此之外,abort函數使當前進程接收到SIGABRT信號而異常終止。
#include<stdlib.h>
void abort(void);
就像 exit函數一樣 ,abort 函數總是會成功的 ,所以沒有返回值。 3.由軟件條件產生信號
/*************************************************************************
 > File Name: alarm.c
 > Author:Lynn-Zhang
 > Mail: [email protected]
 > Created Time: Fri 15 Jul 2016 08:52:02 PM CST
 ************************************************************************/

#include<stdio.h>

int main()
{
    int count=0;
    alarm(1);
    while(1)
    {
        printf("%d\n",count);
        count++;
    }
    return 0;
}

 通過實現以上代碼,調用alarm函數可以設定一個鬧鐘,告訴內核在seconds秒之後給當前進程發SIGALRM信號, 該信號的默認處理動作是終止當前進程。

該程序會在1秒鐘之內不停地數數,並打印計數器,1秒鐘到了就被SIGALRM信號終止。由於電腦配置等的不同,每台電腦一秒鐘之內計數值是不同的一般是不同的。

#include <unistd.h>
unsigned int alarm(unsigned int seconds);

  alarm函數的返回值是0或上次設置鬧鐘剩余的時間。

阻塞信號:

1.信號在內核中的表示:

信號遞達delivery:實際執行信號處理信號的動作 信號未決pending:信號從產生到抵達之間的狀態,信號產生了但是未處理 忽略:抵達之後的一種 動作 阻塞block:收到信號不立即處理 被阻塞的信號將保持未決狀態,直到進程解除對此信號的阻塞,才執行抵達動作 信號產生和阻塞沒有直接關系 抵達和解除阻塞沒有直接關系! 進程收到一個信號後,不會立即處理,它會在恰當的時機被處理。

每個信號都由兩個標志位分別表示阻塞和未決,以及一個函數指針表示信號的處理動作。

在上圖的例子中,

1. SIGHUP信號未阻塞也未產生過,當它遞達時執行默認處理動作。
2. SIGINT信號產生過,但正在被阻塞,所以暫時不能遞達。雖然它的處理動作是忽略,但在沒 有解除阻塞之前不能忽略這個信號,因為進程仍有機會改變處理動作之後再解除阻
塞。
3. SIGQUIT信號未產生過,一旦產生SIGQUIT信號將被阻塞,它的處理動作是用戶自定義函數sighandler。
阻塞信號集也叫作信號屏蔽字。

2.信號集操作函數

#include <signal.h>
int sigemptyset(sigset_t *set);      //初始化set所指向的信號集,使所有信號的對應位清0
int sigfillset(sigset_t *set);       //初始化set所指向的信號集,表示該信號集的有效信號包括系統支持的所有信號
int sigaddset(sigset_t *set, int signo);   //在該信號集中添加有效信號
int sigdelset(sigset_t *set, int signo);    //在該信號集中刪除有效信號
int sigismember(const sigset_t *set, int signo);   //⽤用於判斷一個信號集的有效信號中是否包含某種信號

3.調用函數sigprocmask可以讀取或更改進程的信號屏蔽字(阻塞信號集)。

#include <signal.h>
int sigprocmask(int how, const sigset_t *set, sigset_t *oset);

 如果調用sigprocmask解除了對當前若干個未決信號的阻塞,則在sigprocmask返回前,至少將其中 一個信號遞達。

4. sigpending讀取當前進程的未決信號集,通過set參數傳出

#include <signal.h>
int sigpending(sigset_t *set);

  

http://xxxxxx/Linuxjc/1142285.html TechArticle

Copyright © Linux教程網 All Rights Reserved