自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

Linux信號(hào)(signal) 機(jī)制分析(2)

系統(tǒng) Linux
本文分析了Linux內(nèi)核對(duì)于信號(hào)的實(shí)現(xiàn)機(jī)制和應(yīng)用層的相關(guān)處理。首先介紹了軟中斷信號(hào)的本質(zhì)及信號(hào)的兩種不同分類方法尤其是不可靠信號(hào)的原理。接著分析了內(nèi)核對(duì)于信號(hào)的處理流程包括信號(hào)的觸發(fā)/注冊(cè)/執(zhí)行及注銷等。最后介紹了應(yīng)用層的相關(guān)處理,主要包括信號(hào)處理函數(shù)的安裝、信號(hào)的發(fā)送、屏蔽阻塞等,最后給了幾個(gè)簡(jiǎn)單的應(yīng)用實(shí)例。

[[181771]]

接上文

5. 信號(hào)的發(fā)送

發(fā)送信號(hào)的主要函數(shù)有:kill()、raise()、 sigqueue()、alarm()、setitimer()以及abort()。

5.1 kill()

  1. #include <sys/types.h> 
  2. #include <signal.h> 
  3. int kill(pid_t pid,int signo)  

該系統(tǒng)調(diào)用可以用來(lái)向任何進(jìn)程或進(jìn)程組發(fā)送任何信號(hào)。參數(shù)pid的值為信號(hào)的接收進(jìn)程

pid>0 進(jìn)程ID為pid的進(jìn)程

pid=0 同一個(gè)進(jìn)程組的進(jìn)程

pid<0 pid!=-1 進(jìn)程組ID為 -pid的所有進(jìn)程

pid=-1 除發(fā)送進(jìn)程自身外,所有進(jìn)程ID大于1的進(jìn)程

Sinno是信號(hào)值,當(dāng)為0時(shí)(即空信號(hào)),實(shí)際不發(fā)送任何信號(hào),但照常進(jìn)行錯(cuò)誤檢查,因此,可用于檢查目標(biāo)進(jìn)程是否存在,以及當(dāng)前進(jìn)程是否具有向目標(biāo)發(fā)送信號(hào)的權(quán)限(root權(quán)限的進(jìn)程可以向任何進(jìn)程發(fā)送信號(hào),非root權(quán)限的進(jìn)程只能向?qū)儆谕粋€(gè)session或者同一個(gè)用戶的進(jìn)程發(fā)送信號(hào))。

Kill()最常用于pid>0時(shí)的信號(hào)發(fā)送。該調(diào)用執(zhí)行成功時(shí),返回值為0;錯(cuò)誤時(shí),返回-1,并設(shè)置相應(yīng)的錯(cuò)誤代碼errno。下面是一些可能返回的錯(cuò)誤代碼:

EINVAL:指定的信號(hào)sig無(wú)效。

ESRCH:參數(shù)pid指定的進(jìn)程或進(jìn)程組不存在。注意,在進(jìn)程表項(xiàng)中存在的進(jìn)程,可能是一個(gè)還沒有被wait收回,但已經(jīng)終止執(zhí)行的僵死進(jìn)程。

EPERM: 進(jìn)程沒有權(quán)力將這個(gè)信號(hào)發(fā)送到指定接收信號(hào)的進(jìn)程。因?yàn)?,一個(gè)進(jìn)程被允許將信號(hào)發(fā)送到進(jìn)程pid時(shí),必須擁有root權(quán)力,或者是發(fā)出調(diào)用的進(jìn)程的UID 或EUID與指定接收的進(jìn)程的UID或保存用戶ID(savedset-user-ID)相同。如果參數(shù)pid小于-1,即該信號(hào)發(fā)送給一個(gè)組,則該錯(cuò)誤表示組中有成員進(jìn)程不能接收該信號(hào)。

5.2 sigqueue()

  1. #include <sys/types.h> 
  2. #include <signal.h> 
  3. int sigqueue(pid_t pid, int sig, const union sigval val)  

調(diào)用成功返回 0;否則,返回 -1。

sigqueue()是比較新的發(fā)送信號(hào)系統(tǒng)調(diào)用,主要是針對(duì)實(shí)時(shí)信號(hào)提出的(當(dāng)然也支持前32種),支持信號(hào)帶有參數(shù),與函數(shù)sigaction()配合使用。

