天天看點

linux系統程式設計--信号1概念2信号相關函數3練習計算系統1s計算多少次4信号集5信号捕捉

文章目錄

  • 1概念
    • 1.1特點
    • 1.2信号的狀态
    • 1.3處理方式
    • 1.4信号4要素
    • 1.6概念阻塞信号集,未決信号集
  • 2信号相關函數
    • 2.1 kill(pid_t pid,int sig)發送信号給指定程式
      • 2.1.1pid參數
      • 2.1.2傳回值
      • 2.1.3代碼
    • 2.2 rasie(int sig)自己給自己發信号
      • 2.2.1代碼
    • 2.3abort(void) 給自己發異常終止信号
    • 2.4alarm(unsigned int seconds);鬧鐘/定時器
      • 2.4.1代碼
    • 2.5setitimer 周期性鬧鐘/定時器
      • 2.5.1參數
      • 2.5.2傳回
      • 2.5.3代碼
  • 3練習計算系統1s計算多少次
    • 3.1代碼
  • 4信号集
    • 4.1概念
      • 關系圖
    • 4.2自定義信号集
      • 4.2.1int sigemptyset(sigset_t *set)
      • 4.2.2int sigfillset(sigset_t *set)
      • 4.2.3int sigaddset(sigset_t *set,int signo)
      • 4.2.1int sigdelset(sigset_t *set,int signo)
      • 4.2.1int sigismember(sigset_t *set,int signo)
    • 4.3sigprocmask函數
    • 4.4sigpenging函數
    • 4.5将系統中的未決信号集列印出來signal
  • 5信号捕捉
    • 5.1signal函數
      • 5.1.1函數原型
      • 5.1.2示例代碼
      • 5.1.3結果
    • 5.2sigaction函數
      • 5.2.1 函數原型
      • 5.2.2示例代碼
      • 5.2.3結果

1概念

1.1特點

  • 簡單
  • 攜帶資訊量少
  • 使用在某個特定的場景中()

1.2信号的狀态

  • 産生
    • 鍵盤:ctrl+c
    • 指令:kill
    • 系統函數:kill
    • 軟體件:定時器
    • 硬體錯誤:段錯誤
  • 未決狀态(沒有被處理了,等待被處理)
  • 遞達(信号被處理了)

    狀态關系圖

    linux系統程式設計--信号1概念2信号相關函數3練習計算系統1s計算多少次4信号集5信号捕捉

信号流程圖

1.3處理方式

  • 忽略
  • 捕捉
  • 執行預設處理

1.4信号4要素

  • 編号
  • 信号
  • 對應的事件
  • 預設動作
    linux系統程式設計--信号1概念2信号相關函數3練習計算系統1s計算多少次4信号集5信号捕捉
  • 信号有以下預設處理動作
Term   Default action is to terminate the process(終止).
Ign    Default action is to ignore the signal.(忽略)
Core   Default action is to terminate the process and dump core (see core(5)).(終止 但是會告訴終止的狀态)
Stop   Default action is to stop the process.(暫停)
Cont   Default action is to continue the process if it is currently stopped.(取消暫停)
           

1.6概念阻塞信号集,未決信号集

阻塞信号集,未決信号集在pcb(核心中)裡,而pcb不能直接操作

  • 阻塞信号集
    • 裡面要放着屏蔽的信号
  • 未決信号集
    • 沒有被處理的信号的集合

2信号相關函數

2.1 kill(pid_t pid,int sig)發送信号給指定程式

2.1.1pid參數

pid參數 含義
大于0 發送信号給指定信号
發送信号給與調用kill函數程序屬于同一程序組的所有信号
-1 發送給目前使用者所有組程序
小于-1 取【pid】發給對應程序組

2.1.2傳回值

傳回值 含義
成功
-1 失敗

2.1.3代碼

int main(){
	pid_t pid=fork();
	if(pid>0){
		while(1){
			printf("parent process %d\n",getpid());
			sleep(1);
		}
	}
	//child process 殺死程序
	else if(pid ==0){
		sleep(2);	
		kill(getppid(),SIGKILL);
	}

	return 1;
}
           

