系統(tǒng)之家 - 系統(tǒng)光盤下載網(wǎng)站!

當(dāng)前位置:系統(tǒng)之家 > 系統(tǒng)教程 > Linux信號機(jī)制

Linux信號機(jī)制解析

時(shí)間:2015-07-27 14:19:34 作者:zhijie 來源:系統(tǒng)之家 1. 掃描二維碼隨時(shí)看資訊 2. 請使用手機(jī)瀏覽器訪問: https://m.xitongzhijia.net/xtjc/20150727/53879.html 手機(jī)查看 評論

  在Linux中信號也稱為軟中斷,進(jìn)程在收到信號之后在對信號進(jìn)行處理,可以說就是一個(gè)中斷的過程。本文就來為大家簡單地解析一下Linux信號機(jī)制。

Linux信號機(jī)制解析

  1、安裝信號處理函數(shù)

  在系統(tǒng)編程的層面上與信號的處理關(guān)系最直接相關(guān)的函數(shù)有兩個(gè),他們用來安裝信號處理函數(shù):

  sighandler_t signal(int signum, sighandler_t handler);

  int sigaction(int signum, const struct sigaction *act,,struct sigaction *oldact);

  第一個(gè)函數(shù)signal比較簡單,sighandler_t 是一個(gè)別名,其原型是 typedef void (*sighandler_t)(int),他是一個(gè)函數(shù)指針,接受一個(gè)類型為int的參數(shù)(信號的編號),返回void。例如要對SIGUSR1信號進(jìn)行處理:

  void handler(int sig)

  {

  //strsiganl 功能是把信號的編號轉(zhuǎn)為信號說明的字符串

  printf(“Rcv a signal:%s”,strsignal(sig));

  }

  int main()

  {

  signal(SIGUSR1,handler);

  while(1)

  ;

  }

 。ㄟ@段程序其實(shí)是有問題的,后面會(huì)說到)這段程序本來是一段死循環(huán),但是對他發(fā)送SIGUSR1信號,程序會(huì)從while中“中斷”轉(zhuǎn)去執(zhí)行handler中的代碼。在shell中使用kill命令發(fā)送信號SIGUSR1 于是程序就答應(yīng)出了一段這樣的信息:Rcv a signal:User defined signal 1。signal()的用法幾乎就是這么簡單。但是由于可移植的原因,參與項(xiàng)目開發(fā)時(shí),應(yīng)該使用下面的這個(gè)函數(shù)。

  sigaction()函數(shù)的參數(shù)中有兩個(gè)結(jié)構(gòu)體,其man手冊原型如下:

  struct sigaction {

  void (*sa_handler)(int);

  void (*sa_sigaction)(int, siginfo_t *, void *);

  sigset_t sa_mask;

  int sa_flags;

  void (*sa_restorer)(void);

  };

  據(jù)我所知sa_handler和sa_sigaction其實(shí)是在一個(gè)union中,他們都是指向信號處理函數(shù)的指針。

  sa_mask 是要屏蔽的信號,sa_flags 有多種選項(xiàng)。(關(guān)于這兩點(diǎn)后文再細(xì)說)。從sigaction()原型中可以發(fā)現(xiàn)參數(shù)中有兩個(gè)struct sigaction參數(shù),其中act是要安裝的信號處理,而oldact是用來帶回原來的處理方式方便我們處理完信號后的恢復(fù)。如果不需要拿回之前的信號處理方式可以把第三個(gè)參數(shù)置為NULL,反之如果只想得到之前的處理方式而不像安裝新的信號處理,可以把第二個(gè)參數(shù)置為NULL,這點(diǎn)用signal()是辦不到的。用sigaction()改寫上面的例子是這樣的:

  1 void handler(int sig)

  2 {

  3 printf(“Rcv a signal:%s”,strsignal(sig));

  4 }

  5

  6 int main()

  7 {

  8 struct sigaction act;

  9 sigemptyset(&act.sa_mask);

  10 act.sa_handler = handler;

  11 act.sa_flags = 0;

  12 sigaction(SIGUSR1,&act,NULL);

  13 while(1)

  14 ;

  15 }

  2、信號阻塞、信號的未決

  sigset_t 是一種將信號類型以為位掩碼形式存在的數(shù)據(jù)類型(下文都稱之為信號集),他是多種信號的集合(可以保證容納所有的信號)。操作系統(tǒng)的PCB為每個(gè)進(jìn)程都維護(hù)了一個(gè)這樣的數(shù)據(jù)類型,并將其內(nèi)所有的信號阻塞,使他們不可以實(shí)時(shí)到達(dá)進(jìn)程。當(dāng)信號屏蔽解除時(shí)他們才被傳遞到進(jìn)程。在這之間的狀態(tài)通常被稱為未決(pending)。而在信號阻塞期間多次到來的信號,在信號屏蔽解除時(shí)只會(huì)被報(bào)告一次。

  對sigset_t 處理有一系列函數(shù),其中POSIX標(biāo)準(zhǔn)有5個(gè)

  int sigemptyset(sigset_t *set);

  int sigfillset(sigset_t *set);

  int sigaddset(sigset_t *set, int signum);

  int sigdelset(sigset_t *set, int signum);

  int sigismember(const sigset_t *set, int signum);

  這樣的函數(shù)基本上看參數(shù)就能知道怎么用,不在贅述。

  glibc中還實(shí)現(xiàn)了3個(gè)擴(kuò)展的函數(shù):

  int sigisemptyset(sigset_t *set);

  int sigorset(sigset_t *dest, sigset_t *left, sigset_t *right);

  int sigandset(sigset_t *dest, sigset_t *left, sigset_t *right);

  sigprocmask()函數(shù)可以檢測和更改信號屏蔽集。

  每個(gè)進(jìn)程都有一個(gè)用來描述哪些信號遞送到進(jìn)程時(shí)將被阻塞的信號集,該信號集中的所有信號在遞送到進(jìn)程后都將被阻塞。

  int sigprocmask(int how, const sigset_t *set, sigset_t *oldset);

  how

  說明

  SIG_BLOCK

  將set中的信號與原有的取并集,并更新進(jìn)程的屏蔽字

  SIG_UNBLOCK

  解除原有的信號集中包含set中的信號,(set補(bǔ)集的交集)

  SIG_SETMASK

  將進(jìn)程的屏蔽字設(shè)置為set

  sigpending函數(shù)可以看到信號屏蔽期間那些信號來到過(不計(jì)次數(shù)的)。

  以上就是Linux的信號機(jī)制的解析了,當(dāng)然Linux信號機(jī)制是一個(gè)相對復(fù)雜的系統(tǒng),本文能夠給大家的是一個(gè)初步的了解。

標(biāo)簽 信號機(jī)制

發(fā)表評論

0

沒有更多評論了

評論就這些咯,讓大家也知道你的獨(dú)特見解

立即評論

以上留言僅代表用戶個(gè)人觀點(diǎn),不代表系統(tǒng)之家立場

其他版本軟件

熱門教程

人氣教程排行

Linux系統(tǒng)推薦

掃碼關(guān)注
掃碼關(guān)注

掃碼關(guān)注 官方交流群 軟件收錄