sigqueue的第一個(gè)參數(shù)是指定接收信號(hào)的進(jìn)程ID,第二個(gè)參數(shù)確定即將發(fā)送的信號(hào),第三個(gè)參數(shù)是一個(gè)聯(lián)合數(shù)據(jù)結(jié)構(gòu)union sigval,指定了信號(hào)傳遞的參數(shù),即通常所說(shuō)的4字節(jié)值。

  1. typedef union sigval { 
  2.  
  3.                int  sival_int; 
  4.  
  5.                void *sival_ptr; 
  6.  
  7. }sigval_t;  

sigqueue()比kill()傳遞了更多的附加信息,但sigqueue()只能向一個(gè)進(jìn)程發(fā)送信號(hào),而不能發(fā)送信號(hào)給一個(gè)進(jìn)程組。如果signo=0,將會(huì)執(zhí)行錯(cuò)誤檢查,但實(shí)際上不發(fā)送任何信號(hào),0值信號(hào)可用于檢查pid的有效性以及當(dāng)前進(jìn)程是否有權(quán)限向目標(biāo)進(jìn)程發(fā)送信號(hào)。

在調(diào)用sigqueue時(shí),sigval_t指定的信息會(huì)拷貝到對(duì)應(yīng)sig 注冊(cè)的3參數(shù)信號(hào)處理函數(shù)的siginfo_t結(jié)構(gòu)中,這樣信號(hào)處理函數(shù)就可以處理這些信息了。由于sigqueue系統(tǒng)調(diào)用支持發(fā)送帶參數(shù)信號(hào),所以比kill()系統(tǒng)調(diào)用的功能要靈活和強(qiáng)大得多。

5.3 alarm()

  1. #include <unistd.h> 
  2.  
  3. unsigned int alarm(unsigned int seconds)  

系統(tǒng)調(diào)用alarm安排內(nèi)核為調(diào)用進(jìn)程在指定的seconds秒后發(fā)出一個(gè)SIGALRM的信號(hào)。如果指定的參數(shù)seconds為0,則不再發(fā)送 SIGALRM信號(hào)。后一次設(shè)定將取消前一次的設(shè)定。該調(diào)用返回值為上次定時(shí)調(diào)用到發(fā)送之間剩余的時(shí)間,或者因?yàn)闆]有前一次定時(shí)調(diào)用而返回0。

注意,在使用時(shí),alarm只設(shè)定為發(fā)送一次信號(hào),如果要多次發(fā)送,就要多次使用alarm調(diào)用。

5.4 setitimer()

現(xiàn)在的系統(tǒng)中很多程序不再使用alarm調(diào)用,而是使用setitimer調(diào)用來(lái)設(shè)置定時(shí)器,用getitimer來(lái)得到定時(shí)器的狀態(tài),這兩個(gè)調(diào)用的聲明格式如下:

  1. int getitimer(int which, struct itimerval *value); 
  2. int setitimer(int which, const struct itimerval *value, struct itimerval *ovalue);  

在使用這兩個(gè)調(diào)用的進(jìn)程中加入以下頭文件:

  1. #include <sys/time.h> 

該系統(tǒng)調(diào)用給進(jìn)程提供了三個(gè)定時(shí)器,它們各自有其獨(dú)有的計(jì)時(shí)域,當(dāng)其中任何一個(gè)到達(dá),就發(fā)送一個(gè)相應(yīng)的信號(hào)給進(jìn)程,并使得計(jì)時(shí)器重新開始。三個(gè)計(jì)時(shí)器由參數(shù)which指定,如下所示:

TIMER_REAL:按實(shí)際時(shí)間計(jì)時(shí),計(jì)時(shí)到達(dá)將給進(jìn)程發(fā)送SIGALRM信號(hào)。

ITIMER_VIRTUAL:僅當(dāng)進(jìn)程執(zhí)行時(shí)才進(jìn)行計(jì)時(shí)。計(jì)時(shí)到達(dá)將發(fā)送SIGVTALRM信號(hào)給進(jìn)程。