2.2 rasie(int sig)自己給自己發信号

  • 傳回值( raise() returns 0 on success, and nonzero for failure.)

2.2.1代碼

int main(){
	pid_t pid=fork();
	if(pid>0){//父程序回收子程序
		int s;
		pid_t wpid =wait(&s);
		printf("child died pid =%d\n",wpid);
		//判斷子程序退出狀态
		if(WIFSIGNALED(s)){
			//判斷殺死子程序的是那個信号量
			printf("died bu signal %d\n",WTERMSIG(s));
		}		
	}
	//child process 殺死自己
	else if(pid ==0){	
		raise(SIGINT);
	}

	return 1;
}
           

2.3abort(void) 給自己發異常終止信号

  • 發送的信号為6) SIGABRT
  • 沒有參數 沒有傳回值 永遠不會調用失敗

2.4alarm(unsigned int seconds);鬧鐘/定時器

  • 每個程序隻能有一個鬧鐘
  • 參數是秒數
    • 當時間到達後 函數會發出一個信号:SIGALRM
    • 當秒數=0時 取消鬧鐘
  • 傳回值:上個鬧鐘還有多少秒發資訊

2.4.1代碼

#include<signal.h>
int main(){
	int ret=alarm(5);
	printf("ret =%d\n",ret);
	sleep(2);
	//重新設定定時器
	ret=alarm(2);//ret=3 傳回值為上個鬧鐘的剩餘秒數 
	printf("ret =%d\n",ret);
	while(1){
		printf("hello word\n");
		sleep(2);
		//alarm 時間到了就會自動發出16)SIGALRM信号來終止程序 如果不想制止 需要捕捉信号函數
	}

	

	return 1;
}
           

2.5setitimer 周期性鬧鐘/定時器

原型:

2.5.1參數

  • which定時法則 (對應發送的信号量不同)
    • ITIMER_REAL自然定時法則(計算使用者+核心+損耗 alarm屬于他 )
    • ITIMER_VIRTUAL虛拟定時法則(值計算使用者時間) .
    • ITIMER_PROF (隻計算使用者+核心時間)
  • new value設定鬧鐘屬性
struct itimerval {
               struct timeval it_interval; //定時期循環周期
               struct timeval it_value;    //第一次觸發定時器的時間
           };

           struct timeval {
               time_t      tv_sec;         /* seconds */
               suseconds_t tv_usec;        /* microseconds */
           };

           

2.5.2傳回

On success, zero is returned.  On error, -1 is returned, and errno is set appropriately
           

2.5.3代碼

int main(){
	//設定定時器
	struct itimerval new_val;
	new_val.it_value.tv_sec=2;//2秒
	new_val.it_value.tv_usec=0;//0微秒 兩者相加 等于2.00秒
	//周期性定時
	new_val.it_interval.tv_sec=1;
	new_val.it_interval.tv_usec=0;

	setitimer(ITIMER_REAL,&new_val,NULL);
	while(1){
		printf("hello world\n");
		sleep(1);
	}

	return 1;
}
           

3練習計算系統1s計算多少次

real =使用者+核心+損耗

列印到終端

linux系統程式設計--信号1概念2信号相關函數3練習計算系統1s計算多少次4信号集5信号捕捉

列印到檔案

linux系統程式設計--信号1概念2信号相關函數3練習計算系統1s計算多少次4信号集5信号捕捉
  • 你會發現損耗不一樣,而列印終端的損耗來自檔案IO操作

3.1代碼

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

	return 1;
}
           

4信号集

4.1概念

  • 阻塞信号集
    • 裡面要放着屏蔽的信号 ,将某個信号集放在阻塞信号集,這個信号就不會被程序處理。
    • 阻塞解除後,信号被處理。
  • 未決信号集
    • 沒有被處理的信号的集合

關系圖

linux系統程式設計--信号1概念2信号相關函數3練習計算系統1s計算多少次4信号集5信号捕捉

