天天看点

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信号捕捉

继续阅读