ITIMER_PROF:當(dāng)進(jìn)程執(zhí)行時(shí)和系統(tǒng)為該進(jìn)程執(zhí)行動(dòng)作時(shí)都計(jì)時(shí)。與ITIMER_VIR-TUAL是一對(duì),該定時(shí)器經(jīng)常用來(lái)統(tǒng)計(jì)進(jìn)程在用戶態(tài)和內(nèi)核態(tài)花費(fèi)的時(shí)間。計(jì)時(shí)到達(dá)將發(fā)送SIGPROF信號(hào)給進(jìn)程。

定時(shí)器中的參數(shù)value用來(lái)指明定時(shí)器的時(shí)間,其結(jié)構(gòu)如下:

  1. struct itimerval { 
  2. struct timeval it_interval; /* 下一次的取值 */ 
  3. struct timeval it_value; /* 本次的設(shè)定值 */ 
  4. };  

該結(jié)構(gòu)中timeval結(jié)構(gòu)定義如下:

  1. struct timeval { 
  2. long tv_sec; /* 秒 */ 
  3. long tv_usec; /* 微秒,1秒 = 1000000 微秒*/ 
  4. };  

在setitimer 調(diào)用中,參數(shù)ovalue如果不為空,則其中保留的是上次調(diào)用設(shè)定的值。定時(shí)器將it_value遞減到0時(shí),產(chǎn)生一個(gè)信號(hào),并將it_value的值設(shè)定為it_interval的值,然后重新開始計(jì)時(shí),如此往復(fù)。當(dāng)it_value設(shè)定為0時(shí),計(jì)時(shí)器停止,或者當(dāng)它計(jì)時(shí)到期,而it_interval 為0時(shí)停止。調(diào)用成功時(shí),返回0;錯(cuò)誤時(shí),返回-1,并設(shè)置相應(yīng)的錯(cuò)誤代碼errno:

EFAULT:參數(shù)value或ovalue是無(wú)效的指針。

EINVAL:參數(shù)which不是ITIMER_REAL、ITIMER_VIRT或ITIMER_PROF中的一個(gè)。