4.2自定義信号集

4.2.1int sigemptyset(sigset_t *set)

  • 将set集合置空

4.2.2int sigfillset(sigset_t *set)

  • 将所有信号加入set集合

4.2.3int sigaddset(sigset_t *set,int signo)

  • 将signo信号加入到set集合

4.2.1int sigdelset(sigset_t *set,int signo)

  • 将signo信号從set集合移除

4.2.1int sigismember(sigset_t *set,int signo)

  • 判斷信号是否存在

4.3sigprocmask函數

  • 屏蔽和接觸信号屏蔽,将自定義信号集設定給阻塞信号集
  • 函數原型
    • int sigprocmask(int how,const sigset_t *set,sigset_t *oldset);

4.4sigpenging函數

  • 讀取目前程序的未決信号集
  • int sigpenging(sigset_t *set);
  • 參數:set–核心将未決信号集寫入set中

4.5将系統中的未決信号集列印出來signal

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<fcntl.h>
#include<string.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<signal.h>
#include<sys/time.h>
int main(){
	//手動的屏蔽幾個信号
	//自定義信号集合
	sigset_t myset;
	//清空
	sigemptyset(&myset);
	//添加要阻塞的信号
	sigaddset(&myset,SIGINT);//crtl+c
	sigaddset(&myset,SIGQUIT);//crtl+反斜杠
	sigaddset(&myset,SIGKILL);//這給信号不能屏蔽 阻塞 捕捉
	//将自定義的信号集設定給核心的阻塞信号集
	sigprocmask(SIG_BLOCK,&myset,NULL);
	int i;
	//每隔一秒讀取一次記憶體的未決信号集
	while(1){
		sigset_t pendset;
		sigpending(&pendset);
		for(i=1;i<=31;i++){
			if(sigismember(&pendset,i)){
				printf("1");
			}else{
				printf("0");
			}
		}
		printf("\n");
		sleep(1);
	}
	return 1;
}
           
linux系統程式設計--信号1概念2信号相關函數3練習計算系統1s計算多少次4信号集5信号捕捉

5信号捕捉

5.1signal函數

5.1.1函數原型

回調函數

  • typedef void (*sighandler_t)(int)
  • sighandler_t signal(int signum,sighandler_t handler)

5.1.2示例代碼

void myfunc(int sig){
	printf("catch %d signal\n",sig);
}
int main(){
	//捕捉信号
	signal(SIGINT,myfunc);
	while(1){
		printf("hello\n");
		sleep(1);
	}
	return 1;
}
           

5.1.3結果

linux系統程式設計--信号1概念2信号相關函數3練習計算系統1s計算多少次4信号集5信号捕捉

5.2sigaction函數

5.2.1 函數原型

int sigaction(int signum,//捕捉的信号 
			  const struct sigaction *act,
              struct sigaction *oldact);
struct sigaction {
               void     (*sa_handler)(int);//捕捉回調函數
               void     (*sa_sigaction)(int, siginfo_t *, void *);//不用
               sigset_t   sa_mask;//作用:在信号處理函數執行的過程中 臨時屏蔽指定信号
               int        sa_flags;
               				//0 對應sa_handler
               				//其他值對應sa_sigaction
               void     (*sa_restorer)(void);//現在被廢棄
           };
           

5.2.2示例代碼

void myfunc(int sig){
	printf("hello catch %d signal\n",sig);
	sleep(2);
	printf("wake up\n");
}
int main(){
	struct sigaction act;
	act.sa_flags=0;
	act.sa_handler=myfunc;
	sigemptyset(&act.sa_mask);
	//添加臨時屏蔽
	sigaddset(&act.sa_mask,SIGQUIT);
	//捕捉信号
	sigaction(SIGINT,&act,NULL);
	while(1);
	return 1;
}
           

5.2.3結果

linux系統程式設計--信号1概念2信号相關函數3練習計算系統1s計算多少次4信号集5信号捕捉

繼續閱讀