信號集函數組 - 嵌入式Linux應用編程學習筆記

信號處理的主要方法有兩種,一種是使用簡單的 signal 函數,另一種是使用信號集函數組。

使用 signal 函數處理時,只需把要處理的信號和處理函數列出即可。它主要是用於前 32 種非實時信號的處理,不支持信號傳遞信息,但是由於使用簡單、易於理解,因此也受到很 多程序員的歡迎。

一、signal()函數

下面只給出使用signal()函數的代碼示例:

#include 
#include 
#include 

/*自定義信號處理函數*/
void my_func(int sign_no){ 
    if(sign_no == SIGINT) 
        printf("I have get SIGINT\n"); 
    else if(sign_no == SIGQUIT) 
        printf("I have get SIGQUIT\n"); 
}

int main(){ 
    printf("Waiting for signal SIGINT or SIGQUIT \n "); 

    /*發出相應的信號,並跳轉到信號處理函數處*/ 
    signal(SIGINT, my_func);
    signal(SIGQUIT, my_func); 
    pause(); 
    exit(0); 
}

二、信號集函數組

使用信號集函數組處理信號時涉及一系列的函數,這些函數按照調用的先後次序可分爲以下幾大功能模塊:創建信號集合、登記信號處理器以及檢測信號。其中,創建信號集合主要用於創建用戶感興趣的信號,其函數包括以下幾個。
sigemptyset:初始化信號集合爲空。 

sigfillset:初始化信號集合爲所有信號的集合。 

sigaddset:將指定信號加入到信號集合中去。 

sigdelset:將指定信號從信號集中刪去。 

sigismember:查詢指定信號是否在信號集合之中。 

登記信號處理器主要用於決定進程如何處理信號。這裏要注意的是,信號集裏的信號並不是真正可以處理的信號,只有當信號的狀態處於非阻塞狀態時才真正起作用。因此,首先就要判斷出當前阻塞能不能傳遞給該信號的信號集。這裏首先使用 sigprocmask 函數判斷檢測或更改信號屏蔽字,然後使用 sigaction  函數用於改變進程接收到特定信號之後的行爲。檢測信號是信號處理的後續步驟,但不是必須的。由於內核可以在任何時刻向某一進程發出信號,因此,若該進程必須保持非中斷狀態且希望將某些信號阻塞,這些信號就處於“未決”狀態(也就是進程不清楚它的存在)。所以,在希望保持非中斷進程完成相應的任務之後,就應該將這些信號解除阻塞。Sigpending  函數就允許進程檢測“未決”信號,並進一步決定對它們作何處理。

下面是信號集函數組的示例代碼:

#include 
#include 
#include 
#include 
#include 

void my_func(int signum){
	printf("If you want to quit, please try SIGQUIT\n");
}

int main(){
	sigset_t set, pendset;
	struct sigaction action1, action2;
	int tst_fd;

    /*創建信號集合,把信號SIGQUIT和SIGINT加到信號集合中*/
	if(sigemptyset(&set) < 0)
		perror("sigemptyset");

	if(sigaddset(&set, SIGQUIT) < 0)
		perror("sigaddset");

	if(sigaddset(&set, SIGINT) < 0)
		perror("sigaddset");
		
    /*登記信號處理器,主要用於決定進程如何處理信號,**
    **首先使用sigprocmask()函數判斷檢測或更改信號屏 **
    **蔽字,然後用sigaction()函數改變進程接收到特定 **
    **信號之後的行爲。檢測信號是信號處理的後續步驟,**
    **但不是必須的。                                */
	//if(sigprocmask(SIG_BLOCK, &set, NULL) < 0)
		//perror("sigprocmask");
	//else{
		//printf("blocked\n");
		//sleep(1);
	//}

	if(sigprocmask(SIG_UNBLOCK, &set, NULL) < 0)
		perror("sigprocmask");
	else

	while(1){
		tst_fd = sigismember(&set, SIGINT);
		//printf("tst_fd is %d\n", tst_fd);	
		if(tst_fd > 0){
			sigemptyset(&action1.sa_mask);
			action1.sa_handler = my_func;
			sigaction(SIGINT, &action1, NULL);
		}
		else if(sigismember(&set, SIGQUIT)){
			sigemptyset(&action2.sa_mask);
			action2.sa_handler = SIG_DFL;
			sigaction(SIGTERM, &action2, NULL);
		}
	}
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章