下面是關(guān)于setitimer調(diào)用的一個(gè)簡(jiǎn)單示范,在該例子中,每隔一秒發(fā)出一個(gè)SIGALRM,每隔0.5秒發(fā)出一個(gè)SIGVTALRM信號(hào):

  1. #include <signal.h> 
  2.  
  3. #include <unistd.h> 
  4.  
  5. #include <stdio.h> 
  6.  
  7. #include <sys/time.h> 
  8.  
  9. int sec; 
  10.  
  11.   
  12.  
  13. void sigroutine(int signo) { 
  14.  
  15.         switch (signo) { 
  16.  
  17.         case SIGALRM: 
  18.  
  19.         printf("Catch a signal -- SIGALRM "); 
  20.  
  21.         break; 
  22.  
  23.         case SIGVTALRM: 
  24.  
  25.         printf("Catch a signal -- SIGVTALRM "); 
  26.  
  27.         break; 
  28.  
  29.         } 
  30.  
  31.         return
  32.  
  33.  
  34.   
  35.  
  36. int main() 
  37.  
  38.  
  39.         struct itimerval value,ovalue,value2; 
  40.  
  41.         sec = 5; 
  42.  
  43.   
  44.  
  45.         printf("process id is %d ",getpid()); 
  46.  
  47.         signal(SIGALRM, sigroutine); 
  48.  
  49.         signal(SIGVTALRM, sigroutine); 
  50.  
  51.   
  52.  
  53.         value.it_value.tv_sec = 1; 
  54.  
  55.         value.it_value.tv_usec = 0; 
  56.  
  57.         value.it_interval.tv_sec = 1; 
  58.  
  59.         value.it_interval.tv_usec = 0; 
  60.  
  61.         setitimer(ITIMER_REAL, &value, &ovalue); 
  62.  
  63.   
  64.  
  65.         value2.it_value.tv_sec = 0; 
  66.  
  67.         value2.it_value.tv_usec = 500000; 
  68.  
  69.         value2.it_interval.tv_sec = 0; 
  70.  
  71.         value2.it_interval.tv_usec = 500000; 
  72.  
  73.         setitimer(ITIMER_VIRTUAL, &value2, &ovalue); 
  74.  
  75.   
  76.  
  77.         for (;;) ; 
  78.  
  79.  

該例子的屏幕拷貝如下:

  1. localhost:~$ ./timer_test 
  2.  
  3. process id is 579 
  4.  
  5. Catch a signal – SIGVTALRM 
  6.  
  7. Catch a signal – SIGALRM 
  8.  
  9. Catch a signal – SIGVTALRM 
  10.  
  11. Catch a signal – SIGVTALRM 
  12.  
  13. Catch a signal – SIGALRM 
  14.  
  15. Catch a signal –GVTALRM  

5.5 abort()

  1. #include <stdlib.h> 
  2.  
  3. void abort(void);  

向進(jìn)程發(fā)送SIGABORT信號(hào),默認(rèn)情況下進(jìn)程會(huì)異常退出,當(dāng)然可定義自己的信號(hào)處理函數(shù)。即使SIGABORT被進(jìn)程設(shè)置為阻塞信號(hào),調(diào)用abort()后,SIGABORT仍然能被進(jìn)程接收。該函數(shù)無(wú)返回值。

5.6 raise()

  1. #include <signal.h> 
  2. int raise(int signo)  

向進(jìn)程本身發(fā)送信號(hào),參數(shù)為即將發(fā)送的信號(hào)值。調(diào)用成功返回 0;否則,返回 -1。

6. 信號(hào)集及信號(hào)集操作函數(shù):

信號(hào)集被定義為一種數(shù)據(jù)類型:

  1. typedef struct { 
  2. unsigned long sig[_NSIG_WORDS]; 
  3. } sigset_t  

信號(hào)集用來(lái)描述信號(hào)的集合,每個(gè)信號(hào)占用一位。Linux所支持的所有信號(hào)可以全部或部分的出現(xiàn)在信號(hào)集中,主要與信號(hào)阻塞相關(guān)函數(shù)配合使用。下面是為信號(hào)集操作定義的相關(guān)函數(shù):

  1. #include <signal.h> 
  2. int sigemptyset(sigset_t *set); 
  3. int sigfillset(sigset_t *set); 
  4. int sigaddset(sigset_t *setint signum); 
  5. int sigdelset(sigset_t *setint signum); 
  6. int sigismember(const sigset_t *setint signum); 
  7. sigemptyset(sigset_t *set)初始化由set指定的信號(hào)集,信號(hào)集里面的所有信號(hào)被清空; 
  8. sigfillset(sigset_t *set)調(diào)用該函數(shù)后,set指向的信號(hào)集中將包含linux支持的64種信號(hào); 
  9. sigaddset(sigset_t *setint signum)在set指向的信號(hào)集中加入signum信號(hào); 
  10. sigdelset(sigset_t *setint signum)在set指向的信號(hào)集中刪除signum信號(hào); 
  11. sigismember(const sigset_t *setint signum)判定信號(hào)signum是否在set指向的信號(hào)集中。  

7. 信號(hào)阻塞與信號(hào)未決:

每個(gè)進(jìn)程都有一個(gè)用來(lái)描述哪些信號(hào)遞送到進(jìn)程時(shí)將被阻塞的信號(hào)集,該信號(hào)集中的所有信號(hào)在遞送到進(jìn)程后都將被阻塞。下面是與信號(hào)阻塞相關(guān)的幾個(gè)函數(shù):

  1. #include <signal.h> 
  2. int  sigprocmask(int  how,  const  sigset_t *set, sigset_t *oldset)); 
  3. int sigpending(sigset_t *set)); 
  4. int sigsuspend(const sigset_t *mask));  

sigprocmask()函數(shù)能夠根據(jù)參數(shù)how來(lái)實(shí)現(xiàn)對(duì)信號(hào)集的操作,操作主要有三種:

SIG_BLOCK 在進(jìn)程當(dāng)前阻塞信號(hào)集中添加set指向信號(hào)集中的信號(hào)

SIG_UNBLOCK 如果進(jìn)程阻塞信號(hào)集中包含set指向信號(hào)集中的信號(hào),則解除對(duì)該信號(hào)的阻塞

SIG_SETMASK 更新進(jìn)程阻塞信號(hào)集為set指向的信號(hào)集

sigpending(sigset_t *set))獲得當(dāng)前已遞送到進(jìn)程,卻被阻塞的所有信號(hào),在set指向的信號(hào)集中返回結(jié)果。

