1. 程式人生 > >linux下的信號屏蔽字

linux下的信號屏蔽字

end 沒有 開發環境 include 打印 put red mem 自定義

信號的表示

  我們知道linux下,可以通過kill命令向進程發送信號.

  當進程收到信號,執行處理動作被稱為遞達;

  當進程接收到信號,還未來得及處理被稱之為未決(pending);

  進程可以選擇阻塞某個信號,當某個信號被阻塞(block)時,永遠不會遞達!

  因此,與這三種處理相對應,在進程的pcb中,存在三張位圖來描述信號相關信息!

block、pending與handler

  block是一個位圖,如果某個信號block為1,則表示其永遠也不會遞達,也就是說永遠都不會執行handler表中的函數.

  pending也是一個位圖,如果某個信號pending為1,表示其已經產生,如果為0,表示沒有產生.

  handler指針數組,表示某個信號處理時的默認動作,SIG_DFL表示默認處理,SIG_IGN表示忽略該信號,其它表示自定義處理.

信號的屏蔽與恢復

  知道了這些,我編寫了一個程序,來驗證一下屏蔽、恢復屏蔽一個信號.

////////////////////////////////////
//文件說明:pending.c
//作者:高小調
//創建時間:2017年06月28日 星期三 15時15分45秒
//開發環境:Kali Linux/g++ v6.3.0
////////////////////////////////////
#include<stdio.h>
#include<signal.h>
#include<unistd.h>
#include<stdlib.h>
//屏蔽SIGINT
void blockSIGINT(){
	sigset_t set;
	sigemptyset(&set);
	sigaddset(&set,SIGINT);
	sigprocmask(SIG_BLOCK,&set,NULL);
}
//恢復SIGINT
void recoverSIGINT(){
	sigset_t set;
	sigemptyset(&set);
	sigprocmask(SIG_SETMASK,&set,NULL);
}
//打印未決表
void printPending(sigset_t *set){
	for(int i=1; i<=31; ++i){
		if(sigismember(set,i)){
			putchar(‘1‘);
		}else{
			putchar(‘0‘);
		}
	}
	putchar(‘\n‘);
}
void handler(int sig){
	printf("the No.%d signal is deliver!\n",sig);
}
int main(){
	signal(SIGINT,handler);
	int count = 5;
	printf("block the SIGINT %ds later!\n",count);
	sigset_t set;
	sigemptyset(&set);
	//先將SIGINT屏蔽掉
	while(1){
		if(count==0){
			blockSIGINT();
			printf("SIGINT has benn blocked!\n");
			break;
		}
		sigpending(&set);
		printPending(&set);
		sleep(1);
		--count;
	}
	//再把它恢復過來
	printf("recover the SIGINT %ds later!\n",10-count);
	while(1){
		if(count==10){
			recoverSIGINT();
			printf("SIGINT has been recovered!\n");
			break;
		}
		//恢復之前,信號被阻塞,因此如果產生SIGINT信號,將會處於未決狀態
		sigpending(&set);
		printPending(&set);
		count++;
		sleep(1);
	}
	while(1);
	return 0;
}

linux下的信號屏蔽字