sigsuspend(const sigset_t *mask))用于在接收到某個(gè)信號(hào)之前, 臨時(shí)用mask替換進(jìn)程的信號(hào)掩碼, 并暫停進(jìn)程執(zhí)行,直到收到信號(hào)為止。sigsuspend 返回后將恢復(fù)調(diào)用之前的信號(hào)掩碼。信號(hào)處理函數(shù)完成后,進(jìn)程將繼續(xù)執(zhí)行。該系統(tǒng)調(diào)用始終返回-1,并將errno設(shè)置為EINTR。

8. 信號(hào)應(yīng)用實(shí)例

linux下的信號(hào)應(yīng)用并沒有想象的那么恐怖,程序員所要做的最多只有三件事情:

  1. 安裝信號(hào)(推薦使用sigaction());
  2. 實(shí)現(xiàn)三參數(shù)信號(hào)處理函數(shù),handler(int signal,struct siginfo *info, void *);
  3. 發(fā)送信號(hào),推薦使用sigqueue()。

實(shí)際上,對(duì)有些信號(hào)來(lái)說(shuō),只要安裝信號(hào)就足夠了(信號(hào)處理方式采用缺省或忽略)。其他可能要做的無(wú)非是與信號(hào)集相關(guān)的幾種操作。

實(shí)例一:信號(hào)發(fā)送及處理

實(shí)現(xiàn)一個(gè)信號(hào)接收程序sigreceive(其中信號(hào)安裝由sigaction())。

  1. #include <signal.h> 
  2.  
  3. #include <sys/types.h> 
  4.  
  5. #include <unistd.h> 
  6.  
  7. void new_op(int,siginfo_t*,void*); 
  8.  
  9. int main(int argc,char**argv) 
  10.  
  11.  
  12.         struct sigaction act;   
  13.  
  14.         int sig; 
  15.  
  16.         sig=atoi(argv[1]); 
  17.  
  18.         
  19.  
  20.         sigemptyset(&act.sa_mask); 
  21.  
  22.         act.sa_flags=SA_SIGINFO; 
  23.  
  24.         act.sa_sigaction=new_op; 
  25.  
  26.         
  27.  
  28.         if(sigaction(sig,&act,NULL) < 0) 
  29.  
  30.         { 
  31.  
  32.                 printf("install sigal error\n"); 
  33.  
  34.         } 
  35.  
  36.         
  37.  
  38.         while(1) 
  39.  
  40.         { 
  41.  
  42.                 sleep(2); 
  43.  
  44.                 printf("wait for the signal\n"); 
  45.  
  46.         } 
  47.  
  48.  
  49.   
  50.  
  51. void new_op(int signum,siginfo_t *info,void *myact) 
  52.  
  53.  
  54.         printf("receive signal %d", signum); 
  55.  
  56.         sleep(5); 
  57.  
  58.  

說(shuō)明,命令行參數(shù)為信號(hào)值,后臺(tái)運(yùn)行sigreceive signo &,可獲得該進(jìn)程的ID,假設(shè)為pid,然后再另一終端上運(yùn)行kill -s signo pid驗(yàn)證信號(hào)的發(fā)送接收及處理。同時(shí),可驗(yàn)證信號(hào)的排隊(duì)問(wèn)題。

實(shí)例二:信號(hào)傳遞附加信息

主要包括兩個(gè)實(shí)例:

向進(jìn)程本身發(fā)送信號(hào),并傳遞指針參數(shù)

  1. #include <signal.h> 
  2.  
  3. #include <sys/types.h> 
  4.  
  5. #include <unistd.h> 
  6.  
  7. void new_op(int,siginfo_t*,void*); 
  8.  
  9. int main(int argc,char**argv) 
  10.  
  11.  
  12.         struct sigaction act;   
  13.  
  14.         union sigval mysigval; 
  15.  
  16.         int i; 
  17.  
  18.         int sig; 
  19.  
  20.         pid_t pid;          
  21.  
  22.         char data[10]; 
  23.  
  24.         memset(data,0,sizeof(data)); 
  25.  
  26.         for(i=0;i < 5;i++) 
  27.  
  28.                 data[i]='2'
  29.  
  30.         mysigval.sival_ptr=data; 
  31.  
  32.         
  33.  
  34.         sig=atoi(argv[1]); 
  35.  
  36.         pid=getpid(); 
  37.  
  38.         
  39.  
  40.         sigemptyset(&act.sa_mask); 
  41.  
  42.         act.sa_sigaction=new_op;//三參數(shù)信號(hào)處理函數(shù) 
  43.  
  44.         act.sa_flags=SA_SIGINFO;//信息傳遞開關(guān),允許傳說(shuō)參數(shù)信息給new_op 
  45.  
  46.         if(sigaction(sig,&act,NULL) < 0) 
  47.  
  48.         { 
  49.  
  50.                 printf("install sigal error\n"); 
  51.  
  52.         } 
  53.  
  54.         while(1) 
  55.  
  56.         { 
  57.  
  58.                 sleep(2); 
  59.  
  60.                 printf("wait for the signal\n"); 
  61.  
  62.                 sigqueue(pid,sig,mysigval);//向本進(jìn)程發(fā)送信號(hào),并傳遞附加信息 
  63.  
  64.         } 
  65.  
  66.  
  67. void new_op(int signum,siginfo_t *info,void *myact)//三參數(shù)信號(hào)處理函數(shù)的實(shí)現(xiàn) 
  68.  
  69.  
  70.         int i; 
  71.  
  72.         for(i=0;i<10;i++) 
  73.  
  74.         { 
  75.  
  76.                 printf("%c\n ",(*( (char*)((*info).si_ptr)+i))); 
  77.  
  78.         } 
  79.  
  80.         printf("handle signal %d over;",signum); 
  81.  
  82.  

這個(gè)例子中,信號(hào)實(shí)現(xiàn)了附加信息的傳遞,信號(hào)究竟如何對(duì)這些信息進(jìn)行處理則取決于具體的應(yīng)用。

不同進(jìn)程間傳遞整型參數(shù):

把1中的信號(hào)發(fā)送和接收放在兩個(gè)程序中,并且在發(fā)送過(guò)程中傳遞整型參數(shù)。

信號(hào)接收程序:

  1. #include <signal.h> 
  2.  
  3. #include <sys/types.h> 
  4.  
  5. #include <unistd.h> 
  6.  
  7. void new_op(int,siginfo_t*,void*); 
  8.  
  9. int main(int argc,char**argv) 
  10.  
  11.  
  12.         struct sigaction act; 
  13.  
  14.         int sig; 
  15.  
  16.         pid_t pid;          
  17.  
  18.         
  19.  
  20.         pid=getpid(); 
  21.  
  22.         sig=atoi(argv[1]);      
  23.  
  24.         
  25.  
  26.         sigemptyset(&act.sa_mask); 
  27.  
  28.         act.sa_sigaction=new_op; 
  29.  
  30.         act.sa_flags=SA_SIGINFO; 
  31.  
  32.         if(sigaction(sig,&act,NULL)<0) 
  33.  
  34.         { 
  35.  
  36.                 printf("install sigal error\n"); 
  37.  
  38.         } 
  39.  
  40.         while(1) 
  41.  
  42.         { 
  43.  
  44.                 sleep(2); 
  45.  
  46.                 printf("wait for the signal\n"); 
  47.  
  48.         } 
  49.  
  50.  
  51. void new_op(int signum,siginfo_t *info,void *myact) 
  52.  
  53.  
  54.         printf("the int value is %d \n",info->si_int); 
  55.  
  56.  
  57.    

信號(hào)發(fā)送程序:

命令行第二個(gè)參數(shù)為信號(hào)值,第三個(gè)參數(shù)為接收進(jìn)程ID。

  1. #include <signal.h> 
  2.  
  3. #include <sys/time.h> 
  4.  
  5. #include <unistd.h> 
  6.  
  7. #include <sys/types.h> 
  8.  
  9. main(int argc,char**argv) 
  10.  
  11.  
  12.         pid_t pid; 
  13.  
  14.         int signum; 
  15.  
  16.         union sigval mysigval; 
  17.  
  18.         signum=atoi(argv[1]); 
  19.  
  20.         pid=(pid_t)atoi(argv[2]); 
  21.  
  22.         mysigval.sival_int=8;//不代表具體含義,只用于說(shuō)明問(wèn)題 
  23.  
  24.         if(sigqueue(pid,signum,mysigval)==-1) 
  25.  
  26.                 printf("send error\n"); 
  27.  
  28.         sleep(2); 
  29.  
  30.  

注:實(shí)例2的兩個(gè)例子側(cè)重點(diǎn)在于用信號(hào)來(lái)傳遞信息,目前關(guān)于在linux下通過(guò)信號(hào)傳遞信息的實(shí)例非常少,倒是Unix下有一些,但傳遞的基本上都是關(guān)于傳遞一個(gè)整數(shù)

實(shí)例三:信號(hào)阻塞及信號(hào)集操作

  1. #include "signal.h" 
  2.  
  3. #include "unistd.h" 
  4.  
  5. static void my_op(int); 
  6.  
  7. main() 
  8.  
  9.  
  10.         sigset_t new_mask,old_mask,pending_mask; 
  11.  
  12.         struct sigaction act; 
  13.  
  14.         sigemptyset(&act.sa_mask); 
  15.  
  16.         act.sa_flags=SA_SIGINFO; 
  17.  
  18.         act.sa_sigaction=(void*)my_op; 
  19.  
  20.         if(sigaction(SIGRTMIN+10,&act,NULL)) 
  21.  
  22.                 printf("install signal SIGRTMIN+10 error\n"); 
  23.  
  24.         sigemptyset(&new_mask); 
  25.  
  26.         sigaddset(&new_mask,SIGRTMIN+10); 
  27.  
  28.         if(sigprocmask(SIG_BLOCK, &new_mask,&old_mask)) 
  29.  
  30.                 printf("block signal SIGRTMIN+10 error\n"); 
  31.  
  32.         sleep(10); 
  33.  
  34.         printf("now begin to get pending mask and unblock SIGRTMIN+10\n"); 
  35.  
  36.         if(sigpending(&pending_mask)<0) 
  37.  
  38.                 printf("get pending mask error\n"); 
  39.  
  40.         if(sigismember(&pending_mask,SIGRTMIN+10)) 
  41.  
  42.                 printf("signal SIGRTMIN+10 is pending\n"); 
  43.  
  44.         if(sigprocmask(SIG_SETMASK,&old_mask,NULL)<0) 
  45.  
  46.                 printf("unblock signal error\n"); 
  47.  
  48.         printf("signal unblocked\n"); 
  49.  
  50.         sleep(10); 
  51.  
  52.  
  53.   
  54.  
  55. static void my_op(int signum) 
  56.  
  57.  
  58.         printf("receive signal %d \n",signum); 
  59.  
  60.  

編譯該程序,并以后臺(tái)方式運(yùn)行。在另一終端向該進(jìn)程發(fā)送信號(hào)(運(yùn)行kill -s 42 pid,SIGRTMIN+10為42),查看結(jié)果可以看出幾個(gè)關(guān)鍵函數(shù)的運(yùn)行機(jī)制,信號(hào)集相關(guān)操作比較簡(jiǎn)單。

責(zé)任編輯:龐桂玉 來(lái)源: 嵌入式Linux中文站
相關(guān)推薦

2017-01-16 14:48:42

Linux信號(hào)機(jī)制分析

2024-07-16 10:52:09

2017-08-16 16:20:01

Linux內(nèi)核態(tài)搶占用戶態(tài)搶占

2010-11-02 16:25:55

DB2鎖機(jī)制

2011-06-09 09:45:35

Linux QT 信號(hào)

2011-07-05 18:32:52

QT 信號(hào) 機(jī)制

2011-07-05 18:40:19

QT 信號(hào) 機(jī)制

2011-06-23 13:38:27

QT 元對(duì)象 信號(hào)

2017-05-05 08:57:06

卷積神經(jīng)網(wǎng)絡(luò)機(jī)制

2017-05-03 08:52:13

卷積神經(jīng)網(wǎng)絡(luò)神經(jīng)網(wǎng)絡(luò)非線性激活函數(shù)

2024-07-25 11:53:53

2011-06-23 14:40:13

Qt 信號(hào)

2021-12-10 00:01:53

Vsync信號(hào)機(jī)制

2025-02-03 07:00:00

2010-06-22 10:05:36

Linux監(jiān)控

2012-03-02 12:20:21

Javajmapjstack

2021-11-11 17:40:08

WatchdogAndroid源碼分析

2022-04-01 10:30:29

SignalLinux桌面Fedora

2014-05-22 15:00:16

Android消息處理機(jī)制Looper

2009-04-20 21:20:32

Linux文件系統(tǒng)存儲(chǔ)機(jī)制
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)